jxlatte icon indicating copy to clipboard operation
jxlatte copied to clipboard

great stuff - how about turning it into a ImageIO CoDec?

Open elbosso opened this issue 2 years ago • 10 comments

The Reason for this would be that then any Java app loading an image resource could use JPEG XLs without changing its code - the only thing needed would be to put one more jar into the classpath...

I would be willing to participate in the effort as i wrote a few ImageIO codecs already - though not as complex ones as would be needed here...

One could maybe get inspiration for example from here: https://xmlgraphics.apache.org/batik/javadoc/org/apache/batik/ext/awt/image/codec/imageio/ImageIOJPEGImageWriter.html

elbosso avatar Jun 07 '23 15:06 elbosso

It's on the list of things to do.

Also the file you linked is a writer, not a reader.

Traneptora avatar Jun 07 '23 16:06 Traneptora

yep, I know. But maybe this could be a far away stretch goal. I assume, that one would also find a reader somewhere in there...

elbosso avatar Jun 07 '23 17:06 elbosso

ok - a crude example implementation is done as a prototype. I can use my branch to load JPEG XL using ImageIO - however, there remains the issue that the BufferedImages created by this library seem to be incompatible with ImageIO image saving routines (compare #22)

elbosso avatar Jun 08 '23 03:06 elbosso

Hi,

I'm considering implementing an ImageIO plugin (ImageReader only for now) based on this project. Either by forking, or using this project as a library dependency.

I see issue #22 refers to a method JXImage.asBufferedImage or toBufferedImage, however I don't find these in the current code base..? Was this method removed, or was it only available in a special branch?


Update: I found the code in @elbosso's branch, and was able to adapt it to the current main branch + convert the images to more compatible BufferedImage types. I'm not super-familiar with JPEG XL, so I might be missing why the library uses 32 bit float or integer components for what is normally 8-16 bits...?

haraldk avatar Oct 28 '24 11:10 haraldk

I removed all the BufferedImage and WritableRaster code because java.awt isn't available on android. Currently JXLImage produces an array of ImageBuffer which can be then turned into a BufferedImage by using a WritableRaster and a BandedSampleModel. ImageBuffer represents one channel and is backed by an int[][] or a float[][].

Traneptora avatar Oct 31 '24 09:10 Traneptora

@Traneptora Thanks! After looking some more at the code and testing with various sample images, I can only say, this is seriously impressive stuff! 🤩

I completely understand why you want to keep any AWT dependencies out of the project, keeping it like this makes things more flexible. 👍🏻

I've made an adapter class that can convert to BufferedImages in more "standard" types (8 or 16 bit/sample, pixel interleaved), depending on the bit count in the header. This should allow me to create an ImageIO plugin that creates images that can be easily displayed or converted to other formats.

I have loads of questions though, but I might open another issue for that. 😀

haraldk avatar Oct 31 '24 15:10 haraldk

It's recommended to not use ImageIO.write() to output PNG files because it notably doesn't write any color information to the PNG file (this is why I rolled my own primitive png writer). Also be aware that some JXL files are HDR and thus jxlatte decodes them to an HDR image. If you need images in a particular color space you may want to call JXLImage.transform first.

Traneptora avatar Oct 31 '24 15:10 Traneptora

Hi,

I'm considering implementing an ImageIO plugin (ImageReader only for now) based on this project. Either by forking, or using this project as a library dependency.

I see issue #22 refers to a method JXImage.asBufferedImage or toBufferedImage, however I don't find these in the current code base..? Was this method removed, or was it only available in a special branch?

Update: I found the code in @elbosso's branch, and was able to adapt it to the current main branch + convert the images to more compatible BufferedImage types. I'm not super-familiar with JPEG XL, so I might be missing why the library uses 32 bit float or integer components for what is normally 8-16 bits...?

I am glad I could be of some (little) help and looking forward to the final result!

elbosso avatar Nov 01 '24 08:11 elbosso

It's recommended to not use ImageIO.write() to output PNG files because it notably doesn't write any color information to the PNG file (this is why I rolled my own primitive png writer).

I'm not sure if I understand what you mean? Do you mean that it would not write PNG files from the toBufferedImage method in the old branch? In that case, I have fixed this issue. Or do you mean it does not correctly preserve color information, like ICC profiles or HDR?

If you need images in a particular color space you may want to call JXLImage.transform first.

Excellent, that is actually what I needed! I had some issue with the images coming out way too "warn". Now, after doing the same transform as you do in your PNGWriter the images look just the same (I haven't compared pixel values directly, but they look equal).

samples/bbb.jxl transcoded to PNG using JXLatte PNGWriter:

bbb

samples/bbb.jxl transcoded to PNG using my preliminary code and ImageIO.write (ie. the built in PNGImageWriter):

bbb jxl_tm

PS: Is there any way to access the header information of the file, without having to read the entire file? I will need this for an efficient ImageIO plugin (ie. width, height, number of channels, ICC profile if any and other meta data). If not I will try to create a PR with such a method... 😀

haraldk avatar Nov 01 '24 19:11 haraldk

Currently there is not. It is something I could do, but I haven't added it yet.

Traneptora avatar Nov 01 '24 20:11 Traneptora