alank2 5 Posted December 22, 2021 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
Uwe Raabe 2057 Posted December 22, 2021 What about just Draw the Png to the Bitmap Canvas? Share this post Link to post
alank2 5 Posted December 23, 2021 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
Rollo62 536 Posted December 23, 2021 (edited) 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 December 23, 2021 by Rollo62 Share this post Link to post
Uwe Raabe 2057 Posted December 23, 2021 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
Remy Lebeau 1396 Posted December 23, 2021 9 hours ago, Rollo62 said: There are other, simpler methods to copy a bitmap, but maybe this example is worth noting it, (or here) line-by-line using ScanLine. That is FMX code, but this question was posted in a VCL forum. Share this post Link to post
Remy Lebeau 1396 Posted December 23, 2021 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
alank2 5 Posted December 28, 2021 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
Anders Melander 1783 Posted December 28, 2021 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
Remy Lebeau 1396 Posted December 29, 2021 (edited) 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 December 29, 2021 by Remy Lebeau Share this post Link to post