CCD-raw file processor
An effort to improve the nitty-gritty detail in my pics

see copyright notice. Page created 30-Apr-2010 updated 9-Nov-2019. Use the button groups above to navigate quickly around the site.

[JR logo]

As you'll know if you've explored this website, I can't resist a technical challenge. So, in 2007, I set about deciphering the raw CCD data files which my digital camera disgorged when I pressed the right buttons. I find that sort of thing more rewarding than solving crossword puzzles, plus I was able to go on and write some software that I think makes better-looking pictures than the regular ones. I worked on this project intermittently, but it took a long spell of bad weather (winter 2009-10) for me to put the finishing touches to it. This page documents the results.


[My cameras in 2010]

My workhorse camera in 2010 was a Fujifilm FinePix™ S9500 "bridge" model (on the right in the photo). I bought it in 2006, to replace the 4900Z (centre) which had given me excellent service for the previous 5 years. Before going digital, I'd used a Nikon™ FM (left). The photo itself was taken by my first digital camera, the marvellous little Fujifilm™ DX-10 (1999, 0.8 megapixels).

I was impressed by the S9500's "manual" zoom ring, and consequent rapid start-up. The lens seemed less sharp than the 4900's, but the noise level on its JPEG images was dramatically lower. However, there was one thing that really disappointed me: the camera's image processing, in achieving that impressive noise reduction, wiped out a lot of fine detail. In pictures of distant foliage, grass, close-ups of flower petals etc, it sometimes looked as if the image had been smeared over with a damp cloth!

The camera has a "CCD-Raw" file saving option, and the bundled software included a raw file (to TIFF) converter. The latter, however, ran incredibly slowly - in fact it didn't look as if it would ever get to the end of converting an image on my computer (admittedly not the latest model). So I decided to have a go at writing my own. It's called - not very originally - ReadRaw.


[CCD sensor pattern]

This diagram shows my (simplistic) visualisation of how the R, G and B sensors are laid out on this unusual type of CCD. Having worked out how the pixel values are stored in the raw data file (two different formats are used, depending apparently on the shutter speed), I spent some time pondering on what resolution to extract. Early tests suggested that the optical colour filters were fairly wide, so I decided to see what sort of "luminance" image I could get from just the "green" data, at 2440 x 1830 px. To cut a long story short, my software ended up using that as the basic resolution; even though it only amounts to 4.5 megapixels, I found it interesting to compare the results with the camera's best quality JPEGs (see later).

Following is a description of the ReadRaw program's user interface - technophobes already suffering may wish to skip it. Please be aware that this program is a one-off experiment for my personal use, and is not available commercially.


[ReadRaw dialogue]

On opening a raw data file, ReadRaw displays an image according to the control panel settings. Initially it's the whole picture at 25% magnification (610 x 458 px). Any area can be enlarged to 100% by clicking on a central target point; a second click restores the 25% view. In both modes, the RGB values at the cursor point are shown in the status bar. Options in the File menu include Save (as bitmap file), Extract JPEG (1600 x 1200px image embedded by the camera), Mix, and Divide. The last two enable a second raw file to be merged into the image; this would be either an identically-framed second shot (to reduce the noise level - Mix mode) or an image of a plain white field (to compensate for optical vignetting - Divide mode).

The raw samples are prescaled according to the [white] Balance settings (presets include Custom, Overcast, Tungsten, Unity). The USM controls improve sharpness, using an "Unsharp Mask" process to act only when adjacent pixels exceed a specified difference, to minimise noise amplification. Colour fidelity is determined by the Matrix controls, which, rather simplistically, subtract a fraction of each channel from the others (presets include Custom, sRGB, Enhanced, Vivid, No matrix). Chroma R:G:B selects one of 6 area patterns for the chroma calculations (minimum 2:1:2, maximum 30:61:30). Higher numbers make for less chroma noise, but at the expense of chroma resolution. Expand enables the R and B components to be spacially expanded or (more likely) reduced, to compensate for chromatic aberration. It works by incorporating R and B chroma values displaced from each pixel, which slows down the processing a bit but makes a world of difference at the corners of the image! Gradients defines a transfer curve by the ratios of 5 slope values, each in the range 0.01 to 99, which enables quite complex but smooth contrast mapping. Presets so far are Custom, Hi-comp, Lo-comp, Camera (emulates the camera's transfer curve), Linear. The True Colour option maintains colour saturation at all levels regardless of the transfer curve. The Clip control can be set to equalize the channel saturation points, making washed-out highlights look better. Finally, the nominated Gain, Flare (black level shift) and Gamma are applied to produce 8-bit RGB outputs. If individual settings within a group are changed, the whole group is stored as the "Custom" setting, so it's easy to switch between this and any of the presets. The Apply button refreshes the displayed image. Abort cancels a load or save in progress, and Default restores all parameters to their default values.

The defaults and presets were determined using various photos of test strips and scenes with suitable lighting. Where appropriate I used a JPEG image from the camera for comparison, e.g. to match the transfer curve (ah, so that's why I always had to boost the lowlights to get a good print!). To determine the matrix values, I used a laptop LCD to display a red/green/blue rectangle on a black background, photographed with a filter of the same colour in front of the camera lens. Values were then tweaked to get zero unwanted components in the image file. The result is a good match to the camera's own colorimetry, although the latter seems to give "greener" greens (wasn't it always so with Fuji film?!)

The raw data is cached in memory when a file is opened, and critical parts of the program are coded in assembly language - so it's pretty fast. I've also written a separate utility to replace the JFIF section of a final JPEG file with the Exif from the raw file, so I can graft in the shooting data and thumbnail.


So how does it shape up? Below are comparisons between the camera's rendition and "my" version of two sample images. In each case there are two 100% crops, taken from near the centres of images shot in succession and under the same conditions. The left crop is from a 9Mpx (3488 x 2616) camera image saved in "Fine" JPEG quality - typically 4.5MB on the media. The right one is from a 4.5Mpx (2440 x 1830) ReadRaw conversion, saved as a JPEG file of around 2.5MB and then re-read and upsampled to 3500 x 2625 (this larger size allows for ReadRaw's slightly wider coverage of the CCD area).

[Eggs] [Grass]

Despite the increased noise, I was delighted with the improved detail. The experience also left me wondering how I should rate the number of megapixels in a camera spec...

top ▲