<div dir="ltr"><div>Hi all,</div><div><br></div><div>`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.</div><div><br></div><div>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.</div><div><br></div><div>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.</div><div><br></div><div>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.</div><div><br></div>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.<div><br></div><div>Thanks!</div><div><br></div><div>Daniel</div><div><br></div><div>---</div><div><br></div><div>[1]</div><div>BufferedImage.TYPE_CUSTOM: 2k<br>BufferedImage.TYPE_INT_RGB: 114k<br>BufferedImage.TYPE_INT_ARGB: 93k << 35%<br>BufferedImage.TYPE_INT_ARGB_PRE: 5k<br>BufferedImage.TYPE_INT_BGR: 4k<br>BufferedImage.TYPE_3BYTE_BGR: 10k<br>BufferedImage.TYPE_4BYTE_ABGR: 9k<br>BufferedImage.TYPE_4BYTE_ABGR_PRE: 2k<br>BufferedImage.TYPE_USHORT_565_RGB: 1k<br>BufferedImage.TYPE_USHORT_555_RGB: 1k<br>BufferedImage.TYPE_BYTE_GRAY: 11k<br>BufferedImage.TYPE_USHORT_GRAY: 2k<br>BufferedImage.TYPE_BYTE_BINARY: 5k<br>BufferedImage.TYPE_BYTE_INDEXED: 3k<br>Total: 262k</div><div><br></div><div>[2] <a href="https://github.com/gredler/jdk/commit/b98f6cdf7573b7e89067c757890193517aeb472e">https://github.com/gredler/jdk/commit/b98f6cdf7573b7e89067c757890193517aeb472e</a></div><div><br></div><div>[3]</div><div>public final class PerfTest {<br>    public static void main(final String[] args) {<br>        int w = 1_000;<br>        int h = 1_000;<br>        int accumulator = 0;<br>        BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);<br>        int[] row = new int[w];<br>        long start = System.currentTimeMillis();<br>        for (int i = 0; i < 100_000; i++) {<br>            for (int y = 0; y < h; y++) {<br>                image.getRGB(0, y, w, 1, row, 0, w);<br>                accumulator += row[i % w];<br>            }<br>        }<br>        long end = System.currentTimeMillis();<br>        System.out.println("Total time: " + ((end - start) / 1_000) + " seconds");<br>        System.out.println("Accumulator: " + accumulator);<br>    }<br>}</div><div><br></div></div>