Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

convert png to jpg

Status
Not open for further replies.

AlastairP

Technical User
Feb 8, 2011
286
AU
I am having trouble converting png to jpg

I have tried the following:

Code:
local loimage as gpimage of ffc/_gdiplus.vcx
loimage = newobject("gpimage",home()+"ffc/_gdiplus.vcx")
loimage.createfromfile(lcsource)
loimage.savetofile(lcPic,"image/jpg",'quality=100')

But the result is a black image.
 
using system.app

Code:
DO system.app
with _SCREEN.SYSTEM.Drawing
losrc =  .Bitmap.fromfile(GETFILE("png"))
loEncoderParameters = .imaging.EncoderParameters.New(1)
loEncoderParameter = .imaging.EncoderParameter.New(.imaging.Encoder.Quality, 100)
loEncoderParameters.PARAM.ADD(loEncoderParameter)
losrc.Save("c:\temp\test.jpg",.imaging.imageformat.jpeg,loEncoderParameters)
endwith


hth

n
 
GDIplusX of the VFPX project is the better GDI+ implementation.

But never mind, this is an easy enough task, I think, to also use the FFC.

All you need to do is call SaveToFile with the right parameters:
savetofile_wugbxs.png

The second parameter needs to be a CLSID of an encoder, and for that you have to use...
GetEncoderCLSID_jd3rai.gif


So:
Code:
local loimage as gpimage of ffc/_gdiplus.vcx
loimage = newobject("gpimage",home()+"ffc/_gdiplus.vcx")
loimage.createfromfile(lcsource)
loimage.savetofile(lcPic,loimage.GetEncoderCLSID("image/jpeg"),'quality=100')

Did you get a black image, really or a 0 byte file? Because that's what I get when I don't specify an encoder CLSID. Image viewers/editors might show you a black image then, but there actually isn't one, it's not output.

Just opinion: JPEG already is good at 50% quality and 100% quality isn't necessary, I'd recommend 60%, perhaps 80% in special cases like graphical images, but as said, opinion, even with quality=100 a JPEG is much smaller than a BMP (lossless compression) format, for example, so you're good with whatever you want there.

Chriss
 
I am not having any luck so far, (with either of the above suggestions) but I think I established that the issue may be related to the png having a transparent background.
Has anyone successfully converted transparent background to white?

Alastair
 
I understand "But the result is a black image" as the full image, not the background.

Then first create a completely white image of same size as the PNG and add the PNG on top. You can store the resulting image as JPEG and have converted transparency to white.

If you need the code sample for that, wait until later, but it shouldn't be too hard to find sample code especially if you switch to use GDIPlusX instead of FFC classes, they make some things easier.

Chriss
 
Hi Chris,
I am having a crack at what you suggested and I am half way there. So far I have created a bmp the same size as the original image with white color

Code:
lcFile= 'D:\Docs\Temp\pngtest.png'

loImg = _Screen.System.Drawing.Bitmap.FromFile(lcFile,.T.)
lnHeight = int(loImg.Size.Height)
lnWidth = int(loImg.Size.Width)

DO LOCFILE("system.app")
LOCAL lobmp AS xfcbitmap
LOCAL logfx AS xfcgraphics
WITH _SCREEN.SYSTEM.drawing

   lobmp = .BITMAP.new(lnWidth, lnHeight, 0, .imaging.pixelformat.format24bpprgb)
   logfx = .graphics.fromimage(lobmp)
   logfx.CLEAR(.COLOR.white)
	
[indent]&& need to load the image here and stack on top[/indent]	


   lobmp.SAVE(lcTempBmp, .imaging.imageformat.bmp)
   
ENDWITH
 
Well, mostly you only miss loGfx.DrawImage(loImg,0,0), but all in all there are some more details to change:

Code:
Local loPNG ,loNewBmp, loGfx
Local lcFile, lnWidth, lnHeight
Local loEncoderparameters
lcFile= 'D:\Docs\Temp\pngtest.png'

DO LOCFILE("system.app")

With _Screen.System.Drawing
   loPNG = .Bitmap.New(lcFile)
   lnHeight = loPNG.Height
   lnWidth  = loPNG.Width

   * When working with PNGs, use the pixel format with alpha channel:
   loNewBmp = .Bitmap.New(lnWidth, lnHeight, 0, .Imaging.PixelFormat.Format32bppARGB)
   * Same lnWidth, lnHeight is mandatory, same dpi is optional, but makes DrawImage easier: 
   loNewBmp.SetResolution(loPNG.HorizontalResolution, loPNG.VerticalResolution)
   loGfx = .graphics.FromImage(loNewBmp)
   loGfx.Clear(.Color.white)

   * mainly the only missing line
   loGfx.DrawImage(loPNG,0,0)

   * to get the quality parameter is a bit more complicated in GDIplusX:
   loEncoderparameters = .Imaging.encoderparameters.New(1)
   loEncoderparameters.Param.Add(.Imaging.encoderparameter.New(.Imaging.Encoder.Quality, 100))

   loNewBmp.Save(Forceext(lcFile,'jpeg'), .Imaging.ImageFormat.Jpeg, loEncoderparameters)
Endwith

Notice for PNG it's important to have an alpha channel, so the loNewBMP has to have a pixel format with RGBA or ( in GDI+) ARGB, which means 4 bytes per pixel and therefore 32bpp, all in all .Imaging.PixelFormat.Format32bppARGB. That isn't saved in the jpeg file, but Drawing a PNG with transparency needs the "canvas" graphics object to have an alpha channel, too.

SetResolution (setting the dpi of the loNewBMP to the same as the PNG) is necessary so the same dpi also means the same pixel width/height dimensions when DrawImage is used with just the position parameters. Skip that and the PNG image could become smaller or larger in pixel size. DrawImage takes into account the dpi of both Bitmap objects involved in the drawing. To make it easy and not waste time with resampling and resizing images because of different dpi just set the same resolution (dpi resolution), too besides same pixel size.

And last not least, in memory everything is a bitmap, that's not about the BMP file format, it's about the in memory state of any image, no matter how it's stored as file, PNG or JPEG or GIF and even BMP compression are decompressed to an in memory image with bytes as per pixelformat and need uncompressed size in RAM. Therefore there only is _Screen.System.Drawing.Bitmap and not also _Screen.System.Drawing.JPEG, _Screen.System.Drawing.PNG or anything like that, doesn't mean you are forced to BMP file format. No idea if you thought that when saving as BMP in your code, but I changed that back to JPEG with quality parameter.

Chriss
 
myself said:
Drawing a PNG with transparency needs the "canvas" graphics object to have an alpha channel, too.

Thinking about it, I might be wrong about that. Even if the newbmp is just the three RGB channels finally saved as jpeg without transparency, DrawImage can still process the PNG transparency as it only needs to know the background image RGB without an alpha channel and mixes that with PNG pixel color taking the PNG alpha channel into account. It's just overall simpler to process an image with alpha channel as long as you work on it in memory. Who knows what further ideas you'll add in the future that could use the alpha channel in all the steps before finally saving.

So the reasoning changes, but the recommendation stays to use .Imaging.PixelFormat.Format32bppARGB.


Chriss
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top