Ok, my ColorPlus 200 film roll was developed, and… i’ve got a much better dataset this time!
Here’s an overview of the thumbnails:
The first gradient step is invisible to the naked eye, but it’s there: i had to stretch the histogram a lot in RT to locate the faint rectangle.
The last frame was not just overexposed : “roasted” might be a better term
And here is a log-log plot of the measurements:
On the X axis, are the measured channel values from the digital camera shot of the light source, taking into account the multiplication factors of the ND64 filter (remember the gradient was split in 2 sub-gradients, see previous post for details).
-
the first 18 steps were shot through the ND64 filter
-
the next 16 steps were shot directly
-
with the remaining 3 frames (i didn’t make any mistakes ) i continued shooting the last step, while opening the lens more and more. The entire 34 step gradient was shot at f11, then for the last 3 frames i went to f5.6, f2.8 and f1.4.
I had previously measured the exact multiplication factors of both the ND filter and the different apertures using the digital camera, in order to reconstruct a relative value of light intensity hitting the film.
--- R,G,B ratios ---
f/11 : 1 1 1
f/5.6 : 4.36557059961315 4.42335766423358 4.40650406504065
f/2.8 : 3.78489144882588 3.83580858085809 3.84481344813448
f/1.4 : 2.94866842259292 2.96875672187567 3.01492935217275
ND64 : 1 1 1
No filter : 59.231746031746 60.7208931419458 61.0385232744783
The Y axis indicates the pixel values from the digitized negatives. We can see that there is indeed a linear segment in each of these curves, but it’s not so huge. Keep in mind this is a log-log plot, so by “linear” we mean that the input is raised to a constant exponent.
The current version of the RT’s Film Negative tool does just that: applies a constant exponent to the whole image, as if everything was behaving like that linear segment.
If we can model this curve in a reasonable way (without too many knobs to adjust) we might achieve better color reproduction across a wider dynamic range.
So, let’s rotate this plot, in order to see what we need to achieve: going the other way around, from the digitized film value, to the original scene value. Here it is:
The digitized film images are 16-bit linear sRGB, white balanced on the unexposed film base color. Thus, the pixel value of Dmin appears as a neutral gray with all channels at ~18500.
We can see that, for example, the red channel is only linear between ~3000 and ~13000. I wouldn’t be much concerned about the non-linearity near Dmin (lower densities), since those areas will become deep shadows, where color casts are hardly visible anyway.
Now, let’s overlay the histogram of a real-world picture to this plot:
This picture was also white-balanced on the film base, and the curve values were scaled in order to align the tip of the curve with the actual Dmin value of the picture (notice the small notch on the far right of the histogram). This makes a fair comparison, since everyting is relative to Dmin.
In the blue channel, we can see that a significant number of pixels are outside the linear portion: applying the same constant exponent there, would not give the correct result.
So, not knowing anything about math, i did some random googling and found this little function: the Inverse Hyperbolic Secant.
This function has some interesting properties:
-
it somewhat resembles our curve
-
it’s defined between 0 and 1, so it can be easily mapped to our range
-
it has a slope of exactly -2 at x=0.70710… , so this can be used as a “junction point” to stitch pieces together and make a piece-wise curve.
I then made a very crude function, cutting at the junction point and inserting a line segment in between. These are the tweak-able parameters:
- shoulder size
- linear segment width
- toe size
- slope of linear segment
and here’s how it fits the data (dots are the measured film values, lines are the function plots).
BTW: of course the function is in linear domain, so i had to log the input, and exponentiate the output.
At this point, i stitched together a very primitive processing program in order to experiment a bit with this function (without having to mangle the RT source code every time ), and the results are somewhat encouraging.
The parameters found by fitting the plot were not perfect at first try, anyway the ability to change the length of the linear segment and the size of the curve “shoulder” feels like an advantage, in that it allows to fix some color cast in the highlights, while keeping the rest of the picture unchanged.
Now, the really hard part, is minimizing the number of parameters that the end user must tweak manually. One possible way that comes to mind, is dividing the work in two “stages”:
- first, deal with the middle part of the histogram and adjust the slopes, while actively masking the highlights (similar to what the clipping indicator does), so that the user is not distracted.
- then, uncover the highlights and let the user adjust the linear segments / shoulder size, leaving the slopes unchanged.
As always, ideas and suggestions are welcome
In the meantime, i’ve shot another test roll, this time with a Fuji Xtra 400; same exact procedure except halved exposure times (400 vs 200 ISO), and i’ve got 36 frames instead of 37 (maybe i’ve been too wasteful when loading the roll… or Fujifilm is a bit less generous than Kodak ).
I’m curious to see how the measurements compare between different film types.