HDR Photography on Linux

While hiking last Monday, I was in a pretty place with harsh light. So I took some bracketed shots with the intent of putting them together later. I’ve now spent most of the weekend doing that, so here is a small write-up of what I finally ended up doing. This is a 100% Linux solution, which is the way I like it. You should be able to follow along with your own images.

To start, you need some pictures of the same scene that are exposed differently. Most tutorials on the web claim you need at least 5, but my scene ended up looking fine with just 3. The key thing I made sure of was to get one image where the clouds weren’t blown out, and one image with a lot of shadow detail. I converted these images to 16-bit PNG in Bibble, without making any adjustments whatsoever. This resulted in the following 3 pictures:

picture(crw_1544) picture(crw_1545) picture(crw_1546)

Because I didn’t have a tripod with me, these pictures don’t match up exactly. To address this, you can use hugin. Hugin is primarily used for creating panoramas, but it’s also very useful for lining up multiple exposures. In hugin you can manually select which points line up, or you can have it computed automatically by using autopano. Either way is fine, but I find I get better results by manually placing the points. So run hugin, and add your images. In the Camera and Lens tab, select all images and enter the focal length you used and crop factor (1.6) of your camera. Then in the Control Points tab create control points for your images. Since this isn’t a real panorama, you can pick any pair that is most convenient to work with, as long as each image can be linked to every other image in some way. Four points near the corner for each pair you’re doing should be good. On the Optimizer tab, select Optimize now!. You should end up with a maximum deviation that is less than one. You can keep going if it’s higher, but it’s best to fiddle with your control points until you’ve got that resolved. Next, in the Stitcher pane, change the projection to Rectilinear, and calculate the field of view. Now you can open a panorama preview and use the difference blend mode to make sure your images line up fairly well. It’ll look something like this:

You’ll see some border around your image. Reduce the field of view until every part of the panorama preview is covered by each of your images. This saves you from having to crop later. Finally, still in the Stitcher tab, stitch the images into a high-quality TIFF file.

Open cinepaint. The Gentoo cinepaint package was only version 0.21-1, but 0.21-2 comes with some important fixes to the Bracketing to HDR plugin. I created an ebuild for that version and installed it. In cinepaint, select File->New From->Bracketing to HDR. In the dialog box that pops up, select the numbered .tif files that hugin created. In my case, they were called sespe0000.tif, sespe0001.tif, and sespe0002.tif. Now you need to adjust the time for each exposure. The numbers you enter should be relative to the fastest exposure time in the set. The HDR plugin should already have sorted the images in order from fastest to slowest. My exposure times were 1/500s, 1/180s, and 1/60s, so I entered 1.000, 2.778, and 8.333. Now click Compute Response, and then click HDR. I’m sure there’s a lot more going on in this plugin, but I don’t understand it so I’m not going to talk about it here. Now you have an HDR image that is being displayed by cinepaint:

Save this image as an OpenEXR (.exr) file. You’ll notice that the clouds are still completely blown out, and there is no shadow detail either. This is because cinepaint can only show you a small slice of the entire dynamic range present in the picture. The next step is to perform tone mapping on the HDR image, which is the process of compressing the wide dynamic range in the image down to a range that can be represented on a monitor. The tool I’m using for that is qpfstmo, which requires pfstools and pfstmo. Gentoo doesn’t have a package for any of these, so I created those. They’re probably missing some dependencies, but they worked for me. You can download the ebuild for pfstools, pfstmo, and qpfstmo.

Exit cinepaint, and starts qpfstmo on your .exr file. Pick a medium sized work size, and now you can start experimenting with the various tone mapping algorithms and their parameters. The ones that looked interesting to me were fattal02, and reinhard04. fattal02 seems to give a much larger local contrast, but that makes the entire image look rather surreal. For this image, I prefer reinhard04 with a saturation of 0.6, which retains a more natural look. Once you’ve picked your settings, you can crank your work size up to the full image size, and save the resulting image. Unfortunately qpfstmo can only save in 8-bit PNG format. If you want the resulting file to be in 16-bit PNG format, you’ll have to use the command line interface to the pfs tools. For my example, the command line to use is pfsin sespe.exr | pfstmo_reinhard04 --saturation 0.6 | pfsout sespe.png. Open up the final image in your favorite image editor, and that’s it! You’re done!


If you find any mistakes in this article, or find it useful, or think something’s missing, please let me know in the comments below or e-mail me.

About the author

Living the good life in Seattle, occasionally sharing something interesting with the Internet.