среда, 18 января 2017 г.

#1335. Ошибка в ImageEn _DIBDrawTo. 64 бита

Было:

procedure _DIBDrawTo(DestCanvas: TCanvas; fhdib: THANDLE; orgx, orgy, orgdx, orgdy, destx, desty, destdx, destdy: integer);
var
  bminfo: ^TBITMAPINFO;
begin
  bminfo := GlobalLock(fhdib);
  SetStretchBltMode(destcanvas.handle, COLORONCOLOR);
  if bminfo^.bmiHeader.biBitCount <= 8 then
    // <=256 colors
    StretchDIBits(destcanvas.Handle, destx, desty, destdx, destdy, orgx, orgy, orgdx, orgdy,
      pointer(Cardinal(bminfo) + sizeof(TBITMAPINFOHEADER) + (1 shl bminfo^.bmiHeader.biBitCount) * 4),
      bminfo^, DIB_RGB_COLORS, SRCCOPY)
  else
    // >256 colors
    StretchDIBits(destcanvas.Handle, destx, desty, destdx, destdy, orgx, orgy, orgdx, orgdy,
      pointer(Cardinal(bminfo) + sizeof(TBITMAPINFOHEADER)),
      bminfo^, DIB_RGB_COLORS, SRCCOPY);
  GlobalUnLock(fhdib);
end; 

Надо:

procedure _DIBDrawTo(DestCanvas: TCanvas; fhdib: THANDLE; orgx, orgy, orgdx, orgdy, destx, desty, destdx, destdy: integer);
var
  bminfo: ^TBITMAPINFO;
begin
  bminfo := GlobalLock(fhdib);
  SetStretchBltMode(destcanvas.handle, COLORONCOLOR);
  if bminfo^.bmiHeader.biBitCount <= 8 then
    // <=256 colors
    StretchDIBits(destcanvas.Handle, destx, desty, destdx, destdy, orgx, orgy, orgdx, orgdy,
      pointer(PAnsiChar(bminfo) + sizeof(TBITMAPINFOHEADER) + (1 shl bminfo^.bmiHeader.biBitCount) * 4),
      bminfo^, DIB_RGB_COLORS, SRCCOPY)
  else
    // >256 colors
    StretchDIBits(destcanvas.Handle, destx, desty, destdx, destdy, orgx, orgy, orgdx, orgdy,
      pointer(PAnsiChar(bminfo) + sizeof(TBITMAPINFOHEADER)),
      bminfo^, DIB_RGB_COLORS, SRCCOPY);
  GlobalUnLock(fhdib);
end; 

Cardinal => PAnsiChar.

Вообще полезно просмотреть все исходники на предмет наличия масок:

Pointer(Cardinal
Pointer(Integer
Pointer(Longint

PChar(Cardinal
PChar(Integer
PChar(Longint

PAnsiChar(Cardinal
PAnsiChar(Integer
PAnsiChar(Longint

3 комментария:

  1. а почему не NativeUInt?
    http://docwiki.embarcadero.com/Libraries/Berlin/en/System.NativeUInt
    Логичнее же именно к числу приводить

    ОтветитьУдалить
    Ответы
    1. Логично вообще-то Pointer к Pointer'у приводить. PAnsiChar - вообще-то самый подходящий. Ну или PByte = ^Byte объявлять. Ну или тогда уж IntPtr пользовать, а не NativeUInt. Ну или включать директиву PointerMath.

      Удалить
    2. http://docwiki.embarcadero.com/RADStudio/Seattle/en/Pointer_Math_(Delphi)

      Удалить