Mega Code Archive

 
Categories / Delphi / Graphic
 

Bitmap Rotation

Title: Bitmap Rotation Question: I've been searching for a good and fast BitmapRotation function for some time now, and finally I found a function that did this really fast. Unfortunatelly the source was written in some Delphi and some Assembler. The Assembler was quite easy to exchange with the Move() command, but I also needed it to rotate around the center of the bitmap. After some changes I came up with this solution. It's actually pretty fast for being a Delphi only function, but not as fast as the original one. The BackgroundColor parameter of RotateDraw24 specifies the background color to replace for smoothing the rotation a little bit. Another idea might be to check if the NewColor = SrcBitmap.TransparentColor to make the rotation better for transparent rotation. I don't know who the original author was since the zip file I downloaded didn't say anything about that. Credits go out to him! Answer: Unit Rotation; Interface Uses windows, Graphics; Procedure RotateDraw24(Angle: Real; BackgroundColor: TColor; SrcBitmap, DstBitmap: tbitmap); Implementation Uses SysUtils; Type BScan = Array of PByteArray;//Pointer; Function ScanBitmap(Bit1: TBitmap) : BScan; Var Y : Integer; Begin SetLength(result,bit1.height); For Y := Bit1.Height-1 downto 0 do Result[Y] := Bit1.ScanLine[Y]; End; Procedure RotateDraw24(Angle: Real; BackgroundColor: TColor; SrcBitmap, DstBitmap: tbitmap); var OnS,FrS : BScan; cosr,sinr : Real; x, y : Integer; x2, y2 : Integer; NewColor : Integer; CurColor : Integer; BackColor : Integer; DstPos : Integer; scx, scy : Integer; // Source dcx, dcy : Integer; // Destination Begin Angle := Angle * pi / 180; scx := (SrcBitmap.Width div 2); scy := (SrcBitmap.Height div 2); dcx := (DstBitmap.Width div 2); dcy := (DstBitmap.Height div 2); // Convert the RGB value specified by BackgroundColor to BGR used by the BMP format. BackColor := Rgb(GetBValue(BackgroundColor), GetGValue(BackgroundColor), GetRValue(BackgroundColor)); // if the bitmaps are not in pf32bit, this may take a // little while to convert the pixel formats DstBitmap.pixelformat := pf24bit; SrcBitmap.pixelformat := pf24bit; OnS := ScanBitmap(DstBitmap); FrS := ScanBitmap(SrcBitmap); // get the sin and cos values in fixed format cosr := Cos(Angle); sinr := Sin(Angle); For x:=SrcBitmap.Width-1 downto 0 do Begin For y := SrcBitmap.Height-1 downto 0 do Begin x2 := dcx + Round( (scx-x) * cosr - (scy-y) * sinr ); y2 := dcy + Round( (scx-x) * sinr + (scy-y) * cosr ); // x2 and y2 are now the coordinates of the destination pixel IF x2 -1 Then Begin IF x2 Begin IF y2 -1 Then Begin IF y2 Begin // If x2,y2 is actually inside the rectangle of // the destination bitmap then ... Move(FrS[Y]^[x*3], NewColor, 3); DstPos := x2*3; Move(NewColor, OnS[y2]^[DstPos], 3); IF (x2 0) Then Begin // If smoothing isn't wanted, remove the IF sentence below... Move(OnS[y2]^[DstPos-3], CurColor, 3); IF (CurColor = BackColor) Then Move(NewColor, OnS[y2]^[DstPos-3], 3); End; IF (x2 Begin // If smoothing isn't wanted, remove the IF sentence below... Move(OnS[y2]^[DstPos+3], CurColor, 3); IF (CurColor = BackColor) Then Move(NewColor, OnS[y2]^[DstPos+3], 3); End; End; End; End; End; End; End; End; End. // ------------------------- END OF UNIT ------------------------- Var SrcBitmap : TBitmap; DstBitmap : TBitmap; Begin SrcBitmap := TBitmap.Create; SrcBitmap.LoadFromFile('Coffee Bean.bmp'); DstBitmap := TBitmap.Create; DstBitmap.Width := 200; DstBitmap.Height := 200; DstBitmap.Canvas.Brush.Color := clRed; DstBitmap.Canvas.FillRect( Rect(0, 0, DstBitmap.Width, DstBitmap.Height) ); RotateDraw24(45, DstBitmap.Canvas.Brush.Color, SrcBitmap, DstBitmap); Canvas.Draw(0, 0, DstBitmap); DstBitmap.Free; SrcBitmap.Free; End;