| Bug # | Delphi versions | Description |
| 16 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
BitmapCanvasList not unlocked |
| 405 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
There's a bug in the "ByteSwapColors" procedure of the Delphi 3 graphics.pas unit. "ByteSwapColors" is used various places in graphics.pas to convert an array of RGB values (TPaletteEntry) to BGR values (TRGBQuad) and vice versa. The problem is that the first entry of the array is never converted. |
| 465 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
A bitmap handle is leaked every time a TBitmap opens a RLE encoded bitmap. |
| 15 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
TBitmap There's a bug with the Palette of TBitmap: it displays a random background colour when Transparent = True |
| 51 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
TBitmap There's a palette handle leak in certain cases when PixelFormat is set to pf8bit. |
| 446 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
TBitmap RLE (Run Length Encoded) bitmaps loaded in a TImage are not displayed correctly. Furthermore, viewing a form with such an image as text and then as form again can make the IDE crash silently. |
| 17 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
TBrush While the Style and the Color properties of TBrush should be independent, if you set the Style of a TBrush to bsClear, it also changes the Color to clWhite, and changing the Color of a TBrush will change the Style to bsSolid if it was bsClear. |
| 18 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
TCanvas The documentation for TCanvas.Pixels doesn't mention that -1 can be returned as result. |
| 66 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
TMetaFile The property access method SetWidth has a bug, when using a screen resolution with Large Fonts. |
| 479 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
TMetafile Metafile.SetHeight and TMetafile.SetWidth have scaling errors (by a factor of 10) |
Bug #16; last modified: 18-Nov-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| N/A | N/A | Exists | Fixed | Fixed | Fixed | Fixed | Fixed |
procedure FreeMemoryContexts;
var
I: Integer;
begin
with BitmapCanvasList.LockList do
begin
{$IFDEF FixFreeUnlockList}
try
{$ENDIF}
for I := Count-1 downto 0 do
with TBitmapCanvas(Items[I]) do
if TryLock then
try
FreeContext;
finally
Unlock;
end;
{$IFDEF FixFreeUnlockList}
finally
BitmapCanvasList.UnLockList;
end
{$ENDIF}
end;
end;
...
procedure DeselectBitmap(AHandle: HBITMAP);
var
I: Integer;
begin
if AHandle = 0 then Exit;
with BitmapCanvasList.LockList do
{$IFDEF FixDeselectBMPUnlockList}
try
{$ENDIF}
for I := Count - 1 downto 0 do
with TBitmapCanvas(Items[I]) do
if (FBitmap <> nil) and
(FBitmap.FImage.FHandle
= AHandle) then
FreeContext;
{$IFDEF FixDeselectBMPUnlockList}
finally
BitmapCanvasList.UnLockList;
end
{$ENDIF}
end;
Bug #405; last modified: 10-May-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| N/A | N/A | Exists | Fixed | Fixed | Fixed | Fixed | Fixed |
procedure RedBitmap;
var
hPal : HPalette;
Pal : TMaxLogPalette;
i : Integer;
Bitmap : TBitmap;
begin
// Create a 16 color palette - all entries red
Pal.palVersion := $300;
Pal.palNumEntries := 16;
for i := 0 to Pal.palNumEntries-1 do
with Pal.palPalEntry[i] do
begin
peRed := 255;
peGreen := 0;
peBlue := 0;
peFlags := 0;
end;
hPal := CreatePalette(PLogPalette(@Pal)^);
// Create a bitmap
Bitmap := TBitmap.Create;
try
Bitmap.Width := 50;
Bitmap.Height := 50;
Bitmap.PixelFormat := pf8bit;
// Assign red palette to bitmap
Bitmap.Palette := hPal;
// Save bitmap
Bitmap.SaveToFile('red.bmp');
finally
Bitmap.Free;
end;
end;
The following is the ByteSwapColors() procedure.
As far as I have been able to tell, the problem is caused by the
method used to test for end of loop. I have marked the offending line
below with "*** WRONG ***".
// convert RGB to BGR and vice-versa. TRGBQuad <-> TPaletteEntry
procedure ByteSwapColors(var Colors; Count: Integer);
var
SysInfo: TSystemInfo;
begin
GetSystemInfo(SysInfo);
asm
MOV EDX, Colors
MOV ECX, Count
DEC ECX
JS @@END
LEA EAX, SysInfo
CMP [EAX].TSystemInfo.wProcessorLevel, 3
JE @@386
@@1: MOV EAX, [EDX+ECX*4]
BSWAP EAX
SHR EAX,8
MOV [EDX+ECX*4],EAX
DEC ECX
// JNZ @@1 *** WRONG ***
JNS @@1 // Much better!
JMP @@END
@@386:
PUSH EBX
@@2: XOR EBX,EBX
MOV EAX, [EDX+ECX*4]
MOV BH, AL
MOV BL, AH
SHR EAX,16
SHL EBX,8
MOV BL, AL
MOV [EDX+ECX*4],EBX
DEC ECX
// JNZ @@2 *** WRONG ***
JNS @@2 // Much better!
POP EBX
@@END:
end;
end;
JNS @@1and
JNS @@2respectively.
Bug #465; last modified: 28-Oct-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Unknown | Unknown | Exists | Exists | Exists | Exists | Exists | Fixed |
procedure TBitmap.ReadDIB(Stream: TStream; ImageSize: LongWord);
const
DIBPalSizes: array [Boolean] of Byte = (sizeof(TRGBQuad), sizeof(TRGBTriple));
var
...
DIB: TDIBSection;
Pal, OldPal: HPalette;
OldHandle: HGDIOBJ;
begin
Pal := 0;
Stream.Read(HeaderSize, sizeof(HeaderSize));
OS2Format := HeaderSize = sizeof(OS2Header);
if OS2Format then HeaderSize := sizeof(TBitmapInfoHeader);
GetMem(BitmapInfo, HeaderSize + 12 + 256 * sizeof(TRGBQuad));
...
DC := GDICheck(GetDC(0));
try
if (bmiHeader.biCompression = BI_RLE8)
or (bmiHeader.biCompression = BI_RLE4) or DDBsOnly then
begin
MemDC := 0;
GetMem(BitsMem, ImageSize);
try
Stream.ReadBuffer(BitsMem^, ImageSize);
MemDC := GDICheck(CreateCompatibleDC(DC));
OldHandle := SelectObject(MemDC, CreateCompatibleBitmap(DC, 1, 1));
try
OldPal := 0;
if bmiHeader.biClrUsed > 0 then
begin
Pal := PaletteFromDIBColorTable(0, ColorTable, bmiHeader.biClrUsed);
OldPal := SelectPalette(MemDC, Pal, False);
RealizePalette(MemDC);
end;
try
BMHandle := CreateDIBitmap(MemDC, BitmapInfo^.bmiHeader, CBM_INIT, BitsMem,
BitmapInfo^, DIB_RGB_COLORS);
if (BMHandle = 0) then
if GetLastError = 0 then InvalidBitmap else
RaiseLastWin32Error;
finally
if OldPal <> 0 then
SelectPalette(MemDC, OldPal, True);
end;
finally
DeleteObject(SelectObject(MemDC, OldHandle));
end;
finally
if MemDC <> 0 then DeleteDC(MemDC);
FreeMem(BitsMem);
end;
...
end;
Bug #15; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| N/A | N/A | Exists | Exists | Unknown | Unknown | Unknown | Unknown |
Bug #51; last modified: 11-Jul-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| N/A | N/A | Exists | Exists | Exists | Fixed | Fixed | Fixed |
var pf8BitBitmap: TBitmap = nil;
procedure Set8BitPixelFormat(ABitmap: TBitmap);
begin
if not Assigned(pf8BitBitmap) then begin
pf8BitBitmap:= TBitmap.Create;
pf8BitBitmap.PixelFormat:= pf8Bit;
end;
ABitmap.Assign(pf8BitBitmap);
end;
Then change the TJPEGImage.GetBitmap routine as follows:
// Set the bitmap pixel format
FBitmap.Handle := 0;
if (PixelFormat = jf8Bit) or (jc.d.out_color_space = JCS_GRAYSCALE) then
// FBitmap.PixelFormat := pf8bit {causes palette leak}
Set8BitPixelFormat(FBitmap)
else
FBitmap.PixelFormat := pf24bit;
Finally, include a call to pf8BitBitmap.Free in the unit's finalization
section.
Bug #446; last modified: 18-Nov-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Unknown | Unknown | Unknown | Unknown | Exists | Exists | Exists | Fixed |
What I figured out for the moment is, that there is an error in the streaming procedures for DIB's. At some point the image size may get negative, (because the stored image data is smaller than the unpacked image) and this error is not detected by the VCL. But this cannot be the whole story because the bug appears regardless of the image size. I'm not sure if the error appears with EVERY bitmap but I have found it for all the bitmaps I tested.
Bug #17; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Unknown | Exists | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown |
Bug #18; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Exists | Fixed | Fixed | Fixed | Fixed | Fixed | Fixed | Fixed |
with PaintBox1.Canvas do
begin
theColour := Pixels[0, 0];
if theColour <> -1 then { inside clipping area }
begin
{ valid value in theColour }
Pixels[0, 0] := theColour;
end
{ else ... }
end;
Bug #66; last modified: 8-Oct-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Exists | Fixed | Fixed | Fixed | Fixed | Fixed | Fixed | Fixed |
Value := MulDiv(Value, FInch, 96);to
Value := MulDiv(Value, FInch, Screen.PixelsPerInch);
Bug #479; last modified: 8-Oct-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Absent | Exists | Exists | Exists | Exists | Fixed | Fixed | Fixed |
The error is in the Graphics.pas file code, at the end of TMetafile.SetHeight:
MMHeight := MulDiv(Value, 25400, ScreenLogPixels);and at the end of TMetafile.SetWidth:
MMWidth := MulDiv(Value, 25400, ScreenLogPixels);An inch is 25.4 mm = 25.4*100 = 2540 hundreths of mm.