3

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!

Theolodis
  • 4,977
  • 3
  • 34
  • 53
jdowdell
  • 1,578
  • 12
  • 24

1 Answers1

2

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);
}
jdowdell
  • 1,578
  • 12
  • 24
  • What about doing the same from a source `Bitmap` (instead of calling the slow `.compress()` method on it)? Any suggestions? – Roberto Andrade May 05 '15 at 20:16
  • sometime API has been designed in stupid way, I spent a lot of time, and I don't know why the output file is larger than the input file. I don't have any good reason about the huge output length, thank you, you are saved my time :) – Ahmad AlMughrabi Sep 25 '16 at 21:25
  • Do you use a wrapper? How did you add the dependencies in the project? I am trying to find a way to use it in a spring boot project – agata Jan 11 '23 at 13:21