Programmatically Reducing JPEG file size

那年仲夏 提交于 2019-12-01 04:08:35

Another way to reduce image size is to change compression level. You can do that using ImageWriter.

    ImageWriter writer = null;
    Iterator<ImageWriter> iwi = ImageIO.getImageWritersByFormatName("jpg");
    if (!iwi.hasNext())
        return;
    writer = (ImageWriter) iwi.next();
    ImageWriteParam iwp = writer.getDefaultWriteParam();
    iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT) ;
    iwp.setCompressionQuality(compressionQuality);
    writer.setOutput(...);
    writer.write(null, image, iwp);

The easiest way to do this is to decompress the byte stream into a Java Image, optionally resize it (which makes it smaller) and then regenerate a JPEG image from this with the desired quality setting.

This new image is then what is sent to the client.

Have a look at the ImageIO class. As for reducing file size: since the image would already be a JPEG the only things you could do is reduce the quality or the image size.

Another thing to keep in mind: if the image is a CMYK jpeg it might be bigger. Unfortunately ImageIO can't handle those, but you can try JAI ImageIO to convert from CMYK to RGB (which should be much smaller).

Two of the possible solutions are downscaling the image, here's how you'd do it:

BufferedImage original = //your image here
scaled = original.getScaledInstance(finalWidth, finalHeight, Image.SCALE_SMOOTH); // scale the image to a smaller one

BufferedImage result = new BufferedImage(finalWidth, finalHeight, original.getType());
Graphics2D g = result.createGraphics();     

g.drawImage(scaled, 0, 0, null); //draw the smaller image
g.dispose();

Obviously, you have to calculate the scaled width and height so the image stays by the same aspect ratio.

Once you have drawn it smaller, you can now turn this image into a JPEG file:

BufferedImage image = // this is the final scaled down image

JPEGImageEncoder jpegEncoder = JPEGCodec.createJPEGEncoder(output);
JPEGEncodeParam jpegEncodeParam = jpegEncoder.getDefaultJPEGEncodeParam(image);

jpegEncodeParam.setDensityUnit(JPEGEncodeParam.DENSITY_UNIT_DOTS_INCH);
jpegEncodeParam.setXDensity(92);
jpegEncodeParam.setYDensity(92);

jpegEncodeParam.setQuality( 0.8F , false);
jpegEncoder.encode(image, jpegEncodeParam);

These classes are from the JAI package (more exactly com.sun.image.codec.jpeg) and the JVM might complain that they should not be used directly, but you can ignore that.

You can possibly download JAI from here, if it does not work I have github mirrors setup for the two libraries, JAI core and JAI ImageIO.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!