On Tue, 13 Oct 2026 17:57:35 GMT, Phil Race <[email protected]> wrote:
>>> JPEGQTable.getScaledInstance(scale, false) mentioned above is specified to >>> return a table "clamped to the range 1..32767" >>> ([JPEGQTable.java#L179](https://github.com/openjdk/jdk/blob/f2fd22f7a23505bef47227a97a51bc9e1837111e/src/java.desktop/share/classes/javax/imageio/plugins/jpeg/JPEGQTable.java#L179)), >>> and such a table can be passed to the writer (metadata `dqtable` node, >>> `JPEGImageWriteParam.setEncodeTables`) and to the reader >>> (`JPEGImageReadParam.setDecodeTables`). Before this patch the libjpeg seems >>> writes a 16bit data, and the result decodes. After the patch every entry >>> above 255 is silently clamped to 255, on the write and decode since the >>> code path is shared. >>> >>> So I do not think this is accurate: >>> >>> > ImageIO's native JPEG library is compiled to support baseline JPEG only. >>> > This means 8 bit quantization values in the range 1 -> 255. >> >> The comment is accurate. It should be in the range 1->255 for 8 bit JPEG. >> If someone created a JPEG plugin that supported non-baseline JPEG, ie 12 bit >> samples, then their implementation would have to allow 1->65535 but our >> implementation does not and should not. It is baseline 8 bit only. >> So it is appropriate for the public API to allow 16-bit (to allow for that >> other theoretical plugin) but the plugin implementation in each case will do >> what is appropriate for what it supports. Which is why this check is in the >> implementation. >> >> And the JPEG standard says >> B.2.4.1 Quantization table-specification syntax >> .. >> Pq: Quantization table element precision – Specifies the precision of the Qk >> values. Value 0 indicates 8-bit Qk >> values; value 1 indicates 16-bit Qk values. Pq shall be zero for 8 bit >> sample precision P (see B.2.2). >> >> So allowing 16 bit quantization for an 8 bit JPEG contravenes the spec. > >> From above observation it looks like 8-bit quantization was not strictly >> enforced. With updated code we are changing the way quantization works. > > Yes. It is now fixed. > > So I do not think this is accurate: > > > ImageIO's native JPEG library is compiled to support baseline JPEG only. > > > This means 8 bit quantization values in the range 1 -> 255. > > The comment is accurate. It should be in the range 1->255 for 8 bit JPEG. Not sure. The spec part mentioned above is correct: for 8 bit samples the table entries should be 8 bit. But "ImageIO's native JPEG library is compiled to support baseline JPEG only" is not correct. Our libjpeg is compiled for 8 bit samples, not for "baseline only": it writes and reads 16 bit tables for 8 bit images as a libjpeg extension (libjpeg-turbo does the same). The code I posted above proves it. >If someone created a JPEG plugin that supported non-baseline JPEG, ie 12 bit >samples, then their implementation would have to allow 1->65535 but our >implementation does not and should not Our plugin is already non-baseline without 12 bit samples. And if "--with-libjpeg=system" is used the capabilities are set by the system libjpeg. So this is a behavior change: we drop the libjpeg extension and follow the spec only. It changes the output for any table with an entry above 255, including the tables that getScaledInstance(scale, false) is specified to return (1..32767). This might need a CSR. Another issue: the patch clamps only the table passed by the application. The table already stored in the image file is read by libjpeg itself and is not clamped, and to clamp it the library must be changed, which we cannot do when the system libjpeg is used. So the decoder is inconsistent: the same big table is used as is when it comes from the file, and changed when it comes from setDecodeTables, so the same image decodes to different pixels. Maybe we should clamp on write only and skip it on read? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/33217#discussion_r4265270928
