Hi
If you have an application that processes or creates (using java.awt.Robot) a large number of images (i.e. BufferedImages), the most normal way is to cache them in memory. The question is, how to cache them in the most optimal form?
-
as they are. Namely, directly as BufferedImages?
-
in JPG (or JPEG) format as byte arrays?
-
in PNG format as byte arrays?
Let’s analyze the formats. BufferedImage is a 2-dimensional array of 4 or 3 bytes (ARGB or RGB), JPG is the compression technology of the Joint Photographic Experts Group and PGN is the compression technology of UNISYS. The following codes show you the differences in bytes for the same image Platypus.jpg converted to BufferedImage and PNG format.
import java.io.*;
import java.nio.file.Files;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
// Joe T. Schwarz
public class Test {
public static void main(String... a) throws Exception {
if (a.length < 1) {
System.out.println("Test imagefile");
System.exit(0);
}
byte[] ball = Files.readAllBytes((new File(a[0])).toPath());
//
System.out.print("Content in byte["+ball.length+"] of "+a[0]);
//BufferedImage bimg = ImageIO.read(new FileInputStream(a[0]));
BufferedImage bimg = ImageIO.read(new ByteArrayInputStream(ball));
int w = bimg.getWidth(), h = bimg.getHeight();
int rgb[] = bimg.getRGB(0, 0, w, h, null, 0, w);
//
ByteArrayOutputStream bao = new ByteArrayOutputStream(0x200000);
ImageIO.write(bimg, "JPG", bao);
bao.flush();
bao.close();
byte[] jpg = bao.toByteArray();
bao.reset();
ImageIO.write(bimg, "PNG", bao);
bao.flush();
bao.close();
byte[] pngBuf = bao.toByteArray();
//----------------------------------
System.out.println(" with Width:"+w+"<>Heigh:"+h);
System.out.println("RGB["+rgb.length+"] or in byte["+(rgb.length * 4)+"]");
System.out.println("JPG_buf["+jpg.length+"]<>pngBuf["+pngBuf.length+"]");
}
}
The output of the Platypus.jpg
java Test platypus.jpg
Content in byte[73683] of platypus.jpg with Width:971<>Heigh:605
RGB[587455] or in byte[2349820]
JPG_buf[73650]<>pngBuf[776006]
If you use an ArrayList to cache the images in their original format as BufferedImages, you will need 2349820 bytes for a Platypus. For the same Platypus, you will need only 73650 bytes in JPG and 776006 bytes in PNG. PNG is larger than JPG, but the difference in quality is so small that you will not notice the difference between JPG and PNG.
The disadvantage of JPG or PNG is that you have to work with the images before you can cache them in ArrayList. But computers are so powerful these days that such a calculation is so fast that there is no noticeable performance problem. An example:
public class BufferedList {
private List<byte[]> list = new ArrayList<>();
// add
public void add(BufferedImage bImg) {
try {
ByteArrayOutputStream bao = new
ByteArrayOutputStream(0x200000);
ImageIO.write(bImg, "JPG", bao);
bao.flush();
bao.close();
list.add(bao.toByteArray());
} catch (Exception ex) {
ex.printStackTrace();
}
}
// get
public BufferedImage get(int idx) {
try {
return ImageIO.read(new ByteArrayInputStream(list.get(idx)));
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
...
}