|
@@ -11,43 +11,17 @@ unit BitmapImage;
|
|
|
|
|
|
interface
|
|
|
|
|
|
-{$I ..\Projects\VERSION.INC}
|
|
|
-
|
|
|
uses
|
|
|
Windows, Controls, Graphics, Classes, Resample;
|
|
|
|
|
|
type
|
|
|
-{$IFNDEF IS_D3}
|
|
|
- {$DEFINE CUSTOM_PIXELFORMAT_D2}
|
|
|
-{$ENDIF}
|
|
|
-
|
|
|
-{$IFDEF CUSTOM_PIXELFORMAT_D2}
|
|
|
- TPixelFormat = (pfUndefined, pfDevice, pf1bit, pf4bit, pf8bit, pf15bit, pf16bit, pf24bit, pf32bit, pfCustom);
|
|
|
-{$ENDIF}
|
|
|
- TAlphaFormat = (afIgnored, afDefined, afPremultiplied);
|
|
|
- TAlphaBitmap = class(TBitmap)
|
|
|
- private
|
|
|
- FAlphaFormat: TAlphaFormat;
|
|
|
- procedure PreMultiplyAlpha;
|
|
|
-{$IFDEF CUSTOM_PIXELFORMAT_D2}
|
|
|
- private
|
|
|
- FPixelFormat: TPixelFormat;
|
|
|
- function GetPixelFormat: TPixelFormat;
|
|
|
-{$ENDIF}
|
|
|
- public
|
|
|
- procedure Assign(Source: TPersistent); override;
|
|
|
- procedure LoadFromStream(Stream: TStream); override;
|
|
|
- property AlphaFormat: TAlphaFormat read FAlphaFormat write FAlphaFormat;
|
|
|
-{$IFDEF CUSTOM_PIXELFORMAT_D2}
|
|
|
- property PixelFormat: TPixelFormat read GetPixelFormat;
|
|
|
-{$ENDIF}
|
|
|
- end;
|
|
|
+ TAlphaBitmap = TBitmap;
|
|
|
|
|
|
TBitmapImage = class(TGraphicControl)
|
|
|
private
|
|
|
FAutoSize: Boolean;
|
|
|
FBackColor: TColor;
|
|
|
- FBitmap: TAlphaBitmap;
|
|
|
+ FBitmap: TBitmap;
|
|
|
FCenter: Boolean;
|
|
|
FReplaceColor: TColor;
|
|
|
FReplaceWithColor: TColor;
|
|
@@ -65,7 +39,7 @@ type
|
|
|
protected
|
|
|
function GetPalette: HPALETTE; override;
|
|
|
procedure Paint; override;
|
|
|
- procedure SetAutoSize(Value: Boolean); {$IFDEF UNICODE}override;{$ENDIF}
|
|
|
+ procedure SetAutoSize(Value: Boolean); override;
|
|
|
public
|
|
|
constructor Create(AOwner: TComponent); override;
|
|
|
destructor Destroy; override;
|
|
@@ -100,23 +74,6 @@ procedure Register;
|
|
|
|
|
|
implementation
|
|
|
|
|
|
-{$IFNDEF IS_D6}
|
|
|
-type
|
|
|
- TBlendFunction = record
|
|
|
- BlendOp: BYTE;
|
|
|
- BlendFlags: BYTE;
|
|
|
- SourceConstantAlpha: BYTE;
|
|
|
- AlphaFormat: BYTE;
|
|
|
- end;
|
|
|
-
|
|
|
-const
|
|
|
- AC_SRC_OVER = $00;
|
|
|
- AC_SRC_ALPHA = $01;
|
|
|
-
|
|
|
-function AlphaBlend(DC: HDC; p2, p3, p4, p5: Integer; DC6: HDC; p7, p8, p9,
|
|
|
- p10: Integer; p11: TBlendFunction): BOOL; stdcall; external 'msimg32.dll' name 'AlphaBlend';
|
|
|
-{$ENDIF}
|
|
|
-
|
|
|
procedure Register;
|
|
|
begin
|
|
|
RegisterComponents('JR', [TBitmapImage]);
|
|
@@ -127,7 +84,7 @@ begin
|
|
|
inherited Create(AOwner);
|
|
|
ControlStyle := ControlStyle + [csReplicatable];
|
|
|
FBackColor := clBtnFace;
|
|
|
- FBitmap := TAlphaBitmap.Create;
|
|
|
+ FBitmap := TBitmap.Create;
|
|
|
FBitmap.OnChange := BitmapChanged;
|
|
|
FReplaceColor := clNone;
|
|
|
FReplaceWithColor := clNone;
|
|
@@ -218,13 +175,6 @@ begin
|
|
|
end;
|
|
|
|
|
|
procedure TBitmapImage.Paint;
|
|
|
-const
|
|
|
- Bf: TBlendFunction =(
|
|
|
- BlendOp: AC_SRC_OVER;
|
|
|
- BlendFlags: 0;
|
|
|
- SourceConstantAlpha: 255;
|
|
|
- AlphaFormat: AC_SRC_ALPHA);
|
|
|
-
|
|
|
var
|
|
|
R: TRect;
|
|
|
Bmp: TBitmap;
|
|
@@ -247,7 +197,7 @@ begin
|
|
|
FStretchedBitmap.Assign(FBitmap)
|
|
|
else begin
|
|
|
FStretchedBitmap.Assign(nil);
|
|
|
- if not StretchBmp(Canvas, FBitmap, FStretchedBitmap, W, H, Is32bit) then begin
|
|
|
+ if not StretchBmp(FBitmap, FStretchedBitmap, W, H, Is32bit) then begin
|
|
|
if Is32bit then begin
|
|
|
FStretchedBitmapValid := False;
|
|
|
Bmp := FBitmap;
|
|
@@ -290,11 +240,7 @@ begin
|
|
|
Y := 0;
|
|
|
end;
|
|
|
|
|
|
- if Is32bit then begin
|
|
|
- if AlphaBlend(Handle, X, Y, W, H, Bmp.Canvas.Handle, 0, 0, Bmp.Width, Bmp.Height, Bf) then
|
|
|
- Exit;
|
|
|
- end;
|
|
|
- if (FReplaceColor <> clNone) and (FReplaceWithColor <> clNone) then begin
|
|
|
+ if not Is32bit and (FReplaceColor <> clNone) and (FReplaceWithColor <> clNone) then begin
|
|
|
Brush.Color := FReplaceWithColor;
|
|
|
BrushCopy(Rect(X, Y, X + W, Y + H), Bmp, Rect(0, 0, Bmp.Width, Bmp.Height), FReplaceColor);
|
|
|
end else
|
|
@@ -302,116 +248,4 @@ begin
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
-{$IFDEF CUSTOM_PIXELFORMAT_D2}
|
|
|
-// Types defined to access internal private fields, must match exactly the
|
|
|
-// implementation of both types from Graphics.
|
|
|
-type
|
|
|
- TBitmapImageAccess = class(TObject)
|
|
|
- private
|
|
|
- // TInternalImage
|
|
|
- FRefCount: Integer;
|
|
|
- FMemoryManager: Pointer;
|
|
|
- // TBitmapImage
|
|
|
- FHandle, FPalette: THandle;
|
|
|
- FWidth, FHeight: LongInt;
|
|
|
- FDIBHeader: ^TBitmapInfoHeader;
|
|
|
- FDIBBits: Pointer;
|
|
|
- end;
|
|
|
-
|
|
|
- TBitmapAccess = class(TGraphic)
|
|
|
- private
|
|
|
- FImage: TBitmapImageAccess;
|
|
|
- end;
|
|
|
-{$ENDIF}
|
|
|
-
|
|
|
-{ TAlphaBitmap }
|
|
|
-
|
|
|
-type
|
|
|
- // Some type that we know all Delphi supports and has correct width on all
|
|
|
- // platforms.
|
|
|
- NativeUInt = WPARAM;
|
|
|
-
|
|
|
-procedure TAlphaBitmap.Assign(Source: TPersistent);
|
|
|
-begin
|
|
|
- inherited;
|
|
|
- if Source is TAlphaBitmap then
|
|
|
- FAlphaFormat := TAlphaBitmap(Source).AlphaFormat;
|
|
|
-end;
|
|
|
-
|
|
|
-{$IFDEF CUSTOM_PIXELFORMAT_D2}
|
|
|
-function TAlphaBitmap.GetPixelFormat: TPixelFormat;
|
|
|
-begin
|
|
|
- // We use cached value as default since after the canvas handle has been
|
|
|
- // created the DIB section is no longer valid and the painting must remember
|
|
|
- // whether the bitmap has alpha or not.
|
|
|
- Result := FPixelFormat;
|
|
|
- if TBitmapAccess(Self).FImage = nil then
|
|
|
- Exit;
|
|
|
- with TBitmapAccess(Self).FImage do
|
|
|
- begin
|
|
|
- if (FDIBHeader = nil) or (FDIBBits = nil) then
|
|
|
- Exit;
|
|
|
- Result := pfCustom;
|
|
|
- case FDIBHeader^.biBitCount of
|
|
|
- 1: Result := pf1Bit;
|
|
|
- 4: Result := pf4Bit;
|
|
|
- 8: Result := pf8Bit;
|
|
|
- 16: case FDIBHeader^.biCompression of
|
|
|
- BI_RGB : Result := pf15Bit;
|
|
|
- // BI_BITFIELDS: if FDIBHeader^.dsBitFields[1] = $7E0 then Result := pf16Bit;
|
|
|
- end;
|
|
|
- 24: Result := pf24Bit;
|
|
|
- 32: if FDIBHeader^.biCompression = BI_RGB then Result := pf32Bit;
|
|
|
- end;
|
|
|
- end;
|
|
|
- FPixelFormat := Result;
|
|
|
-end;
|
|
|
-{$ENDIF}
|
|
|
-
|
|
|
-procedure TAlphaBitmap.LoadFromStream(Stream: TStream);
|
|
|
-begin
|
|
|
- inherited;
|
|
|
- if (PixelFormat = pf32bit) and (FAlphaFormat = afDefined) then
|
|
|
- PreMultiplyAlpha;
|
|
|
-end;
|
|
|
-
|
|
|
-function BytesPerScanline(PixelsPerScanline, BitsPerPixel, Alignment: Longint): Longint;
|
|
|
-begin
|
|
|
- Dec(Alignment);
|
|
|
- Result := ((PixelsPerScanline * BitsPerPixel) + Alignment) and not Alignment;
|
|
|
- Result := Result div 8;
|
|
|
-end;
|
|
|
-
|
|
|
-procedure TAlphaBitmap.PreMultiplyAlpha;
|
|
|
-var
|
|
|
- Alpha: Word;
|
|
|
- ImageData, Limit: NativeUInt;
|
|
|
-begin
|
|
|
- if (PixelFormat = pf32bit) then //Premultiply the alpha into the color
|
|
|
- begin
|
|
|
-{$IFNDEF CUSTOM_PIXELFORMAT_D2}
|
|
|
- Pointer(ImageData) := ScanLine[0];
|
|
|
- if ImageData = NativeUInt(nil) then
|
|
|
- Exit;
|
|
|
- Pointer(Limit) := ScanLine[Height - 1];
|
|
|
- // Is bottom up? (this can be distinguished by biHeight being positive but
|
|
|
- // since we don't have direct access to the headers we need to work around
|
|
|
- // that.
|
|
|
- if Limit < ImageData then
|
|
|
- ImageData := Limit;
|
|
|
-{$ELSE}
|
|
|
- Pointer(ImageData) := TBitmapAccess(Self).FImage.FDIBBits;
|
|
|
-{$ENDIF}
|
|
|
- Limit := ImageData + NativeUInt(BytesPerScanline(Width, 32, 32) * Height);
|
|
|
- while ImageData < Limit do
|
|
|
- begin
|
|
|
- Alpha := PByte(ImageData + 3)^;
|
|
|
- PByte(ImageData)^ := MulDiv(PByte(ImageData)^, Alpha, 255);
|
|
|
- PByte(ImageData + 1)^ := MulDiv(PByte(ImageData + 1)^, Alpha, 255);
|
|
|
- PByte(ImageData + 2)^ := MulDiv(PByte(ImageData + 2)^, Alpha, 255);
|
|
|
- Inc(ImageData, 4);
|
|
|
- end;
|
|
|
- end;
|
|
|
-end;
|
|
|
-
|
|
|
-end.
|
|
|
+end.
|