Delphi Tutorial - How to Rotate a Bitmap

'

How to rotate a Bitmap by Using BitBlt

Bitmap rotation is a graphic effect that Delphi does not natively offer. This article shows how to rotate a given image in 90-degree increments. It allows you to rotate any image 0, 90, 180 or 270 degrees.

With a little work, the code can be modified to rotate to any angle, but that is beyond the scope of this article.

procedure RotateBitmap(var hBitmapDC : Longint; var lWidth : Longint;
         var lHeight : Longint; lRadians : real);
var
         I : Longint;               // loop counter
         J : Longint;               // loop counter
         hNewBitmapDC : Longint;    // DC of the new bitmap
         hNewBitmap : Longint;      // handle to the new bitmap
         lSine : extended;          // sine used in rotation
         lCosine : extended;        // cosine used in rotation
         X1 : Longint;              // used in calculating new
                                    //   bitmap dimensions
         X2 : Longint;              // used in calculating new
                                    //     bitmap dimensions
         X3 : Longint;              // used in calculating new
                                    //     bitmap dimensions
         Y1 : Longint;              // used in calculating new
                                    // bitmap dimensions
         Y2 : Longint;              // used in calculating new
                                    // bitmap dimensions
         Y3 : Longint;              // used in calculating new
                                    // bitmap dimensions
         lMinX : Longint;           // used in calculating new
                                    // bitmap dimensions
         lMaxX : Longint;           // used in calculating new
                                    // bitmap dimensions
         lMinY : Longint;           // used in calculating new
                                    // bitmap dimensions
         lMaxY : Longint;           // used in calculating new
                                    // bitmap dimensions
         lNewWidth : Longint;       // width of new bitmap
         lNewHeight : Longint;      // height of new bitmap
         lSourceX : Longint;        // x pixel coord we are blitting
                                    // from the source  image
         lSourceY : Longint;        // y pixel coord we are blitting
                                    // from the source image

begin
         // create a compatible DC from the one just brought
         // into this function
         hNewBitmapDC := CreateCompatibleDC(hBitmapDC);

         // compute the sine/cosinse of the radians used to
         // rotate this image
         lSine := Sin(lRadians);
         lCosine := Cos(lRadians);

         // compute the size of the new bitmap being created
         X1 := Round(-lHeight * lSine);
         Y1 := Round(lHeight * lCosine);
         X2 := Round(lWidth * lCosine - lHeight * lSine);
         Y2 := Round(lHeight * lCosine + lWidth * lSine);
         X3 := Round(lWidth * lCosine);
         Y3 := Round(lWidth * lSine);

         // figure out the max/min size of the new bitmap
         lMinX := Min(0, Min(X1, Min(X2, X3)));
         lMinY := Min(0, Min(Y1, Min(Y2, Y3)));
         lMaxX := Max(X1, Max(X2, X3));
         lMaxY := Max(Y1, Max(Y2, Y3));

         // set the new bitmap width/height
         lNewWidth := lMaxX - lMinX;
         lNewHeight := lMaxY - lMinY;

         // create a new bitmap based upon the new width/height of the
         // rotated bitmap
         hNewBitmap := CreateCompatibleBitmap(hBitmapDC, lNewWidth, lNewHeight);

         //attach the new bitmap to the new device context created
         //above before constructing the rotated bitmap
         SelectObject(hNewBitmapDC, hNewBitmap);

         // loop through and translate each pixel to its new location.
         // this is using a standard rotation algorithm
         For I := 0 To lNewHeight do begin
            For J := 0 To lNewWidth do begin
               lSourceX := Round((J + lMinX) * lCosine + (I + lMinY) * lSine);
               lSourceY := Round((I + lMinY) * lCosine - (J + lMinX) * lSine);
               If (lSourceX >= 0) And (lSourceX <= lWidth) And
               (lSourceY >= 0) And (lSourceY <= lHeight) Then
                   BitBlt(hNewBitmapDC, J, I, 1, 1, hBitmapDC,
                              lSourceX, lSourceY, SRCCOPY);
            end;
         end;

         // reset the new bitmap width and height
         lWidth := lNewWidth;
         lHeight := lNewHeight;

         // return the DC to the new bitmap
         hBitmapDC := hNewBitmapDC;

         // destroy the bitmap created
         DeleteObject(hNewBitmap);

      End;

The following is an example of how the RotateBitmap function might be called: 

procedure TForm1.RotateTest(Sender: TObject);
var
 lRadians : real;
 DC  : longint;
 H, W : integer;
 Degrees : integer;
begin
  Degrees := 45;
  lRadians := PI * Degrees / 180;
  DC := Image1.Picture.Bitmap.Canvas.Handle;
  H := Image1.Picture.Bitmap.Height;
  W := Image1.Picture.Bitmap.Width;
  RotateBitmap(DC, W, H, lRadians);
  Image1.Width := W;
  Image1.Height := H;
  Image1.Picture.Bitmap.Width := W;
  Image1.Picture.Bitmap.Height := H;
  BitBlt(Image1.Picture.Bitmap.Canvas.Handle, 0, 0, W, H, DC, 0, 0, SRCCopy);
  Image1.Refresh;
end;

This tutorial was kindly provided by Serge Perevoznyk


Google
Web www.Delphi-Central.com
Delphi Central - Delphi Programming Tutorials, Hints and Tips