Shelly and Roy 4:58pm, 1 July 2009
My first script-fu is now in the Gimp registry!

Maximize Local Contrast creates a new luminance layer with greatly increased local contrast. It gives a lot more definition with less haloing than Unsharp Mask.

It is quite slow, so you might want to try it on relatively small images to get the feel of it. Increasing the Threshold parameter and decreasing the Radius parameter will give faster performance (and conversely). The default settings on a 6 megapixel image will take minutes to run.

Comments and suggestions would be welcome.

...and I think I found my first bug...
wgoss 7 years ago
Well it runs....a little too slow for me....

I would suggest a better Menu location......For most Script-Fu is gone.....
I would probably locate it in FX-Foundry under Layer effects....

The script, as well as some of the plugins Menu arrangement is poor at best....I have finally tried to work with Filters or FX-Foundry.....

Just a suggestion.....
Vieira PRO 7 years ago
Shelly and Roy wrote
Increasing the Threshold parameter and decreasing the Radius parameter will give faster performance (and conversely).
And less striking effect, I suppose? It might fit my bill, I'll give it a shot.
Shelly and Roy 7 years ago
Actually, if you increase threshold and/or decrease radius, you might start seeing artifacts - dark spots or the like.

Thanks to both of you for trying it out.
jeffegg2 PRO 7 years ago
I boost contrast by adding a copy layer, and changing to soft light, then reduce opacity to about 20%.
Smabbage 7 years ago
jeffegg2: That works nicely. Thanks for the tip.
Shelly and Roy Posted 7 years ago. Edited by Shelly and Roy (member) 7 years ago
jeffegg2: That's a boost to global contrast, which is a useful but different effect. Observe:


As you can see, the original is pretty dull, so the soft-light overlay can be done at 50% without being overdone. But you get a lot more effect from Maximize Local Contrast. It's more like what you get from Unsharp Mask, but better IMO.
Smabbage 7 years ago
Ok. Just tried the script. It too is quite impressive. Had to figure out that once the B&W image was created I needed to select "Overlay" mode but that was me being a bit thick. Nice result. I tend to agree that it does in fact create less haloing than Unsharp Mask. Would like to know a little more about what the parameters do though.
Shelly and Roy Posted 7 years ago. Edited by Shelly and Roy (member) 7 years ago
You don't need to put it in Overlay mode, although I guess you could. My original intent is that you use the Contrast Enhanced layer in Normal mode. I don't give any instructions for putting the color back in; the easiest way would be to put the original image on top of the enhanced image in Color mode. Maybe I'll add that functionality.

The script works much like Stretch Contrast, only instead of stretching everything out relative to the maximum and minimum pixels in the entire image, it adjusts pixel values relative to the maximum and minimum pixels in their vicinity.

The Radius parameter indicates how wide a pixel's influence is, as a maximum or minimum value. There's a little magic in the script that adjusts the radius to be smaller around extreme values and larger around medium values. I found that seemed to help with haloes. If you choose a radius that is too small, contrast will be too localized, and the image will look patchy.

The Threshold parameter is purely a trade-off for speed. Waiting for it to go through 256 iterations could result in people smashing their monitors in frustration. So instead of selecting one color at a time, you can select Threshold colors on each side of a gray value all at once. Threshold of 1 does 3 at a time, 2 does 5, 3 does 7, etc. If the threshold is too high, you'll probably see spots that are a little too dark or light.

I got rid of the Feather parameter. Nothing good can come of making it small, so I hard-coded it to 95%.

The script now installs in FX-Foundry/Photo/Enhance
Smabbage 7 years ago
Thanks for the info. So the intent was to create a sharp black and white image with good contrast?
Shelly and Roy 7 years ago
The intent was to implement the algorithm on black and white, because there's no obvious way to apply it to color. Here's what I would do (and will probably write into it in the future):

Take the Base layer and put it above the Contrast Enhanced layer
Change the Base layer mode to Grain Extract
Merge down
Change the Contrast Enhanced layer mode to Grain Merge

Now it will be an adjustment layer that you can use with your original color image.
Smabbage 7 years ago
Wow! That works so much better than using the Contrast Enhanced layer in overlay mode. Your technique doesn't artificially darken areas of the photo like eyes etc. This option definitely needs to be added to your script.
dogwatcher 7 years ago
Sounds really interesting.. I have to try this! I tinker around with local contrast in b/w images every time, with mixed results.. but I use this old (unsharp mask/big radius/low strength) method...
{Robert} [deleted] 7 years ago
really impressing results! thanks a lot :)
~ n23409 ~ [deleted] 7 years ago
Thanks a lot "Shelly and Roy".
I was missing this feature for a long time.
tom.keil 7 years ago
Here is another simple method to manipulate local contrast:

copy the base layer, filter the copy with the Retinex filter (set sliders that the areas you want to emphazise pop out; and do not care about the strange colours)

set layer mode of the Retinex layer to luminocity and adjust opacity (for portraits 20-30% and for landscapes 50-70% usually do well)

If the Retinex layer is too noisy (that might happen in dark areas), denoise it or give it a surface blur, if you apply this strong this gives your image a painterly look.

Instead of Retinex filter you can also use a tonemapped layer produced in any HDR software of your taste, i.e. QTPFSGUI or Photomatix.

[mountain stable]
dogwatcher 7 years ago
I just tried the script.. :)

I got a b/w layer after running the script on a normal layer.. I changed the overlay mode of the contrast layer to "value" and got a quite interesting result.. nice!

parv. Posted 7 years ago. Edited by parv. (member) 7 years ago
Thank you Shelly & Roy. Here is one presentable result ...


... reduced the opacity of "Contrast Enhanced" layer to 44% & merged it with "Base" layer.
dogwatcher 7 years ago
Hmm.. strange. The picture I wanted to "boost" with this script didn't work at all... Just weird results. Still have to take a deeper look for the reason..
Shelly and Roy 7 years ago
I have updated the script in the Registry so that it generates a Grain Merge layer instead of just the black and white over the base. Keeping Max and Min layers is now optional.

I think this should be the last update. At least for a while.
Smabbage 7 years ago
Can't wait to check it out. Thanks.
Shelly and Roy 7 years ago
Updated again. This time, it's really the last update*. Fixed a bug that had been plaguing me, made a couple of tweaks to keep haloes down, and changed the radius parameter to work as a % of image size.

*until I think of something that needs updated. You know.
{ pranav } 7 years ago
It is a very useful script that you contributed to Gimp users. Thank you for that. Isn't there a way to make it run even faster than it does currently?
Shelly and Roy 7 years ago
If I knew of a way to speed it up, I would write it that way. I haven't thought of one yet. I am talking with someone about making it a plug-in, which could make it faster.

You might try increasing the threshold setting. That will certainly speed it up, and it should be less prone to artifacts since the latest update.
PhotoComiX 7 years ago
@Shelly and Roy

As plugin willl be faster but i do not think that too relevant

BUT i found very relevant that as plugin will be available a Good Preview

The effects of your last scripts are excellent a Preview will allow to easily find the best setting.
schrockinator 7 years ago
Very Nice result!

(I should have listened when you said it takes a little while - I tried it on a 3872 x 2592 image! Should have scaled it down a bit first!)

{ pranav } 7 years ago
Thank you Shelly and Roy! That's a good idea to make it a plugin. I guess that would need you write a log of code....

Yes, your latest version does not produce the artifacts I happened to see with earlier version. I am just thinking if you could provide an option to choose the resultant image size so that it will automatically re-size the image before applying the effect. especially when someone accidentally tries it on too big image.

Wondering what de-noising technique is more useful to get rid of the resulting noise with this script?
Starline Photo 7 years ago
I tried your technique got the this point:
> set layer mode of the Retinex layer to luminocity ???

I can not find a luminocity mode.
parv. 7 years ago
Shelly & Roy, could it be possible not to update the image window whilst your script does its work? More importantly, does not updating the image window with intervening states speed up the process any?
tom.keil 7 years ago
@ Sorry, i am not using english language version, in GIMP in english mode name is value (same like luminocity in PS)
Starline Photo 7 years ago
Thanks Tom
Shelly and Roy 7 years ago
I'll provide an option for downscaling the effect. The original image won't be resized, but the processing will be done on an image 2 or 3 times smaller, so it should be sped up by a factor of 4-9x. That would be a pretty good speed-up. It would also curb the enhancement of noise.

I don't know how to best denoise for this process: lightly on the image before processing, do it to the Grain Merge layer that is produced, or do it on the final result after applying the Grain Merge layer. That would be something to play with.
Shelly and Roy Posted 7 years ago. Edited by Shelly and Roy (member) 7 years ago
The new version is in the Registry. It is a significant improvement in speed and in handling of "difficult" images.

If the version you have doesn't create a layer mask on the adjustment layer, you'll want to get the newest one. I uploaded twice today.
wgoss Posted 7 years ago. Edited by wgoss (member) 7 years ago
Nice work....I reduced my test image time from 17 minutes to 1.5 minutes......setting 4-3-4 used 100 of overlay....

Roys on the Left...the right is Original (Topaz treated image)

{ pranav } 7 years ago
WOW the new version runs lightning fast (as compared to original). Thanks a lot for all your efforts :)
1tommyb 7 years ago
so i was playing with your script, and i love it. it works just great. the thing i was having fun with was going way overboard. now this brings me to a question wich i think i know the answer... if i want to over prosses an image, but cut the faces back closer to normal, i could use a mask layer, and make it 50%?? that is what i was thinking, but is there a better way for me to get the look i was trying for?
Paul Nasca 7 years ago
I am working on a "ldr tonemapping" open source software.
You can see more about it here,

For now, it only enhance the contrast of the highlights and shadows, but I am working on midtones local contrast enhancement.

If I will be satisfied about the results, a good idea is to write a gegl operator with this ;)

mm mike Posted 7 years ago. Edited by mm mike (member) 7 years ago
I'm trying to implement this idea into dlRaw, a new 16-bit RAW converter. It will be somewhat different, because I don't have the builtin functions of gimp at hand.
You can have a first look here:

So the point is, I have to translate the idea to a pixelbased algorithm working on the LAB transform of linear represented 16-bit RGB data. Any help or ideas are appreciated.

greets mike
Shelly and Roy Posted 7 years ago. Edited by Shelly and Roy (member) 7 years ago
New algorithm! No need for threshold or scaling, now, so there are no quality trade-offs.

A word about speed:
As images get larger, the computing requirements grow exponentially.
A 1MP image took about 10 seconds for me. No problem
A 3MP image took about 45 seconds. Not really a problem, but kind of slow.
An 8MP (2736x3648) image took 3 1/2 minutes. That's a bit on the slow side. So there may be reason for me to add a scaling option to deal with very large images. How long is too long?
Update: I added the scaling option.

There aren't too many steps in the process, so the progress meter may make you think it has locked up. Give it a minute and it will move.
Le rictus du singe 7 years ago
Very useful script for everyone to have in his/her "toolbox"!
bluesman43 7 years ago
Great script! I just converted some images (portraits) to black and white and split tone. The script really made them pop.
Thanks so much!
Scott Coulter PRO 7 years ago
Loving this script so far. Used it here:
Alien Landscapes: Mammoth Hot Springs

Thanks for your work on this.
mm mike 7 years ago
Finally I could implement a version of this algorithm into dlRaw. So you can use it with 16 bit processing on your raw files. More information at my site:

Have fun,
PhotoComiX Posted 7 years ago. Edited by PhotoComiX (admin) 7 years ago
@roy and shelly

i saw the script do not take selection in account,

that is fine in most of cases but sometimes may be usuful

I know will be too complex ,and may have disadvantages make the script REALLY works on the selection, but there is a simple workaround to get the equivalent effect.

In few words you just paste over , on a new layer the part of the original layer that you want preserve as it was,

in details

1) on the active layer
check for a alpha channel, if there is not add it

2 invert selection

3 copy layer (do not paste now)

4 now the script will run as now

5 create a new layer on top, paste there

6 now again invert selection

i used this trick for a contrast mask trick beuse other solution were giving ugly result if was feathering on the selection
(feathering may give quite ugly effect if the layer is in mode different then Normal,)
Shelly and Roy 7 years ago
That's clever, PhotoComiX. You could also run the script first, then select the area you want affected, invert the selection, and delete the selection from the adjustment layer the script produced.
PhotoComiX Posted 7 years ago. Edited by PhotoComiX (admin) 7 years ago
Yes and ...OOPSS

OOPSS because i failed to notice that your script create a selection

so step 2 should in case be corrected as

"2 invert selection, save selection to a channel"
and the other slightly changed (to load the selection when needed)

But i am glad you get my idea
Is not relevant that a script or plugin can't use the selection,
since paste on top a copy of the original layer done using the inverted selection offer to the user a equivalent result (identical for what regard the" visible")

and as extra bonus that preserve the original selection
(may be useful if was a complex selection and the user did not expect its deletion, so did not use the precaution to preserve a copy in a channel)
parv. 7 years ago
Shelly and Roy, could you please start using a version number, to be bumped up every time "Maximize Local Contrast" is updated?
Shelly and Roy 7 years ago
I'll try to remember to do that, parv., if ever I update it again.
Wolf-Ulf Wulfrolf 4 years ago
Big thx @ Shelly and Roy for making this awesome script. It's my most-used effect for my pictures... almost every photo I take, gets it's finish with maximize local contrast.

But there's one problem. When I want to apply the script to pictures with fine gradients, as in landscapes with much sky on it, It's always spoiled with banding artifacts.

The final m.l.c. layer shows this effect very clearly... here's an example (just the layer without it's mask):

Is there anything I can do about it? I tried to apply some HSV Noise but this gives just a slight improvement... any tipps?
carlo.caponi 3 years ago
the script doesn't work in gimp-2.8 !
Bernhard Mogens Ege 3 years ago
True. The script fails in gimp 2.8.4.

The error produced is this:

Error while executing script-fu-max-loc-contrast:

Error: ( : 1) Procedure execution of gimp-selection-combine failed on invalid input arguments: Item 'Value' (7) cannot be used because it has not been added to an image
Pit Sütterlin 2 years ago
OK, I now also switched to 2.8.6, and got stung by this issue. Digging around, I finally found a working solution. I'm posting a diff here:

@@ -53,8 +53,10 @@
(min-layer (car (gimp-layer-new theImage smwidth smheight dr-type "Min" 100 NORMAL-MODE)))
(max-layer (car (gimp-layer-new theImage smwidth smheight dr-type "Max" 100 NORMAL-MODE)))
(theRadius (* (/ Radius-pct 100) (max smwidth smheight)) )
- (myChannel (car (gimp-channel-new-from-component theImage GRAY-CHANNEL "Value")))
+ (myChannel 0)
+ (set! myChannel (car (gimp-channel-new-from-component theImage GRAY-CHANNEL "Value")))
+ (gimp-image-add-channel theImage myChannel 0)
; Fill Min with white, Max with black
(gimp-image-add-layer theImage min-layer -1)
(gimp-edit-fill min-layer WHITE-FILL)

OK, this looks quite horrible. Hope it's understandable nevertheless...
Wolf-Ulf Wulfrolf 2 years ago
Pit Sütterlin:
Thank you very much! This saved the script for me. I've uploaded the edited script to my server in case someone else wants to use it and doesn't know how to do this...
François Collard Posted 2 years ago. Edited by François Collard (admin) 2 years ago
Wolf-Ulf Wulfrolf:

When using a script or a plug-in, who cares of FX Foundry? A better location, to me, would be:
"/Filters/Enhance/Maximize Local Contrast..."
Your script fails with:
"Error: ( : 1) Procedure execution of gimp-selection-combine failed on invalid input arguments: L'élément « Value » (14) ne peut être utilisé, car il n'a pas été ajouté à une image "
on Gimp 2.8.10 Windows.
Nothing seems to be patched...
Groups Beta