Hi all, `BufferedImage.getRGB(int, int, int, int, int[], int, int)` is often used for processing of individual image pixels. A common pattern is to loop through each row of pixels, calling this method once per row to populate the row pixel `int[]` and then process it.
There are many types of `BufferedImage`, but one of the most common types is `TYPE_INT_ARGB`. Based on a quick search on GitHub, about one third of all BufferedImages are of this type [1]. This is also the representation which `BufferedImage.getRGB(int, int, int, int, int[], int, int)` uses for its output. I think there may be an opportunity here (in `BufferedImage.getRGB(int, int, int, int, int[], int, int)`) to skip the pixel-by-pixel color model conversion if the `BufferedImage` is already of type `TYPE_INT_ARGB`, which is relatively common. See here [2] for what this optimization could look like. In my local testing, a simple test program [3] went from running in 220 seconds without the change to running in 7 seconds with the change. Separately, a real-world program which uses the row-by-row pixel access pattern went from running in 45 seconds to running in 29 seconds. Does this look like a good change to those of you who know this part of the code? Am I missing something that might make this dangerous or undesirable? Is it making too many assumptions? I know this area is fraught with gotchas -- color models, color spaces, strides, etc. Thanks! Daniel --- [1] BufferedImage.TYPE_CUSTOM: 2k BufferedImage.TYPE_INT_RGB: 114k BufferedImage.TYPE_INT_ARGB: 93k << 35% BufferedImage.TYPE_INT_ARGB_PRE: 5k BufferedImage.TYPE_INT_BGR: 4k BufferedImage.TYPE_3BYTE_BGR: 10k BufferedImage.TYPE_4BYTE_ABGR: 9k BufferedImage.TYPE_4BYTE_ABGR_PRE: 2k BufferedImage.TYPE_USHORT_565_RGB: 1k BufferedImage.TYPE_USHORT_555_RGB: 1k BufferedImage.TYPE_BYTE_GRAY: 11k BufferedImage.TYPE_USHORT_GRAY: 2k BufferedImage.TYPE_BYTE_BINARY: 5k BufferedImage.TYPE_BYTE_INDEXED: 3k Total: 262k [2] https://github.com/gredler/jdk/commit/b98f6cdf7573b7e89067c757890193517aeb472e [3] public final class PerfTest { public static void main(final String[] args) { int w = 1_000; int h = 1_000; int accumulator = 0; BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); int[] row = new int[w]; long start = System.currentTimeMillis(); for (int i = 0; i < 100_000; i++) { for (int y = 0; y < h; y++) { image.getRGB(0, y, w, 1, row, 0, w); accumulator += row[i % w]; } } long end = System.currentTimeMillis(); System.out.println("Total time: " + ((end - start) / 1_000) + " seconds"); System.out.println("Accumulator: " + accumulator); } }