Every once and a while someone will ask me why I still use film. First of all, I have a film camera, and to buy a new one would be a significant chunk of cash. But that’s not the main reason. I like the look of film; I know how the various emulsions work and know what I need to do to get the best image from them; and (above all) I like the fact that I have an artifact when I get my film back from the lab.
Digital does have a lot of advantages, though. It provides instant feedback at the point of making the photograph. It’s also hard to beat the speed and flexibility of a digital workflow. And for 35mm-sized sensors, it’s hard to tell the difference from film.
This article mixes the look of film and the enormous possibilities of digital. It also continues the trend of notes about high dynamic range images that I’ve been posting recently.
Color film is an analog tone reproduction operator. It renders a vast range of illumination values to a particular color image. That is, it maps the high dynamic range world to a lower dynamic range representation. The major factors that influence this tone mapping “function” include the exposure settings (shutter time, aperture, and ISO speed), the film response curves, and development technique. A film response curve for Fuji Velvia, the color film I use, appears below. Notice how the curve is more-or-less flat in the highlights and shadows and that it has an S-shaped curve in between.
If you take some liberties with that S-shaped part of response curve where the real detail in the image is, you might almost say that the curve has a flat part for the shadows, a flat part for the highlights, and a line that connects the two.
When I first started puttering around with high dynamic range images, I began by translating what I knew about how film renders a scene with a lot of tones:
- Film is sensitive across a particular exposure range.
- Parts of the image with less than a certain amount of exposure are rendered as black.
- Overexposed parts of image are rendered as white (technically clear).
- You can’t change the film sensitivity (except with some processing tricks that we’ll ignore).
- You can change the amount of light that is recorded during the exposure.
It wasn’t hard for me to combine this information with the generalization about the film response “curve” to produce a very simple tone-renderer which simulates color slide film in MATLAB. You can download the M-file from my page on MATLAB Central, where you can find some other good stuff. (I’ve also reprinted it below.) I ran it on the HDR image of my office, varying the exposure from 0 EV to 12 EV in half-stop increments, and was very glad to see the same kind of results that I do with film.
But film is so twentieth-century. So I went on to more interesting forms of tone mapping.
function rgbSimulated = simulateFilm(rgbRadiance, nStops)
%simulateFilm Perform film-like tone mapping.
% LDR = simulateFilm(HDR, middleEV) converts the floating-point high
% dynamic range image HDR to a UINT8 low dynamic range image LDR using a
% method that recreates the sensitivity of film. The middleEV value sets
% the middle exposure value (EV) for the rendering. Larger EV numbers
% will generate brighter images; smaller values of middleEV will result
% in darker images.
% The film sensitivity is set to 6 EV, which is comparable to many
% late-model transparency (positive) films.
% Render the same HDR image using different "exposure settings."
% Essentially, simulate exposing the same scene from 0 to 12 EV in 1/2
% stop steps.
% % Read the HDR image and create a buffer for the rendered images.
% hdr = hdrread('office.hdr');
% s = size(hdr);
% ldr = ones(s(1), s(2), 3, 25, 'uint8');
% % Perform the tone mapping.
% for p = 0.5:0.5:12.5
% ldr(:,:,:,p*2) = simulateFilm(hdr, p);
% figure; montage(ldr)
% Author: Jeff Mather
% Copyright 2006-2007 The MathWorks, Inc.
% Set the film sensitivity and the mid-tone log-radiance.
sensitivity = 6;
midPoint = 3;
minLogExposure = midPoint - sensitivity/2;
maxLogExposure = midPoint + sensitivity/2;
% Film works in stops. Convert radiance to base 2 to compute perception.
% Values that are outside the film sensitivity are lost (min or max).
rgbRadiance = rgbRadiance * 2^(nStops);
rgbSimulated = rgbRadiance;
rgbSimulated(rgbRadiance ~= 0) = log2(rgbRadiance(rgbRadiance ~= 0));
rgbSimulated(rgbSimulated < minLogExposure) = minLogExposure;
rgbSimulated(rgbSimulated > maxLogExposure) = maxLogExposure;
% Convert to RGB.
rgbSimulated = uint8(255 * (rgbSimulated - minLogExposure) ./ ...