*.bmp transparency fixes, first (= left-bottom) pixel is used as transparent color (fixes #1211)

git-svn-id: trunk@7968 -
This commit is contained in:
micha 2005-10-16 16:37:19 +00:00
parent f3c9cebd11
commit 96bcfffa4c
3 changed files with 51 additions and 24 deletions

View File

@ -755,7 +755,7 @@ begin
ImgWriter:=nil; ImgWriter:=nil;
try try
IntfImg:=TLazIntfImage.Create(0,0); IntfImg:=TLazIntfImage.Create(0,0);
IntfImg.LoadFromBitmap(Handle,0); IntfImg.LoadFromBitmap(Handle,FImage.FMaskHandle);
if WriterClass=nil then begin if WriterClass=nil then begin
// automatically use a TFPCustomImageWriterClass // automatically use a TFPCustomImageWriterClass

View File

@ -1771,7 +1771,8 @@ procedure TWin32WidgetSet.AllocAndCopy(const BitmapInfo: Windows.TBitmap;
const BitmapHandle: HBITMAP; const SrcRect: TRect; var Data: PByte; const BitmapHandle: HBITMAP; const SrcRect: TRect; var Data: PByte;
var Size: Cardinal); var Size: Cardinal);
var var
bmInfo: TBitmapInfo; bmInfoBuffer: array[0..sizeof(TBitmapInfo)+256*sizeof(Windows.RGBQUAD)] of byte;
bmInfo: TBitmapInfo absolute bmInfoBuffer;
ScreenDC: HDC; ScreenDC: HDC;
begin begin
// initialize bitmapinfo structure // initialize bitmapinfo structure
@ -1784,17 +1785,11 @@ begin
bmInfo.bmiHeader.biPlanes := 1; bmInfo.bmiHeader.biPlanes := 1;
bmInfo.bmiHeader.biBitCount := BitmapInfo.bmBitsPixel; bmInfo.bmiHeader.biBitCount := BitmapInfo.bmBitsPixel;
bmInfo.bmiHeader.biCompression := BI_RGB; bmInfo.bmiHeader.biCompression := BI_RGB;
bmInfo.bmiHeader.biSizeImage := 0;
Size := ((BitmapInfo.bmWidthBytes+3) and not 3) * (SrcRect.Bottom-SrcRect.Top);
ScreenDC := GetDC(0); ScreenDC := GetDC(0);
// allocate memory for pixel data, N scanlines GetMem(Data, Size);
if GetDIBits(ScreenDC, BitmapHandle, SrcRect.Top, SrcRect.Bottom-SrcRect.Top, nil, bmInfo, DIB_RGB_COLORS) <> 0 then GetDIBits(ScreenDC, BitmapHandle, SrcRect.Top, SrcRect.Bottom-SrcRect.Top, Data, bmInfo, DIB_RGB_COLORS);
begin
Size := bmInfo.bmiHeader.biSizeImage;
GetMem(Data, Size);
GetDIBits(ScreenDC, BitmapHandle, SrcRect.Top, SrcRect.Bottom-SrcRect.Top, Data, bmInfo, DIB_RGB_COLORS);
end else begin
Data := nil;
Size := 0;
end;
// release resources // release resources
ReleaseDC(0, ScreenDC); ReleaseDC(0, ScreenDC);
end; end;
@ -3133,13 +3128,13 @@ Begin
begin begin
if (Width = SrcWidth) and (Height = SrcHeight) then if (Width = SrcWidth) and (Height = SrcHeight) then
begin begin
Result := BitBlt(DestDC, X, Y, Width, Height, SrcDC, XSrc, YSrc, SRCCOPY); Result := Windows.BitBlt(DestDC, X, Y, Width, Height, SrcDC, XSrc, YSrc, SRCCOPY);
end else begin end else begin
Result := StretchBlt(DestDC, X, Y, Width, Height, SrcDC, XSrc, YSrc, SrcWidth, SrcHeight, SRCCOPY); Result := Windows.StretchBlt(DestDC, X, Y, Width, Height, SrcDC, XSrc, YSrc, SrcWidth, SrcHeight, SRCCOPY);
end; end;
end else begin end else begin
MaskDC := CreateCompatibleDC(0); MaskDC := Windows.CreateCompatibleDC(0);
SaveObj := SelectObject(MaskDC, Mask); SaveObj := Windows.SelectObject(MaskDC, Mask);
PrevTextColor := Windows.SetTextColor(DestDC, RGB(255,255,255)); PrevTextColor := Windows.SetTextColor(DestDC, RGB(255,255,255));
PrevBkColor := Windows.SetBkColor(DestDC, RGB(0,0,0)); PrevBkColor := Windows.SetBkColor(DestDC, RGB(0,0,0));
if (Width = SrcWidth) and (Height = SrcHeight) then if (Width = SrcWidth) and (Height = SrcHeight) then
@ -3154,8 +3149,8 @@ Begin
end; end;
Windows.SetTextColor(DestDC, PrevTextColor); Windows.SetTextColor(DestDC, PrevTextColor);
Windows.SetBkColor(DestDC, PrevBkColor); Windows.SetBkColor(DestDC, PrevBkColor);
SelectObject(MaskDC, SaveObj); Windows.SelectObject(MaskDC, SaveObj);
DeleteDC(MaskDC); Windows.DeleteDC(MaskDC);
end; end;
Result := true; Result := true;
end; end;

View File

@ -336,11 +336,13 @@ type
BFI: TBitMapInfoHeader; // The header as read from the stream. BFI: TBitMapInfoHeader; // The header as read from the stream.
FPalette: PFPcolor; // Buffer with Palette entries. FPalette: PFPcolor; // Buffer with Palette entries.
FBitsPerPixel: Integer; // bits per pixel (1, 4, 8, 15, 16, 24, 32) FBitsPerPixel: Integer; // bits per pixel (1, 4, 8, 15, 16, 24, 32)
FTransparentColor: TFPColor; // color which should be interpreted as transparent
LineBuf: PByte; // Buffer for 1 scanline. Can be Byte, Word, TColorRGB or TColorRGBA LineBuf: PByte; // Buffer for 1 scanline. Can be Byte, Word, TColorRGB or TColorRGBA
// SetupRead will allocate the needed buffers, and read the colormap if needed. // SetupRead will allocate the needed buffers, and read the colormap if needed.
procedure SetupRead(nPalette, nRowBits: Integer; Stream: TStream; procedure SetupRead(nPalette, nRowBits: Integer; Stream: TStream;
ReadPalette: Boolean); virtual; ReadPalette: Boolean); virtual;
function ColorToTrans(const InColor: TFPColor): TFPColor;
procedure ReadScanLine(Row: Integer; Stream: TStream); virtual; procedure ReadScanLine(Row: Integer; Stream: TStream); virtual;
procedure WriteScanLine(Row: Integer; Img: TFPCustomImage); virtual; procedure WriteScanLine(Row: Integer; Img: TFPCustomImage); virtual;
function BmpRGBAToFPColor(Const RGBA: TColorRGBA): TFPcolor; virtual; function BmpRGBAToFPColor(Const RGBA: TColorRGBA): TFPcolor; virtual;
@ -3073,6 +3075,14 @@ begin
end; end;
end; end;
function TLazReaderBMP.ColorToTrans(const InColor: TFPColor): TFPColor;
begin
if InColor = FTransparentColor then
Result := FPImage.colTransparent
else
Result := InColor;
end;
procedure TLazReaderBMP.SetupRead(nPalette, nRowBits: Integer; Stream: TStream; procedure TLazReaderBMP.SetupRead(nPalette, nRowBits: Integer; Stream: TStream;
ReadPalette: Boolean); ReadPalette: Boolean);
var var
@ -3146,23 +3156,23 @@ begin
img.colors[Column,Row]:=FPalette[0]; img.colors[Column,Row]:=FPalette[0];
4 : 4 :
for Column:=0 to img.Width-1 do for Column:=0 to img.Width-1 do
img.colors[Column,Row]:=FPalette[(LineBuf[Column div 2] shr (((Column+1) and 1)*4)) and $0f]; img.colors[Column,Row]:=FPalette[(LineBuf[Column div 2] shr (((not Column) and 1)*4)) and $0f];
8 : 8 :
for Column:=0 to img.Width-1 do for Column:=0 to img.Width-1 do
img.colors[Column,Row]:=FPalette[LineBuf[Column]]; img.colors[Column,Row]:=FPalette[LineBuf[Column]];
15: 15:
for Column := 0 to img.Width - 1 do for Column := 0 to img.Width - 1 do
Img.colors[Column, Row] := Bmp15BitToFPColor(PWord(LineBuf)[Column]); Img.colors[Column,Row]:=ColorToTrans(Bmp15BitToFPColor(PWord(LineBuf)[Column]));
16 : 16 :
for Column:=0 to img.Width-1 do for Column:=0 to img.Width-1 do
img.colors[Column,Row]:=Bmp16BitToFPColor(PWord(LineBuf)[Column]); img.colors[Column,Row]:=ColorToTrans(Bmp16BitToFPColor(PWord(LineBuf)[Column]));
24 : 24 :
for Column:=0 to img.Width-1 do for Column:=0 to img.Width-1 do
img.colors[Column,Row]:=BmpRGBToFPColor(PColorRGB(LineBuf)[Column]); img.colors[Column,Row]:=ColorToTrans(BmpRGBToFPColor(PColorRGB(LineBuf)[Column]));
32 : 32 : // BmpRGBA already does transparency
for Column:=0 to img.Width-1 do for Column:=0 to img.Width-1 do
img.colors[Column,Row]:=BmpRGBAToFPColor(PColorRGBA(LineBuf)[Column]); img.colors[Column,Row]:=BmpRGBAToFPColor(PColorRGBA(LineBuf)[Column]);
end; end;
end; end;
procedure TLazReaderBMP.InternalRead(Stream: TStream; Img: TFPCustomImage); procedure TLazReaderBMP.InternalRead(Stream: TStream; Img: TFPCustomImage);
@ -3199,6 +3209,22 @@ const
Var Var
PixelMasks: TPixelMasks; PixelMasks: TPixelMasks;
Row : Integer; Row : Integer;
firstLine: boolean;
procedure SaveTransparentColor;
begin
// define transparent color: 1-8 use palette, 15-24 use fixed color
case FBitsPerPixel of
1 : FPalette[(LineBuf[0] shr 7) and 1] := fpimage.colTransparent;
4 : FPalette[(LineBuf[0] shr 4) and $f] := fpimage.colTransparent;
8 : FPalette[LineBuf[0]] := fpimage.colTransparent;
15: FTransparentColor := Bmp15BitToFPColor(PWord(LineBuf)[0]);
16: FTransparentColor := Bmp16BitToFPColor(PWord(LineBuf)[0]);
24: FTransparentColor := BmpRGBToFPColor(PColorRGB(LineBuf)[0]);
32: ; // BmpRGBA already does transparency
end;
end;
begin begin
{ This will move past any junk after the BFI header } { This will move past any junk after the BFI header }
Stream.Position:=Stream.Position+TStreamSeekType(BFI.biSize-SizeOf(BFI)); Stream.Position:=Stream.Position+TStreamSeekType(BFI.biSize-SizeOf(BFI));
@ -3303,8 +3329,14 @@ begin
raise FPImageException.CreateFmt('Wrong bitmap bit count: %d', [BFI.biBitCount]); raise FPImageException.CreateFmt('Wrong bitmap bit count: %d', [BFI.biBitCount]);
end; end;
Try Try
firstLine := true;
for Row := Img.Height - 1 downto 0 do begin for Row := Img.Height - 1 downto 0 do begin
ReadScanLine(Row,Stream); // Scanline in LineBuf with Size ReadSize. ReadScanLine(Row,Stream); // Scanline in LineBuf with Size ReadSize.
if firstLine then
begin
SaveTransparentColor;
firstLine := false;
end;
WriteScanLine(Row,Img); WriteScanLine(Row,Img);
end; end;
finally finally