Reputation: 91
This is my code, I have a background picture width: 245 and height: 150 and a png picture 128x128, so I copy parts of the png picture inside the background picture.
I have also this information:
dstX = x-coordinate of destination point.
dstY = y-coordinate of destination point.
srcX = x-coordinate of source point.
srcY = y-coordinate of source point.
srcW = Source width.
srcH = Source height.
I try to user copyRect like this
procedure TMyClass.FillImage;
var
bg,png: TPngImage;
dstX,dstY,srcW,srcH,srcX,srcY: Integer;
begin
bg := TPngImage.CreateBlank(COLOR_RGB,8,245,150);
png := TPngImage.Create;
png.LoadFromFile('C:\temp\example.png');
dstX := 10;dstY:=0;srcW:=0;srcH:=118;srcX:=128;srcY:=10;
bg.Canvas.CopyRect(Rect(dstX,dstY,srcW,srcH),png.Canvas,Rect(srcX,srcY,png.Width,png.Height));
//With this values not working, I have the same result as before, should start copy in position 138 of bg.
dstX := 138;dstY:=0;srcW:=0;srcH:=118;srcX:=10;srcY:=10;
bg.Canvas.CopyRect(Rect(dstX,dstY,srcW,srcH),png.Canvas,Rect(srcX,srcY,png.Width,png.Height));
end;
With CopyRect, I have two problems.
The background picture has not to be a png format at the beginning because it is created at the beginning with only the width and height but at the end has to be save as png.
I search about this problem, first to copy the image png inside bg I try this, but not success:
http://www.delphitricks.com/source-code/graphic/copy_part_of_one_image_to_another.html
Then for the transparency problem I read
Alphablend and TransparentBlt and Why am I losing transparency when calling BitBlt or CopyRect?
But in my case is different because I do not use a paintbox as you can see, and and using a png image and I copy parts of this image inside another with the information I put above. But maybe this post can inspire someone to help me.
Upvotes: 2
Views: 3906
Reputation: 27377
As GDI + is supported since Delphi XE2 Delphi without external units, the easiest way is probably to ignore GDI due the limitations with alpha channels, and directly use the possibilities of GDI+.
Just create a TGPBitmap of the desired size for your destination PNG.
Create TGPImages providing the (PNG)Files you want to paint.
Draw these images using a TGPGraphics created with the TGPBitmap as Destination and draw the images at the desired position with width/height as you like, there are many overloads in GDIPOBJ for DrawImage with descriptive parameter naming.
Choose your encoder by mime type (e.g.image/bmp, image/jpeg, image/gif, image/tiff, image/png) and save the file using this encoder.
A short example:
uses PNGImage, GDIPOBJ, GDIPAPI, GDIPUTIL;
const
C_FileName1 = 'C:\temp\red.png';
C_FileName2 = 'C:\temp\Yellow.png';
procedure TDemo.Button1Click(Sender: TObject);
var
gp: TGPGraphics;
bg: TGpImage;
gi1: TGpImage;
gi2: TGpImage;
encoderClsid: TGuid;
begin
bg := TGPBitmap.Create(256, 150);
try
gi1 := TGpImage.Create(C_FileName1);
try
gi2 := TGpImage.Create(C_FileName2);
try
gp := TGPGraphics.Create(bg);
try
gp.DrawImage(gi1, 0, 0, 140, 140);
gp.DrawImage(gi2, 20, 20, 30, 30);
gp.DrawImage(gi2, 70, 70, 50, 50);
// Take one of many overloads to crop the image as desired
//function DrawImage(image: TGPImage; x, y, srcx, srcy, srcwidth, srcheight: Single; srcUnit: TUnit): TStatus; overload;
gp.DrawImage(gi2, 150, 30, 60, 40, 60, 80, UnitPixel);
//function TGPGraphics.DrawImage(image: TGPImage; const destRect: TGPRectF; srcx, srcy, srcwidth, srcheight: Single; srcUnit: TUnit; imageAttributes: TGPImageAttributes = nil; callback: DrawImageAbort = nil; callbackData: Pointer = nil): TStatus;
gp.DrawImage(gi2, DestRect , 60, 40, 60, 80, UnitPixel);
finally
gp.Free
end;
GetEncoderClsid('image/png', encoderClsid);
bg.Save('C:\temp\test.png', encoderClsid, nil);
Image1.Picture.LoadFromFile('C:\temp\test.png');
finally
gi2.Free
end;
finally
gi1.Free
end;
finally
bg.Free;
end;
end;
Since TGPGraphics can be used on every canvas (TGPGraphics.Create(aCanvas.Handle)) a peek into GDIPOBJ, GDIPAPI, GDIPUTIL might be interesting.
Upvotes: 3