# Windows SDK GDI: How do I display a bitmap rotated?

• June 10th, 2006, 03:05 AM
Pravin Kumar
Windows SDK GDI: How do I display a bitmap rotated?
Q: How do I display a bitmap rotated?

A: Mirroring or inverting a bitmap about its center point is not difficult to achieve since they do not change its rectangular shape with horizontal and vertical sides. Rotating the bitmap in multiples of 90 degrees also is easy. But displaying a bitmap rotated by an arbitrary angle is difficult since the shape is changed and screen resolutions come into picture. Here I have attempted to achieve this, using simple graphic transformation.

I am presenting a function 'MBRotate()', which takes, as inputs, the handle to a display device context, X and Y positions of the top left corner where the bitmap is to be displayed, handle to the bitmap object and angle of rotation in radians. Rotation direction is positive in anti-clockwise direction and point about which the rotation is performed is the insertion point of the bitmap, which is the top left corner of the bitmap. Since I am using trigonometric functions like 'sin()' and 'cos()' functions for coordinate transformations, I have included '<math.h>' header file. I have written two simple functions to return rotated coordinates of a point and an array of points, latter using the former function. Steps to display the bitmap rotated involves two main steps:
• Get the bitmap dimensions and compute the span when it is rotated. Get minimum and maximum of X and Y coordinates.
• Scans all the points from between the minimum and maximum values of X and Y. Checks whether the point corresponds to a point within the bitmap dimensions. If it is, pick up the corresponding pixel of the bitmap and display.

The code is amply commented.

Code:

```#include &lt;math.h&gt; POINT Rotate(POINT pt, double theta) {   // Gets horizontal and vertical resolution of display   HDC hDC = GetDC(NULL);   int XScale = GetDeviceCaps(hDC, LOGPIXELSX);   int YScale = GetDeviceCaps(hDC, LOGPIXELSY);   ReleaseDC(NULL, hDC);   // Transforms coordinates   int X = (int) (pt.x * cos(theta) - XScale * pt.y * sin(theta) / YScale);   int Y = (int) (pt.y * cos(theta) + YScale * pt.x * sin(theta) / XScale);   // Returns transformed point   POINT P = {X, Y};   return P; } LPPOINT Rotate(LPPOINT lppt, int size, double theta) {   // Replaces the array with transformed points   for (int i = 0; i &lt; size; i++)     lppt&#091;i&#093; = Rotate(lppt&#091;i&#093;, theta);   // Returns the transformed array   return lppt; } BOOL BMRotate(HDC hdc, int x, int y, HBITMAP hbm, double theta = 0) {   // Return value; TRUE if funtion successfully completed   BOOL Done = FALSE;   // Does nothing if bitmap handle is not valid   if (hbm == NULL)     return Done;   // Set mapping mode to MM_TEXT   int MapMode = SetMapMode(hdc, MM_TEXT);   // Creates a compatible memory DC handle to load bitmap   HDC hDC = CreateCompatibleDC(hdc);   if (hDC)    // Device contect handle is not NULL   {     // Selects bitmap to device context     HBITMAP hBM = (HBITMAP) SelectObject(hDC, hbm);     // Gets bitmap dimensions     BITMAP BM;     GetObject(hbm, sizeof(BITMAP), &BM);     int W = BM.bmWidth, H = BM.bmHeight;     // Gets vertical & horizontal screen resolutions     int XScale = GetDeviceCaps(hdc, LOGPIXELSX);     int YScale = GetDeviceCaps(hdc, LOGPIXELSY);     // Evaluate corner points     POINT P&#091;4&#093;;     P&#091;0&#093;.x = 0, P&#091;0&#093;.y = 0;     P&#091;1&#093;.x = W, P&#091;1&#093;.y = 0;     P&#091;2&#093;.x = W, P&#091;2&#093;.y = H;     P&#091;3&#093;.x = 0, P&#091;3&#093;.y = H;     // Rotates the rectangle     Rotate(P, 4, -theta);     // Computes span of rotated rectangle     for (int i = 1, MinX = P&#091;0&#093;.x, MinY = P&#091;0&#093;.y, MaxX = P&#091;0&#093;.x, MaxY = P&#091;0&#093;.y; i &lt; 4; i++)     {       MinX = MinX &lt; P&#091;i&#093;.x ? MinX : P&#091;i&#093;.x;       MaxX = MaxX &gt; P&#091;i&#093;.x ? MaxX : P&#091;i&#093;.x;       MinY = MinY &lt; P&#091;i&#093;.y ? MinY : P&#091;i&#093;.y;       MaxY = MaxY &gt; P&#091;i&#093;.y ? MaxY : P&#091;i&#093;.y;     }     // Computes original rectangle     RECT R = {0, 0, W, H};     // Spans all points of rotated rectangle     for (int iX = MinX; iX &lt; MaxX; iX++)       for (int iY = MinY; iY &lt; MaxY; iY++)       {         POINT P = {iX, iY};         // Rotates back and checks whether in bitmap rectangle         P = Rotate(P, theta);         if (PtInRect(&R, P))  // Valid point         {           // Displays the bit in display device context           SetPixel(hdc, x + iX, y + iY, GetPixel(hDC, P.x, P.y));         }       }       // Deselects bitmap and deletes device context       SelectObject(hDC, hBM);       DeleteDC(hDC);       // Returns TRUE since operation is successful       Done = TRUE;     }   }   // Resets mapping mode to its original value   SetMapMode(hdc, MapMode);   // Returns FALSE since operation is failed   return Done; }```
Here is what I got when I rotated the bitmap by 30 degrees. Point about which rotation is performed is marked for illustration.

For bigger bitmaps, 'GetPixel()'/'SetPixel()' calls will be time consuming. This can be changed by getting the pixel information of the bitmap in an array and reconstructing the rotated pixels from this information. That is beyond the scope of this post since this attempts to illustrate the method to display rotated bitmaps.
<br><br><br>