Reputation: 191
Hi I would like to know if there is any way in Java to reduce the size of an image (use any kind of compression) that was loaded as a BufferedImage and is going to be saved as an PNG.
Maybe some sort of png imagewriteparam? I didnt find anything helpful so im stuck.
heres a sample how the image is loaded and saved
public static BufferedImage load(String imageUrl) {
Image image = new ImageIcon(imageUrl).getImage();
bufferedImage = new BufferedImage(image.getWidth(null),
image.getHeight(null),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2D = bufferedImage.createGraphics();
g2D.drawImage(image, 0, 0, null);
return bufferedImage;
}
public static void storeImageAsPng(BufferedImage image, String imageUrl) throws IOException {
ImageIO.write(image, "png", new File(imageUrl));
}
Upvotes: 19
Views: 39783
Reputation: 1
I was facing the same issue but what worked me was always use jpeg as compression format even in the case of png because in case of png file it was not compressing but increasing the size of file even more.
ImageIO.getImageWriters(type, "jpeg").next() //always jpeg
profileImage formats for me
"data:image/png;base64,/9j/4AAQSkZJRgABAgAAAQABAAD/2wB...//Z"
"data:image/jpeg;base64,/9j/4AAQSkZJRgABAgAAAQABAAD/2wB...//Z"
Complete Code for reference.
public String compressProfileImage(String profileImage, float compressionQuality) throws IOException {
if (profileImage == null || profileImage.isEmpty()) return null;
String[] strings = profileImage.split(",");
if (strings.length < 2)
return null;
byte[] decodedImg = Utils.decodeBase64Tobytes(strings[1]);
// Read image
RenderedImage img = ImageIO.read(new ByteArrayInputStream(decodedImg));
// Create output stream for compressed image data
ByteArrayOutputStream bos = new ByteArrayOutputStream();
// Write image to output stream with compression
ImageWriteParam imageWriteParam = createJPEGImageWriteParam(compressionQuality);
ImageOutputStream ios = ImageIO.createImageOutputStream(bos);
ImageWriter writer = ImageIO.getImageWritersByFormatName("jpeg").next();
writer.setOutput(ios);
writer.write(null, new IIOImage(img, null, null), imageWriteParam);
// Get the compressed image data
byte[] compressedImageData = bos.toByteArray();
return strings[0] + "," + Utils.encodeBase64(compressedImageData);
}
private static ImageWriteParam createJPEGImageWriteParam(float compressionQuality) {
JPEGImageWriteParam jpegParams = new JPEGImageWriteParam(null);
jpegParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
jpegParams.setCompressionQuality(compressionQuality);
return jpegParams;
}
Working code happy coding!!!
Upvotes: 0
Reputation: 4162
By calling ImageIO.write
you use the default compression quality for pngs. You can choose an explicit compression mode which reduces file size a lot.
String inputPath = "a.png";
String outputPath = "b.png";
BufferedImage image;
IIOMetadata metadata;
try (ImageInputStream in = ImageIO.createImageInputStream(Files.newInputStream(Paths.get(inputPath)))) {
ImageReader reader = ImageIO.getImageReadersByFormatName("png").next();
reader.setInput(in, true, false);
image = reader.read(0);
metadata = reader.getImageMetadata(0);
reader.dispose();
}
try (ImageOutputStream out = ImageIO.createImageOutputStream(Files.newOutputStream(Paths.get(outputPath)))) {
ImageTypeSpecifier type = ImageTypeSpecifier.createFromRenderedImage(image);
ImageWriter writer = ImageIO.getImageWriters(type, "png").next();
ImageWriteParam param = writer.getDefaultWriteParam();
if (param.canWriteCompressed()) {
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(0.0f);
}
writer.setOutput(out);
writer.write(null, new IIOImage(image, null, metadata), param);
writer.dispose();
}
Upvotes: 5
Reputation: 421340
Have a look at the ImageWriterParam
class in the same package as the ImageIO
class. It mentions compression.
https://docs.oracle.com/javase/7/docs/api/javax/imageio/ImageWriteParam.html
Also look at the example at http://exampledepot.com/egs/javax.imageio/JpegWrite.html and see if it translates well for PNG files.
Upvotes: 0
Reputation: 1219
You may want to try pngtastic. It's a pure java png image optimizer that can shrink may png images down to some degree.
Upvotes: 5
Reputation: 76026
If it's going to be saved as PNG
, compression will be done at that stage. PNG has a lossless compression algorithm (basically prediction followed by lempel-ziv compression) with few adjustable parameters (types of "filters") and not much impact in compression amount - in general the default will be optimal.
Upvotes: 2