Search code examples
javaimagecompressionjpegfilesize

Is Extreme Image Optimization Possible in Java?


I am attempting to write an image optimization software in Java. The first and most obvious step was to strip EXIF metadata, which I have done successfully. I also tried to compress the images using ImageIO and the compression quality parameter as below:

filepath=chosen.getCanonicalPath()+"-temp.jpg";
file=new File(filepath);
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
if (!writers.hasNext()){
    throw new IllegalStateException("No writers found");
}
OutputStream os = new FileOutputStream(file);
ImageWriter writer = (ImageWriter) writers.next();
ImageOutputStream ios = ImageIO.createImageOutputStream(os);
writer.setOutput(ios);

ImageWriteParam param = writer.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(0.9f);
writer.write(null, new IIOImage(optimized, null, null), param);

However, this really doesn't work all that well. It works sort of okay when the source image is a different format (i.e. not jpeg), but when compressing from jpeg to jpeg, it sometimes even makes the file size larger.

Sites like www.tinyjpg.com claim to (and do) reduce file size of jpeg images by 40%-60% with no quality loss. How on earth do they do this (both procedurally and programmatically)? What types of data are they removing, and how is it possible to remove this data with no quality loss? Is this something I could possibly achieve in Java?

Any guidance and/or resources you can give me are greatly appreciated!


Solution

  • From Wikipedia - JPG - Lossless further compression I would guess that Tiny JPG has been using improved algorithms that were developed after the creation of most standard tools. The improved algorithms are implemented in PackJPG which is conveniently open-sourced. There doesn't appear to be a Java implementation.

    As a side note: PackJPG claims a 20% improvement while Tiny JPG claims 70%. This might be an overstatement but you might want to test both claims anyway.