I think that’s why it helps to understand some of the entire pipeline. To allay your fears, cameras don’t capture negative values, each pixel is a light sensor, and, simplistically, if there’s no light at a pixel, it’ll measure 0, or some positive value close to that (think, “noise”). It won’t say, “gee it’s SO DARK I’m going to report it as a negative number.”
So, the Real raw data from a sensor is an array of light measurements that roughly range from 0 to the saturation limit of the sensor. Those measurements are usually presented by the analog-to-digital converters on the sensor (ADCs) as binary integer numbers. For the dynamic range of our cameras, that is usually delivered as a 16-bit integer, even though the camera’s range may only be 12- or 14-bit. My camera, a Nikon D7000, delivers 14-bit raw data, so it’s maximum possible measurement is 16,384. The light at a pixel may be brighter, but the DAC won’t push out a number bigger than its limit. That, is highlight clipping.
So, when smart folk advocate “editing in 16-bit”, they’re talking about keeping a room big enough for the data to move around while we toadies brighten, white balance, saturate, and do other math things to it. Oh, one of the early math operations usually is some sort of scaling to spread the data “evenly” through the 16-bit range. So, from now on, I’m going to talk about 16-bit image data.
Given the sensor delivers integer data, most processing software continues to work with it that way. Thing is, integer data represents the measurements in a series of “buckets”, 0. 1. 2. 3, … 65536. There is no place for the DAC to put a measurement of 23.586, so it has to go either in 23 or 24. And there is the first loss of beautiful information from the scene. We continue to lose information as we process the image, because each math operation wants to give us those precise rational numbers, but the results have to be truncated or rounded to the nearest integer bucket. There’s ~65K buckets in 16-bit, so we don’t see much difference as we work, but when the data is glommed (that’s a generic math operation ) down to the 8-bit range of, say, JPEG, there are now only 256 buckets, and the wrath of math operations start to show as posterized tone gradations.
Yeah, negative numbers, I’m getting to that…
So, black is black, a total absence of light, and we mostly want 0 to represent that. But math doesn’t respect that notion, for some operations the resulting values can be below 0. Really, that’s okay, because letting the result go negative and keeping that value retains information that we might be able to use later to pull detail back into the visible range. If we just clip it, that data is now gone. On the low end, that’s what “crushing” blacks refers to, and on the high end, “clipping”.
Ideally, what you want your software to do is let the data “spill” out of what can be displayed as operations are applied, and save the clipping for the final output to accommodate the particular medium.
Oh, to the goal of the thread, floating point numbers is a way in computers we can use to restore the ability to deal with the fractional part of image data. Funny thing, the predominant convention in representing image data in floating point is to use the range 0.0 - 1.0, where a 16-bit integer value from an image such as 2248 would be about 0.034301758 in the equivalent floating point image. That has to do with maximizing precision, and that discussion hurts the heads of even computer scientists, so I’ll offer nothing about it here. So in computer floating point, the numbers are still digital, but the buckets are arbitrarily and infinitesimally small and for our purposes are about as close to analog as we can get in our processing. Zero is still our ‘goal black’, but 1.0 is the upper limit for viewing instead of 65536 or (horrors) 255. Note that to use floating point even as early as the hardware delivery, there’s still an integer->floating point conversion required, so we’ll never really escape the fundamental tyranny of the sensor ADC.
My thought about “unbounded floating point pipelines” is to facilitate moving unbounded images between softwares, retaining the out-of-display values, both positive and negative, for working them in other programs that may have particular capabilities to recover them to the visible. FWIW…
Wow, a lot of writing on just one cup of coffee. I don’t mean to tutorialize smart folks here, but I’ve only recently learned some of this and I think it helps to pull it together this way. If you got this far, thanks for reading…