Beep6581 / RawTherapee

A powerful cross-platform raw photo processing program
https://rawtherapee.com
GNU General Public License v3.0
2.81k stars 318 forks source link

Idea: Allow use of libjpegli for jpeg import/export #7125

Open xiota opened 3 months ago

xiota commented 3 months ago

libjpegli was formerly part of the libjxl project. Images are processed in 32-bit float representation, similarly to jxl. This would be useful to expand editing latitude of imported images. libjpeg-turbo also appears to have an option for expanded bit depth, but it must be enabled during build and is disabled by default.

The new library would need to be built statically, to prevent conflict with system libjpeg-turbo. Workflows that already build libjxl may work with adjusted build options. For others, libjpegli sources can be separated from the rest of libjxl and built as a subproject. Which jpeg library to use could be selected during configure for conditional compilation.

I have tested separating libjpegli from libjxl and compiling it as a submodule of a test project that uses it to convert jpegs to and from other formats. This code could be adapted to RawTherapee. (libjpegli is no longer part of libjxl and no longer any need to manually separate it.)

Thoughts? Opinions?

kmilos commented 3 months ago

libjpeg-turbo appears to have an option for expanded bit depth, but it must be enabled during build and is disabled by default.

No longer true since 3.x, it supports multiple sample bit depths OOTB. Code using it does have to be adapted though. However, I don't think you can ask for a higher bit-depth sample to what was encoded...

This would be useful to expand editing latitude of imported images.

Not sure I get this part - isn't RT pipeline float already?

Are you saying that, independent of RT, these are different:

8-bit jpeg -> libjpeg(-turbo) decode -> cast to float (w/ 1/255.f scale) 8-bit jpeg -> libjpegli decode direct to float

and the latter is somehow "better"? Any demos of this improvement?

xiota commented 3 months ago

No longer true since 3.x...

I'll look into it more. Has RawTherapee already been adapted?

Are you saying that, independent of RT, these are different...

jpeg is nominally 8-bits, but because of the transformation, rounding, quantization, etc, fewer bits are used. Then when the process is reversed, there's more rounding, etc to make it fit back into 8-bits. But if more bits are allowed in the process, the gaps between the 8-bit values (converted to float) can be filled in.

It can be seen with GIMP. Open a jpeg photo. Convert to 16-bit. Then look at the histogram. Convert the same photo to 16-bit pnm with djpegli. Look at the histogram.

This works because the transformations are based on sums of smooth curves.

jpeg-vs-jpegli-histograms

kmilos commented 3 months ago

Has RawTherapee already been adapted?

I doubt it, because there are virtually no 12-bit or 16-bit JPEGs out there....

Thanks for the histograms, I get the quantization issues. I guess what I'm saying is - since the plain old JPEG was already heavily quantized, do you really gain anything in terms of noticeable image quality with theoretically more levels when decoding? I suppose it might only become apparent when doing some considerable level stretching when editing...

xiota commented 3 months ago

jpeg is quantized in a different domain, after transformation. The transformation is based on smooth curves, so when the process is reversed, the gaps are filled back in. They're not the exact same values, but it's better than a bunch of spikes.

It's noticeable in GIMP with curve and level adjustments. If RawTherapee has some tricks to improve the image, it may not matter as much. Depends on the users' needs.

xiota commented 3 months ago

It's kind of like the raw vs jpeg debate. Don't need raw if someone nails exposure every time. So why does anyone need a raw processor? (So people who bought into the jpeg side before realizing their mistake have a collection of jpegs they wish were raws... This might help them get a bit more out of them.)

kmilos commented 3 months ago

get a bit more

Sure. Just wondering how much is that "bit" 😉

xiota commented 3 months ago

Sure. Just wondering how much is that "bit" 😉

Suppose it's 2-4 extra bits. I don't really know what that means. How much does each bit allow to increase exposure or any other setting?

kmilos commented 3 months ago

Might get interesting w/ Ultra HDRs (JPEG + gain map). (see also https://github.com/google/libultrahdr)

Lawrence37 commented 3 months ago

How much does each bit allow to increase exposure or any other setting?

Well, it's simple to test. Save an underexposed image as a jpeg. Open it the standard way and with higher precision. Correct the exposure for both versions and compare.

jonnyawsom3 commented 3 months ago

Sure. Just wondering how much is that "bit" 😉

Suppose it's 2-4 extra bits. I don't really know what that means. How much does each bit allow to increase exposure or any other setting?

On the JXL Discord server it was said to be roughly 10.5 bits in a standard 8 bit Jpeg, when encoded and decoded with jpegli from a 16 bit source. The reason for the half-a-bit is because of how the jpeg implementation works, it can technically allow more bits in smooth gradients (where it's needed) but has a lower limit on sharp areas. Jpegli is currently the only implementation that uses this advantage, so the gains are much more noticeable when both encoded and decoded though it, rather than decoding an old file where it has less data to work with (But will still fill in the gaps).