From: "T.G" Newsgroups: borland.public.delphi.graphics References: <3bd6ed42_1@dnews> Subject: Re: How to rotate a bitmap 90, 180 or 360 degrees? Date: Thu, 25 Oct 2001 16:16:45 -0400 Lines: 294 X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 5.50.4133.2400 X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4133.2400 NNTP-Posting-Host: 205.181.245.38 Message-ID: <3bd722ac$1_2@dnews> X-Trace: dnews 1003954860 205.181.245.38 (24 Oct 2001 13:21:00 -0700) Path: dnews Xref: dnews borland.public.delphi.graphics:43121 If you have a DIB then you can use the following for any angle RadAng is angle in radians ClrBack is the back color when you want to rotate to other than multiples of 90 degree. Returns true if rotated and updated hDIB will be returned and old one freed. I converted this from C code from codeguru.com web site. Thanks to Mr. Anshuman Jaffery. Function RotateBitmap(Var hDIB : HGlobal ;radang : Double ;clrBack : TColor) : Boolean; Var lpDIBBits : Pointer; lpbi, hDIBResult : PBitmapInfoHeader; bpp, nColors, nWidth, nHeight, nRowBytes : Integer; cosine, sine : Double; x1,y1, x2,y2, x3,y3, minx,miny, maxx,maxy, ti,x,y, w,h : Integer; nResultRowBytes, nHeaderSize : Integer; i,len : longint; lpDIBBitsResult : Pointer; dwBackColor : DWord; PtrClr : PRGBQuad; RbackClr, GBackClr, BBackClr : Word; sourcex, sourcey : Integer; mask : Byte; PtrByte : PByte; dwpixel : DWord; PtrDWord : PDWord; hDIBResInfo : HGlobal; Begin; // Get source bitmap info lpbi := PBitmapInfoHeader(GlobalLock(hdIB)); nHeaderSize := lpbi^.biSize + lpbi^.biClrUsed * sizeof(TRGBQUAD); lpDIBBits := Pointer(longint(lpbi) + nHeaderSize); bpp := lpbi^.biBitCount; // Bits per pixel ncolors := lpbi^.biClrUsed; // Already computed when bitmap was loaded nWidth := lpbi^.biWidth; nHeight := lpbi^.biHeight; nRowBytes := ((((nWidth * bpp) + 31) and (not 31)) shr 3); // Compute the cosine and sine only once cosine := cos(radang); sine := sin(radang); // Compute dimensions of the resulting bitmap // First get the coordinates of the 3 corners other than origin x1 := ceil(-nHeight * sine); // Originally floor at all places y1 := ceil(nHeight * cosine); x2 := ceil(nWidth * cosine - nHeight * sine); y2 := ceil(nHeight * cosine + nWidth * sine); x3 := ceil(nWidth * cosine); y3 := ceil(nWidth * sine); minx := min(0,min(x1, min(x2,x3))); miny := min(0,min(y1, min(y2,y3))); maxx := max(0,max(x1, max(x2,x3)));// added max(0, maxy := max(0,max(y1, max(y2,y3)));// added max(0, w := maxx - minx; h := maxy - miny; // Create a DIB to hold the result nResultRowBytes := ((((w * bpp) + 31) And (not 31)) div 8); len := nResultRowBytes * h; hDIBResInfo := GlobalAlloc(GMEM_MOVEABLE,len+nHeaderSize); If hDIBResInfo = 0 then Begin Result := False; Exit; End; hDIBResult := PBitmapInfoHeader(GlobalLock(hDIBResInfo)); // Initialize the header information CopyMemory(hDIBResult,lpbi, nHeaderSize); //BITMAPINFO &bmInfoResult = *(LPBITMAPINFO)hDIBResult ; hDIBResult^.biWidth := w; hDIBResult^.biHeight := h; hDIBResult^.biSizeImage := len; lpDIBBitsResult := Pointer(longint(hDIBResult) + nHeaderSize); // Get the back color value (index) ZeroMemory(lpDIBBitsResult, len ); case bpp of 1 : Begin //Monochrome if(clrBack = RGB(255,255,255)) then FillMemory(lpDIBBitsResult,len,$ff ); End; 4, 8 : Begin //Search the color table PtrClr := PRGBQuad(Longint(lpbi)+lpbi^.bisize); RBackClr := GetRValue(clrBack); GBackClr := GetGValue(clrBack); BBackClr := GetBValue(clrBack); for i := 0 to nColors-1 do // Color table starts with index 0 Begin If (PtrClr^.rgbBlue = BBackClr) and (PtrClr^.rgbGreen = GBackClr) and (PtrClr^.rgbRed = RBackClr) then Begin If (bpp=4) then //if(bpp==4) i = i | i<<4; ti := i or (i shl 4) Else ti := i; FillMemory(lpDIBBitsResult, ti, len ); break; End; Inc(PtrClr); End;// If not match found the color remains black End; 16: Begin (* When the Compression field is set to BI_BITFIELDS, Windows 95 supports only the following 16bpp color masks: A 5-5-5 16-bit image, where the blue mask is $001F, the green mask is $03E0, and the red mask is $7C00; and a 5-6-5 16-bit image, where the blue mask is $001F, the green mask is $07E0, and the red mask is $F800. *) PtrClr := PRGBQuad(Longint(lpbi)+lpbi^.bisize); if (PtrClr^.rgbRed = $7c00 ) then // Check the Red mask Begin // Bitmap is RGB555 dwBackColor := ((GetRValue(clrBack) shr 3) shl 10) + ((GetRValue(clrBack) shr 3) shl 5) + (GetBValue(clrBack) shr 3) ; End Else Begin // Bitmap is RGB565 dwBackColor := ((GetRValue(clrBack) shr 3) shl 11) + ((GetRValue(clrBack) shr 2) shl 5) + (GetBValue(clrBack) shr 3) ; End; End; 24, 32: Begin dwBackColor := ((GetRValue(clrBack)) shl 16) Or ((GetGValue(clrBack)) shl 8) Or ((GetBValue(clrBack))); End; End; // Now do the actual rotating - a pixel at a time // Computing the destination point for each source point // will leave a few pixels that do not get covered // So we use a reverse transform - e.i. compute the source point // for each destination point For y := 0 to h-1 do Begin For x := 0 to w-1 do Begin sourcex := floor((x+minx)*cosine + (y+miny)*sine); sourcey := floor((y+miny)*cosine - (x+minx)*sine); if ((sourcex >= 0) And (sourcex < nWidth) And (sourcey >= 0) And (sourcey < nHeight) ) Then Begin // Set the destination pixel case bpp of 1 : Begin //Monochrome mask := PByte(longint(lpDIBBits) + nRowBytes*sourcey + (sourcex div 8))^ And ($80 shr (sourcex mod 8)); If mask<>0 then mask := $80 shr (x mod 8); PtrByte := PByte(longint(lpDIBBitsResult) + nResultRowBytes*y + (x div 8)); PtrByte^ := PtrByte^ And (not ($80 shr (x mod 8))); PtrByte^ := PtrByte^ Or mask; End; 4 : Begin If ((sourcex And 1) <> 0) then mask := $0f else mask := $f0; mask := PByte(longint(lpDIBBits) + nRowBytes*sourcey + (sourcex div 2))^ And mask; if ((sourcex And 1) <> (x and 1)) then Begin If (mask And $f0)<>0 then mask := (mask shr 4) Else mask := (mask shl 4); End; PtrByte := PByte(longint(lpDIBBitsResult) + nResultRowBytes*y + (x div 2)); If ((x and 1) <> 0) then PtrByte^ := PtrByte^ and (not $0f) Else PtrByte^ := PtrByte^ and (not $f0); PtrByte^ := PtrByte^ Or Mask; End; 8 : Begin mask := PByte(longint(lpDIBBits) + nRowBytes*sourcey + sourcex)^; PtrByte := PByte(longint(lpDIBBitsResult) + nResultRowBytes*y + x); PtrByte^ := mask; End; 16: Begin dwPixel := PDWord(longint(lpDIBBits) + nRowBytes*sourcey + sourcex*2)^; PtrDword := PDWord(longint(lpDIBBitsResult) + nResultRowBytes*y + x*2); PtrDword^ := Word(dwpixel); End; 24: Begin dwPixel := PDWord(longint(lpDIBBits) + nRowBytes*sourcey + sourcex*3)^ And $ffffff; PtrDword := PDWord(longint(lpDIBBitsResult) + nResultRowBytes*y + x*3); PtrDword^ := PtrDword^ OR dwPixel; End; 32: Begin dwPixel := PDWord(longint(lpDIBBits) + nRowBytes*sourcey + sourcex*4)^; PtrDword := PDWord(longint(lpDIBBitsResult) + nResultRowBytes*y + x*4); PtrDword^ := dwpixel; End; End; // Case End Else Begin // Draw the background color. The background color // has already been drawn for 8 bits per pixel and less case bpp of 16: Begin PtrDWord := PDWord(longint(lpDIBBitsResult) + nResultRowBytes*y + x*2); PtrDword^ := Word(dwBackColor); End; 24: Begin PtrDWord := PDWord(longint(lpDIBBitsResult) + nResultRowBytes*y + x*3); PtrDword^ := PtrDword^ Or dwBackColor; End; 32: Begin PtrDWord := PDWord(longint(lpDIBBitsResult) + nResultRowBytes*y + x*4); PtrDword^ := dwBackColor; End; End; End; End; End; GlobalUnLock(hDIBResInfo); GlobalUnLock(hDIB); GlobalFree(hDIB); hDIB := hDIBResInfo; Result := True; End; -- TG "Markus Nakhlah" wrote in message news:3bd6ed42_1@dnews... > Hi all! > > How can I rotate a bitmap very fast ? > It just has to be 90, 180 or 360 degrees. > > > Thanks in advance! > > Markus > >