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

Demiurge
2025-09-16 11:23:37
It was originally introduced in server processors and it does not have a benefit unless your scheduler is the bottleneck.
2025-09-16 11:24:24
So unless you are actually starved for available CPU threads, you are lowering your core performance.
2025-09-16 11:25:36
It makes sense to me because you cannot get anything for free. 1 core is still 1 core.
2025-09-16 11:26:06
It's a tradeoff that only makes sense in a very specific scenario
jonnyawsom3
Demiurge So unless you are actually starved for available CPU threads, you are lowering your core performance.
2025-09-16 11:30:46
And yet it's 30% faster https://discord.com/channels/794206087879852103/804324493420920833/1417402872093605948
Meow
2025-09-16 11:51:25
Is it still possible to see the release of v0.12 this year?
A homosapien
2025-09-16 11:55:22
I hope it releases this year
ignaloidas
Demiurge So unless you are actually starved for available CPU threads, you are lowering your core performance.
2025-09-16 11:56:10
unequivocally false - having SMT enabled it at most a minute drop in performance in wast majority of workloads unless you're having another thread using the same core. And even then, you're commonly gaining overall system performance with it, it only makes sense to disable when you have programs that can and do utilize most of the cores resources - which essentially is only HPC. Otherwise, having SMT off only helps if you're single-thread bottlenecked and you don't want said thread to compete with some other thread with core's resources - but that's not what's happening with JXL, because you wouldn't see much of a performance uplift with extra cores if that was the case
jonnyawsom3
Meow Is it still possible to see the release of v0.12 this year?
2025-09-16 11:56:47
Depends. There's a lot of pending things, including a spec change that needs to be resolved, and quite a few tests I need to run before making PRs to squeeze in
ignaloidas unequivocally false - having SMT enabled it at most a minute drop in performance in wast majority of workloads unless you're having another thread using the same core. And even then, you're commonly gaining overall system performance with it, it only makes sense to disable when you have programs that can and do utilize most of the cores resources - which essentially is only HPC. Otherwise, having SMT off only helps if you're single-thread bottlenecked and you don't want said thread to compete with some other thread with core's resources - but that's not what's happening with JXL, because you wouldn't see much of a performance uplift with extra cores if that was the case
2025-09-16 11:59:23
That last statement might not be true for djxl as we found out, but certainly still holds for cjxl. Perhaps since decoding is already so optimized, there's no spare instructions for the second thread in the core while the encoding is much more dynamic and branching
Demiurge
And yet it's 30% faster https://discord.com/channels/794206087879852103/804324493420920833/1417402872093605948
2025-09-16 12:15:55
I would be surprised if it's not still faster with 8 threads and SMT disabled in the BIOS.
ignaloidas unequivocally false - having SMT enabled it at most a minute drop in performance in wast majority of workloads unless you're having another thread using the same core. And even then, you're commonly gaining overall system performance with it, it only makes sense to disable when you have programs that can and do utilize most of the cores resources - which essentially is only HPC. Otherwise, having SMT off only helps if you're single-thread bottlenecked and you don't want said thread to compete with some other thread with core's resources - but that's not what's happening with JXL, because you wouldn't see much of a performance uplift with extra cores if that was the case
2025-09-16 12:19:34
Like I said, I only get a small boost when going from 12 to 13 threads on my 12 core SMT2 machine, and going from 13 to 14 threads yields no benefit at all.
2025-09-16 12:20:54
And the energy use of the CPU actually seems to go DOWN when I keep adding more threads.
2025-09-16 12:21:42
My CPU is drawing LESS power, which indicates that it's tapping into LESS available hardware resources.
2025-09-16 12:22:05
It gets the hottest when I am using only 12 threads.
2025-09-16 12:22:57
This is just my personal experience so far.
2025-09-16 12:23:07
And it makes sense to me.
2025-09-16 12:23:28
I don't expect SMT to be magic
2025-09-16 12:24:00
The CPU only has 12 physical cores.
2025-09-16 12:25:24
It's just a hardware scheduler.
ignaloidas
That last statement might not be true for djxl as we found out, but certainly still holds for cjxl. Perhaps since decoding is already so optimized, there's no spare instructions for the second thread in the core while the encoding is much more dynamic and branching
2025-09-16 12:39:22
Decoding fits the template of "math heavy code with little branching" so I would agree that it probably doesn't gain much from SMT. But I doubt it loses much either
jonnyawsom3
2025-09-16 12:40:40
CPU time doubled, but user time stayed the same. Probably because more threads *were* in 'use', but SMT had to wait for the main cores anyway so half the registered CPU time was just idling
Demiurge
CPU time doubled, but user time stayed the same. Probably because more threads *were* in 'use', but SMT had to wait for the main cores anyway so half the registered CPU time was just idling
2025-09-16 01:08:35
Do you mean "wall time" instead of "user time?"
jonnyawsom3
2025-09-16 01:09:17
Yes
DZgas Ж
2025-09-20 11:00:38
Even with 24GB of memory I still can't encode a 64000x64000 image in jpeg xl <:PepeSad:815718285877444619>
2025-09-20 11:11:48
*For encoding in jpeg cjpeg (mozjpeg) I use the "-revert" flag, encoding uses two megabytes of memory*
Kupitman
DZgas Ж Even with 24GB of memory I still can't encode a 64000x64000 image in jpeg xl <:PepeSad:815718285877444619>
2025-09-20 11:20:56
Windows.
jonnyawsom3
2025-09-20 11:33:23
4 Gigapixels.... How much memory does that use to load?
DZgas Ж
4 Gigapixels.... How much memory does that use to load?
2025-09-20 11:46:07
to open and show 12 gb
Kupitman Windows.
2025-09-20 11:46:56
Screenshot.
Kupitman
2025-09-20 11:47:02
Windows.
2025-09-20 11:47:24
Windows user saying something about ram usage..
DZgas Ж
2025-09-20 11:48:01
Ragebait trolling
Kupitman
2025-09-20 11:48:36
🤣
Quackdoc
DZgas Ж Even with 24GB of memory I still can't encode a 64000x64000 image in jpeg xl <:PepeSad:815718285877444619>
2025-09-20 02:40:09
yeah, libjxl and jxl-oxide memory optimization isn't quite there for decoding sadly.
DZgas Ж
2025-09-20 02:40:25
<:FeelsSadMan:808221433243107338>
A homosapien
2025-09-20 03:24:21
jxl-rs will save <:Stonks:806137886726553651>
Quackdoc
2025-09-20 03:24:51
i wait [PepeHappy](https://cdn.discordapp.com/emojis/654081052012314643.webp?size=48&name=PepeHappy)
lonjil
2025-09-20 04:24:11
How's jxl-rs looking for object size?
veluca
2025-09-20 04:48:38
no clue, but also not super relevant for now 😛
0xC0000054
2025-09-21 11:01:35
Does anyone know of a source for Float16 and Float32 JXL images? I looked through the conformance repository and didn't see any.
jonnyawsom3
2025-09-22 09:46:03
I was converting to PFM and then encoding myself, or exporting from Krita using Blender renders/EXR test files
2025-09-22 12:08:02
Also, this may be noteworthy https://github.com/libjxl/libjxl/issues/3881
0xC0000054
2025-09-22 06:40:04
I managed to create Float16 and Float32 documents by creating new documents in Krita.
2025-09-22 06:43:34
All of my tests with existing JXL HDR images were being saved as 16-bit integer, even though Krita was loading the documents as 32-bit float. No idea why Krita was doing that, but I found the behavior confusing.
jonnyawsom3
0xC0000054 All of my tests with existing JXL HDR images were being saved as 16-bit integer, even though Krita was loading the documents as 32-bit float. No idea why Krita was doing that, but I found the behavior confusing.
2025-09-22 06:46:23
I assume the images were lossy? Krita always loads lossy JXLs as 32-bit float since that's the internal VarDCT representation, the original bitdepth (16-bit int) is purely metadata. Lossless maintains the original bitdepth
0xC0000054
I assume the images were lossy? Krita always loads lossy JXLs as 32-bit float since that's the internal VarDCT representation, the original bitdepth (16-bit int) is purely metadata. Lossless maintains the original bitdepth
2025-09-22 06:55:49
Yes they were lossy. Is that just a performance optimization on Krita's part or are there other advantages over asking libjxl to output an integer format?
jonnyawsom3
2025-09-22 07:00:06
Could ask <@274048677851430913>, I always assumed it's because float is more accurate even when the original file is int. IIRC creating a canvas first will have libjxl decode to the current format instead
Kampidh
2025-09-22 07:02:51
iirc Krita always load any HDR images to linear F32, whether it's JXL, PNG, or AVIF
jonnyawsom3
0xC0000054 Does anyone know of a source for Float16 and Float32 JXL images? I looked through the conformance repository and didn't see any.
2025-09-22 07:14:10
That does raise a point though, <@794205442175402004> shouldn't there be conformance and regression tests for floats? Could even have one of half stored in full, such as converted .HDR files
_wb_
2025-09-22 07:56:55
https://github.com/libjxl/conformance/tree/master/testcases/lossless_pfm
2025-09-22 07:57:06
That one is supposed to test lossless float32
0xC0000054
_wb_ https://github.com/libjxl/conformance/tree/master/testcases/lossless_pfm
2025-09-22 09:48:36
I missed that in the readme. Out of curiosity, what are the sourcetree files? The testcases/blendmodes/sourcetree file looks like it is used to generate the matching test image, but I didn't see any code that uses that file.
jonnyawsom3
0xC0000054 I missed that in the readme. Out of curiosity, what are the sourcetree files? The testcases/blendmodes/sourcetree file looks like it is used to generate the matching test image, but I didn't see any code that uses that file.
2025-09-22 10:07:45
It's <#824000991891554375>, handmade MA trees using the lossless mode of JXL for ultra small images. You can try them here https://jxl-art.lucaversari.it/
Lilli
2025-09-23 02:03:41
uint32_t bits_per_sample; < what you call a sample is a triplet RGB, or is it considered 3 samples?
jonnyawsom3
2025-09-23 02:25:13
Sample is per channel, combined is per pixel (I think)
Lilli
2025-09-23 03:16:01
Thanks 🙂
_wb_
2025-09-24 07:54:20
In RGB, every pixel consists of three samples. In grayscale there's just one sample per pixel, in CMYK there are four.
Lilli
2025-09-25 10:17:45
How do I give a float32 buffer so that it is losslessly compressed as if it was 16bits precision?
2025-09-25 10:18:08
because in c++ there's no float16 type (yet)
2025-09-25 10:19:42
just changing JxlDataType to JXL_TYPE_FLOAT16 doesn't seem to be enough
2025-09-25 10:21:25
afaik once compressed, everything is stored as float32 anyway, so, I just want djxl to read my jxl as a 16bits image
2025-09-25 10:23:40
Do I need to manually feed actual 16bit float? or should I convert to 16bits by multiplying by 65535 on the fly and casting to uint16_t?
jonnyawsom3
2025-09-25 10:25:48
Lossy VarDCT is always float32, but lossless stores the original bit depth. Not sure how best to do it though
spider-mario
Lilli Do I need to manually feed actual 16bit float? or should I convert to 16bits by multiplying by 65535 on the fly and casting to uint16_t?
2025-09-25 11:13:14
either would work, but with different results
Lilli
Lossy VarDCT is always float32, but lossless stores the original bit depth. Not sure how best to do it though
2025-09-25 11:29:27
Ah, so lossless does care about bit depth then, that makes sense... wouldn't be lossless otherwise. I'll convert it to 16bits then and we'll see ! My data is normalized [0,1], so I assume it'd make more sense to use uint16_t since I'd keep more precision than with float16 [0,1]
spider-mario
2025-09-25 12:47:11
depends on your exact data (f16 has higher precision for very small values), but for sensor data, I would expect integers to be perfectly fine (the data from the sensor is likely uniformly quantized itself, and too noisy to warrant the small-value precision anyway)
jonnyawsom3
2025-09-25 01:21:01
I did try to see if any cameras output float, but apparently not
spider-mario
2025-09-25 02:21:02
I doubt there would be much of a point
Lilli
2025-09-25 02:22:50
No but it's the result of a stacking of many camera raws x)
2025-09-25 02:23:02
So it's quite a lot more precise than 16bits
2025-09-25 02:43:23
(but I need 16b output)
jonnyawsom3
2025-09-25 02:48:14
I was thinking of a theoretical world going from the analogue sensor values to float values above 1, to basically remove over and under exposure. But anyway
Lilli
2025-09-25 02:49:39
Anyway, I succeeded in making the float becoming uint16_t on the fly, it works, but it doesn't behave at at all like the lossy one on decompress
jonnyawsom3
2025-09-25 02:54:37
Lossy would've been decoding to the requested format and color space, lossless will be whatever profile it was encoded with, so it could be a viewer issue
Lilli
2025-09-25 04:08:34
It's the android libjxl port that was fine decoding the lossy as float16, but now that I do lossless, it's complaining it's not 16bits There's something wrong with either GIMP's plug-in, or my export parameters/flags I think: I made the test, I created a JXL file from my buffer (float32 [0,1] then stretched to 16bits). When opening it in gimp, I got some bad quality artifacts like it had less bins to go with ( as shown by the histogram ). But then I converted the jxl to a tif, so 16bits to 16bits, I also dumped the value representation, and they are nearly identical.
2025-09-25 04:08:39
JXL
2025-09-25 04:08:49
TIFF
2025-09-25 04:08:51
2025-09-25 04:09:45
Note that the tiff is created using the jxl (I decompress it with libjxl, then export a tif)
2025-09-25 04:19:52
Is it a problem of specifying linear vs perceptual ? Is that what you mean <@238552565619359744>
2025-09-25 04:23:41
Indeed, that's it. I have the exact same histogram as the TIF when using `JxlColorEncodingSetToSRGB` vs using `JxlColorEncodingSetToLinearSRGB` -> why does it matter for lossless? also the filesize has reduced quite a bit... from 122MB to 95MB
2025-09-25 04:26:41
(good news for me hehe)
Lumen
Lilli How do I give a float32 buffer so that it is losslessly compressed as if it was 16bits precision?
2025-09-25 07:06:22
you can do some integer tricks
2025-09-25 07:06:31
the representation of fp32 is quite similar to fp16
2025-09-25 07:06:34
you just need to cut some part
2025-09-25 07:06:45
https://tenor.com/view/monster-naoki-urasawa-kenzo-tenma-surgery-gif-6268996817967018326
spider-mario
2025-09-25 07:24:32
(edge case: some normal f32 become denormals as f16)
2025-09-25 07:24:53
(all f16 denormals are normal as f32)
2025-09-25 07:25:55
(and all f32 denormals round to 0 as f16)
2025-09-25 07:26:34
useful website: https://float.exposed/
Lilli
2025-09-26 08:01:29
Nice !
2025-09-26 08:24:05
Is there any performance impact with respect to using linear sRGB or plain sRGB?
spider-mario
2025-09-26 08:26:04
for lossless? not as far as libjxl is concerned
Lilli
2025-09-26 08:27:30
Yes for lossless 🙂 Thanks for your answer
2025-09-26 08:27:42
But then why is the filesize smaller?
spider-mario
2025-09-26 12:54:03
I’m not sure at all – is it really the only change, and the compression 100% confirmed to be lossless?
2025-09-26 12:54:15
maybe <@794205442175402004> might have an idea?
_wb_
2025-09-26 12:55:05
are you talking about same sample data, different color space tag? or sample data converted to different color space before encoding it losslessly?
jonnyawsom3
Lilli Indeed, that's it. I have the exact same histogram as the TIF when using `JxlColorEncodingSetToSRGB` vs using `JxlColorEncodingSetToLinearSRGB` -> why does it matter for lossless? also the filesize has reduced quite a bit... from 122MB to 95MB
2025-09-26 12:57:00
More info above
_wb_
2025-09-26 12:58:44
Yes but I still don't understand what the workflow is here. What's the original data and how is it getting encoded?
Lilli
2025-09-26 01:11:15
https://drive.google.com/drive/folders/11xCyipF-Dx1BGXKKec6Ye8Xr5LQiEiSY?usp=sharing Image in 16bits covering 0-65535 -> compress losslessly (distance 0 + `JxlEncoderSetFrameLossless`) When using `JxlColorEncodingSetToLinearSRGB` -> 122MB When using `JxlColorEncodingSetToSRGB`-> 95MB The input data is the exact same binary uint16_t
2025-09-26 01:12:31
Using streaming encoding: chunking and outputprocessor
_wb_
2025-09-26 01:14:25
that is weird, it should not make more than 1 byte or so difference (just the header should be different)
Lilli
2025-09-26 01:14:55
I was very surprised as well, so I'm wondering if I'm doing something wrong somehow
_wb_
2025-09-26 01:15:13
and both are actually lossless?
Lilli
2025-09-26 01:15:37
well, almost, compared to my tiff output there are very minor differences
_wb_
2025-09-26 01:16:05
there should not be any difference at all if it's lossless
Lilli
2025-09-26 01:16:18
I thought the same and yet here we are ...
2025-09-26 01:18:20
I thought that for lossless, distance 0 + setFrameLossless were enough, but maybe there's more ?
_wb_
2025-09-26 01:32:05
``` $ compare -verbose -metric pae Original_stack.png converted_sRGB.jxl null: Found a generic profile, type exif Original_stack.png PNG 6643x7526 6643x7526+0+0 16-bit TrueColor sRGB 102.625MiB 0.830u 0:00.841 converted_sRGB.jxl JXL 6643x7526 6643x7526+0+0 16-bit sRGB 91.1145MiB 2.830u 0:00.442 Image: Original_stack.png Channel distortion: PAE red: 12 (0.000183108) green: 7 (0.000106813) blue: 45 (0.000686656) all: 45 (0.000686656) Original_stack.png=> PNG 6643x7526 16-bit sRGB 102.625MiB 8.230u 0:01.152 ```
2025-09-26 01:32:21
``` $ compare -verbose -metric pae Original_stack.png converted_linear_sRGB.jxl null: Found a generic profile, type exif Original_stack.png PNG 6643x7526 6643x7526+0+0 16-bit TrueColor sRGB 102.625MiB 0.840u 0:00.839 converted_linear_sRGB.jxl JXL 6643x7526 6643x7526+0+0 16-bit RGB 116.902MiB 3.050u 0:01.043 Image: Original_stack.png Channel distortion: PAE red: 18 (0.000274662) green: 10 (0.00015259) blue: 63 (0.000961318) all: 63 (0.000961318) Original_stack.png=> PNG 6643x7526 16-bit sRGB 102.625MiB 8.070u 0:00.978 ```
2025-09-26 01:32:38
``` bash-3.2$ cjxl Original_stack.png converted-cjxl.jxl -d 0 JPEG XL encoder v0.11.1 0.11.1 [NEON] Encoding [Modular, lossless, effort: 7] Compressed to 72892.0 kB including container (11.664 bpp). 6643 x 7526, 6.387 MP/s [6.39, 6.39], , 1 reps, 12 threads. bash-3.2$ compare -verbose -metric pae Original_stack.png converted-cjxl.jxl null: Found a generic profile, type exif Original_stack.png PNG 6643x7526 6643x7526+0+0 16-bit TrueColor sRGB 102.625MiB 0.830u 0:00.828 converted-cjxl.jxl JXL 6643x7526 6643x7526+0+0 16-bit sRGB 69.5153MiB 8.610u 0:00.908 Image: Original_stack.png Channel distortion: PAE red: 0 (0) green: 0 (0) blue: 0 (0) all: 0 (0) Original_stack.png=> PNG 6643x7526 16-bit sRGB 102.625MiB 8.350u 0:01.013 ```
2025-09-26 01:33:20
``` $ jxlinfo converted_sRGB.jxl JPEG XL image, 6643x7526, lossy, 16-bit RGB intensity_target: 64000.000000 nits min_nits: 0.000000 relative_to_max_display: 0 linear_below: 0.000000 Color space: RGB, D65, sRGB primaries, sRGB transfer function, rendering intent: Relative ```
Lilli
2025-09-26 01:33:37
It's considered lossy ?
2025-09-26 01:35:39
I'm not sure I understand why
_wb_
2025-09-26 01:36:00
probably using XYB
Lilli
2025-09-26 01:37:25
I never set XYB though
_wb_
2025-09-26 01:38:02
you have to set `uses_original_profile` to true when setting the BasicInfo
2025-09-26 01:38:19
otherwise the image will be converted to XYB
Lilli
2025-09-26 01:38:56
I need to do that only for lossless I suppose
_wb_
2025-09-26 01:39:01
yes
jonnyawsom3
2025-09-26 01:41:37
IIRC doesn't it throw an error now if you try to do lossless XYB?
_wb_
2025-09-26 01:53:12
that would probably be a useful thing to do
Lilli
2025-09-26 02:05:57
Woow, just activating this line gives me this: `lBasicInfo.uses_original_profile = JXL_TRUE;`
2025-09-26 02:06:07
Very nice 😄
_wb_
2025-09-26 02:12:26
that doesn't look right
Lilli
2025-09-26 02:12:39
indeed x)
2025-09-26 02:13:22
as float 16 that's what I get
2025-09-26 02:13:43
but as uint16 I get what's expected and I also get smaller file even
2025-09-26 02:14:11
and jxlinfo says (possibly) lossless
_wb_
2025-09-26 02:15:09
looks like something is broken, can you open a github issue with how you got to that glitchy image? could be some combination of settings that causes chunked encode to break
Lilli
2025-09-26 02:15:50
sure, I will try to do that next week as I need to wrap things up for today
2025-09-26 02:16:06
Thanks for your help ! very nice to gain a few MB
jonnyawsom3
IIRC doesn't it throw an error now if you try to do lossless XYB?
2025-09-26 02:18:10
Ah, I was thinking of this https://github.com/libjxl/libjxl/pull/4238, but it only sets `JxlEncoderSetFrameLossless` when distance is set to 0, not `uses_original_profile `
Lilli Woow, just activating this line gives me this: `lBasicInfo.uses_original_profile = JXL_TRUE;`
2025-09-26 02:21:13
Almost looks like a decoder issue, some of the groups are overlapping or completely off-grid
_wb_
2025-09-26 02:24:20
I would be surprised if it's a decoder issue, to me it looks like an encode-side buffer management/lifetime issue that could be either caused by inappropriate API usage or some bug in libjxl. This kind of thing is what you get if a buffer is overwritten while it is getting consumed.
Lilli
_wb_ I would be surprised if it's a decoder issue, to me it looks like an encode-side buffer management/lifetime issue that could be either caused by inappropriate API usage or some bug in libjxl. This kind of thing is what you get if a buffer is overwritten while it is getting consumed.
2025-09-26 02:28:52
Very strong guess, when setting the runner to 1 thread this issue disappears.
spider-mario
2025-09-26 02:31:52
during encoding or decoding?
Lilli
2025-09-26 02:32:57
Encoding. Because I was setting a buffer in getColorChannelDataAt (the callback) that corresponds to the desired area, converting on the fly my float32 to float16 so that I don't need an entire copy of my image But this buffer isn't thread-safe, and there is no notion of thread id in getColorChannelDataAt
2025-09-26 03:52:09
So right now I just new[] something inside this function, I will benchmark whether using some more sophisticated memory management makes sense.
jonnyawsom3
2025-09-27 01:31:45
Apple dev and AOM head is having some trouble, think they might be mixing up streamed and chunked encoding, but I don't want to give them incorrect info https://github.com/libjxl/libjxl/issues/4459
Melirius
2025-10-09 07:30:43
Hi, I'm analyzing the code of CfL and this line is very suspicious for me: https://github.com/libjxl/libjxl/blob/2a4f12b6ef22672e0f4a399df3b8589856ebace2/lib/jxl/enc_frame.cc#L1012 Effectively on JPEG DCT coefs here quantization table is applied in transposed form, while the coefficients themselves are not transposed. Is it some clever trick or just misprint?
2025-10-09 07:33:14
Even more suspicious this line makes the fact that earlier to find CfL coefficient https://github.com/libjxl/libjxl/blob/2a4f12b6ef22672e0f4a399df3b8589856ebace2/lib/jxl/enc_frame.cc#L884 this quantization table is applied in non-transposed form
_wb_
2025-10-09 08:00:31
It is very well possible that there is some bug in there — though jpegs do roundtrip, so I'm not sure if it's possible that there's something as bad as incorrect coefficient order is going on
jonnyawsom3
2025-10-09 11:45:51
IIRC isn't CFL a JXL only decode feature? So the roundtrip shouldn't be effected. I do recall disabling CFL was better in our tests a long time ago, maybe that's why
_wb_
2025-10-10 07:41:14
no, the point of cfl is to change the quantized dct coefficients that are actually stored, and it can also be applied to recompressed jpegs but only if they're 4:4:4 (cfl is not defined in the subsampled case iirc). I remember we did have to be careful to make sure the original quantized coeffs could still be reconstructed though
2025-10-10 07:41:34
something else, looks like we need to update something in the gdk-pixbuf stuff: ``` /Users/jonsneyers/dev/libjxl/plugins/gdk-pixbuf/pixbufloader-jxl.c:85:15: error: 'gdk_pixbuf_animation_iter_get_type' is deprecated [-Werror,-Wdeprecated-declarations] 85 | GDK_TYPE_PIXBUF_ANIMATION_ITER); | ^ /opt/homebrew/include/gdk-pixbuf-2.0/gdk-pixbuf/gdk-pixbuf-animation.h:48:54: note: expanded from macro 'GDK_TYPE_PIXBUF_ANIMATION_ITER' 48 | #define GDK_TYPE_PIXBUF_ANIMATION_ITER (gdk_pixbuf_animation_iter_get_type ()) | ^ ```
Tirr
2025-10-10 09:06:17
libjxl does integer cfl directly on quantized coeffs during reconstruction, to make sure the original coeffs are recovered exactly
2025-10-10 09:08:09
I wonder if 18181-2 spec has the pseudocode of integer cfl
Melirius
_wb_ It is very well possible that there is some bug in there — though jpegs do roundtrip, so I'm not sure if it's possible that there's something as bad as incorrect coefficient order is going on
2025-10-10 09:29:46
Yes, this is indeed a misprint, but earlier: quantization is in transposed form already, https://github.com/libjxl/libjxl/blob/2a4f12b6ef22672e0f4a399df3b8589856ebace2/lib/jxl/enc_frame.cc#L811, so the correct is to use transposed `scaled_qtable` everywhere (on line 884, specifically). It also slightly helps with JPEG compression ratio on files with non-symmetric tables (e.,g. 18559200 -> 18550162), as now correlations are closer to real ones 🙂 I'll prepare an MR to fix
2025-10-10 09:36:49
Effectively it appears that correlation coefficients were off, but it does not affect reconstruction as they are stored in the JXL file and allow to reconstruct JPEG again bitcorrect
2025-10-10 11:42:52
Made PR https://github.com/libjxl/libjxl/pull/4477
_wb_
2025-10-10 12:54:27
Nice! There are probably more of such minor encoder bugs, stuff that doesn't cause anything to break but that is still suboptimal.
2025-10-10 12:57:42
I wonder why non-symmetric quantization tables are used in JPEG, at least for 4:4:4 images (for 4:2:2 images I can understand why)
2025-10-10 12:59:52
that is, why treat horizontal signals different from vertical signals? it doesn't really make sense to me, especially considering that often the actual image orientation is modified in Exif
Melirius
_wb_ that is, why treat horizontal signals different from vertical signals? it doesn't really make sense to me, especially considering that often the actual image orientation is modified in Exif
2025-10-10 01:06:23
If the tables are fitted to the image, some asymmetry is expected. Also `Table K.1 – Luminance quantization table` from JPEG standard is asymmetric
_wb_
2025-10-10 01:07:09
does any encoder fit quant tables to the image? seems tricky
2025-10-10 01:07:30
I know the Annex K tables are asymmetric but I always wondered why
Melirius
_wb_ I know the Annex K tables are asymmetric but I always wondered why
2025-10-10 01:23:04
I think as we have eyes placed horizontally, we are more sensitive to horizontal changes: standard tables are less grained along horizontal direction
_wb_
2025-10-10 01:25:10
yeah but if you rotate your camera, the orientation of the encoded image data does not match the actual/rendered image orientation
Melirius
2025-10-10 01:29:46
Wow, CI is failing on skcm https://github.com/libjxl/libjxl/actions/runs/18405468224/job/52449627594?pr=4477
2025-10-10 06:04:03
I've experimented a bit: if I use an average between the first and last max bin index for CfL, JPEG compression is even better, that makes sense in view of the statistical modelling applied. Performance is effectively unaffected, so should I prepare a PR for such an improvement?
2025-10-10 06:04:43
Or there were some obscure reasons to use the first max bin index?
_wb_
2025-10-10 07:34:57
No, go ahead, just make sure to check if the improvement is consistent across jpegs from various sources
JKUser4592
2025-10-14 07:29:24
Are there currently any Android apps that can play animated JXL files on mobile devices?
jonnyawsom3
2025-10-14 07:57:31
You already asked in <#794206170445119489> and Reddit
HCrikki
2025-10-14 08:28:25
oupson's jxlviewer says it explicitly supports animated images as well. just tried on recent android, it works (iinm old android versions may lack the mime for jxl) you can get it from github, google play, and fdroid/izzydroid
2025-10-14 08:29:42
however its not a gallery app. with specific images (ie from file manager or another gallery), you can choose to "open with" jxlviewer
2025-10-14 08:31:21
https://github.com/oupson/jxlviewer
RaveSteel
HCrikki however its not a gallery app. with specific images (ie from file manager or another gallery), you can choose to "open with" jxlviewer
2025-10-14 08:50:18
It does work as a gallery now, with in-app file selection etc.
2025-10-14 08:50:23
But it is pretty slow
HCrikki
2025-10-14 08:51:35
didnt show all folders for me, only 2 with missing images. no configurable options either
2025-10-14 08:53:46
fossify and poc had an issue before that a folder with jxls HAD to have at least one image in another format before the app would show that folder. maybe related
JKUser4592
RaveSteel But it is pretty slow
2025-10-15 12:56:06
yeah, it was very slow the first time it plays them. But then it suddenly crashes.
jonnyawsom3
2025-10-15 01:09:17
Have you turned a video into a JXL?
JKUser4592
2025-10-15 01:26:51
An APNG to JXL
Melirius
_wb_ No, go ahead, just make sure to check if the improvement is consistent across jpegs from various sources
2025-10-16 09:32:03
Done https://github.com/libjxl/libjxl/pull/4480
_wb_
2025-10-16 09:13:34
nice!
username
2025-10-16 09:40:14
I wonder what was/is causing the failing testcase on [#4296](https://github.com/libjxl/libjxl/pull/4296)? apparently the logs for what the conformance tests run expired so they can't be viewed anymore
_wb_
2025-10-17 03:00:20
I dunno, maybe the change caused the synthesized ICC profiles to be different (in the name field only but still) and then the conformance script is applying no-op color conversion from one to the other, which should not change anything but probably lcms2 is still doing something that causes it to not really be a no-op.
jonnyawsom3
2025-10-19 06:59:02
I'm not sure what's more surprising to me, someone using effort 11, or someone using effort 11 so much that they noticed a 6 byte regression a few days after a PR https://github.com/libjxl/libjxl/issues/4483
spider-mario
2025-10-19 07:04:01
oh, but that’s our very own <@688076786525143117>
JendaLinda
2025-10-19 08:26:11
Everything must be tested.
Lucas Chollet
2025-10-20 08:33:51
Related to [this](https://github.com/libjxl/libjxl/issues/4482) issue (about lossless & gaborish). There is this note in the spec: > NOTE 1 Fully-specified noise generation has the advantage of allowing encoders to compensate for the noise that a decoder will add. The latitude (maximum deviation) between decoders is smaller than the largest magnitude of the generated noise. How is that implemented (if it is) in practice?
_wb_
2025-10-20 10:20:22
It is not, we don't currently have an encoder that will automatically use noise generation. You can manually add noise but it will just be signalled on top of the image as it is, the encoder is not trying to do noise reduction before encoding or anything like that. But we did want to make it fully specified so at least in principle, an encoder can know what the decoded image will look like and if needed compensate for it if the generated noise makes the image look weird in some region or whatever.
Lucas Chollet
2025-10-20 10:39:36
Make sense, thanks
username
2025-10-20 10:37:19
2025-10-20 10:37:19
<@1346460706345848868> would you be able to investigate this? https://github.com/libjxl/libjxl/pull/4232#issuecomment-2854414759
2025-10-20 10:37:57
in the past you had [mentioned](https://github.com/libjxl/libjxl/pull/4154#issuecomment-2815265621) looking into trying to reduce the size
Melirius
2025-10-21 05:30:14
Yes, I unfortunately moved to other things lately. If you are interested, I move it to the next thing to do in priority list
jonnyawsom3
2025-10-23 03:01:30
At some point, could we get these pending PRs merged? <https://github.com/google/jpegli/pulls> The repo hasn't had an update in 8 months, with significant bugs present in the current version discouraging adoption by some (Empty DHT, APP14, Static builds)
A homosapien
2025-10-23 06:07:03
The drop-in compatible jpegli .dlls aren't compatible. Also, compiling jpegli .dlls are disabled by default on windows for reasons I don't quite understand.
jonnyawsom3
2025-10-23 06:12:58
There's a PR which re-enables compiling DLLs, suggesting it worked for them, but all programs either crashed or errored when we tried replacing the DLLs
2025-10-23 06:13:46
(Namely Krita, RawTherapee and cjxl)
vtorri
2025-10-23 08:37:33
hello, will there be a new release soon ?
A homosapien
2025-10-23 10:06:02
2025-10-23 10:06:02
Soon™
vtorri
2025-10-24 04:57:08
thanks
AccessViolation_
_wb_ It is not, we don't currently have an encoder that will automatically use noise generation. You can manually add noise but it will just be signalled on top of the image as it is, the encoder is not trying to do noise reduction before encoding or anything like that. But we did want to make it fully specified so at least in principle, an encoder can know what the decoded image will look like and if needed compensate for it if the generated noise makes the image look weird in some region or whatever.
2025-10-28 04:42:20
how could this be done? could JXL apply noise generation selectively by creating an empty frame with synthesized noise, creating another frame that works as the mask, and selectively subtract-blending the noise frame with the original image that has noise synthesis applied?
_wb_
2025-10-28 04:44:52
No, generated noise can only statistically look like real noise, it will be different on the pixel level. But an encoder could apply any kind of denoising algorithm on its input and encode that as the image, estimate the amplitude of the noise (comparing original to denoised image) and signal that amount of noise to be generated decode time
AccessViolation_
2025-10-28 04:47:51
ah, then with this noise being luma-modulated (iirc) there's no real way to for example dial back the noise in a certain area to avoid that specific part of the image looking weird?
2025-10-28 04:48:45
I assumed applying noise selectively would be theoretically possible by subtracting another noise frame that was multiplied by a mask
2025-10-28 04:50:52
well regardless, I'm hopeful for a noise replacing feature in the encoder in the future, that sounds great
_wb_
2025-10-28 05:03:39
You could selectively apply noise by first encoding the image without noise as the first frame, then patch-copy it to a second frame and add noise to it, and then alpha blend them and use the alpha to modulate noise locally. Comes at a cost in decode time to do it like that, but it's an approach that would work in principle.
AccessViolation_
2025-10-28 08:58:32
oh I see
Demiurge
_wb_ No, generated noise can only statistically look like real noise, it will be different on the pixel level. But an encoder could apply any kind of denoising algorithm on its input and encode that as the image, estimate the amplitude of the noise (comparing original to denoised image) and signal that amount of noise to be generated decode time
2025-10-30 01:07:21
But the encoder already inadvertently denoises the image as an unintended result of the quantization. Maybe the encoder should measure how much noise was removed and try to add it back with noise synth. Without changing the encoding process at all aside from the measurement step afterwards
jonnyawsom3
2025-10-30 04:05:39
AKA, fix `--noise 1`
_wb_
Demiurge But the encoder already inadvertently denoises the image as an unintended result of the quantization. Maybe the encoder should measure how much noise was removed and try to add it back with noise synth. Without changing the encoding process at all aside from the measurement step afterwards
2025-10-30 07:47:54
Yes, that would be a good start.
Demiurge
2025-10-30 08:37:49
Yes. And it can even be applied conveniently to existing images. Just compare the original with the lossy and measure the amount of noise that was lost. Then it can be added with a simple metadata change.
2025-10-30 08:38:12
The question is: what's the best way to measure the noise?
_wb_
2025-10-30 08:43:07
I'm sure there must be literature on that, but just subtracting one from the other and computing some stats on the residuals should already be reasonable. Maybe median amplitude of residuals?
jonnyawsom3
2025-10-30 08:47:13
Isn't it this? <https://github.com/libjxl/libjxl/blob/4523cf652f568f1fbb57bf9a10ae3caae785cd9f/lib/jxl/enc_noise.cc#L271>
2025-10-30 08:48:20
Or does that just take a guess instead of checking the difference to the encoded result
_wb_
2025-10-30 09:48:37
it takes only one image as input so I assume it is trying to estimate the noise in the input
spider-mario
2025-10-30 10:39:12
I wrote a tool that takes a source image and a denoised image and estimates the `--photon_noise` parameter to use, but it really only estimates noise LUTs of the photon kind
2025-10-30 10:40:49
ah, right, and I’m not sure I was done recalibrating the photon noise scaling to match the one in libaom
jonnyawsom3
2025-10-30 10:55:55
So recalibration and then integration into libjxl?
spider-mario
2025-10-30 12:23:06
I don’t know how deeply it would make sense to integrate it; I had it as a separate command-line tool
2025-10-30 12:23:28
`$ tools/estimate_noise ref.png denoised.png` and it tells you what it thinks is the most suitable photon noise parameter
2025-10-30 12:23:35
which you have to copy and apply yourself
jonnyawsom3
2025-10-30 12:32:38
I thought I'd make sense to replace the code I linked above, though if the image has already been encoded, it might be useful to do <https://github.com/libjxl/libjxl/issues/4328> first for setting the noise after
username
2025-10-30 12:41:03
speaking of photon noise, this is kinda an annoying bug: https://github.com/libjxl/libjxl/issues/4368
veluca
2025-10-30 09:13:23
**Call for jxl-rs testing :-)** Hi everyone, jxl-rs has reached a point where the current `main` branch decodes all the jxl files that we are aware of, but there are always files we are not aware of! We would be grateful if you could download jxl-rs, run it on a bunch of images, and open issues for those images that *do not decode correctly* (or don't decode at all) In the meantime, we'll continue speeding things up 🙂
2025-10-30 09:13:33
afed
2025-10-30 09:30:39
probably better also in <#803379415106584626>
jonnyawsom3
2025-10-30 09:41:33
I certainly have a knack for making exotic files, so I'll see what I can ~~break~~ do
username
2025-10-30 10:11:35
speaking of, what's the status of tone mapping in jxl-rs? it's the only thing not formally marked off of the stages tracking bug and the person who was assigned to do it seemingly never came back? https://github.com/libjxl/jxl-rs/issues/58
veluca
2025-10-30 10:13:50
I don't think it's implemented
lonjil
2025-10-30 10:32:53
If I wanted to automatically test it on a large number of images, what would be the best method? Checking PAE against what libjxl produces?
veluca
2025-10-30 10:51:48
should work
RaveSteel
2025-10-31 12:17:57
Seems to have problems decoding JXL art
2025-10-31 12:18:08
At least the ones I've tested
Demiurge
_wb_ I'm sure there must be literature on that, but just subtracting one from the other and computing some stats on the residuals should already be reasonable. Maybe median amplitude of residuals?
2025-10-31 01:28:15
Yeah, something simple like that. And then, what's the best way to translate the median amplitude into an ISO value?
2025-10-31 01:28:45
Well, I'm sure that's the easy part
2025-10-31 01:30:10
Anyways, it's a good quick and dirty hack that could give a small but meaningful little bump to perceived fidelity. Like a low hanging fruit.
Quackdoc
veluca **Call for jxl-rs testing :-)** Hi everyone, jxl-rs has reached a point where the current `main` branch decodes all the jxl files that we are aware of, but there are always files we are not aware of! We would be grateful if you could download jxl-rs, run it on a bunch of images, and open issues for those images that *do not decode correctly* (or don't decode at all) In the meantime, we'll continue speeding things up 🙂
2025-10-31 01:49:48
~~time to add image-rs support~~
2025-10-31 01:50:08
that would be really nice for testing lik
2025-10-31 01:50:10
lol
Demiurge
2025-10-31 06:40:56
Yeah. Integration is king
2025-10-31 06:41:24
Maybe even a libjxl C api translation layer
2025-10-31 06:41:52
For all the existing libjxl support
jonnyawsom3
veluca **Call for jxl-rs testing :-)** Hi everyone, jxl-rs has reached a point where the current `main` branch decodes all the jxl files that we are aware of, but there are always files we are not aware of! We would be grateful if you could download jxl-rs, run it on a bunch of images, and open issues for those images that *do not decode correctly* (or don't decode at all) In the meantime, we'll continue speeding things up 🙂
2025-10-31 09:15:29
It's good/bad timing, because I've been speaking with a GitHub developer about allowing JXL uploads for libjxl as a trial run. Would be nice if we could skip renaming them to `.jpg`, but I'm not sure what progress they made
Demiurge
2025-10-31 12:52:34
Does .bin work? Is it really some stupid filename restriction?
jonnyawsom3
2025-10-31 01:18:50
They use whitelisted extensions, not even mime types. So renaming JXL to JPG still loads fine in supported browsers You can see it on the jxl-rs issues we made <https://github.com/libjxl/jxl-rs/issues/422>
Laserhosen
veluca should work
2025-10-31 06:46:30
For lossy JXLs (modular and VarDCT), I'm getting different pixel values from djxl (v0.11.1) and jxl_cli (main). PAE is consistently `257 (0.00392157)` for 8-bit images, less for higher bit depths. Is there any deviation allowed, or should it always be `0 (0)`?
_wb_
2025-10-31 07:07:22
257 is just an off-by-one in 8-bit, which is allowed and can be caused by several things, including float arithmetic differences between implementations, dithering being done differently, etc.
jonnyawsom3
2025-10-31 07:12:54
jxl-rs has no dithering currently IIRC while libjxl v0.11 had 8x8 bayer, now using blue noise in v0.12
Laserhosen
2025-10-31 07:18:34
I've also found a couple that don't decode with jxl-rs. Will raise bugs soon.
veluca
Laserhosen I've also found a couple that don't decode with jxl-rs. Will raise bugs soon.
2025-10-31 07:42:27
That's probably something we should fix 🙂
lonjil
2025-10-31 07:45:35
ppm output doesn't seem to work
Laserhosen
2025-10-31 07:55:04
It seems to write an empty ppm if the image has alpha
jonnyawsom3
2025-10-31 09:32:54
Looks like they're waiting on my jpegli PRs, and v0.12 of libjxl https://newsgroup.xnview.com/viewtopic.php?t=48869
HCrikki
2025-10-31 09:45:10
worth reporting. xnview's export of jpeg when using *jpegli* seems to use libjpeg rather than jpegli when you choose **greyscale** (massively lower visual quality for low bpp - blockiness and artifacts match the non-jpegli codec they used before)
jonnyawsom3
2025-10-31 09:52:08
Maybe it was this? https://github.com/google/jpegli/pull/103
HCrikki
2025-10-31 10:01:17
no visible connection, current and old xnviewmp versions show the same issue when opting to export jpg as **greyscale** instead of 16m color
jonnyawsom3
2025-10-31 10:11:23
As in the exact same file, or just poor quality? Because that PR hasn't been in a release and they said they use the libjxl version
AccessViolation_
veluca **Call for jxl-rs testing :-)** Hi everyone, jxl-rs has reached a point where the current `main` branch decodes all the jxl files that we are aware of, but there are always files we are not aware of! We would be grateful if you could download jxl-rs, run it on a bunch of images, and open issues for those images that *do not decode correctly* (or don't decode at all) In the meantime, we'll continue speeding things up 🙂
2025-10-31 10:33:07
> all the jxl files that we are aware of I love the way you phrased that all the jxl files we are aware of. all 113 of them <:KekDog:805390049033191445>
2025-10-31 10:34:18
very excited about this landmark. I've got a few weird jxl files to test
HCrikki
2025-10-31 10:39:27
the difference in visual quality in export between jpegli and non-jpegli when selecting to output as greyscale seems to result from some mismapped bit attribution (ie for a screenshot, jpegli at 4% is 15kb and non-jpegli 24kb - increasing quality % till 24kb jpegli export is almost exact match in artefacts, blocks. odd for jpegli export to greyscale from a colored input is not supposed to be visually worse than the old jpg codec xnviewmp export used
jonnyawsom3
2025-11-03 11:03:22
People have been rebasing jpegli PRs onto the libjxl repo because the Google ones haven't been merged for months. The Google repo is more up to date, so we don't want to accidentally skip commits between the two. I know I've brought it up a few times lately, I just don't want the jpegli fixes to miss the v0.12 release, causing even more issues and PRs to pile up https://github.com/libjxl/libjxl/pull/4504
spider-mario
2025-11-03 05:06:28
2025-11-03 05:06:29
yeah, this is yet another case of “original PNG had gAMA=0.45455 and no sRGB chunk, so now software that didn’t look at the gAMA tag but does look at the ICC profile renders the image correctly”
2025-11-03 05:08:57
```console $ pngcheck -v original.png File: original.png (5973 bytes) chunk IHDR at offset 0x0000c, length 13 140 x 64 image, 32-bit RGB+alpha, non-interlaced chunk gAMA at offset 0x00025, length 4: 0.45455 <---- chunk pHYs at offset 0x00035, length 9: 3777x3777 pixels/meter (96 dpi) chunk IDAT at offset 0x0004a, length 5879 zlib: deflated, 32K window, fast compression chunk IEND at offset 0x0174d, length 0 No errors detected in a.png (5 chunks, 83.3% compression). $ pngcheck -v decoded.png File: decoded.png (7331 bytes) chunk IHDR at offset 0x0000c, length 13 140 x 64 image, 32-bit RGB+alpha, non-interlaced chunk gAMA at offset 0x00025, length 4: 0.45455 chunk iCCP at offset 0x00035, length 314 profile name = 1, compression method = 0 (deflate) compressed profile = 311 bytes chunk cHRM at offset 0x0017b, length 32 White x = 0.3127 y = 0.329, Red x = 0.64 y = 0.33001 Green x = 0.3 y = 0.6, Blue x = 0.15 y = 0.06 chunk IDAT at offset 0x001a7, length 6888 zlib: deflated, 32K window, superfast compression chunk IEND at offset 0x01c9b, length 0 $ magick decoded.png decoded.icc $ cd-iccdump decoded.icc icc: […] Text: en_US: RGB_D65_SRG_Rel_g0.45455 [100 bytes] ```
_wb_
2025-11-03 05:36:26
ugh it's annoying that so much software gets it wrong that getting it right makes it look like we're wrong.
Zamarusdz
2025-11-03 05:44:49
I see so according to you they actually didn't take into account the gAMA that basically says it's sRGB and with the added ICC profile they do render it as such. On the other hand i'm already an "advanced" end user for windows and i don't have any software that render those correctly. Yeah i suppose it can be a frustrating problem.
Tirr
2025-11-03 05:46:40
those gamma22 vs. sRGB issues are really... something
lonjil
2025-11-03 06:31:40
I was planning to build a bunch of old libjxl versions to see if any differences in the output would trip up jxl-rs, but it seems like some of the older dependencies can't be compiled anymore? What a pain.
spider-mario
Zamarusdz I see so according to you they actually didn't take into account the gAMA that basically says it's sRGB and with the added ICC profile they do render it as such. On the other hand i'm already an "advanced" end user for windows and i don't have any software that render those correctly. Yeah i suppose it can be a frustrating problem.
2025-11-03 06:32:24
the gAMA (or more specifically the absence of an `sRGB` chunk) says it’s _not_ sRGB, but probably a lot of software assumes it is
Quackdoc
Tirr those gamma22 vs. sRGB issues are really... something
2025-11-03 07:06:13
sRGB is such a nightmare. Why can't we just retire it T.T
lonjil
spider-mario the gAMA (or more specifically the absence of an `sRGB` chunk) says it’s _not_ sRGB, but probably a lot of software assumes it is
2025-11-03 07:16:17
but 2.2 gamma is the real definition of sRGB (any other definition you may have heard is fake) so assuming that gAMA=0.45455 is sRGB is fine 😄
Quackdoc
2025-11-03 07:35:13
SRGB never actually defined it, it only hinted it
lonjil but 2.2 gamma is the real definition of sRGB (any other definition you may have heard is fake) so assuming that gAMA=0.45455 is sRGB is fine 😄
2025-11-03 07:36:44
Ofc I agree that 2.2 is how it should be, but it can be reasonably thought to not be, especially with all the "sRGB pseudo specs" so to speak
Zamarusdz
2025-11-03 08:04:24
So the difference is actually due to chrome's approximation when sRGB is assumed and when it is actually declared <:galaxybrain:821831336372338729>
_wb_
2025-11-03 10:09:59
uhm any spec of sRGB has that silly linear segment, I am sorry
lonjil
2025-11-03 10:31:12
yeah but it was just an encoding trick. Microsoft and HP assumed that the average CRT monitor would have a pure 2.2 gamma, and the silly linear segment plus gamma 2.4 segment was chosen to be an as close an approximation of that as possible, while supposedly making the math easier on some systems.
_wb_
2025-11-03 11:07:29
Yeah it was basically an approximation to make intermediate linear uint16 work, and then that became spec even when there's no real need anymore to avoid float arithmetic.
Quackdoc
lonjil yeah but it was just an encoding trick. Microsoft and HP assumed that the average CRT monitor would have a pure 2.2 gamma, and the silly linear segment plus gamma 2.4 segment was chosen to be an as close an approximation of that as possible, while supposedly making the math easier on some systems.
2025-11-03 11:22:58
didn't a reference number of 2.2 come from an average of desktop CRTs iirc I remember reading that
lonjil
2025-11-03 11:23:54
yeah
Quackdoc
2025-11-03 11:46:07
but yeah, sRGB was designed to work well on rec709 CRTs, the linear bits was done since 8bit pipelines simply didn't well work at that level without it
monad
lonjil I was planning to build a bunch of old libjxl versions to see if any differences in the output would trip up jxl-rs, but it seems like some of the older dependencies can't be compiled anymore? What a pain.
2025-11-04 09:27:11
I got you, currently encoding: (0.3.7) -d !0,1,15 -s !3,5,7,9 (0.5.0) -d !0,1,15 -e !3,5,7,9 (0.6.1) -d !0,1,25 -e !1,3,5,7,9 (0.7.0) -d !0,1,25 -e !1,3,5,7,9 (0.8.2) -d !0,1,25 -e !1,3,5,7,9 (0.9.0) -d !0,1,25 -e !1,3,5,7,9 (0.11.0) -d !0,1,25 -e !1,3,5,7,10
2025-11-04 10:02:16
Someone want to guide me in automatically detecting discrepancies between the PNG decodes?
_wb_
2025-11-04 01:03:28
`compare -verbose -metric pae one.png two.png null:` ? Assuming they're in the same colorspace, since that command doesn't do any color management
monad
2025-11-04 01:18:00
Thanks, yeah, I had no intuition for a threshold, but realized I could just sort on error and visually inspect the worst.
TheBigBadBoy - 𝙸𝚛
monad Someone want to guide me in automatically detecting discrepancies between the PNG decodes?
2025-11-04 06:00:52
what about comparing the hashes once the image is decoded with `ffmpeg -v warning -i input.png -f hash -` ?
monad
2025-11-04 06:11:59
Thanks, if you expect it's sensitive enough I might try it. Anyway, I already compared many images and only saw one obvious but common issue at very high distance.
TheBigBadBoy - 𝙸𝚛
2025-11-04 06:25:36
well that ffmpeg command can only be used to compare hashes, so it is either completely lossless, or lossy (but you can't know how much)
monad
2025-11-04 06:39:46
Ah, looks like SHA256, not in line with this use case.
TheBigBadBoy - 𝙸𝚛
monad Ah, looks like SHA256, not in line with this use case.
2025-11-04 07:47:35
wdym, you would like another hash?
2025-11-04 07:48:14
or you would like to get a error-distance between 2 files (like the command from wb)
monad
2025-11-04 07:50:43
I am comparing decodes between two softwares. There is flexibility in the result, so I should detect differences of some significance.
2025-11-04 07:51:39
I mainly didn't know a threshold to target, but instead of figuring that out I just sorted on error and verified visually.
2025-11-04 07:54:09
I'm aware of hashes which are suitable for measuring error, but not aware of a really precise one off the top of my head and didn't consider a benefit worth investigating.
TheBigBadBoy - 𝙸𝚛
2025-11-04 07:54:50
ohh right, mb I thought you just wanted to know the boolean "Is it lossless"
A homosapien
2025-11-07 02:07:08
2025-11-07 02:07:09
We fixed the DCT visualizations on Windows. PR just opened. <:Stonks:806137886726553651>
jonnyawsom3
2025-11-07 01:01:51
<@794205442175402004> I don't suppose you could merge it? https://github.com/libjxl/libjxl/pull/4509
_wb_
2025-11-07 01:41:09
I clicked the button
jonnyawsom3
2025-11-07 01:48:28
Thanks
AccessViolation_
2025-11-07 02:10:15
you need to be a trained merge conflict resolution associate to press that button
monad
2025-11-07 03:33:21
_wb_
2025-11-07 04:16:28
what do you mean with "on grey background"? is this an image with alpha?
monad
2025-11-07 04:16:41
yep
_wb_
2025-11-07 04:18:11
hm, interesting, I hadn't thought about the interaction between alpha and dithering
monad
2025-11-07 04:21:23
added the background to emphasize the dither in the lower gradient. but the colors in the opaque parts are very flat too, compared to the jxl-rs result.
_wb_
2025-11-07 05:13:39
jxl-rs doesn't do any dithering at all atm or what does it do?
2025-11-07 05:15:45
when did we add dithering? in 0.8 there's no dithering yet, right?
2025-11-07 05:16:58
is this with premultiplied alpha or regular PNG-style alpha?
2025-11-07 05:18:16
I would expect this to be more of an issue with premultiplied/associated alpha than with unassociated...
2025-11-07 05:24:34
I don't quite understand what information is in the alpha and what is in the grayscale image, is the upper part fully opaque and only the region at the bottom-left is transparent, with a gradient in the alpha channel for that black shadow?
2025-11-07 05:26:44
These images look like they're 6-bit instead of 8-bit, the step size between color bands in the 0.8 image is more like 4 units in 8-bit than like 1 unit; same with the dithering in 0.10 and 0.12
2025-11-07 05:27:39
so there's something I'm missing here, I don't understand how it can look like that
2025-11-07 05:28:17
you didn't decode to 8-bit linear and then converted to sRGB or something like that, did you?
veluca
_wb_ jxl-rs doesn't do any dithering at all atm or what does it do?
2025-11-07 06:12:00
no dithering
_wb_
2025-11-07 06:23:07
Then 0.8 and jxl-rs should be more similar, no?
veluca
2025-11-07 06:36:06
that seems like a valid point
A homosapien
2025-11-07 07:19:21
Man, blue noise dithering looks soo better than ordered.
AccessViolation_
2025-11-07 07:19:54
oh is 0.12 blue noise dithered?
2025-11-07 07:20:02
I didn't even recognize it as dithering
2025-11-07 07:21:17
looks better indeed
A homosapien
AccessViolation_ I didn't even recognize it as dithering
2025-11-07 07:24:39
That's the idea! 😄
AccessViolation_
2025-11-07 07:41:13
how does it actually decide when to dither? does it keep track of the input bit depth so that it doesn't dither on output if it's 8 -> 8 bit, but does if it's 12 -> 8 bit or something?
2025-11-07 07:43:17
oh I'm dumb I assume the application embedding libjxl can just request dithering if the image output bit depth is higher than what it wants to display
ignaloidas
2025-11-07 07:46:58
FWIW with VarDCT you could always just dither anyways, I don't think it's particularly wrong
monad
2025-11-07 07:47:37
I don't know where the error is if there is one. Attached are the default decodes to PNG from each decoder. For the comparison visual I did naively convert to GIMP's Linear sRGB on import, not noticing any difference.
AccessViolation_
ignaloidas FWIW with VarDCT you could always just dither anyways, I don't think it's particularly wrong
2025-11-07 07:49:28
fair point. it can be a bit tedious when comparing the compression quality of different formats and the JXL is dithered unlike all the other ones. in an ideal world image viewers try to display the image's original bit depth and the GPU dithers it on a display pixel level instead of an image pixel level, but for whatever reason we're not there yet
ignaloidas
2025-11-07 07:50:58
I don't see how would you dither accurately on a display pixel level? Unless you mean feeding the GPU the 32 bit raws or whatever, scaling, and only then dithering
lonjil
2025-11-07 07:51:40
That is what is meant, yes
_wb_
2025-11-07 07:52:52
Doesn't need to be 32-bit, if it's just 2 bits more precision than the display itself, that's already enough to make a difference.
AccessViolation_
2025-11-07 07:54:14
yes, ideally you'd be able to send a framebuffer of any commonly supported bit depth to the GPU and it works with the display driver+firmware to either do *screen pixel level* spatial dithering (in principle similar to the way libjxl dithers), or temporal dithering (where the display changes the color of a pixel thousands of times per second so you see the average of those, a value which the hardware could not natively be signaled to display)
2025-11-07 07:55:03
but I don't know enough about this to know what the blockers are to get something like this generally working for every computer in practice
ignaloidas
2025-11-07 07:58:20
temporal dithering is being done by displays already to get a bit more color accuracy, but that has a limited bitdepth and people sometimes complain about the flashing because in the end you can't do it *that* fast
_wb_
2025-11-07 07:59:22
temporal dithering is how cheap 8-bit displays work, they are actually 6-bit with temporal dithering to pretend to be 8-bit, iirc
AccessViolation_
ignaloidas temporal dithering is being done by displays already to get a bit more color accuracy, but that has a limited bitdepth and people sometimes complain about the flashing because in the end you can't do it *that* fast
2025-11-07 08:01:16
that's right. I haven't heard of cases where people can see temporal dithering - to me it seems more likely that you'd see the pulse-width modulation, which is the rapidly flashing of the entire display to change brightness, instead of *actually* changing the brightness, but I believe it
ignaloidas
AccessViolation_ that's right. I haven't heard of cases where people can see temporal dithering - to me it seems more likely that you'd see the pulse-width modulation, which is the rapidly flashing of the entire display to change brightness, instead of *actually* changing the brightness, but I believe it
2025-11-07 08:03:00
the problem is that generating randomness for each pixel each frame is kinda hard to do in display, so the randomness might be shared over larger areas
AccessViolation_
2025-11-07 08:04:03
ohh I see
ignaloidas
2025-11-07 08:06:39
also, this is a good graph on what frequencies can result on visible flicker depending on intensity change and frequency
2025-11-07 08:08:55
2KHz is basically safe, but you can't really push LCDs to that kind of speed and self-emissive displays usually build color depth off PWM anyways
AccessViolation_
2025-11-07 08:10:47
what does the ripple axis mean?
2025-11-07 08:12:55
oh that's the risk lmao
2025-11-07 08:13:14
I cannot reason today
ignaloidas
2025-11-07 08:13:23
ripple = difference between peeks and valleys of signal
2025-11-07 08:13:43
this is a standard for electrical engineers lol, ripple is a very well understood metric
jonnyawsom3
AccessViolation_ how does it actually decide when to dither? does it keep track of the input bit depth so that it doesn't dither on output if it's 8 -> 8 bit, but does if it's 12 -> 8 bit or something?
2025-11-07 08:14:02
For lossy, it's always float 32 so always dithered unless output as float 32. For lossless, it dithers when requested bitdepth is lower than stored bitdepth. libjxl dithers by default but can be told not to (I think)
AccessViolation_
2025-11-07 08:14:46
that's odd. I know it's all float 32 but that's not the behavior I would have expected
2025-11-07 08:16:37
though yeah it's lossy regardless so it's fair I suppose
ignaloidas ripple = difference between peeks and valleys of signal
2025-11-07 08:18:47
ah okay. then for temporal dithering that should be very low risk regardless since you'd probably be switching between two neighboring pixel values
ignaloidas
2025-11-07 08:21:09
between two 8 bit values - if you got a 8 bit native panel then 30Hz is a safe zone, but for 6 bit native panels you want to push it quite a bit further
2025-11-07 08:22:17
oh, and also, need to take gamma into account, forgot that myself
AccessViolation_
2025-11-07 08:22:36
I just remembered Firefox will dither high bit depth images for you but also on an image pixel level, which is a shame because it very directly controls the frame buffer it's sending to the GPU. you wouldn't even need GPU support, it could just, do that. I think
ignaloidas
2025-11-07 08:24:33
Oh, and in dark scenes, temporal dithering won't work well without higher refresh rates - the difference between the neighboring values is bigger in relative %
lonjil
AccessViolation_ though yeah it's lossy regardless so it's fair I suppose
2025-11-07 08:27:23
the dither actually makes it less lossy :D if only by a small amount
AccessViolation_
2025-11-07 08:28:40
oh, interesting
2025-11-07 08:29:37
you'd think that simply rounding every high bit depth pixel to the nearest natively supported pixel is by definition the least lossy?
2025-11-07 08:29:53
numerically speaking
lonjil
2025-11-07 08:30:44
that can cause the average over a region to drift in a particular direction
2025-11-07 08:31:09
dither ensures that the average over a region stays closer to the high bit depth average
AccessViolation_
2025-11-07 08:31:41
ah, that makes sense. neat
spider-mario
2025-11-07 10:33:23
I know that at least NVIDIA GPUs do support this “send high bit-depth framebuffer; dither to monitor’s actual bit depth”
2025-11-07 10:33:31
there are settings for that in nvidia-xsettings
2025-11-07 10:34:18
apparently, it’s harder to enable on Windows https://www.nvidia.com/en-us/geforce/forums/game-ready-drivers/13/277754/dithering-option-in-nvidia-control-panel/
2025-11-07 10:34:33
> There is a dithering option on Linux. Why you can't do this on Windows, the most popular operating system? I'm begging you, Nvidia, please, do this for us.
2025-11-07 10:36:51
https://github.com/SLStyler/Dithering-for-Windows-Simple-BAT-/blob/main/Dither.bat I don’t know what reaction to have to someone writing this as a BAT
2025-11-07 10:37:31
ah, it invokes a PowerShell
2025-11-07 10:38:14
and VBScript
AccessViolation_
2025-11-07 10:50:53
on intel iGPUs it looks like you might be able to do it by writing a register using an intel program which I did manage to install, but it doesn't work for a lot of people
2025-11-07 10:51:15
someone pointed to a 1700 page manual pdf
2025-11-07 10:52:17
links to forum posts that 404
2025-11-07 10:53:00
I'll check this out in more detail later, I'm too sleepy for this
ignaloidas
2025-11-07 10:53:35
This kind of thing is the responsibility of the window manager/compositor to properly set up
AccessViolation_
2025-11-07 10:54:18
oh hmm
2025-11-07 10:57:17
I might ask the cosmic-comp people about this. currently there are no color management settings in the settings app, so I doubt it's implemented well in the compositor yet
2025-11-07 10:57:46
though hdr and night light functionality are planned, I bet those require similar base features to get working
ignaloidas
2025-11-07 10:59:21
if proper hdr with color management is planned then yeah, that's most of the base features needed
AccessViolation_
2025-11-07 10:59:37
their wallpaper thing supports jxl though so they score some points with that :)
ignaloidas
2025-11-07 11:00:25
I'm just wondering now, whether automatically dithering if bit-depth is higher than can be displayed is the correct move? Especially on lower res displays it can be kinda noticable
AccessViolation_
2025-11-07 11:03:22
color banding is noticeable too, so either way you're going to have artifacts. since you're going to have artifacts anyway, I'd argue dithering would be better since it's visually closer to the intended image
2025-11-07 11:05:20
dang I thought I was onto something when I found this command but it doesn't list bit depth at all
jonnyawsom3
AccessViolation_ color banding is noticeable too, so either way you're going to have artifacts. since you're going to have artifacts anyway, I'd argue dithering would be better since it's visually closer to the intended image
2025-11-08 03:43:32
I'm sure we could tune the dither a bit more too. It seems like some areas are both too light and too dark in the comparison above, so maybe a tighter range would help
monad
2025-11-08 09:24:03
ssimu2 is as confused as I am, djxl output post 0.6 gets -100 scores
username
2025-11-08 09:36:12
why does jxl-rs and libjxl 0.6 look nicer?
2025-11-08 09:36:19
I wonder what changed
AccessViolation_
2025-11-08 09:41:27
there is an infamous issue where older versions of cjxl produced nicer output in certain conditions and people have been trying to adjust the tuning in recent versions to get quality back
2025-11-08 09:42:06
https://discord.com/channels/794206087879852103/1278292301038227489
spider-mario
2025-11-08 09:42:17
this is the same cjxl/.jxl, though; only the decoder is changing
AccessViolation_
2025-11-08 09:42:53
oh! that's surprising. my bad
2025-11-08 09:44:40
jxl-rs, the most recently developed one, does a really nice job too
2025-11-08 09:46:42
everyone's been cooking 💚
veluca
AccessViolation_ everyone's been cooking 💚
2025-11-08 11:27:48
this image kinda points at me not really believing in small PRs, doesn't it xD
AccessViolation_
2025-11-08 11:33:56
I was actually originally going to write "veluca has been cooking" since I was under the the impression you were the main development force, but I figured I'd check the contributors in case there was a larger team
Tirr
2025-11-08 11:37:33
I'd say veluca is doing most of the tricky things in jxl-rs recently, but yeah everyone is doing their job
ignaloidas
monad ssimu2 is as confused as I am, djxl output post 0.6 gets -100 scores
2025-11-08 12:22:20
I've been thinking a bit, could this be an issue with how gamma distorts the probability distribution? e.g. sRGB 99.5 shouldn't dither to 50% 99 50% 100, because the with gamma, 99.5 isn't actually "in the middle" of those values?
jonnyawsom3
I'm sure we could tune the dither a bit more too. It seems like some areas are both too light and too dark in the comparison above, so maybe a tighter range would help
2025-11-08 12:41:53
It did seem like images were slightly brighter, but it was also 4am with a dodgy viewer in terms of color management
2025-11-08 12:44:04
For a second I thought of Gaborish, but that would be encoder side changes
monad
2025-11-08 12:44:56
dither itself is a red herring given the issue was introduced in 0.7, coinciding with different color profile representation in the PNGs
2025-11-08 12:45:56
something crushes the colors, like Jon hinted
ignaloidas
ignaloidas I've been thinking a bit, could this be an issue with how gamma distorts the probability distribution? e.g. sRGB 99.5 shouldn't dither to 50% 99 50% 100, because the with gamma, 99.5 isn't actually "in the middle" of those values?
2025-11-08 12:47:26
hmm, nope, checked how much error that introduces, at least on sRGB only happens to really dark colors and even then the error is very small (~2% max)
jonnyawsom3
monad dither itself is a red herring given the issue was introduced in 0.7, coinciding with different color profile representation in the PNGs
2025-11-08 12:56:27
Maybe this? (or one of the other PNG color management issues) https://github.com/libjxl/libjxl/issues/4503
monad
2025-11-08 01:22:48
Laserhosen
2025-11-08 07:08:55
Wondering whether it's safe to use `save_as_reference = 3` when encoding (using a hacked encode.cc that allows this) as long as patches are disabled...
2025-11-08 07:09:05
Can the encoder decide to use ID 3 internally for anything else? Or could it in the future?
2025-11-08 07:10:55
Anecdotally it works fine 🙂
_wb_
2025-11-08 07:46:49
iirc the encoder currently only uses one id for patches and one for frame blending, so there should be two ids not used for anything, right <@179701849576833024> ?
Laserhosen
2025-11-08 08:15:05
I can often get a smaller file by making manual use of that extra reference frame than I can if I let patches use it. Especially for animations with repeated frames.
2025-11-08 08:21:23
And I guess a follow-on question if id 3 isn't going to be used for anything else: should the API restriction be relaxed such that clients *can* use reference 3 as long as all frames explicitly disable patches?
_wb_
2025-11-08 08:32:49
oh, are you implementing an animation encoder on top of libjxl that is manually using reference frames? that sounds interesting!
2025-11-08 08:37:37
if you're willing to open source it, we could add this to the libjxl repo and make cjxl use it when encoding animations. That would also make it easier to align what is needed in the libjxl api with what is needed to do more effective animation encoding. E.g. I can imagine you may at some point also want to manually define patches instead of just using frame blending, and that's also something we don't have an api for (yet)
Laserhosen
2025-11-08 08:39:20
Sort of... it's become a bit of a mess and needs rewriting from scratch TBH, but basically you feed it a JSON file that references other (single-frame) files that become the frames of the result, along with crop offsets, save_as_reference, blend_source, etc.
2025-11-08 08:39:36
You have to manually work out the best blend source (and do the appropriate cropping / "alpha diffing")
2025-11-08 08:40:09
By finding the most similar previous frame that you also have a spare reference slot for.
veluca
_wb_ iirc the encoder currently only uses one id for patches and one for frame blending, so there should be two ids not used for anything, right <@179701849576833024> ?
2025-11-08 08:49:32
I believe that's true, yep
Laserhosen
Laserhosen And I guess a follow-on question if id 3 isn't going to be used for anything else: should the API restriction be relaxed such that clients *can* use reference 3 as long as all frames explicitly disable patches?
2025-11-09 03:09:01
i.e., would it make sense to do something like this? https://github.com/libjxl/libjxl/pull/4512
jonnyawsom3
2025-11-10 01:08:23
<@532010383041363969> I noticed you removed this adjustment for X compared to B a long time ago. Do you recall if you ever added something similar back again? At a glance I can't see anything in Adaptive Quant that's compensating for the different range of the channels
2025-11-10 01:09:30
2025-11-10 01:13:46
I could be mistaken though, so we'll keep tuning the DCTs and then look into tuning AQ too
Laserhosen
Laserhosen i.e., would it make sense to do something like this? https://github.com/libjxl/libjxl/pull/4512
2025-11-11 07:18:05
<@794205442175402004>, is this worth pursuing?
_wb_ if you're willing to open source it, we could add this to the libjxl repo and make cjxl use it when encoding animations. That would also make it easier to align what is needed in the libjxl api with what is needed to do more effective animation encoding. E.g. I can imagine you may at some point also want to manually define patches instead of just using frame blending, and that's also something we don't have an api for (yet)
2025-11-11 07:18:17
I'm working on this by the way... it will be on Github eventually.
2025-11-11 07:18:53
When I've removed some of the broken features and added some kind of documentation.
_wb_
Laserhosen <@794205442175402004>, is this worth pursuing?
2025-11-11 08:17:01
yeah why not, I can see how it can be useful to have control over all reference slots and not letting the encoder reserve one if it's not using patches anyway.
TheBigBadBoy - 𝙸𝚛
2025-11-12 11:09:07
is it normal for v0.11.1 to crash for lossless transcode of XYB JPEG input?
Laserhosen
2025-11-12 11:20:08
IIRC it doesn't support RGB JPEGs that are subsampled, which is what cjpegli produces by default with --xyb
2025-11-12 11:21:32
https://github.com/libjxl/libjxl/issues/3605
jonnyawsom3
Laserhosen IIRC it doesn't support RGB JPEGs that are subsampled, which is what cjpegli produces by default with --xyb
2025-11-12 11:27:44
Yeah, the PR has been pending for a few months https://github.com/google/jpegli/pull/136
TheBigBadBoy - 𝙸𝚛
2025-11-12 11:30:24
ok thanks
2025-11-12 11:31:00
waiting for this to be merged [⠀](https://cdn.discordapp.com/emojis/992849031011242034.webp?size=48&name=dorime)
jonnyawsom3
2025-11-12 11:31:32
Everyone's waiting for all the PRs
2025-11-12 11:31:35
<:NotLikeThis:805132742819053610>
2025-11-12 11:32:31
Everything from fixing decode failures and crashes to quality improvements have been ready for most of the year but not looked at
TheBigBadBoy - 𝙸𝚛
2025-11-12 11:33:10
I knew for APP14 but didn't know (or forgot) this one <:KekDog:805390049033191445>
jonnyawsom3
TheBigBadBoy - 𝙸𝚛 I knew for APP14 but didn't know (or forgot) this one <:KekDog:805390049033191445>
2025-11-12 11:38:25
APP14, Empty DHT, Bad ICC, RGB subsampling, Static builds not being static, build failures, no DLL for Windows... All have PRs
2025-11-12 11:40:03
Some are over a year old, fixing issues that still get opened on libjxl
spider-mario this is the same cjxl/.jxl, though; only the decoder is changing
2025-11-14 03:34:30
It turns out you had already brought up the issue. It seems like libjxl is still defaulting to Linear images when outputting 8bit sRGB
2025-11-14 03:34:59
I've re-opened the original issue about it, and closed many others as duplicates https://github.com/libjxl/libjxl/issues/2289
2025-11-14 09:06:32
We ended up fixing it ourselves, or at least attempting to. I think sRGB as default makes sense, since you can always specifically request linear output for more advanced users https://github.com/libjxl/libjxl/pull/4516
2025-11-18 06:22:43
Ended up finding this again https://github.com/libjxl/libjxl/pull/1341
2025-11-18 06:22:57
Unfortunately got disabled in this commit <https://github.com/libjxl/libjxl/commit/27afa5e4c2e66d917746f407674369f19b6fca47#commitcomment-141216453>
AccessViolation_
2025-11-18 10:55:31
I did not miss C build systems
spider-mario
2025-11-18 12:51:31
🤨 how do we end up requiring that function
Tirr
2025-11-18 12:53:32
they're experimenting with toml configs https://discord.com/channels/794206087879852103/794206170445119489/1440005688871878787
spider-mario
2025-11-18 12:55:18
oh, right, thanks
2025-11-18 12:57:00
<@384009621519597581> https://github.com/skystrife/cpptoml is apparently header-only, in case that helps
AccessViolation_
2025-11-18 02:12:10
oh nice, thanks
2025-11-18 02:21:06
``` error: exception handling disabled, use ‘-fexceptions’ to enable 920 | throw array_exception{"Arrays must be homogenous."}; | ^ ``` will this be a problem for this library
2025-11-18 02:29:43
actually since this will probably a fork I'll just enable the feature...somewhere
2025-11-18 02:44:46
I don't know why there's like 50 makefiles but I think I found the right one 😅
2025-11-18 02:45:29
this is probably strikingly obvious to everyone else, I've barely touched C ^^"
2025-11-18 03:03:33
> Mixing code compiled with `-frtti` with that compiled with `-fno-rtti` may not work lovely
2025-11-18 03:07:52
apologies for microblogging my struggles
jonnyawsom3
2025-11-18 03:17:49
Also <@604964375924834314>, do you think there'd be any issues caused by this? AFAIK you can always request Linear via the API or the djxl command, so it just makes the default more compatible for non-managed viewers and the average person https://github.com/libjxl/libjxl/pull/4516
spider-mario
2025-11-18 03:33:57
I think my first thought is along the lines of “I hope our sRGB implementation behaves correctly above 1”, + that it exposes us to the controversy of “what is the sRGB TF, really” (especially combined with the first point, given that the divergence between piecewise and g2.4 widens)
2025-11-18 03:35:24
if anything, maybe “gamma 2.2” might be a safer default
2025-11-18 03:35:56
(^ this sentence is the output of the process “I don’t know what to believe anymore”)
AccessViolation_
2025-11-18 03:37:01
I might need some help with this one ``` [ 93%] Linking CXX executable djxl [ 93%] Linking CXX executable benchmark_xl /usr/bin/ld: ../lib/libjxl_extras_codec.a(jpg.cc.o):(.data.rel.ro+0x10): undefined reference to `typeinfo for sjpeg::SearchHook' collect2: error: ld returned 1 exit status gmake[2]: *** [tools/CMakeFiles/djxl.dir/build.make:107: tools/djxl] Error 1 gmake[1]: *** [CMakeFiles/Makefile2:1421: tools/CMakeFiles/djxl.dir/all] Error 2 gmake[1]: *** Waiting for unfinished jobs.... ```
2025-11-18 03:39:26
```diff --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -118,7 +120,8 @@ else () else() # WIN32 list(APPEND JPEGXL_INTERNAL_FLAGS -fsized-deallocation - -fno-exceptions + # -fno-exceptions # Disabled for TOML parsing library + -frtti # Enabled for TOML parsing library # Language flags -fmath-errno ```
spider-mario
2025-11-18 03:52:46
easiest might be to disable sjpeg (edit `CMakeCache.txt`, look for `SJPEG` to find the variable that controls whether to build it, set it to `no` / `false`, rebuild)
AccessViolation_
2025-11-18 04:06:48
thank you!
jonnyawsom3
spider-mario I think my first thought is along the lines of “I hope our sRGB implementation behaves correctly above 1”, + that it exposes us to the controversy of “what is the sRGB TF, really” (especially combined with the first point, given that the divergence between piecewise and g2.4 widens)
2025-11-18 05:16:53
A smarter way could be defaulting to Linear for high bitdepth, and sRGB for 8bit. But you know the code best, so we just did a one line fix to close all the issues about Linear PNGs getting saved
AccessViolation_
2025-11-18 06:06:01
got the config file working ^^ you can tune block selection without having to recompile
2025-11-18 06:08:39
jonny, should I send you a copy while I work on this further
jonnyawsom3
2025-11-18 06:09:21
Sure, would make my tuning faster since I'm approaching smaller tweaks now
Quackdoc
spider-mario if anything, maybe “gamma 2.2” might be a safer default
2025-11-18 06:53:07
big agree
2025-11-18 06:53:27
g22 being default is the only sane option
AccessViolation_
2025-11-18 07:18:44
<@238552565619359744> (and anyone else interested) this is for the build that allows you to tune block selection via a config file. read the included README, it's important
2025-11-18 07:21:04
I know it's inconvenient to set up, I'll be setting up something proper so it'll just be a fork of libjxl on github
2025-11-21 12:34:52
<@207980494892040194> <@238552565619359744> public fork with the changes to allow tuning parameters from a config file between runs https://github.com/AccessViolation95/libjxl-tuning
2025-11-21 12:38:02
2025-11-21 12:38:02
~~this change isn't checked into git, so you'll need to do this yourself after cloning or building. until I find a way to disable building of SJPEG somewhere else~~ resolved
2025-11-21 12:41:10
sapian, maybe you could create a windows build for jonny? I don't want to juggle all the dependencies and changes to my environment that I'd have to make to get cross compiling from linux to windows working ^^"
2025-11-21 12:42:07
last time I tried to install python it...didn't go well
A homosapien
AccessViolation_ sapian, maybe you could create a windows build for jonny? I don't want to juggle all the dependencies and changes to my environment that I'd have to make to get cross compiling from linux to windows working ^^"
2025-11-21 01:44:24
For Windows, I needed to remove `-fno-rtti` from `CMakeLists.txt`. Otherwise it looks like I got a working build. 👍
2025-11-21 01:46:33
`SJPEG` seems to be fine when compiling for windows. I'm turning it back on.
AccessViolation_
2025-11-21 01:47:33
oh huh
2025-11-21 01:49:34
oh right yeah I think I neglected to change the build setting for windows
A homosapien
2025-11-21 02:20:51
The encoding speeds are slower, is that due to `cjxl` trying to read from an external file every time it makes a DCT block decision?
username
A homosapien The encoding speeds are slower, is that due to `cjxl` trying to read from an external file every time it makes a DCT block decision?
2025-11-21 02:21:54
try on a RAM-disk maybe?
A homosapien
2025-11-21 02:22:09
good idea
2025-11-21 02:34:17
Still about 20x slower, even when on a ramdisk ``` cjxl-main wallpaper_1.ppm --disable_output --num_reps 5 JPEG XL encoder v0.12.0 a8589583 [_AVX2_] {Clang 21.1.5} 1920 x 1080, geomean: 9.300 MP/s [9.128, 9.389], 5 reps, 12 threads. cjxl-tune wallpaper_1.ppm --disable_output --num_reps 5 JPEG XL encoder v0.12.0 b06b9a83 [_AVX2_] {Clang 21.1.5} 1920 x 1080, geomean: 0.378 MP/s [0.376, 0.387], 5 reps, 12 threads.```
jonnyawsom3
2025-11-21 02:47:04
Maybe parse the text once and store the values, instead of parsing for every DCT block
AccessViolation_
2025-11-21 03:39:27
it's probably not doing disk I/O every time because the OS will cache it in memory, but you're probably right about that being the slowdown. specifically the TOML library parses it ever time
2025-11-21 03:44:01
parsing it once was my initial plan but it would probably require more significant modifications to the code. I'd have to parse the config somewhere near the top of the call graph and pass a reference it along to eventually end up where it's needed
2025-11-21 03:46:55
which I could do, but keeping these changes localized has the advantage that it's trivial to pull in improvements to other parts of upstream libjxl
2025-11-21 03:50:24
I'll take a look at it, maybe it wouldn't be that many more modifications
jonnyawsom3
2025-11-21 03:50:49
Either way, it's already helping me make some more precise adjustments, and should speed things up tenfold
AccessViolation_
2025-11-21 03:51:22
really glad to hear ^^
A homosapien The encoding speeds are slower, is that due to `cjxl` trying to read from an external file every time it makes a DCT block decision?
2025-11-21 04:15:02
do you intend to run performance benchmarks for different configs as well? if so I'll get to resolving this soon, if not I'll probably keep it like this for the time being
2025-11-21 04:16:31
or if you're testing images that are so large that the slowdown becomes a pain
2025-11-21 04:32:16
also let me know if at any point you'd like more variables to be added to the config. they're trivial to add
A homosapien
AccessViolation_ do you intend to run performance benchmarks for different configs as well? if so I'll get to resolving this soon, if not I'll probably keep it like this for the time being
2025-11-21 06:57:02
I'm willing to give it a shot, right now I'm just testing a simple 1080p image.
AccessViolation_
2025-11-21 06:58:54
ah I think you misunderstood me. I was asking if you're actively bothered by the slowness of it so I know whether I should fix it now or if this is fine for the time being
A homosapien
2025-11-21 08:23:17
Oh, it doesn't bother me too much. It's fine for now.
Jim
2025-11-22 06:58:56
When trying to build the wasm, it gets all the way to the end and 1 test fails. Anyone else getting this? ``` 4808/4818 Test #4818: test_wasm_jxl_decoder ............................................................................................................................................................................................................***Failed 0.15 sec Running testSdr /---/libjxl/tools/wasm_demo/jxl_decoder_test.js:47 jxlModule.HEAP8.set(encoded, buffer); ^ TypeError: Cannot read properties of undefined (reading 'set') at testSdr (/---/libjxl/tools/wasm_demo/jxl_decoder_test.js:47:19) at runTest (/---/libjxl/tools/wasm_demo/jxl_decoder_test.js:15:3) at Array.forEach (<anonymous>) at /---/libjxl/tools/wasm_demo/jxl_decoder_test.js:138:9 Node.js v22.15.1 ... 99% tests passed, 1 tests failed out of 4817 Total Test time (real) = 271.30 sec The following tests did not run: 4814 - GaussBlurTest.SlowTestDirac1D (Disabled) The following tests FAILED: 4818 - test_wasm_jxl_decoder (Failed) Errors while running CTest ```
2025-11-22 09:20:31
Submitted a bug and pull request
gggol
2025-11-23 03:32:04
Created 2 JPEGs with GIMP, using the Advanced Options [x] Use arithmetic coding, and cjxl would not transcode them. JPEG XL encoder v0.11.1 [AVX2] Note: Implicit-default for JPEG is lossless-transcoding. To silence this message, set --lossless_jpeg=(1|0). Encoding [JPEG, lossless transcode, effort: 7] ./lib/jxl/jpeg/enc_jpeg_data_reader.cc:144: JXL_FAILURE: Invalid comps_in_scan: 3 ./lib/jxl/jpeg/enc_jpeg_data.cc:402: JXL_FAILURE: Error reading JPEG ./lib/jxl/encode.cc:2095: Error during decode of input JPEG Error while decoding the JPEG image. It may be corrupt (e.g. truncated) or of an unsupported type (e.g. CMYK). EncodeImageJXL() failed. Eye of Gnome could view one, but gave an error with the other: Error interpreting JPEG image file (Suspension not allowed here) Firefox and Chromium could view both images.
RaveSteel
2025-11-23 04:00:37
post the images please
Tirr
2025-11-23 04:03:01
JPEG with arithmetic coding isn't well supported generally, and JPEG XL as a format doesn't support losslessly transcoding arithmetic coded JPEG
ignaloidas
2025-11-23 04:03:54
I understand not supporting bit-reconstruction, but it should be able to losslessy transcode still, no?
Tirr
2025-11-23 04:07:35
that depends on how you define "loss" here (I meant in bitstream level), but yeah I guess preserving only coeffs may be possible
_wb_
2025-11-23 06:18:38
Yes, that should be possible, but libjxl currently doesn't support it. Would be a good idea to add that though
jonnyawsom3
2025-11-23 06:50:01
It likely wouldn't have the same space savings, but if you wanted to convert Arithmetic JPEGs to JXL for wider support, then it might make sense
ignaloidas
2025-11-23 06:53:25
Arithmetic is around 10% savings over regular JPEG, JXL is around 20% savings, so it is still a meaningful improvement (though indeed smaller)