Possible BufferedImage.getRGB optimization

Daniel Gredler djgredler at gmail.com
Fri Aug 22 12:03:38 UTC 2025


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);
    }
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/client-libs-dev/attachments/20250822/ed166d33/attachment.htm>


More information about the client-libs-dev mailing list