I have a large (300x300px) PNG image which I need to rescale. In an other SO question I read about StretchBlt
and HALFTONE
in order for better scaling.
My problem is how do I draw the PNG image transparent, or at least paint the black corners white?
As you can see on the attached image I get black corners.
And here is the original image:
Here is what I've tried so far.
unit MainU;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls;
type
TFormMain = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
FormMain: TFormMain;
implementation
{$R *.dfm}
uses
Pngimage;
type
TIRButton = class(TImage)
protected
procedure Paint; override;
public
constructor Create(AOwner: TComponent); override;
end;
TGraphicControlAcess = class(TGraphicControl);
TGraphicAcess = class(TGraphic);
THalfTonePngImage = class(TPngImage)
protected
procedure Draw(ACanvas: TCanvas; const Rect: TRect); override;
end;
{ TIRButton }
constructor TIRButton.Create(AOwner: TComponent);
begin
inherited;
Center := True;
Proportional := True;
end;
procedure TIRButton.Paint;
var
ParentCanvas: TCanvas;
begin
ParentCanvas := TGraphicControlAcess(Self).Canvas;
TGraphicAcess(Picture.Graphic).Draw(ParentCanvas, DestRect);
end;
{ THalfTonePngImage }
procedure THalfTonePngImage.Draw(ACanvas: TCanvas; const Rect: TRect);
var
p: TPoint;
dc: HDC;
begin
dc := ACanvas.Handle;
GetBrushOrgEx(dc, p);
SetStretchBltMode(dc, HALFTONE);
SetBrushOrgEx(dc, p.X, p.Y, @p);
ACanvas.Brush.Color := clWhite;
ACanvas.FillRect(Classes.Rect(0, 0, Width, Height));
StretchBlt(
dc, 0, Rect.Top, Rect.Right - Rect.Left, Rect.Bottom - Rect.Top,
Canvas.Handle, 0, 0, Width, Height, ACanvas.CopyMode
);
end;
procedure TFormMain.FormCreate(Sender: TObject);
var
Image: THalfTonePngImage;
begin
Image := THalfTonePngImage.Create;
Image.LoadFromFile('X200IR_11_EmgBrake.png');
with TIRButton.Create(Self) do
begin
Width := 100;
Height := 100;
Picture.Assign(Image);
Parent := Self;
Anchors := [akLeft, akTop, akRight, akBottom];
end;
Image.Free;
end;
end.
The corners of the source image are transparent. It's not visible in the correct image because the white background. StretchBlt
doesn't support transparency. Since it doesn't, transparent pixels are indistinguishable from black. (If the ARGB color is FF 00 00 00
and we remove the alpha channel, we're left with 00 00 00
)
You need to use TransparentBlt
.
For reference this is the image when placed on a green background. It makes it easier to see the transparency.