Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.04.11;
Скачать: CL | DM;

Вниз

Поворот Bitmap - а   Найти похожие ветки 

 
chuckloon ©   (2003-10-22 17:16) [0]

Я загрузил Bitmap в TBitmap. Подскажите алгоритм или библиотечку для быстрого поворота его на произвольный угол.


 
MBo ©   (2003-10-22 17:28) [1]

xNew:=xC+(xOld-xC)*cos(fi)+(yOld-yC)*sin(fi)
yNew:=yC-(xOld-xC)*sin(fi)+(yOld-yC)*cos(fi)

лучше для каждой точки нового повернутого битмапа находить соотв. точку исходного


 
miek ©   (2003-10-23 20:14) [2]

В моем SpriteUtils есть быстрый, но неряшливый (некрасиво выглядит на углах, далеких от кратным 45) алгоритм. Правда, все заточено для KOL.


 
Mihey ©   (2003-10-23 20:29) [3]

http://delphibase.endimus.ru/?action=viewfunc&topic=mediaimg&id=10186


 
miek ©   (2003-10-23 23:52) [4]

2Mihey: Там неоптимизировано.


 
марсианин   (2003-10-24 01:37) [5]

FastLib умеет неплохо вращать, можно посмотреть исходник
еще есть такая апишная ф-ция PlgBlt. она может делать многое в т.ч. вращать.


 
Вилис   (2003-10-24 08:26) [6]

2 марсианин
Что за ф-ия и где она лежит?!


 
MacroDenS ©   (2003-10-24 13:24) [7]

еще в кладовку я что-то подобное видел, вращения, там прозрачность.... полазь посмотри


 
Mihey ©   (2003-10-24 15:45) [8]

Тогда Graphic32.


 
Fenik ©   (2003-10-25 00:17) [9]

> miek ©  (23.10.03 23:52) [4]
> 2Mihey: Там неоптимизировано.


В смысле, не на асме?
Как можно оптимизировать?


 
марсианин   (2003-10-25 04:55) [10]

2Вилис  (24.10.03 08:26) [6]

в хелпе глянь. лежит в gdi32.dll кажись. т.е. из набора стандартных ф-ий

код примерно такой

var Points:array[0..2,0..1] of integer;

w2 := srcWidth div 2; h2 := srcHeight div 2;

Points[0][0] := Round(-w2*Cos(angle) - h2*Sin(angle) + x0);
Points[0][1] := Round(-w2*Sin(angle) + h2*Cos(angle) + y0);

Points[1][0] := Round(-w2*Cos(angle) + -h2*Sin(angle) + x0);
Points[1][1] := Round(-w2*Sin(angle) - h2*Cos(angle) + y0);

Points[2][0] := Round( w2*Cos(angle) - h2*Sin(angle) + x0);
Points[2][1] := Round( w2*Sin(angle) + h2*Cos(angle) + y0);

PlgBlt(destDC, Points, srcDC, 0,0,srcWidth,srcHeight,0,0,0);


sin и cos надо только 1 раз посчитать а не 3
х0,у0 - координаты центра


 
miek ©   (2003-10-25 21:38) [11]

2Fenik:
>В смысле, не на асме?
>Как можно оптимизировать?

Асм ни при чем, хотя помогает немного выиграть.

Главное - чтобы в основном цикле были только сложение и вычитание. На худой конец - сдвиги. И никакой плавающей точки.
Вот тогда - да, оптимизировано.


 
Fenik ©   (2003-11-22 23:08) [12]

>miek ©  (25.10.03 21:38) [11]

Как же заменить вот это:

MBo ©  (22.10.03 17:28) [1]
xNew:=xC+(xOld-xC)*cos(fi)+(yOld-yC)*sin(fi)
yNew:=yC-(xOld-xC)*sin(fi)+(yOld-yC)*cos(fi)

сложение и вычитанием?


 
MBo ©   (2003-11-23 07:57) [13]

>Как же заменить вот это:
>сложение и вычитанием?
В выражениях много констант, меняется только то, что в скобках, причем линейно при движении по строке - xOld на единицу. Вот и преобразуй.


 
miek ©   (2003-11-23 09:45) [14]

2F: Заменяется это все линиями по Брезенхэму. Сложение, вычитание, сравнение. Учись, студент.


 
Micah'GF ©   (2003-11-23 19:56) [15]

=> [10] марсианин  
подскажи, плиз, как правильно PlgBlt объявить !?!?!? в хелпе даже по BitBlt ничего не нашел...
в инете нашел только для Си
BOOL PlgBlt(HDC hdcDest, CONST POINT *lpPoint, HDC hdcSrc, int nXSrc, int nYSrc, int nWidth, int nHeight, HBITMAP hbmMask, int xMask, int yMask );
как это в Дельфях написать?!?


 
Micah'GF ©   (2003-11-23 20:31) [16]

ээээ... вроде немного разобрался... подключил модуль windows и заработало..
НО!
sedtDC и srcDC должно быть чем?!?! (незнаю как подругому сформулировать вопрос)

sDC := sDIB.Canvas.Handle;
dDC := GetDC(dDIB.Canvas.Handle);  <<< здесь говорят что Canvas does not allow drawing
result := PlgBlt(dDC, Points, sDC, 0,0, sDIB.Width, sDIB.Height,0,0,0);


а хочется всего то из sDIB повернуть растр и поместить в dDIB..
приведи пример если не трудно.


 
Sergio Bassy   (2003-11-24 13:39) [17]

sedtDC и srcDC - это дескрипторы контекста устройства (Device Context) или просто хэндл соответственно куда рисовать и источника рисунка.

получают их с помощью GetDC()


 
Sergio Bassy   (2003-11-24 13:41) [18]

а ещё есть хорошая библиотека для работы с изображениями: IPL2
(Image Processing Library - Библиотека обработки изображений)
Поворот, преобразования Фурье (прямое и обратное), и прочее...


 
марсианин   (2003-11-26 22:27) [19]

если юзаешь TBitmap то ничего получать не надо:



var destBitmap, SrcBitmap:TBitmap;
.....................
Points[1][0] := Round( - w2*Cos(angle)  + h2*Sin(angle) + x0); //поправочка:)
....................

PlgBlt(destBitmap.Canvas.Handle, Points, SrcBitmap.Canvas.Handle, 0,0, SrcBitmap.Width, SrcBitmap.Height,0,0,0);


если на АПИ пишешь, могу написать конечно, но неуверен что поможет:)


 
Micah'GF ©   (2003-11-26 23:12) [20]

юзаю TBitmap и TDIB...
если делать так:
PlgBlt(destBitmap.Canvas.Handle, Poin......
то говорят Canvas does not allow drawing,даже когда пытаюсь риовать на канвас формы и с BitBlt тоже самое говорит..
может что то инициализировать\получить\подготовить\... ?!?!?!


 
марсианин   (2003-11-27 22:30) [21]

как битмапы инициализируешь? ничего не забыл? размеры, глубина цвета?


 
miek ©   (2003-11-28 16:34) [22]

В общем, предлагаю код в студию вынести, а там ясно будет.


 
Micah'GF ©   (2003-11-29 13:47) [23]

var
 Points: lpPoint;
 x0, y0: integer;
 w2, h2: integer;
 sDIB, dDIB: TDIB;
 angle: single;
 sDC, dDC: hDC;
begin
 sDIB := TDIB.Create;
 dDIB := TDIB.Create;
 angle := 0;

 sDIB.LoadFromFile("notload.bmp");
 w2 := sDIB.Width div 2;
 h2 := sDIB.Height div 2;

Points[0][0] := Round(-w2*Cos(angle) - h2*Sin(angle) + x0);
Points[0][1] := Round(-w2*Sin(angle) + h2*Cos(angle) + y0);
Points[1][0] := Round(-w2*Cos(angle) + -h2*Sin(angle) + x0);
Points[1][1] := Round(-w2*Sin(angle) - h2*Cos(angle) + y0);
Points[2][0] := Round( w2*Cos(angle) - h2*Sin(angle) + x0);
Points[2][1] := Round( w2*Sin(angle) + h2*Cos(angle) + y0);
}

//sDC := GetDC(Form1.Handle);  <<< если рисовать на это DC то вылазит тоже самое
PlgBlt(dDIB.Canvas.Handle, Points, sDIB.Canvas.Handle, 0,0, 92, 92, 0,0,0);
BitBlt(Form1.Canvas.Handle, 0, 0, 92, 92, sDIB.Canvas.Handle, 0, 0, SrcCopy);
//ReleaseDC(Form1.Handle, sDC);

//  DXPaintBox2.DIB := dDIB;
 sDIB.Free;
 dDIB.Free;
end;

вот..


 
марсианин   (2003-11-29 21:43) [24]

а с TBitmap работает? очень удивлюсь если нет.. ХЗ что у тебя там.. я когда писал программу вращения вместо TDIB брал TFastDIB, инициализация - тоже Create и LoadFromFile - все работало на "ура".. попробуй брейк-поинт поставить и посмотреть чему равен dDIB.Canvas.Handle ....

короче это тебе домашнее задание:)

зы х0, у0 не забудь проиницЫализировать


 
Micah'GF ©   (2003-11-30 09:28) [25]

PlgBlt(Form1.Canvas.Handle, Points, sDIB.Canvas.Handle, 0, 0, sDIB.Width, sDIB.Height, 0,0,0);
вот так заработало!!! и в битмап теперь пишет... незнаю что сделал...
только вот в TDIB.Canvas всеравно не пишет...

ХЫ. как преобразовать angle чтобы вращение стало линейным?


 
марсианин   (2003-11-30 12:53) [26]

похоже, в том коде что ты привел, dDIB вообще не инициализируешь. размеры хотя бы установил..

что значит "вращение стало линейным"? оно круглое по определению:)


 
Micah'GF ©   (2003-11-30 14:20) [27]

посмотри внимательнее - инициализируется и уничтожается.

неуверен в каких единицах должен задаваться угол angle , но если задавать в целых единицах то изображение поворачивается приблизительно (на глаз) на 10-15°..


 
Micah'GF ©   (2003-11-30 14:20) [28]

посмотри внимательнее - инициализируется и уничтожается.

неуверен в каких единицах должен задаваться угол angle , но если задавать в целых единицах то изображение поворачивается приблизительно (на глаз) на 10-15°..


 
марсианин   (2003-12-02 23:17) [29]

угол в радианах!!!!
все точно должно быть.. ты ж положение картинки точками задаешь.. попробуй рисовать точки без картинки

насчет dDIB - размеры задай - ширину, высоту.. и еще глубину цвета.. а то он пустой у тебя.


 
A_nik   (2003-12-03 16:18) [30]

Чтобы еще увеличить скорость расчета можно использовать вместо отдельного вызова Sin и Cos одновременный SinCos работает в два раза быстрее (модуль Math).

var
 Sin, Cos: Extended;
begin
 SinCos(angle,Sin,Cos);
 Points[0][0] := Round(-w2*Cos - h2*Sin + x0);
 Points[0][1] := Round(-w2*Sin + h2*Cos + y0);
 Points[1][0] := Round(-w2*Cos + -h2*Sin + x0);
 Points[1][1] := Round(-w2*Sin - h2*Cos + y0);
 Points[2][0] := Round( w2*Cos - h2*Sin + x0);
 Points[2][1] := Round( w2*Sin + h2*Cos + y0);
...
end;


 
miek ©   (2003-12-03 21:48) [31]

Тяжелый случай. Еще предложи синус рядом Тэйлора рассчитавать, да. "Мы взяли еще Фанты и тормознули крутейший Пень-4"...


 
chuckloon.   (2003-12-04 15:56) [32]

Все бля нах пошли тупые овцеебы...
И ваш полное говно, а иодератор пидор, - сидит целыми днями и срет в рот админу... НИХРЕНА вы не знаете, тупой сайт и все вы уроды..
Короче сосите писю и да прибудет с вами мир....

var
Points: lpPoint;
x0, y0: integer;
w2, h2: integer;
sDIB, dDIB: TDIB;
angle: single;
sDC, dDC: hDC;
begin
sDIB := TDIB.Create;
dDIB := TDIB.Create;
angle := 0;

sDIB.LoadFromFile("notload.bmp");
w2 := sDIB.Width div 2;
h2 := sDIB.Height div 2;

Points[0][0] := Round(-w2*Cos(angle) - h2*Sin(angle) + x0);
Points[0][1] := Round(-w2*Sin(angle) + h2*Cos(angle) + y0);
Points[1][0] := Round(-w2*Cos(angle) + -h2*Sin(angle) + x0);
Points[1][1] := Round(-w2*Sin(angle) - h2*Cos(angle) + y0);
Points[2][0] := Round( w2*Cos(angle) - h2*Sin(angle) + x0);
Points[2][1] := Round( w2*Sin(angle) + h2*Cos(angle) + y0);
}

//sDC := GetDC(Form1.Handle);  <<< если рисовать на это DC то вылазит тоже самое
PlgBlt(dDIB.Canvas.Handle, Points, sDIB.Canvas.Handle, 0,0, 92, 92, 0,0,0);
BitBlt(Form1.Canvas.Handle, 0, 0, 92, 92, sDIB.Canvas.Handle, 0, 0, SrcCopy);
//ReleaseDC(Form1.Handle, sDC);

//  DXPaintBox2.DIB := dDIB;
sDIB.Free;
dDIB.Free;
end;


 
Yr2   (2003-12-04 19:14) [33]

Для всех, кроме этого придурка chuckloon:
- при "простом" пересчёте по формулам, здесь приведенным, изображение выглядит "зубчато". Особенно это заметно при повороте НЕ фотографических изображений, а, например, чертежей, карандашных эскизов и т.п. Для исправления этого эффекта применяются специальные алгоритмы. Некоторые из них реализованы в библиотеке DImageEn фирмы HiComponents, которую можно взять здесь:
http://www.hicomponents.com/zzdownloads_imageen.asp
работает с любыми форматами и много чего умеет.
я не рекламирую. я с ней просто работаю.


 
miek ©   (2003-12-04 23:56) [34]

Если кто-нибудь знает формулу обратного пересчета координат для поворачиваемого растра (то есть координаты приемника в соответствующие координаты источника), буду очень благодарен.


 
MBo ©   (2003-12-05 07:24) [35]

>miek ©   (04.12.03 23:56) [34]

Логика - нужно получить матрицу аффинного преобразования на угол (-Fi) вокруг центра xC,yC
Это произведение матриц переноса на -dx -dy, поворота вокруг 0, обратного переноса. В формулах [1] меняются местами Old и New и знаки при синусах

xOld:=xC+(xNew-xC)*cos(fi)-(yNew-yC)*sin(fi)
yOld:=yC+(xNew-xC)*sin(fi)+(yNew-yC)*cos(fi)

В статье "Поставить точку..." это есть, правда, там еще движение центра по спирали приделано.


 
miek ©   (2003-12-05 19:22) [36]

Спасибо, скоро sпопробую.


 
miek ©   (2003-12-06 16:37) [37]

Формула работает, и не так уж медленно (без особой оптимизации 70-75 тактов на пиксел). Картинка, конечно, все равно неровная, но зато каждый пиксел приемника проходится по одному разу. Значит, можно будет делать нормальный альфа-блендинг и прочие фокусы.


 
miek ©   (2003-12-06 20:32) [38]

И вот как это выглядит (ипсользую мою библиотеку, но принцип ясен):

var
 t1, t2: pdib;
 sx, sy, i, j, zx, zy: integer;
 z1, z2, xnew, ynew, c, s, fi: single;
 c1, c2: comp;
 p: pointer;
begin
 fi:= -str2int( editbox5.text)*pi/180;

 c:= cos( fi);
 s:= sin( fi);

 for j:= 0 to sy-1 do
   begin
     p:= t2.Scanline[j];
     z1:= -j*s;
     z2:= j*c;
     for i:= 0 to sx-1 do
       begin
         zx:= round( z1);
         zy:= round( z2);
         if (zx>=0) and (zx<sx) and (zy>=0) and (zy<sy) then
           dword( p^):= t1.GetRawPixel( zx, zy);
         z1:= z1+c;
         z2:= z2+s;
         inc( integer( p), 4);
       end;
   end;
end;



Страницы: 1 вся ветка

Текущий архив: 2004.04.11;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.047 c
1-1082362011
serg128
2004-04-19 12:06
2004.04.11
Как заполнить данными MS Outlook из своего приложения?


14-1081966152
Liona
2004-04-14 22:09
2004.04.11
А такие как админы этого форума - тут есть?


14-1082402837
Gomosapin
2004-04-19 23:27
2004.04.11
Помогите решить простую задачу. Pascal


14-1082022130
stone
2004-04-15 13:42
2004.04.11
Стенография для программиста :))


14-1082028252
$tranger
2004-04-15 15:24
2004.04.11
Опрос населения