How to get java wrapper for libjpeg-turbo to actually compress?

1.3k views Asked by At

I'm having trouble getting libjpeg-turbo in my java project to actually compress an image. It writes a .jpg fine - but the final size of the result is always e.g. almost the same as a 24bit windows .bmp of the same image. A 480x854 image turns into a 1.2 Megabyte jpeg with the below code snippet. If I use GRAY sampling it's 800Kb (and these are not fancy images to begin with - mostly a neutral background with some filled primary color discs on them for a game I'm working on).

Here's the code I've got so far:

// for some byte[] src in RGB888 format, representing an image of dimensions
// 'width' and 'height'
try
{
    TJCompressor tjc = new TJCompressor(
            src,
            width
            0,  // "pitch" - scanline size
            height
            TJ.PF_RGB  // format
    );
    tjc.setJPEGQuality(75);
    tjc.setSubsamp(TJ.SAMP_420);
    byte[] jpg_data = tjc.compress(0);
    new java.io.FileOutputStream(new java.io.File("/tmp/dump.jpg")).write(jpg_data, 0, jpg_data.length);
}
catch(Exception e)
{
    e.printStackTrace(System.err);
}

I'm particularly having a hard time finding sample java usage documentation for this project; it mostly assumes a C background/usage. I don't understand the flags to pass to compress (nor do I really know the internals of the jpeg standard, nor do I want to :)!

Thanks!

1

There are 1 answers

3
jdowdell On

Doh! And within 5 minutes of posting the question the answer hit me.

A hexdump of the result showed that the end of the file for these images was just lots and lots of 0s.

For anybody in a similar situation in the future, instead of using jpg_data.length (which is apparently entirely too large for some reason), use TJCompressor.getCompressedSize() immediately after your call to TJCompressor.compress().

Final result becomes:

// for some byte[] src in RGB format, representing an image of dimensions
// 'width' and 'height'
try
{
    TJCompressor tjc = new TJCompressor(
            src,
            width
            0,  // "pitch" - scanline size
            height
            TJ.PF_RGB  // format
    );
    tjc.setJPEGQuality(75);
    tjc.setSubsamp(TJ.SAMP_420);
    byte[] jpg_data = tjc.compress(0);
    int actual_size = tjc.getCompressedSize();
    new java.io.FileOutputStream(new java.io.File("/tmp/dump.jpg")).
            write(jpg_data, 0, actual_size);
}
catch(Exception e)
{
    e.printStackTrace(System.err);
}