Skip to content

Add JPEG-XL support#2181

Merged
jcupitt merged 21 commits intomasterfrom
add-jxl
Apr 25, 2021
Merged

Add JPEG-XL support#2181
jcupitt merged 21 commits intomasterfrom
add-jxl

Conversation

@jcupitt
Copy link
Copy Markdown
Member

@jcupitt jcupitt commented Apr 3, 2021

It seems to work, but there are a few caveats:

  • libjxl cannot write in chunks or tiles, you have to write the whole image in one go
  • libjxl seems not to support metadata such as a preview image, EXIF, XMP, etc.
  • I can't see the API to attach an ICC profile
  • libjxl is missing error messages

TODO:

  • add a "shrink" option to read out 8x shrunk DC image?
  • add animation support
  • sort out gamma for scRGB load and save

@jcupitt jcupitt marked this pull request as draft April 3, 2021 17:45
@fredprodibi
Copy link
Copy Markdown

Wow this looks amazing how can I use it? I m using libvips with .NET 5

exiftool managed to read and write exifs
https://exiftool.org/history.html

cjxl copies the input profile to the output profile by default and their is an option
-x key=value, --dec-hints=key=value
icc_pathname refers to a binary file containing an ICC profile.
so I guess an option like -x icc_pathname=myicc.icc would do it

the encoder options definetly does something I m using cjxl -d 0.5 input.png output.jxl to get higher fidelity and the result in file size and visual quality is different from the defaut -d 1

I haven't tried libjxl only cjxl

@jcupitt
Copy link
Copy Markdown
Member Author

jcupitt commented Apr 13, 2021

Hi @fredprodibi,

You'd need to build from source, it's a bit tricky unless you've done a lot of C/C++ dev, but take a look at the win build repo if you feel brave:

https://github.com/libvips/build-win64-mxe

Yes, I think I've must have made an error hooking up the encode options. It needs more work.

@fredprodibi
Copy link
Copy Markdown

@jcupitt thank you! I would actually need it for macos and linux, to you know when the .NET nuget package will have those changes?

I have posted your questions to the jpg xl issues board and Lode Vandevenne responded
https://gitlab.com/wg1/jpeg-xl/-/issues/208

@jcupitt
Copy link
Copy Markdown
Member Author

jcupitt commented Apr 13, 2021

I doubt if it'll be in the nuget package for a while, this is still very early.

Thanks for posting my questions there, I responded to Lode.

@jcupitt jcupitt marked this pull request as ready for review April 16, 2021 14:07
@jcupitt
Copy link
Copy Markdown
Member Author

jcupitt commented Apr 16, 2021

Thi still has some missing features, but I think it's good enough to merge, as long as we say it's an experimental addition.

Let's sort out the scRGB issues in master, and leave metadata and shrink-on-load until libjxl adds support. Animation support can wait.

@fredprodibi
Copy link
Copy Markdown

@jcupitt amazing work, when you say good enough to merge, does it means it will make it's way to the nuget package?

I just updated my project to use NetVips 2.0.0 with Netips.Native.linux-x64 8.10.6

@jcupitt
Copy link
Copy Markdown
Member Author

jcupitt commented Apr 17, 2021

Oh not for several months, at least, and it would be up to the nuget package maintainer, not me.

@fredprodibi
Copy link
Copy Markdown

I see! thank you!

@cmahnke
Copy link
Copy Markdown

cmahnke commented Apr 17, 2021

Congratulations from me as well, I'll play around with it the next few days, the first issue I've found (maybe it's related to my lack of knowledge):

Using copy the options are picked up:

bash-5.1# vips copy front.tif front.jxl[lossless=true,effort=8]
JxlBasicInfo:
    have_container = 0
    xsize = 4946
    ysize = 6933
    bits_per_sample = 8
    exponent_bits_per_sample = 0
    intensity_target = 0
    min_nits = 0
    relative_to_max_display = 0
    linear_below = 0
    uses_original_profile = 0
    have_preview = 0
    have_animation = 0
    orientation = 0
    num_color_channels = 3
    num_extra_channels = 0
    alpha_bits = 0
    alpha_exponent_bits = 0
    alpha_premultiplied = 0
    preview.xsize = 0
    preview.ysize = 0
    animation.tps_numerator = 0
    animation.tps_denominator = 0
    animation.num_loops = 0
    animation.have_timecodes = 0
JxlPixelFormat:
    data_type = JXL_TYPE_UINT8
    num_channels = 3
    endianness = 0
    align = 0
JxlEncoderOptions:
    tier = 0
    distance = 2.35
    effort = 8
    lossless = 1

While calling jxlsave doesn't

bash-5.1# vips jxlsave front.tif front.jxl[lossless=true,effort=8]
JxlBasicInfo:
    have_container = 0
    xsize = 4946
    ysize = 6933
    bits_per_sample = 8
    exponent_bits_per_sample = 0
    intensity_target = 0
    min_nits = 0
    relative_to_max_display = 0
    linear_below = 0
    uses_original_profile = 0
    have_preview = 0
    have_animation = 0
    orientation = 0
    num_color_channels = 3
    num_extra_channels = 0
    alpha_bits = 0
    alpha_exponent_bits = 0
    alpha_premultiplied = 0
    preview.xsize = 0
    preview.ysize = 0
    animation.tps_numerator = 0
    animation.tps_denominator = 0
    animation.num_loops = 0
    animation.have_timecodes = 0
JxlPixelFormat:
    data_type = JXL_TYPE_UINT8
    num_channels = 3
    endianness = 0
    align = 0
JxlEncoderOptions:
    tier = 0
    distance = 2.35
    effort = 7
    lossless = 0

Is this intended?

@jcupitt
Copy link
Copy Markdown
Member Author

jcupitt commented Apr 17, 2021

Yes, that's expected. If you call a save/load operation directly, you pass args as --Q etc. Try:

vips jxlsave front.tif front.jxl --lossless --effort 8

Copy link
Copy Markdown
Member

@lovell lovell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, but as you say libjxl does feel a bit experimental (especially the encoder) in its current state. I've left a few very minor comments inline.

@jcupitt
Copy link
Copy Markdown
Member Author

jcupitt commented Apr 18, 2021

OK, all comments addressed, thank you very much!

@jcupitt
Copy link
Copy Markdown
Member Author

jcupitt commented Apr 18, 2021

I added a note to the docs saying this is an experimental feature.

@cmahnke
Copy link
Copy Markdown

cmahnke commented Apr 18, 2021

@jcupitt: Thanks for your help, actually I like this options format even more. Anyways, where do you want us to collect issues (if at all)?

This is certainly a missing sanity check:

bash-5.1# vips jxlsave front.tif front.jxl --distance 0
jxlsave: JxlEncoderProcessOutput

bash-5.1# ls -al front.jxl 
-rw-r--r--    1 root     root             0 Apr 18 17:30 front.jxl

@jcupitt
Copy link
Copy Markdown
Member Author

jcupitt commented Apr 18, 2021

Hi @cmahnke, until we merge, please post anything you notice to this PR.

Yes, I saw distance == 0 caused a segv too. It looked like a libjxl issue to me, so I didn't try to work around it.

@cmahnke
Copy link
Copy Markdown

cmahnke commented Apr 18, 2021

Might be the API, cjxl can handle it and falls back to lossless mode:

bash-5.1# cjxl front.png front-d0.jxl -d 0
  J P E G   \/ |
            /\ |_   e n c o d e r    [v0.3.7 | SIMD supported: AVX2,SSE4,Scalar]

Read 4946x6933 image, 16.8 MP/s
Encoding [Modular, lossless, squirrel], 1 threads.
Compressed to 46740650 bytes (10.905 bpp).
4946 x 6933, 0.12 MP/s [0.12, 0.12], 1 reps, 1 threads.

Using the same image, but trying effort 8 also gets vips killed (this doesn't seem to be a vips issue) - I've asked at discord if the JPEG XL devs look here otherwise I'll create reports at GitLab...

But actually I'm looking into this to improve my IIIF tool chain - dzsave works with jxl files as input.

@jcupitt
Copy link
Copy Markdown
Member Author

jcupitt commented Apr 18, 2021

cjxl has an if to flip to lossless mode if distance == 0, perhaps we should do that too, if distance really does have to be >0.

Yes, you can read jxl with dzsave, though it'll eat memory (libjxl won't decode an image in chunks, you always have to ask for the whole thing). I asked and the devs say chunk-wise decoding is coming.

You can also write an iiif pyramid with jxl tiles, which sounds interesting. Chrome ought to be able to display them. I made a comparison image:

x

jpeg-xl seems to roughly match heic for compression efficiency, so perhaps half the size of regular jpeg.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants