> If an image has RGBA encoding and all pixels are opaque, then
> `SwingFXUtils.fromFXImage(image, null)` selects TYPE_INT_ARGB_PRE pixel
> format but the JPEG ImageIO writer cannot encode this alpha-bearing image
> pixel format since it has no support for it and returns false; so an empty
> byte array is created.
>
> Issue is when `bimg` (used to store the returned pixel data from
> `fromFXImage`) is null`, fromFXImage` uses the JavaFX PixelReader’s storage
> format, not the alpha values of individual pixels.
> For an RGBA PNG, JavaFX commonly decodes the pixels into premultiplied
> ARGB/BGRA, so `fxFormat.getType()` is one of INT_ARGB_PRE/BYTE_BGRA_PRE so
> `getBestBufferedImageType` returns `BufferedImage.TYPE_INT_ARGB_PRE` because
> the pixel format has an alpha component. It does not inspect whether every
> alpha value happens to be 255.
>
> The existing `fromFXImage` code only calls `checkFXImageOpaque()` when the
> caller supplies a non-null `bImg` BufferedImage.
> If `bImg `is null, all-opaque RGBA PNG produces an alpha-capable
> BufferedImage i.e., BufferedImage.TYPE_INT_ARGB_PRE
>
> if (bimg == null) {
> bimg = new BufferedImage(iw, ih, prefBimgType);
> }
>
> and since JPEG has no standard alpha channel so it cannot store transparency,
> so when `ImageIO.write(image, "jpg", out)` runs, ImageIO looks for a
> registered JPEG writer which can encode that pre-multiplied-alpha image type,
> but the JPEG writer rejects an alpha-bearing BufferedImage, so
> `ImageIO.write` finds no suitable writer and returns false
> so OutputStream is not written into and have 0 bytes
> [Basically the JPEG writer does not check whether the alpha values are all
> 255; it only sees that the input image has an alpha channel and declines to
> write it]
>
> The proposed JavaFX change avoids the rejection for an RGBA-formatted but
> fully opaque image by returning TYPE_INT_RGB, which JPEG can encode.
> ie., for a JavaFX image with an alpha-capable format but only opaque pixels,
> `fromFXImage(image, null)` is made to choose RGB format rather than ARGB.
> Additionally, checkFXImageOpaque is improved to scan one row at a time
> instead of costly full-image scan so that unnecessary Color object for each
> pixels is not created just to inspect alpha.
>
> A regression subtest is added to existing testcase
>
> ---------
> - [x] I confirm that I make this contribution in accordance with the [OpenJDK
> Interim AI Policy](https://openjdk.org/legal/ai).
Prasanta Sadhukhan has updated the pull request incrementally with one
additional commit since the last revision:
Review comment
-------------
Changes:
- all: https://git.openjdk.org/jfx/pull/2254/files
- new: https://git.openjdk.org/jfx/pull/2254/files/60f36ab3..e8020798
Webrevs:
- full: https://webrevs.openjdk.org/?repo=jfx&pr=2254&range=01
- incr: https://webrevs.openjdk.org/?repo=jfx&pr=2254&range=00-01
Stats: 9 lines in 1 file changed: 4 ins; 4 del; 1 mod
Patch: https://git.openjdk.org/jfx/pull/2254.diff
Fetch: git fetch https://git.openjdk.org/jfx.git pull/2254/head:pull/2254
PR: https://git.openjdk.org/jfx/pull/2254