Occasionally you may want to resize and save a JPEG image. If you can use ImageMagick, the story is quick, but if you really want to complete it with Java only, you will use ImageIO.
However, please note that the storage quality of JPEG images is automatically set to "75" with the simplest implementation method (check with Java 8). I was addicted to it.
The implementation itself is simple, but if you want to change the storage quality, it is NG.
public static byte[] resize(final byte[] src, final double scale) throws IOException {
try (ByteArrayInputStream is = new ByteArrayInputStream(src);
ByteArrayOutputStream os = new ByteArrayOutputStream()) {
BufferedImage srcImage = ImageIO.read(is);
BufferedImage destImage = resizeImage(srcImage, scale);
//Storage quality will be "75"
ImageIO.write(destImage, "jpeg", os);
return os.toByteArray();
}
}
This is the correct answer. You can specify the storage quality quality
from 0 to 1.0. 1.0 is equivalent to quality 100.
public static byte[] resize(final byte[] src, final double scale, final float quality) throws IOException {
try (ByteArrayInputStream is = new ByteArrayInputStream(src);
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageOutputStream ios = ImageIO.createImageOutputStream(os)) {
BufferedImage srcImage = ImageIO.read(is);
BufferedImage destImage = resizeImage(srcImage, scale);
//Storage quality follows user specifications
ImageWriter writer = ImageIO.getImageWritersByFormatName("jpeg").next();
ImageWriteParam param = writer.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(quality);
writer.setOutput(ios);
writer.write(null, new IIOImage(destImage, null, null), param);
writer.dispose();
return os.toByteArray();
}
}
The implementation of the resizing method resizeImage
that appeared in the previous two examples is as follows. The image quality is not good by default when resizing the image, but you can improve the image quality by specifying TYPE_BICUBIC
when converting to affine.
public static BufferedImage resizeImage(final BufferedImage image, final double scale) throws IOException {
int width = (int) (image.getWidth() * scale);
int height = (int) (image.getHeight() * scale);
BufferedImage resizedImage = new BufferedImage(width, height, image.getType());
//Resize by affine conversion (priority is given to image quality)
AffineTransform transform = AffineTransform.getScaleInstance(scale, scale);
AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BICUBIC);
op.filter(image, resizedImage);
return resizedImage;
}
When resizing in Java, the memory & CPU load becomes unacceptably large as the image data becomes large, so I think that the scenes that can be used are quite limited.
Recommended Posts