JPEG XL

Info

rules 57
github 35276
reddit 647

JPEG XL

tools 4225
website 1655
adoption 20712
image-compression-forum 0

General chat

welcome 3810
introduce-yourself 291
color 1414
photography 3435
other-codecs 23765
on-topic 24923
off-topic 22701

Voice Channels

General 2147

Archived

bot-spam 4380

libjxl

_wb_
2023-08-28 05:13:20
With clang on Linux it's more like 3-4 MB iirc
username
2023-08-28 05:17:43
around how much binary size is taken up per SMID target? also where's the place/file that should be looked in for the full amount of compile time SIMD targets that libjxl can do?
_wb_
2023-08-28 06:33:06
You can control it with HWY_TARGETS iirc
Cacodemon345
2023-08-28 07:40:18
3-4 MB is still too large for some projects, especially at this time where the format is facing a chicken-or-egg problem due to it being barely 1 year since the library got standardized.
2023-08-28 07:41:08
At the very least the decoder should have a target to close on the size of libwebp.
Traneptora
2023-08-29 02:52:09
If you're on a system where a 3MB library is a problem you should be disabling SIMD targets that aren't relevant for your system
jonnyawsom3
2023-08-29 03:02:45
Disabling SIMD entirely might be best for GZDoom, since the textures should be very small anyway and it's made to run on very low end hardware
_wb_
2023-08-29 06:10:14
You can also compile without some features like JPEG reconstruction, which you don't need if you just want to load images
2023-08-29 06:10:49
libjxl_dec on Android could be less than 200kb
jonnyawsom3
2023-08-29 06:19:30
Yeah, that too. I imagine it might have things like the PNG encoder included by default too
Cacodemon345
Disabling SIMD entirely might be best for GZDoom, since the textures should be very small anyway and it's made to run on very low end hardware
2023-08-29 10:11:57
How to do that?
Traneptora
Yeah, that too. I imagine it might have things like the PNG encoder included by default too
2023-08-29 11:43:08
libjxl doesn't but cjxl does
2023-08-29 11:43:18
er, djxl
Cacodemon345
2023-08-29 12:11:42
Ok tried with HWY_COMPILE_ONLY_SCALAR, didn't work out.
Traneptora
2023-08-29 12:21:10
elaborate
Cacodemon345
2023-08-29 12:26:31
Executable size remains the same.
Traneptora
2023-08-29 02:01:07
how are you linking in highway?
2023-08-29 02:01:23
you need to compile highway with those options, and highway's static library size should decrease
MSLP
Cacodemon345 3-4 MB is still too large for some projects, especially at this time where the format is facing a chicken-or-egg problem due to it being barely 1 year since the library got standardized.
2023-08-29 02:48:02
Damn, too bad j40 jxl decoder isn't being developed anymore. That decoder compiled code size about 240KB and probably the jxl features supported by it would be sufficient for use with textures.
yoochan
2023-08-29 02:58:47
perhaps jxl-oxide would give good size too ?
MSLP
2023-08-29 03:01:22
but is there C interface for jxl-oxide?
yoochan
2023-08-29 03:06:01
I don't know 😄 <@206628065147748352> ?
Tirr
2023-08-29 03:12:50
for C bindings: there isn't any yet
2023-08-29 03:13:29
and for binary size: cargo-bloat reports 463.5 KiB for jxl-oxide related crates
2023-08-29 03:14:03
the size is for code section only
afed
MSLP Damn, too bad j40 jxl decoder isn't being developed anymore. That decoder compiled code size about 240KB and probably the jxl features supported by it would be sufficient for use with textures.
2023-08-29 03:18:07
yeah, for game engines current features may be enough, except that decoding speed is not so good (due to lack of optimization)
jonnyawsom3
2023-08-29 03:36:23
I was tempted to mention, even the WASM is only 800KB, so it should definitely be possible to lower the size
_wb_
2023-08-29 03:51:18
There's always a bit of a trade-off between binary size and speed, e.g. things like loop unrolling and inlining can make things a faster but also increase binary size. If binary size is really an issue, you could also consider compressing the binary — it should be possible to compress it a bit
2023-08-29 03:54:23
my libjxl.so is 3296 kb but default gzip reduces that to 1365kb
2023-08-29 03:54:40
libjxl_dec is 1460kb and default gzip reduces it to 580kb
username
2023-08-29 03:58:51
isn't binary compression sort of a platform/OS specific thing? (I haven't looked into it that much really), I mean I guess there isn't really anything stopping it from being done on most platforms but it's more of an issue of how complex of a thing it is to say integrate into a build system or have at the same functional level between all platforms for a project that aims for many.
_wb_
2023-08-29 03:59:10
let me try building for just SSE4 and no-simd, instead of the default which also has SSE2 and AVX2, to see what the binary size is then
2023-08-29 04:01:17
I mean on some platforms you get binary compression for free because the way software is shipped is in e.g. Apple's .dmg or Android's .apk files it does already use compression, at least optionally
MSLP
2023-08-29 04:01:42
I think reasonable would be SSE2-only, since every x86-64 supports SSE2
_wb_
2023-08-29 04:02:03
just like javascript/wasm or svg in practice gets compressed using deflate or brotli because on the web you can use transfer encodings
2023-08-29 04:06:20
ah right, SSE2-only does make sense, no point having scalar code on x64
2023-08-29 04:09:44
with SSE2-only, libjxl is 2130 kb (914kb with gzip), and libjxl_dec is 792kb (339kb with gzip)
Cacodemon345
2023-08-29 04:10:19
Is this with MSVC and static linking?
_wb_
2023-08-29 04:10:56
no this is just my libjxl.so compiled with clang
2023-08-29 04:11:50
after stripping debug symbols, it is 1911 kb for libjxl and 694kb for libjxl_dec (316kb when using gzip)
Cacodemon345
2023-08-29 04:14:10
Not a good sign that it somehow ends up with more code in static executables on MSVC then.
username
2023-08-29 04:18:41
could be some defined or undefined compiler or linker flags bloating the size, I don't really know the full list of them for MSVC but adding something like `/Gw` could reduce the size by a minor or major amount https://learn.microsoft.com/en-us/cpp/build/reference/gw-optimize-global-data
_wb_
2023-08-29 04:23:24
Reducing binary size hasn't been a focus, only for Android Chrome there was at some point some effort spent to keep it low. Probably you can make a jxl decoder in under 100 kb on x64, if you are careful.
username
2023-08-29 05:38:36
the main reason size is such a concern in this situation is because GZDoom wants to be really careful not to introduce third party libraries that are seldom used and bloat up the size and image format wise they are planning to introduce GPU friendly formats in the future so for them they can't see a reason to add JXL unless it incurs a very small increase to the total size of the binaries or unless it's very critical to something content/asset wise which currently it isn't
afed
2023-08-29 05:50:54
adding avif then makes even more pointless when its highest advantages are in low fidelity, but very bad lossless compression and for high fidelity it can be worse than even good jpeg encoders and I don't think low fidelity for lossy is very much in demand for games, unlike web especially for GZDoom, used mostly in games with retro stylized pixel textures and images
username
2023-08-29 05:52:59
currently they have dropped the idea of adding JXL or AVIF and have put it as something to possibly be re-looked into in the future while they shift their focus onto other things
yurume
MSLP Damn, too bad j40 jxl decoder isn't being developed anymore. That decoder compiled code size about 240KB and probably the jxl features supported by it would be sufficient for use with textures.
2023-08-30 05:01:11
FYI I'm trying to revive it recently, though I need to answer some questions first (see <#1020056709831594005>)
HCrikki
2023-08-30 09:39:34
Not added recently but missing is Zoner (strong rival for lightroom and acdsee). Silently added since mid 2022, not mentioned anywhere but in list of supported formats.
2023-08-30 09:40:02
Seems its running old or unoptimized jxl code so itd be good to check if fully spec compliant or any features incomplete
surma
2023-08-30 11:07:07
Does JXL support pure single threading
_wb_
2023-08-30 02:34:35
this is what i'm getting with bloaty on a default libjxl build
Cacodemon345
2023-08-30 02:54:32
With highway library statically linked along with Brotli it would shoot up to 5 MB or more.
2023-08-30 02:55:15
The actual static library files of libjxl on MSVC is over 80MB+ in size however.
2023-08-30 02:56:16
Even if the final executable is order of magnitudes smaller.
2023-08-30 02:56:51
I do know that unused code removal would do the job of reducing to 5.4MB.
yoochan
2023-08-30 03:55:19
don't you have some way to clean static libraries from the unused symbols ? (like what is done when you link an exe ?)
novomesk
2023-08-30 04:02:13
My Qt plugin on Windows is built in MSVC and uses also static linking. With libjxl, hwy, brotli bundled-in, the final size of the plugin is 5.63 MB https://github.com/novomesk/qt-jpegxl-image-plugin/releases/tag/v0.4.3 This is how I built it: https://github.com/novomesk/qt-jpegxl-image-plugin/blob/main/appveyor.yml
Traneptora
2023-09-05 01:51:07
Probably doesn't know you can mark it as a draft
jonnyawsom3
2023-09-05 03:15:00
I thought they were testing the PR template or something
_wb_
2023-09-20 05:19:33
https://www.bestpractices.dev/en/projects/7845
2023-09-20 05:19:42
Answered a lot of questions
2023-09-20 05:20:14
https://www.bestpractices.dev/projects/7845/badge
2023-09-20 05:21:32
2023-09-20 05:22:06
Maybe will see how far we are from gold
2023-09-20 05:22:43
Not today tho
runr855
2023-09-22 10:10:28
Has the 0.9.0 idea been dropped? Now with iOS 17 and MacOS 14 any further optimizations and bug fixes would be great to get out quick. Or 1.0 might be closer than expected
jonnyawsom3
2023-09-22 10:24:34
Originally 0.9 was going to be skipped, and major bugs fixed for a 1.0 release, but if I recall the scope grew too large so now it's back to a 0.9 first
spider-mario
spider-mario maybe adding a manifest to our executables to use the new “utf8” locale would work and let us not have to change any code
2023-09-23 05:24:49
it seems to be what ArgyllCMS went with: (3.0 changelog) > Added manifest to MSWindows executables to use UTF-8 code pages on Windows 1903 and later. This should improve non-ASCII filename and path handling.
Nekotekina
2023-09-25 02:40:00
hi, why decoding jxl images (especially lossless) takes so much time?
Nova Aurora
Nekotekina hi, why decoding jxl images (especially lossless) takes so much time?
2023-09-25 03:40:32
How big of a file are you using and what is your system?
Nekotekina
2023-09-25 03:46:04
files around Full HD 1-2 MiB
2023-09-25 03:47:44
Ubuntu 22.04
2023-09-25 03:48:42
CPU 10920X
Nova Aurora
2023-09-25 03:50:02
Huh, those are pretty much instant for me on much worse hardware
Nekotekina
2023-09-25 04:35:13
I'll try to rebuild latest versino
Nova Aurora
Nova Aurora Huh, those are pretty much instant for me on much worse hardware
2023-09-25 04:40:38
Yeah less than half a second on libjxl from the arch repos
2023-09-25 04:40:50
On my school laptop
yoochan
2023-09-25 07:05:50
Watch for the buffer overflows! Years after being released, a 0-day breach was found in libwebp https://arstechnica.com/security/2023/09/incomplete-disclosures-by-apple-and-google-create-huge-blindspot-for-0-day-hunters/
Nekotekina
2023-09-25 09:28:44
https://github.com/libjxl/libjxl/issues/1097
2023-09-25 09:28:47
crap
veluca
2023-09-25 09:45:18
a fix for that will be available in the near future
2023-09-25 09:45:34
it's been blocked on some *amazingly annoying* CMS related work
_wb_
2023-09-26 03:58:15
Is there a way to use the fuzzer or something else to create a corpus of small files that are corrupt in all possible ways? It could be a useful complement to the conformance testing to also have some set of bad inputs so you can check that a decoder properly and quickly rejects them (as opposed to crashing or wasting lots of resources)...
Tirr
2023-09-26 04:02:51
uh, maybe write a wrapper that crashes on decode error?
2023-09-26 04:03:51
btw there's a set of files that made jxl-oxide crash https://discord.com/channels/794206087879852103/1065165415598272582/1109524145374502932
_wb_
2023-09-26 04:05:43
(we could then also add that to the libjxl tests and make some good improvement in code coverage stats, since many missed lines are error conditions that are just never reached with valid inputs)
Nekotekina
veluca it's been blocked on some *amazingly annoying* CMS related work
2023-09-28 11:03:09
is it on libjxl side or gdk?
veluca
2023-09-28 11:03:39
libjxl side
2023-09-28 11:03:46
The work, I mean
Nekotekina
2023-09-28 11:15:23
oh I mean, where is the problem lying
veluca
2023-09-28 11:58:33
ah, the core of the issue is that `lcms` is amazingly slow
2023-09-28 11:59:03
and the gdk plugin uses lcms to handle color conversions, if they are ever needed (but also if they are not)
2023-09-28 11:59:19
and in particular, most often they are not, but lcms still slows stuff down
2023-09-28 11:59:57
the cms work in libjxl allows skipping the conversions if not needed, which fixes the issue
2023-09-28 12:00:01
(presumably)
yoochan
2023-09-28 12:00:25
what do you recommend instead of lcms ? if this one is slow ?
2023-09-28 12:01:24
the fast version of lcms exists but is not free 😄
veluca
2023-09-28 12:01:37
skcms does a decent job at it
2023-09-28 12:01:49
assuming you don't need the things it doesn't support
2023-09-28 12:02:11
but it also has the problem of not being shipped as a dynamic library, which most OS maintainers don't like
yoochan
2023-09-28 12:05:01
couldn't skcms be included in libjxl 🙂
veluca
2023-09-28 12:05:53
tell that to debian maintainers 😛
yoochan
2023-09-28 12:07:01
they wouldn't see it if it's embedded at source level 🙂
_wb_
2023-09-28 12:18:14
the lcms2 fast float plugin makes things somewhat better: https://littlecms.com/plugin/
yoochan
2023-09-28 12:18:48
but it doesn't seems to be free, nor open
_wb_
2023-09-28 12:19:17
well it's GPL3
2023-09-28 12:19:39
so it's free and open, just not permissive
yoochan
2023-09-28 12:19:41
really ? ok... I have missread
_wb_
2023-09-28 12:21:11
you can get a more permissive (i.e. non-copyleft) license if you want to use it in proprietary software, but for something like gdk-pixbuf which is GPL anyway, I don't think there's a problem using the fast float plugin
yoochan
2023-09-28 12:21:51
nice, gdk should do that 🙂
afed
2023-09-28 05:16:06
is that an internal libjxl cms that doesn't require third party libs or just a workaround for the slow stuff?
_wb_
2023-09-28 06:51:18
In most cases, the internal libjxl cms can directly produce output in the desired colorspace.
2023-09-28 06:53:26
At least any display space in current use (sRGB, P3, Rec2020 PQ/HLG, AdobeRGB 1998, etc) can be output by libjxl if the JXL image is using XYB...
spider-mario
afed is that an internal libjxl cms that doesn't require third party libs or just a workaround for the slow stuff?
2023-09-28 08:17:23
it does require a third-party library (either skcms or lcms2, chosen at build time), but in many cases, it is able to skip having that third-party cms do expensive transforms
2023-09-28 08:18:29
in the case of the gdk pixbuf plugin, non-sRGB JXLs will probably still go through that cms’ gamut mapping to convert to sRGB
bonnibel
2023-09-29 02:10:05
Hey, I was wondering if the signs for calculating "linear Y" in <https://github.com/libjxl/libjxl/blob/8c36f40991c0966f6cf03abe045f494267ceab32/lib/jxl/enc_photon_noise.cc#L65> are correct? If I'm reading everything right it results in this conversion from linear RGB to linear Y ``` M = // matrix B = // bias mixed = M x Linrgb + B Y = (∛mixed[0] + ∛mixed[1])/2 - ∛B Liny = (Y - ∛B)³ + B = ((∛mixed[0] + ∛mixed[1])/2 - ∛B - ∛B)³ + B ```
Demiurge
veluca tell that to debian maintainers 😛
2023-09-29 03:16:39
Why would anyone bother wasting their breath on them?
2023-09-29 03:18:11
No one can save idiots from themselves. If a distro wants to cripple themselves then Debian will continue to do so forever and no one has the power to stop them nor should they care.
veluca
2023-09-29 07:31:21
Well, that implies no libjxl package in most debian-derived distributions, which is a lot of them
_wb_
2023-09-29 07:47:34
I think it's not a bad distro policy to use dynamic libraries as much as possible. Maybe skcms should be shipped as a library...
novomesk
_wb_ I think it's not a bad distro policy to use dynamic libraries as much as possible. Maybe skcms should be shipped as a library...
2023-09-29 10:45:01
Yes, skcms should be packaged as other libraries. We need that skcms developers make some release or at least Tag.
Traneptora
2023-09-29 01:02:36
https://skia.googlesource.com/skcms/ doesn't supporting opening issues, unfortunately
2023-09-29 01:06:51
ah, I found the tracker
2023-09-29 01:06:51
https://issues.skia.org/issues/302602705
Demiurge
2023-09-29 03:59:14
I think the distro should respect the intent of the upstream devs, not the other way around...
2023-09-29 03:59:54
If Debian is braindead that is a problem with Debian that no one else can solve but Debian
2023-09-29 04:00:34
Lots of libraries are intended to be copied into other programs rather than distributed as a standalone library.
2023-09-29 04:00:38
That is just reality
2023-09-29 04:00:54
Debian can choose to fight with reality but they should not force everyone else to
2023-09-29 04:01:39
Just because a lot of people use a braindead distro doesn't mean everyone should be forced to capitulate to stupidity
2023-09-29 04:03:17
Just tell those people "sorry your distro doesn't work, use a different distro or here's a direct download... oh wait, how do I make a Debian package? Why is it so overcomplicated to distribute a .deb? Wow this sucks"
_wb_
2023-09-29 04:37:55
It's nice to use dynamic libraries though, to save on disk space and for faster upgrades (including security updates). Imagine if every application would ship their own outdated version of libjxl...
Demiurge
2023-09-29 04:39:14
Yeah, but in practice, library upgrades typically require recompile regardless... Like with SSL libraries especially...
2023-09-29 04:41:08
Dynamic linked binaries are actually just a terrible method to provide shared services like that. A more logical system would be something like plan9
2023-09-29 04:43:07
Dynamic linking is too fragile and poorly thought out. It's a quick and dirty hack
novomesk
2023-09-29 04:44:15
Every distro has their own rules which are based on years of experience: https://wiki.gentoo.org/wiki/Why_not_bundle_dependencies
lonjil
Demiurge Yeah, but in practice, library upgrades typically require recompile regardless... Like with SSL libraries especially...
2023-09-29 08:24:29
Security updates are almost always API and ABI preserving patches. Certainly this is the case with SSL libraries.
Fraetor
_wb_ It's nice to use dynamic libraries though, to save on disk space and for faster upgrades (including security updates). Imagine if every application would ship their own outdated version of libjxl...
2023-09-29 10:20:27
Or notably, libwebp.
Traneptora
Demiurge Dynamic linking is too fragile and poorly thought out. It's a quick and dirty hack
2023-09-30 01:59:46
??? dynamic linking prevents you from having to recompile libraries and reverse dependencies to update them
2023-09-30 01:59:55
it also saves memory and disk space
2023-09-30 01:59:57
it's great
2023-09-30 02:00:10
it's not at all a "hack"
yoochan
2023-09-30 06:25:28
That's why ubuntu paddle backwards, trying to impose snaps as the new way to distribute apps... Yuck
veluca
Traneptora it's great
2023-09-30 08:01:01
I have very mixed feelings about dynamic linking 😛
Demiurge
lonjil Security updates are almost always API and ABI preserving patches. Certainly this is the case with SSL libraries.
2023-09-30 05:10:36
Pretty sure openssl for example says to always recompile when there is an update, for security reasons.
Traneptora ??? dynamic linking prevents you from having to recompile libraries and reverse dependencies to update them
2023-09-30 05:12:18
Technically that is no different for static libraries either, they just need to be re-linked not recompiled unless the headers change...
2023-09-30 05:15:27
But either way, linking at runtime is still a pretty fragile hack for shared code and there are much better ways to accomplish the same goals, like the way plan9 does things
2023-09-30 05:15:50
Plan9 does not even support dynamic linking at all
lonjil
2023-09-30 05:47:58
So IPC everything?
Demiurge
2023-09-30 08:36:40
That's a lot more logical way of doing the same thing, yeah
kokoniara
2023-10-02 01:54:08
how do i know what failed here? i copied the [sample](https://github.com/libjxl/libjxl/blob/e4eb1f093e27d91fc8c4e3611d2ae2a5c12fa07b/examples/encode_oneshot.cc#L198-L215) and it no worky
2023-10-02 02:06:05
i see `error` in `JxlEncoderStruct` but how do i get that
2023-10-02 02:06:10
im not good with pointers
_wb_
2023-10-02 06:51:45
JxlEncoderGetError — but it helps more to build your libjxl with debug messages (e.g. ./ci.sh opt instead of ./ci.sh release) so you get something more informative than just an error code
circa
2023-10-06 08:54:39
Hi all, I’ve been noticing that the encoding efficiency (in bpp) gets worse the smaller the image is. Is that normal behaviour ? How can it be explained ?
jonnyawsom3
2023-10-06 09:06:31
The smaller the image the less redundant data there is
circa
2023-10-06 09:24:39
Yeah that’s what I figured but I’ve been comparing with another format (homemade and a bit intricate but uses jpeg) which is not impacted as badly
_wb_
2023-10-06 10:01:12
jpeg is closer to 'fixed cost per 8x8 block' than jxl — of course both will compress smooth/solid regions better than high entropy regions, but jxl can take more advantage of large 'easy' regions than jpeg can
circa
2023-10-06 10:15:42
Ok yes i understand, thanks. I have another question about those large easy region. I have had issues with banding in smooth gradients. I read that you apply a selective smoothing algorithm on the DC image, is that at any effort ?
_wb_
2023-10-06 10:32:04
yes, the adaptive dc smoothing is always enabled I think
circa
2023-10-06 10:46:57
Ok interesting. Any parameter I should enable to limit those artefacts ?
_wb_
2023-10-06 11:04:24
jxl should be quite good by default at avoiding banding... but the decoder doesn't do any dithering atm so you should decode to 16-bit png and do your own dithering...
circa
2023-10-06 11:10:33
For sure, thank you for your answers 🙂
Demiurge
2023-10-07 01:23:23
Sounds like a good example of economy-of-scale.
2023-10-07 01:23:48
Literally as image size scales up
2023-10-07 01:24:08
Also smaller images tend to have a lot more entropy per pixel
2023-10-07 01:24:54
Large images tend to have a lot more blurry and smooth area
_wb_ jxl should be quite good by default at avoiding banding... but the decoder doesn't do any dithering atm so you should decode to 16-bit png and do your own dithering...
2023-10-07 01:32:46
Sounds like a libjxl decoder bug, when decoding to an 8 bit buffer the output should always be dithered if it's lossy
2023-10-07 01:33:40
And if that isn't the default behavior that ought to be considered faulty.
2023-10-07 01:34:16
Hence the noticeable banding issues that make the perceived quality of jpegxl suffer
2023-10-07 01:34:33
Harms the reputation of the format
a goat
2023-10-07 01:37:57
iirc there is an additive noise you can apply to an image as an encoding option
Demiurge
2023-10-07 01:39:12
There is a film grain option in the encoder
2023-10-07 01:39:43
ISO photon noise or something like that
a goat
2023-10-07 01:40:10
Demiurge
2023-10-07 01:40:10
You can specify how much to apply
_wb_
Demiurge Sounds like a libjxl decoder bug, when decoding to an 8 bit buffer the output should always be dithered if it's lossy
2023-10-07 01:56:17
I agree, at least by default. But dithering should be applied after color conversion, so this was stuck on getting the new decoder cms api implemented...
a goat
2023-10-07 01:58:10
There was an interesting paper I read the other day about a universal colored noise generation algorithm. I wonder if such a trick might be useful for generating dithering over a wide array of images
2023-10-07 02:03:10
https://dl.acm.org/doi/10.1145/2185520.2185572
_wb_
2023-10-07 02:14:14
Just 4x4 ordered dither is fine for avoiding banding in 8-bit sRGB...
Demiurge
2023-10-07 02:38:31
Dither can get pretty fancy and clever and awesome
2023-10-07 02:39:46
And impossible to distinguish from "natural" or usual noise
2023-10-07 02:41:42
And yes, technically it ought to take color space into account but that should be easy since lossy JXL is nearly always stored in the same color space in order for the lossy compression to be effective, right? So why would this be a showstopper?
2023-10-07 02:43:47
Lossy JXL is nearly always stored in the same perceptual color space, isn't it? Oh, but it is often decoded to an arbitrary color space, where the dithering needs to take place...
2023-10-07 02:44:07
So that's probably why it can't be done yet...
2023-10-07 02:44:45
Maybe the default needs to decode to a 16 bit buffer/file instead of 8 bit
2023-10-07 02:45:10
Like djxl should produce 16 bit files
2023-10-07 02:45:30
Until dithering is ready
lonjil
2023-10-07 02:53:08
I love it when computer drawn art with solid coloring gets naively dithered 🙂
spider-mario
a goat There was an interesting paper I read the other day about a universal colored noise generation algorithm. I wonder if such a trick might be useful for generating dithering over a wide array of images
2023-10-07 02:55:25
as far as I know, to dither digital signals, triangular noise is the preferred option
2023-10-07 02:55:38
you can get that by summing two uniforms together
2023-10-07 02:56:59
dithering with uniform noise decorrelates the first moment (the mean) of the quantisation error from the signal, but not the second moment (the variance, if the mean is zero), so you get noise modulation (the signal modulates the power of the noise)
2023-10-07 02:57:18
triangular noise decorrelates the variance as well, though not necessarily higher moments AFAIU
2023-10-07 02:57:22
but the higher moments are considered less important; decorrelating the first two is the point considered “good enough” for audio
2023-10-07 02:58:03
as you sum more and more uniforms, the limit is Gaussian noise, which decorrelates all moments, but also spans a wider range of values, so you get less headroom (with an actual gaussian, none, since it has infinite support) and more noise
2023-10-07 03:10:36
https://www.researchgate.net/publication/3317523_A_theory_of_nonsubtractive_dither https://www.recordingblogs.com/wiki/dithering#:~:text=Common%20dithers%20in%20audio%20processing,moments%20of%20the%20error%20uncorrelated%2E https://www.airwindows.com/tpdf-dither/#:~:text=TPDF%20is%20the,TPDF%20dither%20does%2E
yoochan
2023-10-07 06:46:09
Thank you for the readings!
boogerlad.
2023-10-08 10:33:32
Are there any high quality comparisons of photos with noise generated natively by camera, noise removed via jpeg xl, and noise synthesized by jpeg xl? I'm not really a believer of psycho visual tricks but i'd love to be converted
spider-mario
2023-10-08 10:53:02
just as a minor clarification, most of the noise in digital photos is not generated by the camera itself, but is rather a consequence of the discrete and seemingly stochastic nature of photon arrival
2023-10-08 10:53:19
fewer photons => less certainty as to the underlying “flux” (/ more variation from pixel to pixel, i.e. noise)
2023-10-08 10:53:25
https://en.wikipedia.org/wiki/File:Photon-noise.jpg
2023-10-08 10:55:42
this is the behaviour that the `--photon_noise` option in `cjxl` attempts to simulate
2023-10-08 10:59:00
photon arrival is considered a Poisson process, which implies that the standard deviation of the number of photons arriving in a given time interval is the square root of the underlying rate
2023-10-08 11:02:29
(e.g. if you photograph a grey card that is of such brightness that over a 1/100s exposure, each pixel should collect 10k electrons on average, then you’ll see a standard deviation of 100 electrons across them, i.e. an SNR of 100, or 40 dB)
2023-10-08 11:04:12
there is a technique called “Photon Transfer” (https://doi.org/10.1117/3.725073) where you actually make use of that fact to reverse-engineer how many electrons each digital step in the raw files corresponds to
2023-10-08 11:05:02
Bill Claff has published the result of doing that for many cameras, based on crowdsourced data (I contributed the raw data for the Canon G1 X III and Canon EOS R6 based on his instructions) https://www.photonstophotos.net/Charts/PTC.htm
2023-10-08 11:06:59
so, for the iPhone 14 Pro Max https://www.photonstophotos.net/Charts/PTC.htm#Apple%20iPhone%2014%20Pro%20Max, for example, K_ADC = 4.828 e⁻/DN means that each digital step corresponds to 4.828 electrons
2023-10-08 11:07:20
and you can see that photon shot noise (the second grey curve) is the dominant source of noise over much of the range
2023-10-08 11:08:16
read noise (the horizontal grey line, and 1.624 DN for the iPhone 14 Pro Max) is more important at the lowest signal levels, while photo response non-uniformity (0.68% for the iPhone 14 Pro Max) takes over at very high levels
2023-10-08 11:08:26
those latter two _are_ introduced by the camera
Jyrki Alakuijala
2023-10-09 06:19:39
I love the photon noise -- great aesthetics -- I think we got this nearly ideally right -- if we'd do it again, perhaps it would have been nice to add an 8x8 control field to be able to modulate it locally
2023-10-10 08:16:51
we don't do real photon noise but I decided that it is better to do the noise in Laplacian
2023-10-10 08:17:21
that way there is a stricter impact for the noise -- it cannot accidentally create a lot of low frequency energy
2023-10-10 08:17:46
and every image has an amazing accident if we let it -- dices are being thrown millions of times for every image 😄
2023-10-10 08:32:07
Many noise generation systems get confused about the quantity of the noise -- Shot noise increases with intensity, but after the gamma compression curve is applied, there is more noise in the dark parts than light parts. I observe five approaches to the modeling: 1. constant noise everywhere, possibly by adding a noise image into the gamma compressed signal 2. use more noise in bright areas with some heuristic such as sqrt(I) because it is shot noise and that's the definition 3. use heuristically more noise in dark areas than the brightest areas because that is what one can observe in some real-life samples 4. psysical+psychovisual: calculate shot noise in linear space, then gamma compress 5. JPEG XL approach: calculate shot noise in linear space, high pass it (Laplacian) so that it doesn't create new low frequency features, then gamma compress
2023-10-10 08:34:24
often image compression is tiled -- if one does high pass filtering or otherwise grains that relate to more than one pixel -- one needs to communicate the noise signal over the tiles in JPEG XL this is easy since it only depends on the seed of the randon number generator which is known by all the tile workers, and can be computed without waiting for neighbouring tiles in some other systems, tiles need to wait for top/left tiles to be ready so that they can absorb their film grain state machines
circa
2023-10-11 08:53:53
Just noticed speed performance is pretty bad on windows. For instance, it doesn’t seem to take advantage of every threads (same performance between 32 cores and limiting to 8 cores). Is this expected ?
jonnyawsom3
2023-10-11 10:19:44
Multithreading depends on the image size and how many groups the image is split into (If I recall) The bulk of processing also isn't multithreaded, so a single core will be used after the first step of encoding (From my experience, but I only have 8 cores)
monad
2023-10-11 06:48:06
Rather depends on effort. Lossless? e3 and below avoids MA tree learning. Lossy? e6 and below, with e6 probably saturating best.
Demiurge
2023-10-14 04:03:17
There's less of a problem with noise modulation in images compared with sound
2023-10-14 04:04:50
In fact, noise modulation can be a very good thing if you can mask the noise and make it less perceptible.
2023-10-14 04:05:39
Unfortunately I don't think anyone has actually tried to apply such good ideas in practice
2023-10-14 04:21:39
As far as dither goes anyways
runr855
2023-10-21 12:01:00
Is there an official way to download a jpegli binary, or will I need to built libjxl myself?
jonnyawsom3
2023-10-21 12:11:28
Should find it inside these https://artifacts.lucaversari.it/libjxl/libjxl/latest/
2023-10-21 12:12:22
I know the github actions builds also include it, but that's easier as a permanent link
runr855
2023-10-21 03:29:49
Thank you
qdwang
2023-10-24 07:04:25
Hi guys, I'm trying to encode some RGBA data to jxl by using libjxl in Rust. For RGB data, everything works fine, but with RGBA data, nothing comes out and it will cause the 0x81 issue. Don't know what's wrong with my code: https://gist.github.com/qdwang/12304a925f1b0d3c1231a3b2dd0d63a6 I just use a 4x4 pure red rect sample in the code.
2023-10-25 11:44:40
It seems I need to set `num_extra_channels: 1` to BasicInfo, but I don't want to keep the alpha channel information. My goal is to let it ignore the alpha channel. The `num_extra_channels: 1` will increase size in the encoded result
Traneptora
It seems I need to set `num_extra_channels: 1` to BasicInfo, but I don't want to keep the alpha channel information. My goal is to let it ignore the alpha channel. The `num_extra_channels: 1` will increase size in the encoded result
2023-10-25 05:59:00
libjxl doesn't accept 4-byte RGB
2023-10-25 05:59:25
you need to convert it to rgb24, not rgb0
qdwang
2023-10-25 06:32:02
alright, I get it. Thank you
2023-10-26 02:40:52
By the way, it there a method to limit the memory consumption during the `JxlEncoderProcessOutput` process?
2023-10-26 02:41:59
My target device has a low memory embedded and I can accept longer processing time.
2023-10-26 02:57:26
Oh it seems I need to use `JxlEncoderAddChunkedFrame` to add frame
Demiurge
2023-10-26 09:18:01
libjxl is a quick and dirty c++ codebase forked from Google PIK code and it is not very wise about memory consumption at this stage of development.
2023-10-26 09:20:25
It might be wise, if you need a small, fast, easy to hack on, and memory conscious encoder, to implement a compliant encoder from scratch in a programming language that's easier to hack on, like C...
2023-10-26 09:21:58
Because libjxl will only improve after you start writing and submitting patches, and who wants to get hacking on a C++ project honestly?
2023-10-26 09:22:43
I dunno if that's a mean thing to say, but that's basically how I feel, but maybe it's just me...
2023-10-26 09:23:42
At least with a C++ project it's possible to mix C and C++ in the same project and slowly convert all the source files away from C++ if you want them to be more readable...
2023-10-26 09:25:18
I doubt anyone will argue over which language makes it easier to read someone else's code.
2023-10-26 09:26:47
C++ is harder to parse, for humans as well as computers...
qdwang
2023-10-27 12:09:13
I am trying to understand how `JxlEncoderAddChunkedFrame` actually works to save memory usage. It calls `JxlEncoderAddImageFrame` in the soucecode. So my guess is this: Use a small tile size to be set to the BasicInfo's `xsize ysize`, and add tiles by using `JxlEncoderAddImageFrame` and `JxlEncoderProcessOutput` repeatedly. Am I right? But the problem is, how can the output compressed tiles combine together? In my test, they will overlap one by one because of the `xsize ysize` set before. And there is no `x` and `y` position to tell where they should be settled.
veluca
2023-10-27 12:16:04
the answer is that it doesn't actually save memory yet
2023-10-27 12:16:13
but it's not something you can achieve via API usage
2023-10-27 12:16:29
I was going to implement that but vacation took priority 😛
w
2023-10-27 12:27:21
what you do is just add a bunch of swap
qdwang
veluca I was going to implement that but vacation took priority 😛
2023-10-27 12:29:12
Thanks for your reply. I was trying to encode a 48M photo, it will take 2 - 4GB memory if the entire image was loaded
w what you do is just add a bunch of swap
2023-10-27 12:30:43
yeah, it true
w
2023-10-27 12:30:46
<@902036286074925096> couldn't even decode 4MP jxl without having to use swap
Kleis Auke
2023-10-27 02:24:09
Instead of a callback-based approach (`JxlChunkedFrameInputSource`), has a 'push'-based tile/scanline streaming encode API also been considered? For libvips, a function similar to libtiff's `TIFFWriteTile` and/or `TIFFWriteScanline` functions would be easier to integrate (/cc <@310374889540550660>).
Demiurge
2023-10-27 03:52:24
Cropped decode or resized decode would be nice to have in the api
jonnyawsom3
2023-10-27 03:55:22
I thought that was already implemented? Or maybe I'm thinking of Oxide
Demiurge
2023-10-27 04:29:53
Maybe some kind of scale factor option. Where it decodes a blurrier version of the images without the high frequency data
2023-10-27 04:31:05
With the option of decoding to abuffer with the same size as the original image or to a smaller buffer that has been scaled down by the scale factor
_wb_
2023-10-27 04:39:18
we had that in djxl at some point, but I guess that was before we switched it to libjxl
tufty
Kleis Auke Instead of a callback-based approach (`JxlChunkedFrameInputSource`), has a 'push'-based tile/scanline streaming encode API also been considered? For libvips, a function similar to libtiff's `TIFFWriteTile` and/or `TIFFWriteScanline` functions would be easier to integrate (/cc <@310374889540550660>).
2023-10-27 04:52:58
yes, libvips savers run in a background thread ... they are given a tile of pixels to encode and write to the output so a libtiff / libjpeg / libwebp / etc. style push API for encoding would be a lot simpler for us
2023-10-27 04:54:30
we'd need to use some kind of complicated threaded buffer to work with `JxlChunkedFrameInputSource` (I think)
Demiurge
_wb_ we had that in djxl at some point, but I guess that was before we switched it to libjxl
2023-10-27 06:48:54
Well maybe the old code can be added to libjxl public API somehow...
2023-10-27 06:50:20
libvips is awesome btw and a great way for jpegxl to get adopted by software that uses libvips already
tufty
2023-10-27 07:05:00
thanks! we love jxl, and include libjxl support in the standard builds we distribute \o/ 8.16 ought to have improved jxl support, hopefully
Demiurge
2023-10-27 10:24:05
libvips is also, frankly, a great way for libjxl to figure out how to improve the public API it exposes, to better provide what libvips needs and expects. Same with other consumers of libjxl, like krita and ffmpeg.
2023-10-27 10:24:44
It is good if the developers that use libjxl can share critique and outline what they need and expect from libjxl
bonnibel
2023-10-27 10:47:41
(speaking of ffmpeg, looks like it still can't decode f32 jxls without converting them to u16, rip) (except for greyscale images)
Traneptora
My target device has a low memory embedded and I can accept longer processing time.
2023-10-30 02:10:50
This is the primary purpose of libhydrium, fwiw
2023-10-30 02:11:06
tho development has stalled a bit because of work
qdwang
2023-11-04 07:40:02
just checked the hydrium repo, looks good
2023-11-06 07:25:02
Hi guys, I’m wondering what does setting JXL_ENC_FRAME_SETTING_EFFORT actually do in the code? It’s not mentioned in the documentation. It just says the encoder’s speed is affected.
Traneptora
Hi guys, I’m wondering what does setting JXL_ENC_FRAME_SETTING_EFFORT actually do in the code? It’s not mentioned in the documentation. It just says the encoder’s speed is affected.
2023-11-06 07:41:52
it's the same thing as the effort setting on the CLI
2023-11-06 07:41:56
--effort or -e
_wb_
Hi guys, I’m wondering what does setting JXL_ENC_FRAME_SETTING_EFFORT actually do in the code? It’s not mentioned in the documentation. It just says the encoder’s speed is affected.
2023-11-06 08:23:05
https://github.com/libjxl/libjxl/blob/main/doc/encode_effort.md
qdwang
2023-11-06 09:35:31
<@853026420792360980> <@794205442175402004> Thanks for the replies.
HCrikki
2023-11-08 12:23:04
about compression effort, is e7 always the default unless specified otherwise?
2023-11-08 12:23:50
like, the default isnt different depending on resolution. ie default being e9 for all images under 300x300 resolution and e5 default for anything larger than 2000x2000
_wb_
2023-11-08 01:58:41
e7 is the libjxl default, but for an application it could make sense to set different defaults depending on resolution (and maybe also depending on quality)
qdwang
2023-11-08 02:20:40
will effort affect the bit depth of the result?
diskorduser
will effort affect the bit depth of the result?
2023-11-08 02:27:19
I think effort doesn't change the bit depth of encodes
qdwang
diskorduser I think effort doesn't change the bit depth of encodes
2023-11-08 02:55:36
Thanks.
2023-11-08 03:05:37
In my test on trying a 10bit 48m pixels Apple ProRAW image with complex color scene. Both with 0.46 distance. For effort = 1, it will consume 800mb to 2.5gb memory, results in a 10.4mb jxl file For effort = 7, it will always consume 4gb memory at least, results in a 9.1mb jxl file
2023-11-08 03:07:55
Don't know why for effort=1, the memory consumption is so unstable
2023-11-08 03:08:19
btw, i was running with parallel threads
2023-11-08 03:12:19
For effort = 9, it will consume about 12gb memory, results in a 8.8mb jxl file
2023-11-08 03:15:36
Encoding without parallel threads for effort = 1 will constantly consume 2gb memory
yoochan
2023-11-08 03:20:27
ok, but the size ! does it compress well ?
qdwang
yoochan ok, but the size ! does it compress well ?
2023-11-08 03:23:06
I didn't check the image quality by my eyes. I think for a distance=0.46, the quality=96, so it should be ok
_wb_
2023-11-08 03:25:13
For lossy jxl (vardct mode), bit depth is just metadata, it doesn't change the internal representation.
qdwang
_wb_ For lossy jxl (vardct mode), bit depth is just metadata, it doesn't change the internal representation.
2023-11-08 03:26:00
Thanks for the explain.
_wb_
2023-11-15 07:24:57
<@987371399867945100> https://github.com/libjxl/libjxl-tiny/blob/8eae18172059d54f5c734ca814f23b96eebff859/encoder/enc_frame.cc#L389 shouldn't that just be `left = 0;`?
2023-11-15 07:32:42
Looking at the code: libjxl-tiny is using a fixed MA tree which for AcStrategy and Quantfield uses `West` as context and for Quantfield also as predictor. Correct?
2023-11-15 07:37:06
AcStrategy and Quantfield are auxiliary images that are flattened to 1D because due to variable block sizes the number of values per row is variable. That causes `West` for the first value of a row to correspond to the rightmost value of the previous row, which is a bit annoying for row-based approaches...
2023-11-15 07:39:42
What happens if you just don't use any context and no prediction for those fields? Would it make much of a difference?
szabadka
_wb_ <@987371399867945100> https://github.com/libjxl/libjxl-tiny/blob/8eae18172059d54f5c734ca814f23b96eebff859/encoder/enc_frame.cc#L389 shouldn't that just be `left = 0;`?
2023-11-15 08:24:58
The modular image containing the control fields has the ac strategy in the first row and the quant field in the second, and the LEFT predictor uses the value one row up at the first column, therefore we have to start that with the first ac strategy value for the quant field predictor.
_wb_ What happens if you just don't use any context and no prediction for those fields? Would it make much of a difference?
2023-11-15 08:29:37
Not sure what the impact would be size-wise, but unfortunately it would be a bit tricky to change it in the current state. I started from the very flexible full jxl code and tweaked it a bit and then I changed to the fixed MA tree by using the previous version of the code to dump all the hard-coded tables for the fixed tree. Doing any change now would require changing a lot of these things and then debugging why it does not work.
_wb_
szabadka The modular image containing the control fields has the ac strategy in the first row and the quant field in the second, and the LEFT predictor uses the value one row up at the first column, therefore we have to start that with the first ac strategy value for the quant field predictor.
2023-11-15 08:32:31
ah right! forgot that the fields are combined in rows — we did that so quant field values could use corresponding (or neighboring) ac strategy values as context
2023-11-15 08:33:47
yeah I see that the tree is just a dump in the code, nothing that can be changed easily
2023-11-15 08:37:02
I'd try using the Zero predictor for both control fields, and either no context or maybe North context for the quant field (`if y > 0` in the MA tree). But yes editing this tree will not be convenient.
2023-11-15 08:39:57
Main thing to change is change the relevant `West` predictor to `Zero` (`Set` in jxl_from_tree terms), the rest could be done without changing the tree but by just making the cmap map everything to the same ctx so the context doesn't actually depend on `left` anymore.
2023-11-15 08:42:46
maybe for debugging it would in any case be useful to have something that can decode the MA trees in a jxl file and print them out in jxl_from_tree syntax — and then we could just use that to print the current tree written by libjxl-tiny, edit it, and use some hacked version of jxl_from_tree to dump it again. WDYT?
szabadka
2023-11-15 10:12:12
yes, this sounds good, something like jxlinfo, but it would probably have to use the internal APIs
2023-11-15 11:44:58
<@794205442175402004> is there a collection of jxl_from_tree input files somewhere?
_wb_
szabadka <@794205442175402004> is there a collection of jxl_from_tree input files somewhere?
2023-11-15 11:53:17
Check <#824000991891554375> 🙂
2023-11-15 03:02:23
what is the range of values for ac strategy and quant field that actually get used by libjxl-tiny?
2023-11-15 03:04:43
if the set of values that are used is limited and not a continuous range of integers, perhaps it would be useful to use a modular Palette transform (also in the case of libjxl btw)
vtorri
2023-11-17 07:29:56
hello
2023-11-17 07:30:03
will there be a new release soon ?
veluca
2023-11-17 10:04:24
there should be one, yeah
afed
2023-11-18 02:43:31
do common png libraries have an interface for streaming encoding/decoding?
Demiurge
2023-11-19 11:15:19
Is there any known issue with 0.8.2, with converting a (greyscale) PNG with an ICC profile into a lossy JXL, and then decoding back to PNG again, and getting a much darker or lighter image than the original PNG?
2023-11-19 11:16:43
Because I see no reason why it should look substantially darker or lighter after simply doing `cjxl x.png y.jxl; djxl y.jxl z.png`
2023-11-19 11:17:48
Is this a known issue?
2023-11-19 11:31:34
Also why does jxlinfo say "(possibly) lossless" for losslessly transcoded JPEG with reconstruction data, instead of something more fitting like, I dunno, just saying "lossy"
2023-11-19 11:32:59
Since it's lossy DCT encoding from a lossy JPEG...
Demiurge Because I see no reason why it should look substantially darker or lighter after simply doing `cjxl x.png y.jxl; djxl y.jxl z.png`
2023-11-19 11:40:07
This only happens with lossy encoding. With -d 0 I can cjxl and djxl all I want and get the same looking PNG.
2023-11-19 11:40:17
Which doesn't actually make sense
2023-11-19 11:42:01
Maybe there is a bug in the software I'm using to display or decode the color information.
w
2023-11-19 11:42:32
yeah dot gain profiles and grayscale gamma profiles are often not used correctly
2023-11-19 11:43:43
and just because it's jpeg doesnt mean it's lossy
2023-11-19 11:44:04
it's just an image
Demiurge
2023-11-19 11:45:11
It's using an inherently lossy algorithm so it would make the most sense to just say "lossy"
w
2023-11-19 11:45:20
then the encoding is lossy
2023-11-19 11:45:29
but say you get a jpeg out of a camera
2023-11-19 11:45:33
there's nothing better than that
Demiurge
2023-11-19 11:45:36
Since that's probably what the intended purpose of that information in jxlinfo is for
w
2023-11-19 11:45:37
nothing lossless
2023-11-19 11:45:44
so the least loss is the jpeg
2023-11-19 11:46:16
i thought we all went over this
Demiurge
2023-11-19 11:46:42
I'm just trying to guess at what the intended purpose is of the behavior and information displayed by jxlinfo.
w
2023-11-19 11:47:02
i think it's just to say what the jxl is
Demiurge
2023-11-19 11:47:38
I think that lossy/lossless thing is supposed to say whether it's encoded using a lossless algorithm or not.
w
2023-11-19 11:48:06
oh
2023-11-19 11:48:21
then having the word "possibly" is bad i guess
Demiurge
2023-11-19 11:48:30
But I'm not sure if the intended behavior is actually documented somewhere.
2023-11-19 11:48:59
So I wouldn't know if that's actually what it's intended for
w
2023-11-19 11:49:18
well who is jxlinfo even supposed to be for
Demiurge
2023-11-19 11:54:48
Well, lemme look at the source code...
username
2023-11-19 11:56:32
lossy = VarDCT lossless = Modular "possibly" is added at the end of lossless so people don't think the contents of the image is lossless
Demiurge
2023-11-19 11:56:33
It looks like what it's really doing is, checking to see if it's encoded using the file's original color profile or not.
lonjil
2023-11-19 11:56:44
PNG is inherently lossy because it maxes out at 16 bits, and what if you have 32 bit data? Now making a PNG is a lossy operation...
2023-11-19 11:57:12
hell, converting a normal 8-bit JPEG to PNG is a lossy operation, you lose some of the information that existed in the JPEG
Demiurge
2023-11-19 11:57:48
Looks like it has nothing to do with modular vs vardct
ajekb78
2023-11-19 04:19:32
Can anyone help clear up my confusion about how ICC profiles work with jxl? I'm working to add support to Siril. My implementation is heavily based on the reference implementation, with some adaptations to suit interfacing with the internal image data structures we use. When saving an image I can provide an ICC profile, and when loading one I can retrieve the ICC profile from the jxl. However the two don't seem to be the same - working with an image in BT.2020 I save it as jxl and provide the BT.2020 ICC profile, but when I open it the ICC profile description is RGB_D65_SRG_Rel_Lin and the primaries have been changed to the sRGB primaries. The colors have been converted correctly so it looks ok when displayed but I'm not editing in my chosen colorspace any more. I would have expected that when providing an ICC profile that profile would be embedded in the file and the conversion back from XYB would convert back to the provided profile. Is this not the case (or is there a way of specifying this behaviour that I haven't spotted?)
spider-mario
2023-11-19 04:30:03
it should not do that unless sRGB output is explicitly requested when decoding
2023-11-19 04:30:43
when saving, libjxl should save a color encoding that is at least equivalent to your Rec. 2020 ICC profile
2023-11-19 04:30:54
does jxlinfo confirm that it is not the case in the saved .jxl file?
ajekb78
2023-11-19 04:46:58
Now I'm even more confused... jxlinfo returns: ``` $ jxlinfo -v M42-unstretched32.jxl JPEG XL image, 3112x2084, lossy, 32-bit float (8 exponent bits) RGB num_color_channels: 3 num_extra_channels: 0 have_preview: 0 have_animation: 0 Intrinsic dimensions: 3112x2084 Orientation: 1 (Normal) Color space: 1256-byte ICC profile, CMM type: "lcms", color space: "RGB ", rendering intent: 0 ``` and the 1256-byte size of the ICC profile it mentions matches the size of the profile I provided when saving. But when I load it and retrieve the ICC profile with JxlDecoderGetColorAsICCProfile(), and then export the ICC profile as a file, the size is 732 bytes (this is the one with the description I mentioned above).
2023-11-19 05:08:43
Oh. I've just noticed - I'm retrieving the profile with JxlDecoderGetColorAsICCProfile(dec.get(), &format, JXL_COLOR_PROFILE_TARGET_DATA, icc_profile->data(), icc_profile->size()); should that be JXL_COLOR_PROFILE_TARGET_ORIGINAL instead?
spider-mario
2023-11-19 05:22:08
ah, right
2023-11-19 05:23:04
target_data is the colorspace in which libjxl returns it when decoding, which is not guaranteed to be the colorspace in which it was originally supplied (although we have been landing changes to make it possible to request it to be output in a specific colorspace)
ajekb78
2023-11-19 05:38:30
Ah, OK. I'll wait for those changes to mature then, and for now I'll just take it in the target_data colorspace and transform it to the user's preferred working colorspace.
2023-11-19 07:30:13
Is it allowed to call JxlDecoderGetColorAsICCProfile() twice, once wiht JXL_COLOR_PROFILE_TARGET_DATA and a second time with JXL_COLOR_PROFILE_TARGET_ORIGINAL (with the appropriate calls to JxlDecoderGetICCProfileSize()) in order to get both the original and the decoded data ICC profiles?
spider-mario
2023-11-19 07:59:14
as far as I know, yes, there shouldn’t be any issue with doing that
2023-11-19 07:59:18
or if there is, it’s a bug
ajekb78
2023-11-19 08:14:13
thanks. That should let me retrieve the decoded data color profile and the user's original color profile and do the conversion myself.
Traneptora
ajekb78 Now I'm even more confused... jxlinfo returns: ``` $ jxlinfo -v M42-unstretched32.jxl JPEG XL image, 3112x2084, lossy, 32-bit float (8 exponent bits) RGB num_color_channels: 3 num_extra_channels: 0 have_preview: 0 have_animation: 0 Intrinsic dimensions: 3112x2084 Orientation: 1 (Normal) Color space: 1256-byte ICC profile, CMM type: "lcms", color space: "RGB ", rendering intent: 0 ``` and the 1256-byte size of the ICC profile it mentions matches the size of the profile I provided when saving. But when I load it and retrieve the ICC profile with JxlDecoderGetColorAsICCProfile(), and then export the ICC profile as a file, the size is 732 bytes (this is the one with the description I mentioned above).
2023-11-20 01:52:18
so the TLDR is that jxl files are typically encoded in an absolute space called XYB. Upon decoding, you can request the pixels in a variety of RGB spaces, but it will default to sRGB unless you tell it otherwise
2023-11-20 01:53:34
So if the user is working in BT2020/PQ, you can request that
Quackdoc
2023-11-20 02:02:15
something that I dont see ~~shilled~~ advertised enough is that jpegxl is an image format with good color management baked into it, I see a lot about how XYB is good for compression, but IMO what matters a lot more is that it will just look fine on even a rudimentary color managed application so long as tonemapping doesn't need to take place
2023-11-20 02:04:03
also is it lowercase xyb or upper, I keep seeing it in both
username
2023-11-20 02:05:25
uppercase
Quackdoc
2023-11-20 02:05:36
thx
ajekb78
2023-11-20 07:28:52
I got it working in the end. I wasn't able to request the RGB data directly in the original colorspace but I was able to make the decoder provide the ICC profiles for both the decoded data and the original one provided when the data was saved and do the conversion myself, which is good enough.
qdwang
2023-11-20 01:44:40
Hi guys, i'm having trouble to set lossless encoding. I'm using a pure mockup sample u16 RGB image data 100x100 pure red. ``` 1. JxlEncoderSetBasicInfo 2. JxlEncoderFrameSettingsCreate 3. JxlEncoderSetFrameDistance 4. JxlEncoderAddImageFrame ``` This lossy setup progress has no error. ``` 1. JxlEncoderSetBasicInfo (with uses_original_profile changed to 1) 2. JxlEncoderFrameSettingsCreate 3. JxlEncoderSetFrameLossless 4. JxlEncoderAddImageFrame ``` This lossess setup will cause a `JXL_ENC_ERROR` on step 4. And `JxlEncoderGetError` will get `JXL_ENC_ERR_API_USAGE`.
2023-11-20 01:50:49
Other settings are untouched
2023-11-20 02:01:31
Oh i get it, I must set color encoding manually
2023-11-21 02:42:02
Hi guys, I cannot find a way to set `Intensity` in libjxl
2023-11-21 02:43:05
for C++ code, one can use `jxl::SetIntensityTarget`, but it's not exposed in c api
2023-11-21 02:45:28
oh, it can be set in basic info
Demiurge
2023-11-21 06:36:39
Will djxl PNG output use fpnge in the future? I hope so...
2023-11-21 06:37:09
the PNG compression stage takes up most of the runtime of DJXL sadly
qdwang
oh, it can be set in basic info
2023-11-21 07:08:08
But setting intensity doesn't mean to make it a HDR image. According to my test here in jxl channel: https://discord.com/channels/794206087879852103/794206170445119489/1176554409040298025 Don't know how to make a 16bit PNG to be a HDR JXL
Traneptora
But setting intensity doesn't mean to make it a HDR image. According to my test here in jxl channel: https://discord.com/channels/794206087879852103/794206170445119489/1176554409040298025 Don't know how to make a 16bit PNG to be a HDR JXL
2023-11-21 09:54:31
you most likely need to set the metadata, like primaries or transfer
2023-11-21 09:55:01
untagged png typically defaults to sRGB or bt709/gamma22
afed
2023-11-22 11:13:49
how much does it affect compression? https://github.com/libjxl/libjxl/pull/2957
veluca
2023-11-22 11:53:06
Very little, it does affect speed though
Jim
2023-11-22 11:53:08
The author added test info to the pull request and the answer is... Looks like almost no change in compression, but at a loss of speed. 0.001% increase in file size: +1 KB for the file tested. 16% slower speed. 98% lower memory usage. This is what I expected just quickly glancing at the code. It looks like most of it is breaking things out into smaller functions and doing better memory management, but the author could explain it more.
afed
2023-11-22 12:09:33
due to smaller pre-buffering/cache and reading speed is the bottleneck? wondering how Halic can keep high speed, with also very low memory consumption, good tuning for data block sizes?
veluca
2023-11-22 12:43:31
part of the slowdown is just that disk IO is measured in the MP/s now ;P
2023-11-22 12:43:39
but I'll give it a pass with a profiler later
afed
2023-11-22 12:50:52
maybe add options for larger cache, memory consumption would also be higher, but still much smaller than normal mode and predictable and not depending on image size?
veluca
2023-11-22 01:30:45
Who knows 😛 I have to admit I am not sure at all where the slowdown is coming from
afed
afed how much does it affect compression? https://github.com/libjxl/libjxl/pull/2957
2023-11-22 10:03:25
https://discord.com/channels/794206087879852103/803645746661425173/1177006237913718944
Demiurge
2023-11-23 10:48:14
The slowdown is only when streaming like with pipelines?
2023-11-23 10:49:22
Maybe there's a pause to flush the output buffer and refill the input buffer?
afed
2023-11-23 11:15:56
streaming is "--streaming_input --streaming_output" modes and for HDD the difference is similar, so not like the drive speed is the main factor
qdwang
2023-11-26 01:45:33
When editing JXL files in iOS Photos App, if the transfer function in color encoding is not `HLG` or `PQ`, it will display like the screenshot. I think it's a bug caused by Photos App. But I'm wondering if there can be a tweak on libjxl options to overcome this Apple's issue..
Traneptora
2023-11-26 01:53:22
unsure if apple is using libjxl or if they are using their own implementation
Quackdoc
2023-11-26 01:55:56
Well, isn't that peculiar?
qdwang
2023-11-26 01:56:59
apple will convert any image to HEIC and edit the heic file.
2023-11-26 01:57:50
I think the problem is in the conversion
Quackdoc
2023-11-26 01:57:52
thats terrible lol
2023-11-26 01:58:08
That's so bad. Why would they do that...
lonjil
2023-11-26 01:58:23
TIL iOS contains a copy of AMD's FSR
qdwang
Quackdoc That's so bad. Why would they do that...
2023-11-26 01:58:30
Then they can keep the original file untouched for later revert
Quackdoc
Then they can keep the original file untouched for later revert
2023-11-26 01:59:29
They could use something that doesn't suck like EXR. That would be a good choice.
qdwang
2023-11-26 02:01:02
apple just love heic
Quackdoc
2023-11-26 02:11:31
Such a weird design choice.
lonjil
2023-11-26 02:15:13
oh here we go, iOS legal notices says > JPEG XL Project Authors ( libjxl ) > Copyright © the JPEG XL Project Authors. All rights reserved. > [insert license text here] Right after Joyent's events library and before jQuery.
2023-11-26 02:15:35
so they probably use libjxl
Traneptora
2023-11-26 02:20:59
it wouldn't be in the FOSS license list
qdwang
lonjil so they probably use libjxl
2023-11-26 02:26:54
im using the nightly libjxl, maybe they are using older version
2023-11-26 02:29:06
but i tried with 0.8.2 cjxl before, still causing this issue
lonjil
2023-11-26 02:29:07
i wouldn't be surprised if the version they're using is a year old
qdwang
2023-11-26 05:02:16
I tried to set the ICC profile bytes exported from Apple swift code, it still has this issue.
2023-11-27 11:12:25
Is the `have_preview` in basic info telling the encoder to generate a preview for jxl result or it's just indicating the src input contains a preview? I set `have_preview` to 1 and nothing happens.
2023-11-27 11:31:14
Another question is for `modular` encoding mode, do i only need to set `JXL_ENC_FRAME_SETTING_RESPONSIVE` to 1 to enable progressive encoding? And for `VarDCT` encoding mode, do i need to set all the three `JXL_ENC_FRAME_SETTING_PROGRESSIVE_AC`, `JXL_ENC_FRAME_SETTING_QPROGRESSIVE_AC` and `JXL_ENC_FRAME_SETTING_PROGRESSIVE_DC` to 1 to enable progressive encoding?
2023-11-27 01:49:02
It seems I only need to choose one progressive mode for VarDCT
2023-11-27 02:34:15
Will progressive encoding reduce the generating size for modular mode? I tested on a 12MB image: modular with progressive => 4.2MB jxl modular without progressive => 6.9MB jxl (by setting `JXL_ENC_FRAME_SETTING_RESPONSIVE`)
CrushedAsian255
Will progressive encoding reduce the generating size for modular mode? I tested on a 12MB image: modular with progressive => 4.2MB jxl modular without progressive => 6.9MB jxl (by setting `JXL_ENC_FRAME_SETTING_RESPONSIVE`)
2023-11-28 02:43:19
if it's that smaller why isn't it default?
Traneptora
Is the `have_preview` in basic info telling the encoder to generate a preview for jxl result or it's just indicating the src input contains a preview? I set `have_preview` to 1 and nothing happens.
2023-11-28 05:25:50
it tells you whether or not the image has a Preview Frame
CrushedAsian255 if it's that smaller why isn't it default?
2023-11-28 05:27:13
it isn't clear what other variables are controlled here. progressive enables squeeze, which isn't exactly good at lossless
2023-11-28 05:27:32
for lossy modular, squeeze is enabled by default
qdwang
CrushedAsian255 if it's that smaller why isn't it default?
2023-11-28 09:37:53
Actually the progressive setting is enable by default for modular mode. You can try it first.
Traneptora it tells you whether or not the image has a Preview Frame
2023-11-28 09:40:12
Thanks
afed
2023-11-28 02:36:21
is there any plans to use streaming by default for modes that don't get much worse, like e1, if the slowdown issues are fixed? it would be easier for ffmpeg and other software that uses libjxl, without extra options, although I don't know if ffmpeg has any capabilities for streaming input and output for images
Traneptora
afed is there any plans to use streaming by default for modes that don't get much worse, like e1, if the slowdown issues are fixed? it would be easier for ffmpeg and other software that uses libjxl, without extra options, although I don't know if ffmpeg has any capabilities for streaming input and output for images
2023-11-28 08:55:16
ffmpeg operates on a frame-by-frame basis for the most part
2023-11-28 08:56:21
the decoders receive packets, which contain enough info for a full decoded picture
2023-11-28 08:56:37
which for the most part is one packet per JXL still image
2023-11-28 08:57:55
the encoder outputs one AVPacket per frame of input, so in that regard, streaming doesn't help
gb82
lonjil TIL iOS contains a copy of AMD's FSR
2023-11-29 03:35:35
Where is it used?
Quackdoc
2023-11-29 02:42:33
this was unexpectedly very fast I didnt expect a 6s decode on this machine ```ps OS: Arch Linux i686 Host: Compaq Mini 110c-1100 0394110000001C00000300000 CPU: Intel Atom N270 (2) @ 1.600GHz GPU: Intel Mobile 945GM/GMS/GME, 943/940GML Express Memory: 215MiB / 977MiB ``````ps jxlinfo mona.jxl 11/29/2023 09:35:40 AMJPEG XL file format container (ISO/IEC 18181-2) JPEG XL image, 5221x2847, lossy, 8-bit RGB Color space: RGB, D65, sRGB primaries, sRGB transfer function, rendering intent: Relative Brotli-compressed xml metadata: 772 compressed bytes ``````ps root@archiso ~ # hyperfine --runs 5 'djxl mona.jxl --disable_output' Benchmark 1: djxl mona.jxl --disable_output Time (mean ± σ): 5.944 s ± 0.007 s [User: 10.453 s, System: 0.925 s] Range (min … max): 5.934 s … 5.954 s 5 runs hyperfine --runs 5 'djxl mona.jxl --disable_output' 53.07s user 5.03s system 188% cpu 30.790 total ```
Demiurge
2023-11-30 11:57:06
``` JPEG XL decoder v0.8.2 954b4607 [SSE4,SSSE3,SSE2] Read 14744762 compressed bytes. Decoded to pixels. 23164 x 18480, 56.52 MP/s [56.52, 56.52], 1 reps, 1 threads. real 0m7.740s user 0m6.564s sys 0m1.157s ``` I wonder why it's spending more than a full second just waiting on the system when num_threads = 1 (and disabled output)
Quackdoc
2023-11-30 12:09:13
if you run strace -c djxl ... it will tell you
2023-11-30 12:10:15
its likely futex or something taking up the brunt of it
Demiurge
2023-11-30 01:17:03
even with num_threads = 1 though?
2023-11-30 01:17:09
Seems odd
2023-11-30 01:21:06
I twonder if it's like that in the library as well, and I wonder if single threaded performance can be improved. I noticed djxl decodes images much faster than software that links to libjxl
Traneptora
Demiurge ``` JPEG XL decoder v0.8.2 954b4607 [SSE4,SSSE3,SSE2] Read 14744762 compressed bytes. Decoded to pixels. 23164 x 18480, 56.52 MP/s [56.52, 56.52], 1 reps, 1 threads. real 0m7.740s user 0m6.564s sys 0m1.157s ``` I wonder why it's spending more than a full second just waiting on the system when num_threads = 1 (and disabled output)
2023-11-30 01:48:19
num_threads=1 is one controller and one worker
2023-11-30 01:48:27
you want to set num_threads=0 to disable threading
2023-11-30 01:48:51
if num_threads = N, that means N worker threads and one master thread
2023-11-30 01:49:29
in that regard num_threads=1 is very much not useful
Demiurge
2023-11-30 02:06:36
``` --num_threads=N Sets the number of threads to use. The default 0 value means the machine default. ```
Traneptora
Demiurge ``` --num_threads=N Sets the number of threads to use. The default 0 value means the machine default. ```
2023-11-30 02:07:14
they must have changed how that works then
Demiurge
2023-11-30 02:07:34
I can confirm that it's decoding on multiple threads when set to 0
2023-11-30 02:07:55
anyways it just seems like an unexpectedly large amount of sys overhead
sklwmp
2023-11-30 02:08:09
cjxl says: ``` --num_threads=N Number of worker threads (-1 == use machine default, 0 == do not use multithreading). ``` djxl says: ``` --num_threads=N Sets the number of threads to use. The default 0 value means the machine default. ```
2023-11-30 02:08:14
weirdly inconsistent
Traneptora
2023-11-30 02:08:17
interesting
afed
2023-11-30 02:09:04
JPEG XL decoder v0.10.0 77a39356 `Number of worker threads (-1 == use machine default, 0 == do not use multithreading).`
sklwmp
2023-11-30 02:09:52
ah yes, they fixed it in git master
Demiurge
2023-11-30 02:16:24
...what happened to 0.9?
w
2023-11-30 02:18:11
789
afed
2023-11-30 02:19:19
0.9 for upcoming release, 0.10 current dev git version
Demiurge
w 789
2023-11-30 02:20:31
lol. Good answer
2023-12-01 02:49:33
I hope fpnge will be integrated into djxl soon in a release. Many have already gotten a bad impression of decoding times thanks to the slow PNG encoding
2023-12-01 02:50:21
And they aren’t aware that it is not the decoding that takes a long time, but the PNG encoding
veluca
2023-12-01 07:31:11
send a pr 🙂
2023-12-01 07:31:23
but the bigger issue is that it's x86 only...
Demiurge
2023-12-01 09:34:48
I haven’t taken a look at djxl’s source yet, so I don’t even know why it’s so slow to begin with, or what library it’s using
tufty
2023-12-01 12:53:53
I tried making a deepzoom image using JXL as the tile format http://www.rollthepotato.net/~john/deepzoom-jxl/
2023-12-01 12:54:10
it actually works! you need safari on macos though (of course)
2023-12-01 12:55:23
looks like this in on a mac:
2023-12-01 12:55:31
it's very fast and smooth!
2023-12-01 12:56:01
it's a 46,000 x 32,000 pixel image from openslide
2023-12-01 12:56:31
I had to add a tiny patch to openseadragon to add jxl to the list of allowed tile formats, but that's all
2023-12-01 12:59:55
so .... my feeling is that JXL needs a tiled mode to make it useful for larger images at the moment, JXL is not practical for images larger than about 2k x 2k (imo), making it unsuitable even for large cell phone pictures
Quackdoc
tufty so .... my feeling is that JXL needs a tiled mode to make it useful for larger images at the moment, JXL is not practical for images larger than about 2k x 2k (imo), making it unsuitable even for large cell phone pictures
2023-12-01 01:11:25
Interesting that you have come to that conclusion. even my old winxp compaq only needs 5s to decode an `5221x2847` image, my s9+ with libjxl 0.8.2 it can decode a `7680x4320` in 2s on a single thread, when little libjxl go as many threads as it wants, it's 0.5s on a lossless jpeg transcode. for an image without reconstruction, it still only takes 4s, IMO that's still quite fast and iirc libjxl git is quite a bit faster then this.
tufty
Quackdoc Interesting that you have come to that conclusion. even my old winxp compaq only needs 5s to decode an `5221x2847` image, my s9+ with libjxl 0.8.2 it can decode a `7680x4320` in 2s on a single thread, when little libjxl go as many threads as it wants, it's 0.5s on a lossless jpeg transcode. for an image without reconstruction, it still only takes 4s, IMO that's still quite fast and iirc libjxl git is quite a bit faster then this.
2023-12-01 01:16:30
the main issue is memory use, for example: ``` $ /usr/bin/time -f %M:%e vips copy nina.jpg nina.jxl 2302672:4.45 ``` 2.3gb of ram to encode a 6k x 4k jpg you need a tiled format to get memory use during encode and decode under control (imo)
veluca
2023-12-01 01:17:33
we're working on that
2023-12-01 01:17:37
without tiles 😉
2023-12-01 01:18:09
i.e. cjxl -e1 -d0 will encode pretty much any PPM using only \~10mb of memory
tufty
2023-12-01 01:18:56
doesn't it still need to have the whole input image in memory though?
veluca
2023-12-01 01:19:08
that's why I said ppm
2023-12-01 01:19:10
😉
2023-12-01 01:19:21
it's not needed now
2023-12-01 01:19:31
(with the streaming encoding API)
tufty
2023-12-01 01:20:39
the streaming encoding API is push, not pull, so it's very hard to use a tiled mode would be much, much simpler for downstream libraries to integrate
veluca
2023-12-01 01:21:23
> the streaming encoding API is push, not pull, so it's very hard to use did you mean pull and not push?
tufty
2023-12-01 01:21:49
hehe I suppose it depends where you sit
veluca
2023-12-01 01:21:49
the streaming *decoding* API is push and not pull, and I can see that being problematic
2023-12-01 01:21:54
(also on the todo list)
2023-12-01 01:23:01
currently streaming encoding does "please give me this rectangle of pixels"
2023-12-01 01:23:42
and streaming decoding will give you some pixels somewhere without particular guarantees on where (but that can be fixed with reasonable effort)
tufty
2023-12-01 01:23:54
ooop you're right, sorry, I meant the decode API
2023-12-01 01:24:38
not enough coffee
veluca
2023-12-01 01:24:42
hehe
2023-12-01 01:25:05
btw, does alignment of the rectangles we ask for in the encoder API matter?
2023-12-01 01:25:47
(it is reasonable to promise 128-alignment and 128x size, but it is also a lot simpler if we can only promise, say, 16x alignment and size)
tufty
2023-12-01 01:27:37
libvips would like to give libjxl top to bottom strips, ideally imagine converting a PNG to JXL (for example) ... libpng will supply pixels top to bottom in strips, so if the saver needs something other than that, there will have to be a lot of buffering somewhere
veluca
2023-12-01 01:27:57
yeah there's nothing that can be done about that
tufty
2023-12-01 01:27:58
ah you mean pixel alignment? no, doesn't matter
veluca
2023-12-01 01:28:15
jxl is internally tiled
2023-12-01 01:28:31
so *somewhere* something needs to buffer to convert to/from formats that decode top-down
2023-12-01 01:29:23
IIRC stuff newer than webp is like that
tufty
2023-12-01 01:30:51
do you plan to support "please give me this rect of pixels" in the decode api? that would be very nice
veluca
2023-12-01 01:31:12
plan is a strong word, but it might be the next thing we do after streaming encoding
tufty
2023-12-01 01:31:25
hehe
2023-12-01 01:31:47
ok, then I shall continue to wait patiently and stop asking for a tiled mode
2023-12-01 01:31:57
thanks for clearing this up for me!
veluca
2023-12-01 01:32:35
fwiw, the current streaming decoding API *will* give you things in 128x128 to 2048x2048 tiles, likely in top-to-bottom order
2023-12-01 01:32:45
(plus or minus a few pixels here and there)
tufty
2023-12-01 01:32:45
(^^ that deepzeoom JXL demo is fun btw, if you can find a mac)
veluca
2023-12-01 01:33:25
(in fact, you'll get the tiles in the order that they are in the file, modulo threads, which is usually raster order)
tufty
2023-12-01 01:33:36
I don't think I'll be able to use the current streaming decode API, I'll wait for a pull version
veluca
2023-12-01 01:33:43
yeah that seems fair
2023-12-01 01:34:15
but streaming encoding is IMO the more urgent thing, decoding is fairly well memory optimized and takes little more than the output
tufty
2023-12-01 01:34:18
I'll add streaming encode though, that seems pretty easy
veluca
2023-12-01 01:34:38
encoding OTOH can easily take ludicrous amounts of memory
tufty I'll add streaming encode though, that seems pretty easy
2023-12-01 01:35:08
yeah it will not really help for now (except -d0 -e1, and even that is ~alpha), but working on it...
afed
2023-12-01 02:15:28
is there any png encoders/decoders that support streaming? to also support one of the most used compressed formats libpng as far as I know?
tufty
2023-12-01 02:19:59
libspng too
2023-12-01 02:20:37
libheif (AVIF and HEIC) and libwebp don't have streaming, but I can't think of others offhand