Possible BufferedImage.getRGB optimization

Philip Race philip.race at oracle.com
Thu Sep 4 21:54:06 UTC 2025


It doesn't seem like a change that needs a project.
I would make sure that call to colorModel.getRGB(..) isn't needed and I 
think that you aren't doing that.
Basically it needs to be sRGB already (as that is the target color space).

-phil.

On 9/4/25 1:37 PM, Daniel Gredler wrote:
> Hi Jeremy, Laurent,
>
> Thanks for having a look. What sorts of changes are you thinking of 
> when you propose a separate project?
>
> For myself, I don't really have a bigger-picture vision of systematic 
> changes that I'd like to make. Similar to JDK-8337681, JDK-8344668 and 
> JDK-8356814, this suggestion is just an ad hoc optimization 
> opportunity that came up based on spending some time with a profiler.
>
> My takeaway right now is that this specific suggestion doesn't look 
> obviously stupid to anyone, and is worth triple checking on my end. If 
> my local sanity checks all come back green, I would create a small 
> issue in JBS and submit a PR, and then let the review process carry on 
> as usual. It can take a little time, but it seems to me that useful 
> optimizations, submitted individually, can be incorporated without too 
> many issues.
>
> Which takes me back to my original question -- what type of change(s) 
> are you thinking about, where proving things out in a separate project 
> is necessary?
>
> Take care,
>
> Daniel
>
>
> On Sat, Aug 30, 2025 at 11:47 AM Laurent Bourgès 
> <bourges.laurent at pm.me> wrote:
>
>     Hi guys,
>
>     I do love optimizing java2d, so Ido support & sponsor your
>     buffered image (ARGB PRE or not) changes.
>
>     Let's start a github project to start this concrete patch... as I
>     did for the marlin renderer or we could use the marlin repository
>     to host your changes to java.awt or java2d packages.
>
>     See jdk (25?) branch:
>     https://github.com/bourgesl/marlin-renderer/tree/jdk/src/main/java/sun/java2d
>
>     Cheers,
>     Laurent
>
>
>
>     -------- Message d'origine --------
>     Le 22/08/2025 14:04, Daniel Gredler a écrit :
>
>         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/20250904/531a7b54/attachment.htm>


More information about the client-libs-dev mailing list