Jump to content
alank2

How to load a PNG file into TImage, then copy another PNG file into it

Recommended Posts

Using cppbuilder I can load a PNG file into a TImage, but then I want to merge another PNG file into it using CopyRect.  I think there is some issue with it not being a bitmap that causes it to give an error when I try.  I've tried some searching about this, but didn't really see anything that helped.  Is thee a way to load the PNG, then perform some operation on it that renders it as a bitmap that I can then CopyRect to?

Share this post


Link to post

Do you have an example of how to do that?  I tried something with Draw earlier unsuccessfully as well.

Share this post


Link to post

There are other, simpler methods to copy a bitmap, but maybe this example is worth noting it, (or here) line-by-line using ScanLine.

var
  srce, dest: TBitmapSurface;
  path: string;
  scan: integer;
  w, h1, h2: integer;
begin
  path := 'C:\tmp\Imgs\res.bmp';

  srce := TBitmapSurface.Create;
  try
    TBitmapCodecManager.LoadFromFile(path, srce);

    dest := TBitmapSurface.Create;
    try
      // first half
      w := srce.Width;
      h1 := srce.Height div 2;
      dest.SetSize(w, h1, TPixelFormat.RGBA);
      for scan := 0 to h1-1 do
        Move(srce.Scanline[scan]^, TBitmapSurface(dest).Scanline[scan]^, srce.Width * 4);
      Image1.Bitmap.Assign(dest);

      // second half
      h2 := srce.Height - h1;
      dest.SetSize(w, h2, TPixelFormat.RGBA);
      for scan := h1 to srce.Height-1 do
        Move(srce.Scanline[scan]^, TBitmapSurface(dest).Scanline[scan-h1]^, srce.Width * 4);
      Image2.Bitmap.Assign(dest);

    finally
      dest.Free;
    end;
  finally
    srce.Free;
  end;

(the example explains how to handle very large images).


Here also a simpler solution (just don't use the "with" ...)

 

Edited by Rollo62

Share this post


Link to post
8 hours ago, alank2 said:

Do you have an example of how to do that? 

Sure that:

var
  bmp: TBitmap;
  png: TPngImage;
begin
  bmp := TBitmap.Create;
  try
    png := TPngImage.Create;
    try
      png.LoadFromFile('c:\Program Files (x86)\Embarcadero\Studio\21.0\bin\Artwork\Windows\UWP\cppreg_UwpDefault_150.png');
      bmp.SetSize(png.Width, png.Height);
      png.Draw(bmp.Canvas, TRect.Create(TPoint.Zero, png.Width, png.Height));
      bmp.SaveToFile('c:\temp\test.bmp');
    finally
      png.Free;
    end;
  finally
    bmp.Free;
  end;
end;

Depending on your Delphi version you might even succeed with a simple

bmp.Assign(png);

 

Share this post


Link to post
17 hours ago, alank2 said:

I think there is some issue with it not being a bitmap that causes it to give an error when I try.

What kind of error?

17 hours ago, alank2 said:

I've tried some searching about this, but didn't really see anything that helped.  Is thee a way to load the PNG, then perform some operation on it that renders it as a bitmap that I can then CopyRect to?

I've concatenated PNGs together before, but that was a long time ago, and IIRC I had to resort to a 3rd party PNG library to accomplish it (TPNGImage wasn't yet available in the VCL at the time).  Copying the source PNGs to a temp bitmap, and then converting that bitmap back to a PNG, just didn't have the correct result for me (maybe it screwed up the alpha channels, I don't remember).  So I had to drop down a layer and work with the raw PNG pixel data directly.  The resulting PNGs were clean, but the effort was not.

Share this post


Link to post

The error was can only modify an image if it contains a bitmap.  It works with BMP files, but not PNG files.

 

Is the Draw method above something that will convert it from PNG to BMP?

 

I ended up just using two TImage's, one placed on top of the other, to do what needed to be done, but I would have liked to figure out how to make PNG's work with CoptRect().

 

Thanks!

Share this post


Link to post
9 minutes ago, alank2 said:

Is the Draw method above something that will convert it from PNG to BMP?

If you only want to convert from PNG to BMP then just assign the TPNGImage to the TBitmap.

If you want a bitmap containing two PNGs side by side (or one on top of the other), then create a TBitmap of the desired size and then draw the PNGs onto the bitmap canvas at the desired locations.

 

Uwe's examples contains most of the necessary code.

 

13 minutes ago, alank2 said:

I would have liked to figure out how to make PNG's work with CoptRect()

You can't. CopyRect requires a TCanvas and TPNGImage ain't got it. TCanvas is a wrapper around a GDI device handle (HDC).

Share this post


Link to post
On 12/28/2021 at 9:53 AM, alank2 said:

The error was can only modify an image if it contains a bitmap.  It works with BMP files, but not PNG files.

That error comes from the VCL TImage.Canvas property getter, when the TImage.Picture.Graphic is holding a TGraphic object other than a TBitmap.  The TImage.Canvas property is simply just a shortcut to the held TBitmap.Canvas.  So you can't use it to draw/modify a non-bitmap graphic.

Edited by Remy Lebeau

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×