in Code

Running jpegtran From a Qt Application

Continuing on with my obsession with smaller images, I thought I’d give an example of how to include jpegtran with your Qt app and how to call it using QProcess to optimize jpegs. Why do this? The use-case I had was that I was downloading images from the net from within my application and I wanted to ensure that they were optimized. I could have read them in and used my modifications to QImageWriter & co. to write them back out, but we are dealing with JPEG which is a lossy format, so I wanted a lossless way to optimize the images.

The first thing to do is download and compile jpegsrc [which contains jpegtran] for whichever platforms you are targeting. I won’t go into details here – the process is pretty straightforward.

As your standard Lazy Developer™, I like to let tools do as much of the work as possible, so I use qmake to copy the jpegtran executable to the correct place. In my .pro file I have the following:

The interesting bits are lines 13-16 for the Mac, and lines 20-23 for Windows. On the Mac, declaring QMAKE_BUNDLE_DATA will copy the files specified to the path specified. Very compact way to put things in the correct place in the application bundle. In this case, we’re putting it in $${TARGET}.app/Contents/MacOS which is next to your application executable. On Windows, we’re simply using the shell to copy the jpegtran.exe file into the same directory as our executable. You’re free to put these additional executables anywhere you like, these are just the locations I prefer.

So now that we have the jpegtran executable in place, let’s look at how to access it from our application. Here’s a function to run jpegtran on a given file. Keep in mind standard caveats about error handling and so on…

I think that’s pretty straightforward!

Back to the internet download use-case I described at the beginning. First I download the image from the net to a tmp dir, then I run the someClass::optimizeImage() function on it, putting the result in the location I want it. It’s fast, so you don’t even notice it and you end up with a lossless optimized copy of the image from the net. Simple.

Note that you can add code to handle PNGs quite easily. I’ve done this in my own code using optipng. Just compile it, copy it just like we’re doing with jpegtran in the .pro file, and add the handler in an else if statement in someClass::optimizeImage(). One caveat with PNGs: they are much slower to optimize, so you might want to do some asynchronous magic to handle that case so you aren’t blocking user input.

Hope that helps someone out there in Internetland!

Write a Comment

Comment