<html><head><style id="css_styles" type="text/css"><!--blockquote.cite { margin-left: 5px; margin-right: 0px; padding-left: 10px; padding-right:0px; border-left: 1px solid #cccccc }
blockquote.cite2 {margin-left: 5px; margin-right: 0px; padding-left: 10px; padding-right:0px; border-left: 1px solid #cccccc; margin-top: 3px; padding-top: 0px; }
a img { border: 0px; }
li[style='text-align: center;'], li[style='text-align: center; '], li[style='text-align: right;'], li[style='text-align: right; '] {  list-style-position: inside;}
body { font-family: Helvetica; font-size: 9pt; }
.quote { margin-left: 1em; margin-right: 1em; border-left: 5px #ebebeb solid; padding-left: 0.3em; }
a.em-mention[href] { text-decoration: none; color: inherit; border-radius: 3px; padding-left: 2px; padding-right: 2px; background-color: #e2e2e2; }
._em_placeholder {color: gray; border-bottom: 1px dotted lightblue;} ._em_placeholder:before{color:gray; content: '{{ ';} ._em_placeholder:after{color:gray; content: ' }}';}
--></style></head><body style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;"><div>Daniel,</div><div><br /></div><div>I agree BufferedImage.getRGB can be much too slow, and it looks like you already found the work-around I’ve been using for years:</div><div>image.getRaster().getDataElements(..)</div><div><br /></div><div>But I’m not a reviewer for the client-libs project so I don’t think I can’t speak to your bigger question:</div><div><br /></div><div>> <span>Does this look like a good change to those of you who know this part of the code?</span></div><div><span><br /></span></div><div>Until one (or more) veteran reviewers respond, <span>I’d turn this topic around and ask a different question:</span></div><div><br /></div><div>Do you think there’d be an appetite for a separate GitHub project that enhanced the BufferedImage? Over time if it gained traction that might make applying some of its enhancements to BufferedImage.java more persuasive to this group.</div><div><br /></div><div>Regards,</div><div> - Jeremy</div><div><br /></div>
<div>
<div>------ Original Message ------</div>
<div>From "Daniel Gredler" <<a href="mailto:djgredler@gmail.com">djgredler@gmail.com</a>></div>
<div>To <a href="mailto:client-libs-dev@openjdk.org">client-libs-dev@openjdk.org</a></div>
<div>Date 8/22/2025 8:03:38 AM</div>
<div>Subject Possible BufferedImage.getRGB optimization</div></div><div x-em-quote=""><br /></div>
<div id="x8b63710e453641c"><blockquote cite="CAPA+ug6j4MicbR-c8xQxwb_r3P5VVPa1ZPCdE=u8BQLYEDeyFQ@mail.gmail.com" type="cite" class="cite2">
<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" class="__cef_visited">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></div>
</body></html>