# Bitmap rotation

This is a discussion on Bitmap rotation within the Game Programming forums, part of the General Programming Boards category; How do you rotate a bitmap image? Rotating each pixel doesn't work. There must be a way, because The GIMP ...

1. ## Bitmap rotation

How do you rotate a bitmap image? Rotating each pixel doesn't work. There must be a way, because The GIMP can do it.

I'm using the SDL.

2. If you don't mind using a module you could use
http://freshmeat.net/projects/sge/

The important part of that article is the multiplication matrix it gives.

3. Thanks. I'll see if I can get it to work.

4. Do you mean rotating the actual texture on the surface it is applied to, or rotating the surface?

5. Rotate the quad that the texture uses.

6. What do you mean?

7. Think:
* What is the difference between a normal bitmap and a rotated one?
* What happens to the bounding rectangle of the bitmap when you rotate the bitmap?
* What is the difference between a rotated quadrilateral in 3D graphics and a bounding rectangle of a bitmap?

You can rotate a bitmap many ways. If you really want to use 2D and not 3D vertices in that you want to rotate a blitted bitmap you can do this:

1. Set texture coords for each corner of the box.
2. Compute the new bounding box after rotation.
3. Polyfill the box using linear interpolation.
4. Figure out the x,y coords of pixel.
5. Figure out the u,v coords of texel.

Essentially linear interpolate for x,y and u,v.

Pixel(x,y,Texture[u][v]);

To do a polyfill:

1. Create two arrays called leftside and rightside and clear to -1.
2. Start at the top of the figure.
3. Find the next vertex in either direction.
4. If vertex is lower than prev, it goes in leftside array
5. If vertex is higher than prev, it goes in rightside array.
6. Compute x's and u,v for leftside and rightside at point P on a line between CurVertex and NextVertex using formula for slope.
7. Save x's in leftside and rightside accordingly and increment a y line counter.
8. When done, start at y coord for top and set loopcounter to 0.
9. Draw textured line from leftside[loopcounter] to rightside[loopcounter]
10. Increment y and loop counter and check for loopcounter>y line counter.
11. If true, exit, else goto 9.

This is a simple old-school polygon fill algo used in many older DOS 3D games. It only works on convex shapes.

This will draw a bitmap w/o rotation and scaling.

Code:
DWORD dwTexOffset=0;
UINT uCurX=Texture.X;
UINT uCurY=Texture.Y;
DWORD dwPixelOffset=(uCurY*Screen.Width)+uCurX;
DWORD dwStartPixelOffset=dwPixelOffset;
DWORD dwWidthCounter=0;
DWORD dwHeightCounter=0;

do
{
DWORD dwPixelColor=Texture[dwTexOffset];
if (dwPixelColor!=Texture.dwTransparent)
SetPixel(dwPixelOffset,Texture[dwTexOffset];

dwTexOffset++;
dwPixelOffset++;
dwWidthCounter++;
if (dwWidthCounter>TextureWidth)
{
dwStartPixelOffset+=Screen.Width;
dwPixelOffset=dwStartPixelOffset;
dwWidthCounter=0;
dwHeightCounter++;
}
} while (dwHeightCounter<TextureHeight);
This code is best suited for assembly. You can use inline or pure. I'll write an inline version here.

Code:
void BitBltEx(WORD uX, WORD uY,
DWORD *pSurface,
DWORD *pTexture,
DWORD dwTexWidth,DWORD dwTexHeight,
DWORD dwSurfWidth,
DWORD dwTransColor)
{
// (ESP-4)   DWORD dwTexOffset=0;
// (ESP-8)   DWORD dwPixelOffset;
// (ESP-12) DWORD dwStartPixelOffset;
// (ESP-16) DWORD dwWidthCounter=0;
//Height counter not needed since LOOP decrements ECX
_asm {

;Allocate stack space for local variables
sub esp,16

;dwTexOffset=0;
mov [esp-4],0

;Compute surface offset
mov  eax,uY
mov  ebx,dwSurfWidth
mul   eax,ebx
mov [esp-8],eax
mov [esp-12],eax

;Zero out counters
mov [esp-16],0

;Set up pointers
mov esi,[pTexture]
mov edi,[pSurface]

;Setup loop
LOOPSTART:
mov ecx,dwTexHeight

;Blit one pixel if cur pixel is not trans
;Retrieve current pixel
lodsd
cmp eax,dwTransColor
jne  NOBLIT
;BLIT here
movsd

NOBLIT:
//Increment counters
//esi and edi auto-increment according to direction flag
//on movsd
inc [esp-16]

cmp [esp-16],dwTexWidth
jb  SAMELINE
mov eax,[esp-12]
mov [esp-8],eax
mov [esp-16],0
SAMELINE:
LOOP LOOPSTART

;clean up stack