The Delphi Bug List

Entry No.
15
VCL - Graphics - Graphics - TBitmap
There's a bug with the Palette of TBitmap: it displays a random background colour when Transparent = True
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 4.03 5.0 5.01 6.0 6.01 6.02 Kylix 1.0
N/AN/AExistsExistsExistsExistsExistsExistsExistsExistsExistsUnknownUnknownUnknownN/A
Description
Reported by Brian Lowe; checked by Chris Rankin; Torbjørn Pedersen
A Delphi 3 bug has been confirmed by Borland [but not fixed in the Delphi 3 update release]. It is a palette bug in TBitmap. It manifests as strange colors in TImage when Transparent = True, but only on some bitmaps. It also causes problems when using TCanvas.BrushCopy on some bitmaps. The bitmaps which illustrate the problem are 256 color or greater and have colors in palette locations 8 - 15 which are different from palette entries 248 - 255. In other words, to NOT have this problem, the bitmap must contain the last 8 system colors in palette locations 8 - 15.
The attached bitmap (zipped; 2.59 kb) has the problem; load it into a Delphi 3 TImage and set Transparent := True to see it.
Note from the checker:
When you load this bitmap, the parts of the form visible behind the image appear to be cyan. Turning transparency off turns these areas back to the default form colour.
User-contributed comments
Dmitri
11 Mar 2001  05:37 PM GMT
May be fixed in Graphics.pas the following function:

function TransparentStretchBlt(DstDC: HDC; DstX, DstY, DstW, DstH: Integer;
  SrcDC: HDC; SrcX, SrcY, SrcW, SrcH: Integer; MaskDC: HDC; MaskX,
  MaskY: Integer): Boolean;
const
  ROP_DstCopy = $00AA0029;
var
  MemDC: HDC;
  MemBmp: HBITMAP;
  BkMemDC: HDC;
  BkMemBmp: HBITMAP;
  Save: THandle;
  BkSave: THandle;
  SavePal: HPALETTE;
  BkSavePal: HPALETTE;
begin
  Result := True;
  if (Win32Platform = VER_PLATFORM_WIN32_NT) and (SrcW = DstW) and (SrcH = DstH) then
    begin
      MemBmp := GDICheck(CreateCompatibleBitmap(SrcDC, 1, 1));
      MemBmp := SelectObject(MaskDC, MemBmp);
      try
        MaskBlt(DstDC, DstX, DstY, DstW, DstH, SrcDC, SrcX, SrcY, MemBmp, MaskX,
          MaskY, MakeRop4(ROP_DstCopy, SrcCopy));
      finally
        MemBmp := SelectObject(MaskDC, MemBmp);
        DeleteObject(MemBmp);
      end;
    end
  else
    begin
      MemDC := GDICheck(CreateCompatibleDC(0));
      try
        MemBmp := GDICheck(CreateCompatibleBitmap(SrcDC, SrcW, SrcH));
        try
          Save := SelectObject(MemDC, MemBmp);
          try
            SavePal := SelectPalette(SrcDC, SystemPalette16, False);
            SelectPalette(SrcDC, SavePal, False);
            if SavePal <> 0 then
              SavePal := SelectPalette(MemDC, SavePal, True)
            else
              SavePal := SelectPalette(MemDC, SystemPalette16, True);
            try
              RealizePalette(MemDC);
              BkMemDC := GDICheck(CreateCompatibleDC(0));
              try
                BkMemBmp := GDICheck(CreateCompatibleBitmap(SrcDC, DstW, DstH));
                try
                  BkSave := SelectObject(BkMemDC, BkMemBmp);
                  try
                    BkSavePal := SelectPalette(SrcDC, SystemPalette16, False);
                    SelectPalette(SrcDC, BkSavePal, False);
                    if BkSavePal <> 0 then
                      BkSavePal := SelectPalette(BkMemDC, BkSavePal, True)
                    else
                      BkSavePal := SelectPalette(BkMemDC, SystemPalette16, True);
                    try
                      RealizePalette(BkMemDC);
             
                      StretchBlt(MemDC, 0, 0, SrcW, SrcH, MaskDC, MaskX, MaskY, SrcW, SrcH, SrcCopy);
                      StretchBlt(MemDC, 0, 0, SrcW, SrcH, SrcDC, SrcX, SrcY, SrcW, SrcH, SrcErase);
                      
                      StretchBlt(BkMemDC, 0, 0, DstW, DstH, MaskDC, MaskX, MaskY, SrcW, SrcH, SrcCopy);
                      StretchBlt(BkMemDC, 0, 0, DstW, DstH, DstDC, DstX, DstY, DstW, DstH, SrcAnd);
                      
                      StretchBlt(BkMemDC, 0, 0, DstW, DstH, MemDC, 0, 0, SrcW, SrcH, SrcInvert);
                      StretchBlt(DstDC, DstX, DstY, DstW, DstH, BkMemDC, 0, 0, DstW, DstH, SrcCopy);
                    finally
                      if BkSavePal <> 0 then SelectPalette(BkMemDC, BkSavePal, False);
                    end;
                  finally
                    if BkSave <> 0 then SelectObject(BkMemDC, BkSave);
                  end;
                finally
                  DeleteObject(BkMemBmp);
                end;
              finally
                DeleteDC(BkMemDC);
              end;
            finally
              if SavePal <> 0 then SelectPalette(MemDC, SavePal, False);
            end;
          finally
            if Save <> 0 then SelectObject(MemDC, Save);
          end;
        finally
          DeleteObject(MemBmp);
        end;
      finally
        DeleteDC(MemDC);
      end;
    end;
end;
Edge Tender
08 Sep 2002  11:22 AM GMT
No problem found under Delphi 6.02, Enterprise Edition
Win2k, Prof. SP3, Simplified Chinese
Niels Keurentjes
13 Sep 2002  11:17 AM GMT
Funny thing is that it only pops up for me on Win98/WinME and not on NT-based systems (tried NT/2K/XP and all correct transparency).
Latest update of this entry: 1999-09-09

Post a comment on this bug


Index page
Delphi Bug List home page
The Delphi Bug Lists are presently maintained by Jordan Russell, who has taken over this task from Reinier Sterkenburg since August 2000.
All feedback is appreciated. See also the feedback section of the Delphi Bug List home page.