| Код | procedure CopyRotateTransparentBrush(_B_in,_B_out: TBitmap; _x,_y,centerX,centerY:integer; trColor:Tcolor; _angle: Double); const MaxPixelCountA = MaxInt div SizeOf(TRGBQuad); type PRGBAArray = ^TRGBAArray; TRGBAArray = array[0..MaxPixelCountA-1] of TRGBQuad; var cosRadians,_Rad,sinRadians : Double; x,y,x_cor,y_cor,x_corS,y_corS,inXOut,inXPr,inXRotated,inYOut,inYPr,inYRotated: Integer; RowOut, RowIn: PRGBAArray; rc1, bc1, gc1:byte; _w,_h:integer; begin _Rad:=_angle; sinRadians:=Sin(_Rad); cosRadians:=Cos(_Rad); _w:=_B_in.Width; _h:=_B_in.Height; if _x<0 then x_corS:=abs(_x) else x_corS:=0; if _y<0 then y_corS:=abs(_y) else y_corS:=0; if (_x+_w)>_B_out.Width then x_cor:=_x+_w-_B_out.Width else x_cor:=0; if (_y+_h)>_B_out.Height then y_cor:=_y+_h-_B_out.Height else y_cor:=0; rc1:=GetRValue(trColor); gc1:=GetGValue(trColor); bc1:=GetBValue(trColor); for x:=_h-1-y_cor downto y_corS do begin RowIn:=_B_out.Scanline[x+_y]; inXPr:=2*(x-centerY)+1; for y:=_w-1-x_cor downto x_corS do begin inYPr:=2*(y-centerX)+1; inYRotated:=Round(inYPr*CosRadians-inXPr*sinRadians); inXRotated:=Round(inYPr*sinRadians+inXPr*cosRadians); inYOut:=(inYRotated-1) div 2 + centerX; inXOut:=(inXRotated-1) div 2 + centerY; if (inYOut>=0)and(inYOut<=_w-1)and (inXOut>=0)and(inXOut<=_h-1) then begin RowOut:=_B_in.Scanline[inXOut]; RowIn[y+_x]:=RowOut[inYOut]; end; end; end; end;
|
Как пример, оптимизировать еще больше смысла не вижу, проще тогда напряму к данным обращаться в памяти (асм или указатели мучать), для "интерфейсных" операций достаточно, в играх конечно будет подтормаживать. _x,_y - координаты вывода верхнего левого угла на результирующий битмап, centerX,centerY - центр вращения. trColor - "прозрачный" цвет, _angle - угол поворота в радианах.
Для повышения качества рекомендую перед поворотом увеличить (просто через canvas.copyrect(), без "качества") исходное изображение (в 2-4 раза) и его повернуть, а потом уменьшить обратно уже повернутое. |