<div dir="ltr"><div>Hi Jeremy, Laurent,</div><div><br></div><div>Thanks for having a look. What sorts of changes are you thinking of when you propose a separate project?</div><div><br></div><div>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.</div><div><br></div><div>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.</div><div><br></div><div>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?</div><div><br></div><div>Take care,</div><div><br></div><div>Daniel</div><div><br></div></div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Sat, Aug 30, 2025 at 11:47 AM Laurent Bourgès <<a href="mailto:bourges.laurent@pm.me">bourges.laurent@pm.me</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><p dir="ltr">Hi guys,</p>
<p dir="ltr">I do love optimizing java2d, so Ido support & sponsor your buffered image (ARGB PRE or not) changes.</p>
<p dir="ltr">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.</p>
<p dir="ltr">See jdk (25?) branch:<br>
<a href="https://github.com/bourgesl/marlin-renderer/tree/jdk/src/main/java/sun/java2d" target="_blank">https://github.com/bourgesl/marlin-renderer/tree/jdk/src/main/java/sun/java2d</a></p>
<p dir="ltr">Cheers,<br>
Laurent</p>
<div>
 <br>
 <br>
 -------- Message d'origine --------
 <br>
 Le 22/08/2025 14:04, Daniel Gredler <u></u>
  a écrit :
  <br>
  <blockquote>
   <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" target="_blank">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>
  </blockquote>
 <u></u>
</div></blockquote></div>