16 bit float export looks weird in other applications, but 32 bit float is fine

Yes, it’s less precise than 32-bit float (duh).

However, half float is more than adequate for photography - you get approx. 30 stops of dynamic range (good luck representing anything more than 16 stops with uint16) and constant quantization per stop (agreed limited). The quantization error is still smaller than the photon shot noise. As @agriggio points out, there is no need to represent every single integer in highlights because those measurements are noisy anyway (see e.g. why NEF lossy compression works).

Caveat emptor: half float is supposed to be a storage format. If you do many round trips of demanding processing on the intermediate half float data, then I guess there is some small risk the quantization errors might start accumulating… VFX industry (OpenEXR) doesn’t seem to have a problem with it though…

@Waveluke

Are TIFF tags (SMin and SMax in particular) identical beween 16-bit and 32-bit exports?

half-float isn’t a first-class member of the C++ data type collection, so the developer is at the mercy of software implementations. I’ve only dealt with one implementation; are they all IEEE-754?

I used it to provide a 32-bit amenable build of rawproc for lesser Windows machines, but abandoned keeping up with the wonky typecasting and pre-processor #IF#THEN#ELSEs. With that and what @heckflosse has pointed out, I’ll not be using it in my further programming…

True that. As evidenced, more can go wrong with half floats depending on implementation, and is definitely not a mature/established format. But dynamic range & quantization are fundamentally not an issue.

And since the problem appears only in dark areas, you comment also made me think this is what also might be happening. If RT is exporting floats normalized in the [0, 1.0] range (and assuming it does the half float conversion correctly), it might happen that other apps handle half float subnormal numbers (< 2^-14) belonging to deep darks incorrectly on import…

Many apps assume files with 32-bit or 0-1 data to be float. In GIMP, at least you can define what you are importing.

@kmilos helped me understand some of what was going on with Octave: Learning Octave on Windows - #8 by afre. I don’t think it was worth the trouble even if I determined a simple workflow for it.

That was related to floating point TIFF interoperability between apps in general, nothing 16-bit half float specific in that particular case.

What I am saying is that apps aren’t able to identify “16-bit float” files or display them properly even if they could. Instead, they go by some unspoken convention and as a consequence aren’t flexible in this area.

Hi @afre, do you have examples?

I don’t think it works that way. Either the app supports and interprets floating point TIFF tags properly (regardless of stored bit width), or it doesn’t. The internal 16-bit<->32-bit conversion step on import/export is (should be) independent of that and should be the only place where things could go wrong. Writing completely separate TIFF code paths that do different things for 16-bit and 32-bit floats would be foolish.

1 Like

Honestly, I haven’t looked into this in a very long time, like a decade or so, except for my questions on Octave. I will defer to your (global your) assessment.

What I have left to say is that people have different ideas of what should be and what happens to be. My wish list is very long but usually things aren’t ideal.

@agriggio PS, though I haven’t used it since CC; get my intel through third party sources now. They seem to waffle on certain features, so things sometimes work and other times break. It depends on how you are importing; e.g. various HDR import methods, file / layer import, import via CR, smart object import, etc.

PS Come to think about it, scripting for PS might be a way around the confusion. One can be more explicit with what one is doing. See Adobe Photoshop Scripting.

I have been inclined to believe that 16 bit half float would be fine in terms of precision, and 11 bit for the actual numeral seems to be sufficient for photo and video, given the noise inherent in digital imagery from cameras. I re-opened the 16 bit half float in Rawtherapee and haven’t run into banding issues, even with drastic adjustments.

@Waveluke Would it be possible to share the 16-bit half float image to test in darktable master?

1 Like

Here you go:BMPCC_1_2020-11-22_0713_C0000_000033.tif (12.4 MB)

1 Like

I checked several apps and this is my result without trying to get it to work.

Okay
GIMP, Krita, RawTherapee (obviously)

Not Okay
IrfanView, G’MIC preview (faint with dots) @David_Tschumperle
Inkscape (blank shape)
PhotoFlow (crash) @Carmelo_DrRaw
darktable (lighttable says can’t find file even though it has space invader icon; darkroom keeps on loading and fan keeps on running)

Thanks. I don’t see any problems with darktable 3.3.0+651~gb6bbd0d56 either.

@afre Native support for reading 16-bit half float TIFFs was added to darktable only last week :wink:

FWIW, there are only a handful of 16-bit half float subnormal values in that image, but quite a few negative ones, which third party apps seem not to handle. Min is -0.485107421875, max is 4.48828125.

Did not come out OK with my (quite old) version of Photoshop. Imported very flat as if it assumed a gamma of one. Converting to 16bit mode with a gamma of 2.2 restored the contrast but still left the colours washed out. Have you tried saving it with an output profile that specifically has a gamma of 1.0

As I mentioned in "Clip out-of-gamut colors" check box - #76 by RichardRegal the only way I could get a picture to look the same in both programs was to use an output profile with a gamma of 1.0.

I did submit a bug report as Floating Point Exports have the wrong gamma · Issue #5893 · Beep6581/RawTherapee · GitHub but the consensus there was a problem with how other programs interpreted things then it was not a problem with RT.

G’MIC displays okay (display-referred) when I do the following:

gmic BMPCC_1_2020-11-22_0713_C0000_000033.tif c 90%,100% \
n 0,255 afre_jchz sh 1 afre_brightness. 100 afre_contrast. 100 rm. afre_ijchz \
n 0,255 round o BMPCC-gmic.jpg

c 90%,100% is a crazy amount to clip but it shows that the actual mid-tones are in the 90-100% range. Or more precisely, in the 60-100% range if you clip the negative values first. The next two lines make the image more presentable.

Another look with 65% clipping above 0, showing a bit more more the shadows. Could be 60% as mentioned but it won’t look nice in your web browser.

Just in case somebody else is interested and for future reference, I only just now figured out NumPy supports float16 natively! So if you have imageio & tifffile installed, you can check out these files very simply as:

import imageio
import numpy as np
im = imageio.imread('BMPCC_1_2020-11-22_0713_C0000_000033.tif')
print(im.shape)
print(im.dtype)
print(im.min().astype(np.float32))
print(im.max().astype(np.float32))

NB: Seems the np.float16 class tostring() overload is limited to 3 significant digits, hence the casting (which is also needed on the whole image if you want to show it using e.g. matplotlib)

1 Like