(Using java 8) Given a image user needs to be able to specify min/max image size in pixels and also maximum size of saved image in kbs, image is saved as jpg.
So I have the first bit working, by resizing buffered image:
public static BufferedImage resizeUsingImageIO(Image srcImage, int size)
{
int w = srcImage.getWidth(null);
int h = srcImage.getHeight(null);
// Determine the scaling required to get desired result.
float scaleW = (float) size / (float) w;
float scaleH = (float) size / (float) h;
MainWindow.logger.finest("Image Resizing to size:" + size + " w:" + w + ":h:" + h + ":scaleW:" + scaleW + ":scaleH" + scaleH);
//Create an image buffer in which to paint on, create as an opaque Rgb type image, it doesn't matter what type
//the original image is we want to convert to the best type for displaying on screen regardless
BufferedImage bi = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB);
// Set the scale.
AffineTransform tx = new AffineTransform();
tx.scale(scaleW, scaleH);
// Paint image.
Graphics2D g2d = bi.createGraphics();
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, size, size);
g2d.setComposite(AlphaComposite.SrcOver);
g2d.drawImage(srcImage, tx, null);
g2d.dispose();
return bi;
}
The image is eventually output as a jpg as follows
public static byte[] convertToByteArray(BufferedImage bi) throws Exception
{
final ByteArrayOutputStream output = new ByteArrayOutputStream();
//Convert JPEG and then a byte array
if (ImageIO.write(bi, FILE_SUFFIX_JPG, new DataOutputStream(output)))
{
final byte[] imageData = output.toByteArray();
return imageData;
}
}
but is there a way I specify a max image size , and make it perform more compression as required to get underneath that size.
And should I set limits to width and height in first stage based on total size required, i.e if the total size is too small it would be impossible to get a good image if compression to a size that is too small
I don't know an "easy" or "elegant" way to do this.
However, 1.5 years ago, I wrote this code snippet: It is a small utility that allows selecting the image resolution, compression quality and resulting JPG file size, and shows a preview of the resulting image.
The slider for the image quality and the spinner for the JPG file size are "linked": When you change the quality, the resulting file size will be updated. When you change the file size, the quality will be adjusted so that the resulting image is not larger than the given file size (if possible).
The quality adjustment is done using some sort of a "binary search" (see the
computeQuality
method), because the predicting the file size depending on the compression is hard (or even impossible). Of course, this implies some computational cost, but there are not so many alternatives, I guess. (You could define another stopping criterion. At the moment, it tries hard to find the "perfect" quality for the given file size limit). Maybe one or another method from this utility may be helpful for you, anyhow.