[delphi] Повернуть TImage на 90°

stm5643616

Есть картинка, загруженная на TImage. Задача - повернуть ее на 90°, 180° или 270°.

elenangel

сдается мне что только попиксельно руками. если скорость некритична то двумя for'ами в буфер такого же размера

elenangel

вот так:

procedure TForm1.Button1Click(Sender: TObject);
var
w,h,i,j:integer;
b1,b2:TBitmap;
r:integer;
begin
w := Image1.Width;
h := Image1.Height;

b1 := nil;
b2 := nil; // исправился

try
b1 := TBitmap.Create;
b2 := TBitmap.Create;
b1.Assign(Image1.Picture.Graphic);

r := 90;
case r of
// +90°
90:
begin
b2.Width := h;
b2.Height := w;
for i := 0 to w-1 do begin
for j := 0 to h-1 do begin
b2.Canvas.Pixels[j,w-i] := b1.Canvas.Pixels[i,j];
end
end;
end;
// +180°
180:
begin
b2.Width := w;
b2.Height := h;
for i := 0 to w-1 do begin
for j := 0 to h-1 do begin
b2.Canvas.Pixels[w-i,h-j] := b1.Canvas.Pixels[i,j];
end
end;
end;
// +270°
270:
begin
b2.Width := h;
b2.Height := w;
for i := 0 to w-1 do begin
for j := 0 to h-1 do begin
b2.Canvas.Pixels[h-j,i] := b1.Canvas.Pixels[i,j];
end
end;
end;
end;
Image2.Picture.Assign(b2);
Image2.Width := b2.Width;
Image2.Height := b2.Height
finally
b1.Free;
b2.Free;
end;
end;

stm5643616

спасибо

ppplva

Сдается мне, что твоя функция корректно работает только при 90 градусах.

0000

Взято с DRKB. Раньше был сайт drkb.ru, ща он сдох - так что качай на торрентс.ру.
[Тут был код, похожий на приведенный выше]

elenangel

я не сказал что нужно использовать эту функцию а написал код содержащий все 3 необходимых варианта. для простоты один из вариантов законстантен в коде. человек
минимально знакомый с паскалем легко сделает все что ему нужно на основе приведенного текста.

356ft85

обойтись кстати можно буфером в одну переменную типа TCOlor
а для увеличения скорости еще заюзать ScanLine

elenangel

если в исходный Image записана jpg картинка то нет доступа даже к Pixels. поэтому я и создал 2 Bitmap в которые копируется исходная картинка и результат. можно конечно идти и по сканлайнам, но для этого уже придется включать мозг. для разовой обработки картинки годятся и Pixels, всякая оптимизация нужна если необходимо делать что-то скажем 25 раз в секунду для потока картинок.

zorin29

Мне кажется, что если мы освобождаем объекты в finally, то создавать их надо не внутри try-блока, а снаружи. Тогда даже если первый TBitmap.Create слетит с Exception-ом, не будет делаться попытка b2.Free.
Поправьте, если я ошибаюсь.

zorin29

Я писал когда-то алгоритм какого-то пиксельного фильтра: над каждым пикселем делалось константное число операций - порядка 5 умножений. На моем тогдашнем Celeron 500 большие картинки обрабатывались недопостимо медленно - пришлось делать через ScanLine.

Dasar

Мне кажется, что если мы освобождаем объекты в finally, то создавать их надо не внутри try-блока, а снаружи.
да, правильнее снаружи, и на каждое создание отдельный try
можно еще внутри блока finally проверять на null-и

yroslavasako

можно еще внутри блока finally проверять на null-и
а разве free не делает это само?

Andbar

а разве free не делает это само?
делает, но для этого его нужно обнулить перед try-finally блоком :smirk: :p

elenangel

b2.Free проверяет выделена ли память. можно даже сделать b2:=nil; b2.Free; и исключения не будет

elenangel

да, действительно, стоило сделать присваивания nil. заломало просто.
upd. исправил чтоб не резало глаз особо придирчивым

elenangel

я делал что-то вроде детектора движения на последовательности картинок в порядке курсовой. после первой же попытки использовать Pixels забросил это. вместо этого использовал встроенные в Windows DIB images, которые позволяют обращаться к картинке как к области памяти. очень удобно, можно даже на ассемблере вставки делать, и быстро работает. единственное что к остальной проге привязка несколько неудобная получается.
Оставить комментарий
Имя или ник:
Комментарий: