On Mon, 7 Oct 2024 15:13:17 GMT, Michael Strauß <mstra...@openjdk.org> wrote:

> This PR is an improved version of #1093.
> 
> JavaFX can load BMP, GIF, PNG, and JPEG images with its built-in image 
> loaders. It has been a long-standing request to support more image formats, 
> most notably (but not limited to) SVG. However, adding more built-in image 
> loaders is a significant effort not only in creating the functionality, but 
> also in maintaining the additional dependencies.
> 
> This will probably not happen any time soon, so we are left with three 
> alternatives:
> 1. Accept the fact that JavaFX will never be able to load additional image 
> formats.
> 2. Create a public image loader API, and hope that developers in the JavaFX 
> ecosystem will create image loader plugins.
> 3. Leverage the existing Java Image I/O API.
> 
> From these options, I think we should simply support existing Java APIs; both 
> because it is the shortest and most realistic path forward, but also because 
> I don't think it is sensible to bifurcate pluggable image loading in the Java 
> ecosystem.
> 
> Of course, Java Image I/O is a part of the `java.desktop` module, which as of 
> now, all JavaFX applications require. However, it has been noted in the 
> previous PR that we shouldn't lock JavaFX into the `java.desktop` dependency 
> even further.
> 
> I've improved this PR to not permanently require the `java.desktop` 
> dependency: if the module is present, then JavaFX will use Image I/O for 
> image formats that it can't load with the built-in loaders; if the module is 
> not present, only the built-in loaders are available.
> 
> I have prepared a small sample application that showcases how the feature can 
> be used to load SVG images in a JavaFX application: 
> https://github.com/mstr2/jfx-imageio-sample

I left some comments.

modules/javafx.graphics/src/main/java/com/sun/javafx/iio/ImageStorage.java line 
201:

> 199:             return null;
> 200:         }
> 201:     }

Can we document why this is done?  If I had to guess: loading 
`XImageLoaderFactory`, even though it is present in this module, may fail 
loading dependent classes (`ImageIO`).

modules/javafx.graphics/src/main/java/com/sun/javafx/iio/javax/XImageLoader.java
 line 203:

> 201:                     case TYPE_BYTE_INDEXED -> "TYPE_BYTE_INDEXED";
> 202:                     default -> Integer.toString(image.getType());
> 203:                 });

Hm, since we can't select which format an image reader will output, lacking 
conversions for these can mean that a lot of AWT supported image formats still 
can't be loaded in FX.  For some formats that can have multiple representations 
that can mean some images load while others won't.  For example, if GIF wasn't 
natively supported, then it wouldn't work via ImageIO either (since it is 
TYPE_BYTE_INDEXED afaik).

I also wonder what SVG will generally output (`TYPE_BYTE_GRAY`?)

modules/javafx.graphics/src/main/java/com/sun/javafx/iio/javax/XImageLoader.java
 line 217:

> 215:         }
> 216: 
> 217:         return ByteBuffer.wrap(Arrays.copyOf(data, size - offset));

This doesn't look correct.  If `offset` isn't zero, then dropping the last few 
bytes seems incorrect.  It should start the copy from `offset`?

I would think this should be: `ByteBuffer.wrap(data, offset, size - offset)` 
(avoids copy but may waste some space).

Or if you still want to make a copy, then `Arrays.copyOfRange(data, offset, 
size)`.

Note: I have the impression that calling `getData` means the bank won't be 
modified anymore, so there may not be a need to copy it.

modules/javafx.graphics/src/main/java/com/sun/javafx/iio/javax/XImageLoader.java
 line 230:

> 228:         }
> 229: 
> 230:         return IntBuffer.wrap(Arrays.copyOf(data, size - offset));

See other comment.

modules/javafx.graphics/src/main/java/com/sun/javafx/image/PixelUtils.java line 
215:

> 213:         getB2BConverter(PixelGetter<ByteBuffer> src, 
> PixelSetter<ByteBuffer> dst)
> 214:     {
> 215:         if (src ==        ByteRgba.getter) {

minor: I'd be in favor of fixing this formatting.  I know it means well, but it 
really isn't improving readability.  Perhaps it is more of a job for a `switch` 
or `Map` lookup.

modules/javafx.graphics/src/main/java/com/sun/javafx/image/impl/BaseByteToByteConverter.java
 line 296:

> 294:         {
> 295:             srcscanbytes -= w * 3;
> 296:             srcscanbytes -= w * 4;

This really doesn't look right.  Should it not be `dstscanbytes` on the 2nd 
line, and also multiplied by `3` instead of `4`?

It looks like this was incorrect in the original?

modules/javafx.graphics/src/main/java/com/sun/javafx/image/impl/BaseByteToByteConverter.java
 line 318:

> 316:         {
> 317:             srcscanbytes -= w * 3;
> 318:             srcscanbytes -= w * 4;

Same comment.

modules/javafx.graphics/src/main/java/com/sun/javafx/image/impl/IntBgr.java 
line 43:

> 41:     public static final IntPixelAccessor accessor = Accessor.instance;
> 42: 
> 43:     public static IntToIntPixelConverter ToIntArgbPreConverter() {

This method is not following Java naming conventions:

Suggestion:

    public static IntToIntPixelConverter toIntArgbPreConverter() {

modules/javafx.graphics/src/main/java/com/sun/javafx/image/impl/IntBgr.java 
line 68:

> 66:             int b = (pixel >> 16) & 0xff;
> 67:             return (255 << 24) | (r << 16) | (g << 8) | b;
> 68:         }

Not sure if we optimizing here, but could eliminate two shifts like this:

Suggestion:

        public int getArgb(int[] arr, int offset) {
            int pixel = arr[offset];
            int r = pixel & 0xff;
            int g = pixel & 0xff00;
            int b = pixel & 0xff0000;
            return (255 << 24) | (r << 16) | g | (b >> 16);
        }

modules/javafx.graphics/src/main/java/com/sun/javafx/image/impl/IntBgr.java 
line 72:

> 70:         @Override
> 71:         public int getArgbPre(int[] arr, int offset) {
> 72:             return PixelUtils.NonPretoPre(getArgb(arr, offset));

It seems `PixelUtils` contains methods not following Java naming conventions.  
This should be `nonPreToPre` IMHO (and others as well).

modules/javafx.graphics/src/main/java/com/sun/javafx/image/impl/IntRgb.java 
line 43:

> 41:     public static final IntPixelAccessor accessor = Accessor.instance;
> 42: 
> 43:     public static IntToIntPixelConverter ToIntArgbPreConverter() {

This method is not following Java naming conventions:

Suggestion:

    public static IntToIntPixelConverter toIntArgbPreConverter() {

modules/javafx.graphics/src/main/java/com/sun/javafx/image/impl/IntRgb.java 
line 63:

> 61:         @Override
> 62:         public int getArgb(int[] arr, int offset) {
> 63:             return arr[offset] | (0xff << 24);

Second variant I seen of `255 << 24` now; perhaps this may be better to make 
into a constant for clarity?  Or if we're going for short `-1 << 24`? :)

Suggestion:

    private static final int OPAQUE = 0xff000000;

modules/javafx.graphics/src/main/java/com/sun/prism/Image.java line 225:

> 223:         // GRAY, RGB, BGRA_PRE, and INT_ARGB_PRE are directly supported 
> by Prism.
> 224:         // We'll need to convert all other formats that we might 
> encounter to one of the supported formats.
> 225:         // TODO: 3D - need a way to handle pre versus non-Pre

Is this TODO still relevant?

modules/javafx.graphics/src/main/java/javafx/scene/image/Image.java line 75:

> 73:  * <li><a href="http://www.libpng.org/pub/png/spec/";>PNG</a></li>
> 74:  * </ul>
> 75:  * For all other formats, JavaFX uses the {@link javax.imageio Java Image 
> I/O API} on supported platforms.

This doesn't look like a valid javadoc link; in Eclipse at least it doesn't do 
anything.  Perhaps:

Suggestion:

 * For all other formats, JavaFX uses the {@link javax.imageio.ImageIO Java 
Image I/O API} on supported platforms.

-------------

PR Review: https://git.openjdk.org/jfx/pull/1593#pullrequestreview-2370443197
PR Review Comment: https://git.openjdk.org/jfx/pull/1593#discussion_r1802046200
PR Review Comment: https://git.openjdk.org/jfx/pull/1593#discussion_r1802069617
PR Review Comment: https://git.openjdk.org/jfx/pull/1593#discussion_r1802078956
PR Review Comment: https://git.openjdk.org/jfx/pull/1593#discussion_r1802079276
PR Review Comment: https://git.openjdk.org/jfx/pull/1593#discussion_r1802083595
PR Review Comment: https://git.openjdk.org/jfx/pull/1593#discussion_r1802087453
PR Review Comment: https://git.openjdk.org/jfx/pull/1593#discussion_r1802087587
PR Review Comment: https://git.openjdk.org/jfx/pull/1593#discussion_r1802104560
PR Review Comment: https://git.openjdk.org/jfx/pull/1593#discussion_r1802100014
PR Review Comment: https://git.openjdk.org/jfx/pull/1593#discussion_r1802103877
PR Review Comment: https://git.openjdk.org/jfx/pull/1593#discussion_r1802103126
PR Review Comment: https://git.openjdk.org/jfx/pull/1593#discussion_r1802102566
PR Review Comment: https://git.openjdk.org/jfx/pull/1593#discussion_r1802110851
PR Review Comment: https://git.openjdk.org/jfx/pull/1593#discussion_r1801838924

Reply via email to