Scanning Negatives

I took an interest in photography before cameras went digital. And it took me a few years to go digital myself. The inevitable result is that I have lots of negatives with my earlier shots. Scanning these seemed to make sense, so I have been playing with films scanners and their related software for quite a while. I was never quite satisfied with the whole process though, so I never did bulk-scan my archives. Recently I went back to film, experimenting with B&W for the first time. The intention was to go through the whole process of development myself and scan in the end result; the rest of the workflow would then be my usual.

My ideal scanning workflow is very simple, and is based around Epson flatbed scanners with transparency adapter: at work I have access to an Epson V700 and back home I use my trusty Perfection 4990. The software that gets bundled with these (SilverFast AI) is good enough, but has two drawbacks for me:

  • It’s Windows, so I need to use it in a virtual machine, which is not ideal.
  • It tries to do too much, figuring out where the frames are, inverting negatives and adjusting exposure, etc.

In my ideal workflow I wanted to have the following:

  1. Scan the whole page at once with a fixed and consistent exposure. On the scanners I use this contains four strips of six frames each.
  2. Cut up the strips into frames in a reliable and predictable way. That is, don’t try to be too smart about finding frame edges – after all I know there will be exactly four strips of six frames each. And registration on the scanner is reliable enough (not pixel perfect, of course, but within less than a mm I think). Just crop generously around the expected frame boundary positions.
  3. Save the resultant frames in a lossless compressed format without any further processing. Effectively this becomes the equivalent of the digital camera’s RAW images.
  4. For colour scans it would be nice if I the scan would also contain the IR pass that the scanner can do, as this would come in useful for automated dust removal. Still, I don’t want to trust the scanner’s internal processing for dust removal: just keep the IR scan as a separate channel, thank you very much. For B&W (silver) film the IR scan would be pointless, as the silver is just as opaque as the dust to IR.

SilverFast could do the first step well enough, but coughs up badly with the rest. Did I say I wanted things to be predictable? I also tried VueScan, which is about the only alternative available. This has the advantage of being available for Linux as well, which is nice. However, when I download the trial version to see if it’s worth paying money for, it would not even work (segfaulted on the first run). I did not try again.

What followed may be rather geeky, but worked just fine. After all, I did major in image processing. For scanning I wrote a very short script that uses the SANE drivers:


source="-d epson2 --source Transparency"
mode="--mode Gray --depth 16"
resolution="--resolution 3200"

scanimage $source $mode $resolution $area |pnmtopng

The output of this script can simply be redirected to a file, which will be written in PNG format with lossless compression. The scanning area for the transparency is 150×246 mm, so we can easily select one the strips by replacing the blank area (defaults to full page) with the following:

area="-l 0 -t 0 -x 37.5 -y 246" # column 1

For colour negatives it’s just a matter of changing the mode from Gray to Colour. Sadly, the scanner driver does not support the IR channel, at least not out of the box. Note that I went with 3200 dpi, which on 35 mm film (24×36 mm) equates to 13.7 Mpx.

To cut up the negatives I wrote a small python program that takes the full-page scan file as input, cuts up the individual frames, and saves them to a specified folder. You can even choose to extract just one film strip, specify the first frame number, and rotate each frame by a multiple of 90°. It does require a system with a healthy amount of RAM, as a 3200 dpi full page scan (gray, 16-bit) is around 1.2 GiB uncompressed. What this program does is rather simple:

  1. It starts by determining the negative holder mask, by thresholding at 5% of the highest recorded intensity. Since the holder is solid black plastic, no light will go through, so effectively only sensor noise will be present in those regions. It would have to be a very badly overexposed negative to result in film as dense as that.
  2. This mask is used to determine the strip positions, so that each strip can be extracted as a single rectangular region.
  3. Each strip contains exactly six frames, so we set the nominal frame boundaries by dividing up the strip into six equal rectangles.
  4. For safety, we expand the nominal boundaries outward by 5%, to be sure we don’t cut out any scan region corresponding to this frame. The boundaries at the edges of the strip are not moved as these have been safely determined earlier.
  5. Following any requested rotation (normally 90° counter-clockwise for horizontal shots), each frame is saved in PNG format. I have experimented with other lossless formats, but this seems to be the most reliable (and non-exotic) format with good compression. JPEG2000 lossless has slightly better compression, but would require a separate conversion step as PIL does not support it.

film1301a-36If you made it this far, here’s a sample of the result. I did say that the development did not go well: you can see just how thin the negatives are. Observe also how the negative holder shows up top and bottom (so we can trust that the strip locator is safe). The actual frame edges are not well centered, but well within the cut region. This horizontal movement is really the only variable in the scanning process.

St-Martha's-(130136)From this point on, processing involved an inversion layer, global curves for exposure correction and contrast enhancement, and the expected dust and scratch removal. The image itself was taken just a few minutes from the one in my earlier post. Lens used was the 17-40mm f/4L at its wider end. The underdevelopment meant that the scan had to be pushed significantly, so that the grains really show up. Also, there is no useful detail left in the deeper shadow areas, so the image had to be kept rather dark. Thankfully, the look works for the subjects I chose to try the film on, and I found that I have more usable shots than I could have hoped for. As always, comments welcome.



  1. […] with intermittent agitation, as recommended. The negatives were scanned on an Epson V700 using the scripts I developed earlier. Processing involved a slight perspective correction and the usual selective curves for contrast […]

Leave a Comment

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s