Leica Adding a "Gamma Curve" to a digital image: Thinking out Loud and Experiments


Product of the Fifties
A quick Google search on how the eye perceives intensity-


Looks very much like how Film records intensity.

Sensitometry - Wikipedia

And a mathematical formula to compute an "S" chaped curve:

Logistic function - Wikipedia

The problem: Digital Sensors and Cameras have a linear response to intensity. So what happens if you adjust the linear response of the M Monochrom to look more like what the eye would see or film would record? I'm aiming at more mid-tone separation without losing shadow and highlight details.

Well, this FORTRAN programmer just cannot resist adding this function to code that processes linear-DNG files. You could add a "gamma" type curve using "curves" in Photoshop. As far as I know, Photoshop leaves the image with the same bit-depth as read-in. Something has to get lost in the translation, ie applying a curve means some intensity values get stretched, others get thrown together.

What I am thinking: first make the Linear DNG into a 16-bit file by multiplying (left bit shift) by 4. Reset the "White" and "Black" levels in the DNG header. Applying a Gamma curve will start to fill in the missing positions of the histogram rather than lumping them together.

Make sense? Is there anyway to do this in an existing piece of Software?
Last edited by a moderator:
I've computed suitable Gamma curves using a Sigmoid Function, implemented in Fortran... I like to figure things out using Fortran. I wrote my own Graphics package in the 1980s for a group at work, paid for my 1990 T-Bird with it and have been using it from 1988 on. Nikki even used it for her 5th grade Science Fair project.

ANYWAY- next step is a look-up table to convert linear values to a 16-bit DNG. Going to 16-bits means that there is less of a chance that pixels of close intensity do not get thrown into the same output value after the conversion, the 16-bit "avoids collisions". Yes- going to Jpeg throws most of it away, but you want to wait until the last possible step before losing bit-depth. This is as far away from DNG-8 as you can get. I hate DNG-8. Leica ruined a perfectly good camera by limiting it to DNG-8.

My Gamma Curves- give an idea of how to map intensity. The Graphics are written using HPGL. I found an HP7470 emulator for Win7. Pen and Ink plotter...
Last edited by a moderator:
Can you actually change the response of the sensor? It would be wonderful if that were possible, but I was under the impression sensor response to light levels was solely a function of its physical build characteristics. This is not my field and I don't profess to be very knowledgeable about it -- just wondering out loud. If you'd be changing the handling of the data, post sensor, it seems like that would be after the damage is done, i.e., after the highlights have been blown out or the shadows so underexposed they lack any detail.

Maybe the D/A converter would be a good place to adjust things.

It would be nice to be able to dial back the sensor's contrast (or increase it's range) depending on the contrast of the scene.

I often raise shadow detail or try to salvage highlights using the curves function of Photoshop or Lightroom. It's one of the best ways to do those things without screwing up the contrast of the middle values.
I've used non-linear A/D's before, Logarithmic scale. Most sensors used these days saturate at "only" 40,000 to 60,000 or so counts. The sensor responds linearly to light. The best you can hope for is to get more bits to work with and get higher counts before saturating. The M8 CCD saturates at about 60,000- but the DNG-8 used crippled it. 14-bits (16384) starts to get you there. 14 bits works out as you get noise underneath the saturation count. Sizing the A/D to be able to digitize and store the ratio of saturation count to noise count is usually a safe bet for a full image. That's what I do not understand about the M246: saturation count is ~40,000, but only 3750 levels are used to store it. That means the noise must be average of ~12 counts.

If the saturation count ever started getting into the "millions" using a logarithmic scale A/D would make sense. Unobtanium? Saturation count for the first generation CCD's was ~60,000. The improvements have been in reducing noise.

ANYWAY! I got the code to work, it is generating the curves, storing to a "14-bit indexed look-up Table with 16-bit output" and changing the DNG header to use all 16-bits. Basically you get the same effects on contrast in Photoshop or Lightroom by using curves, tones, levels- etc: BUT they keep the image as 14-bits. as you expand some regions of the histogram, other regions get combined into the same intensity level. Converting the image to 16 bits simply gives you more space between bins, retains more detail.

This is the "first crack" to see if things worked, remember- this is a few hours of writing the code.

Original image, straight export to Jpeg.

by fiftyonepointsix, on Flickr

Gamma curve 1.5, -2:2, centered. 16-bit DNG, Black set to 0, white set to 65535.

Converted 5046
by fiftyonepointsix, on Flickr

Original image, straight export to Jpeg.

by fiftyonepointsix, on Flickr

Gamma curve 1.5, -2:2, centered. 16-bit DNG, Black set to 0, white set to 65535.

Converted 5058
by fiftyonepointsix, on Flickr

Next time someone says the M Monochrom files are flat, think I'll try out the Gamma 3.0 curve...
Last edited by a moderator:
I changed the shape of the Gamma curve to pull out the dark areas.

Straight export using Lightroom,

Join to see EXIF info for this image (if available)
L1005046 by fiftyonepointsix, on Flickr

I did not like the way the tree came out.

Join to see EXIF info for this image (if available)
L1005046_100crop by fiftyonepointsix, on Flickr

SO: Gamma= 1.5, X0= -1.

Join to see EXIF info for this image (if available)
G5046 by fiftyonepointsix, on Flickr

Join to see EXIF info for this image (if available)
G5046_100crop by fiftyonepointsix, on Flickr

Brings the tree out of the "Black". I set the Black cutoff in the DNG to 0. Since I have 16-bits, I can always set it in LR or PS. If Black is set in the DNG, nothing below that value can be recovered. It is set to a count of 60 or so in the original. So the tree is gone.
Last edited by a moderator:
The next exercise will be continuously changing the value of some of the parameters of the translation curve. I think you can basically do a "high dynamic range" out of the single image by varying the parameters to generate Gamma, the X0 variable. I love Fortran.
The proof will be in the shadows and highlights -- if you can eke out more detail or a more complex gradation than is possible with curves in PS or LR, without screwing up the mid tones, you'd be on to something.
I will try some localized noise reduction based on intensity being close to the "Dark Current", ie "Dark Shadows", followed by a sharpening filter. I wrote my first noise reduction filter in Fortran in 1979. Negatives scanned in with a "scanning densitometer" onto computer tape. It filled a room.
Apologies if this misses the mark, and while I was enchanted by Alain Briot's participation in the older LL's forums in his explanations of 'curves', I've been using the 'gamma' rather than 'curves' function in Paint Shop Pro for years. My process is iterative, and partly based on "there is no contrast/color/luminosity that's perfect for all of my viewing situations". So I get as close as I can initially, then I generate a series of alternates over subsequent hours or even days, then with comparisons eventually settle on a 'best' version for filing. The iterations vary gamma, brightness, contrast, and sometimes even color or b&w tone. For some reason, varying one parameter such as curves only, even with all of the available sub-options, doesn't look the same.
I'm discovering the "no one size fits all". I spent most of the 1980s doing image processing, more "image processing and recognition" for image analysis. I will probably expand the code to generate histograms on the images and then try to come up with automatic selection. I guess this is what a processing machine does with looking at a negative and selecting filters for the print. Of course with the Monochrom- like selecting filters for polycontrast paper.
As an aside, I sent a lot of color negatives (35 mm) off to "Fuji Labs" in the mid-80s from the L.A. area, and they did an incredible job with getting the best print whatever the exposure of the negative. I wish I had more documentation on it, or better yet, how they did what they did. Since then I tried a couple others including Price Club (now Costco), and none of those did more-or-less perfect prints. Either the color or contrast was off, or there were technical errors. My habit with Fuji Labs was to send in 2 or 3 negatives and get 2 or 3 of 8x12 prints each, and they nailed it every time. So I dunno - I get the idea it wasn't just automated - someone there was looking...
I'm certain that there is a quality control involved, unfortunately the Fuji lab in the Northern Virginia area did not have it. Out of focus, bad color, scratched negatives- way too many times. One of the reasons I bought the M8 was Kodak getting out of processing film. I always had good results from them.
On my viewscreen, it looks like the original to step 2 improved the skin tone more than anything else, then step 3 continued that but the end result was a thickening of the "density" (for lack of a better term) of the image. Of course that depends on the dynamic range of the viewscreen - my MBPro and iPad and iPhone 6-plus are all "retina", but they're not the same ... not nearly.

I've made the statement in the past that the M Monochrom has the lowest non-uniformity of any sensor that I've used. The low-noise level is amazing. I've looked at the numbers using custom code, but never generated metrics on performance. That- I used to do for digital sensors in the early 1980s.

After several years, I can verify that comment.

This table is from the above website, the last two columns are dark signal non-uniformity (DSNU) and Photo Response Non Uniformity (PRNU) is - like Fixed Pattern Noise (FPN) - a way of expressing errors in the output from sensors. The lower the value, the better the raw image. I will never sell my M Monochrom, or M9. My M8 is one of the last in the production line. I'll keep it as well. 35 years ago- would have selected the M Monochrom based on the last two columns alone.

Camera ModelISOBlack

Leica CL1000.1110.0040.0150.0150.0106%0.4%
Leica CL[HCG]4000.1380.0040.0080.0050.0069%0.4%
Leica M (Typ 240)2000.0280.0090.0050.0100.005213%2.0%
Leica M (Typ 262)2000.0330.0060.0040.0140.007327%0.6%
Leica M Monochrom3200.0970.0040.0290.0040.0086%0.1%
Leica M Monochrom (Typ 246)3200.0080.0130.0080.0100.03986%0.5%
Leica M-D (Typ 262)2000.0310.0130.0060.0080.00794%0.5%
Leica M81600.0410.0050.0060.1570.0126%5.1%
Leica M91600.1400.0050.0050.0070.0065%0.4%
Leica M101000.0790.0060.0090.0060.00657%0.3%
Leica M10 Monochrom1600.0500.0110.0210.0060.00529%0.2%
Leica M10 Monochrom[HCG]8000.0410.0110.0110.0050.00435%0.4%
Leica M10-P1000.1190.0070.0090.0220.01074%0.4%
Leica M10-R1000.0840.0130.0200.0070.00636%0.3%
Leica M10-R[HCG]4000.0350.0070.0100.0060.00441%0.4%
Leica Q (Typ 116)1000.3030.0050.0560.0140.00813%0.8%
Leica Q2500.0640.0070.0090.0180.00812%0.4%
Leica Q2[HCG]8000.4140.0040.0070.0050.00520%0.7%
Leica S-E (Typ 006)1000.3050.0050.0090.0240.0114%0.6%
Leica S (Typ 007)1000.0760.0390.0260.0300.01541%0.4%
Leica SL (Typ 601)500.6800.0100.0610.0090.00714%0.6%
Leica SL (Typ 601)[HCG]2000.3120.0120.0150.0050.00523%0.5%
Leica SL2501.5870.0040.0100.0200.0139%0.3%
Leica T1000.0050.0050.0060.0210.00711%0.4%
Leica TL1000.0040.0050.0050.0180.01113%0.4%
Leica TL21000.0000.0040.0040.0240.01352%0.3%
Leica X11000.1350.0040.0050.0300.10672%0.4%
Last edited: