Главная страницаОбратная связьКарта сайта

Повернуть DIB-изображение

Оформил: DeeCo
Автор: http://www.swissdelphicenter.ch

function RotateBitmap(var hDIB: HGlobal; radang: Double; clrBack: TColor): Boolean;
 // (c) Copyright original C Code: Code Guru 
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;

Обсудить статью на форуме


Если Вас заинтересовала или понравилась информация по разработке на Delph - "Повернуть DIB-изображение", Вы можете поставить закладку в социальной сети или в своём блоге на данную страницу:

Так же Вы можете задать вопрос по работе этого модуля или примера через форму обратной связи, в сообщение обязательно указывайте название или ссылку на статью!
   


Copyright © 2008 - 2024 Дискета.info