... without clipping.
The page Maximise local contrast shows how we can maximise local tonal contrast, varying what we mean by "local", and using a blend to control the degree of the effect.
This page applies the same method to the L*a*b* channels of an image to increase or maximise local colour contrast. This increases saturation, but also increases the local differences between colours.
The method described in Maximise local contrast is applied independently to all three channels: L*, a* and b*. There is an option to affect only L*, or only a* and b*, in which case the other channels are replaced by those from the input.
Channels a* and b* have their neutral point at 50%, so multiply and divide must be with respect to that point. We subtract 50% from those channels, so for %INLAB%%BLR% and %MAXC% they nominally range from -50% to +50%. However, %MINBLR% varies from -100% to +100 in all channels, so %DIV% varies from 0 to 100%.
The script maxLocCol.bat does the work.
Option | Description |
---|---|
%1 | Input image. |
%2 | Output file. |
%3 | Sigma to find the local mean. Default: 2. |
%4 | Sigma to find local maxima. Default: %3. |
%5 | Blend percentage. Default: 100. |
%6 | Apply to channels Lab or L or ab. Default: Lab. |
%7 | Post-process, eg -auto-level. Default: no post-process. |
For example:
set SRC=toes.png call %PICTBAT%maxLocCol ^ %SRC% ^ mlcl_sc1.png 0.5 |
|
call %PICTBAT%maxLocCol ^ %SRC% ^ mlcl_sc2.png 1 |
|
call %PICTBAT%maxLocCol ^ %SRC% ^ mlcl_sc3.png 2 |
|
call %PICTBAT%maxLocCol ^ %SRC% ^ mlcl_sc4.png 3 |
|
call %PICTBAT%maxLocCol ^ %SRC% ^ mlcl_sc5.png 10 |
|
call %PICTBAT%maxLocCol ^ %SRC% ^ mlcl_sc6.png 20 |
|
call %PICTBAT%maxLocCol ^ %SRC% ^ mlcl_sc7.png 50 |
Generally, the two sigmas should be equal. If the second is larger than the first, the contrast is reduced. If the second is smaller than the first, contrast is increased.
call %PICTBAT%maxLocCol ^ %SRC% ^ mlcl_sc13.png 1 3 |
|
call %PICTBAT%maxLocCol ^ %SRC% ^ mlcl_sc31.png 3 1 |
We can use the blend parameter from 0 to 100 to control the degree of the effect, or use a value beyond that range.
call %PICTBAT%maxLocCol ^ %SRC% ^ mlcl_bz0.png 0.5 . 25 |
|
call %PICTBAT%maxLocCol ^ %SRC% ^ mlcl_bz1.png 2 . 25 |
|
call %PICTBAT%maxLocCol ^ %SRC% ^ mlcl_b1.png 0.5 . 50 |
|
call %PICTBAT%maxLocCol ^ %SRC% ^ mlcl_b2.png 2 . 50 |
|
call %PICTBAT%maxLocCol ^ %SRC% ^ mlcl_b3.png 2 . 150 |
|
call %PICTBAT%maxLocCol ^ %SRC% ^ mlcl_b4.png 2 . -150 |
By default, the process modifies all three channel of Lab. Instead, the operation can be restricted to just L or ab.
All three channels: call %PICTBAT%maxLocCol ^ %SRC% ^ mlcl_lab.png 0.5 . 50 Lab |
|
Just the L* channel: call %PICTBAT%maxLocCol ^ %SRC% ^ mlcl_l.png 0.5 . 50 L |
|
Just the a* and b* channels: call %PICTBAT%maxLocCol ^ %SRC% ^ mlcl_ab.png 0.5 . 50 ab |
Restricting to just the L* channel gives a similar result to Maximise local contrast, but is slower and uses more memory.
Restrict to just a* and b*, at two different sigmas, and three different blend percentages.
call %PICTBAT%maxLocCol ^ %SRC% ^ mlcl_m1.png 0.5 . 50 ab call %PICTBAT%maxLocCol ^ %SRC% ^ mlcl_m1b.png 2 . 50 ab |
|
call %PICTBAT%maxLocCol ^ %SRC% ^ mlcl_m2.png 0.5 . 100 ab call %PICTBAT%maxLocCol ^ %SRC% ^ mlcl_m2b.png 2 . 100 ab |
|
call %PICTBAT%maxLocCol ^ %SRC% ^ mlcl_m3.png 0.5 . 150 ab call %PICTBAT%maxLocCol ^ %SRC% ^ mlcl_m3b.png 2 . 150 ab |
The script also returns the name of a temporary file in mlclAVG. This image is black where there is no detail and lightest where there is most detail, so we can use it as a mask for the effect. (See also Adaptive blur and sharpen.) Working with the last example above:
Greatest effect in areas with detail %IMG7%magick ^ %SRC% ^ mlcl_m3b.png ^ ( %mlclAVG% -auto-level ) ^ -compose Over -composite ^ mlcl_mskd.png |
|
Greatest effect in areas with no detail %IMG7%magick ^ %SRC% ^ mlcl_m3b.png ^ ( %mlclAVG% -auto-level -negate ) ^ -compose Over -composite ^ mlcl_mskdn.png |
For the source, we can use a JPEG image. However, the detail that is revealed may be JPEG artefacts:
Make a JPEG image %IMG7%magick ^ %SRC% ^ -quality 50 ^ mlcl_src_jpg.jpg |
|
Maximise local colour contrast call %PICTBAT%maxLocCol ^ mlcl_src_jpg.jpg ^ mlcl_sj.png 0.5 . 100 ab |
The script makes grizzled old men even more so.
set SKIN_SRC=%PICTLIB%20130201\AGA_1201_sRGB.tiff for /F "usebackq" %%L in (`%IMG7%magick identify ^ -format "ss_size=%%wx%%h" ^ %SKIN_SRC%`) do set %%L echo ss_size = %ss_size%
ss_size = 4924x7378
As usual, we operate on the full-size image and create small versions for the web.
set WEBSIZE=-resize 600x600
%IMG7%magick ^ %SKIN_SRC% ^ -strip ^ +write mlcl_face.miff ^ %WEBSIZE% ^ mlcl_face_sm.miff |
|
Process just the L channel. call %PICTBAT%maxLocCol ^ mlcl_face.miff ^ mlcl_face_mlc_l.miff 20 . . L %IMG7%magick ^ mlcl_face_mlc_l.miff ^ %WEBSIZE% ^ mlcl_face_mlcl_l_sm.miff |
|
Process just the ab channels. call %PICTBAT%maxLocCol ^ mlcl_face.miff ^ mlcl_face_mlc_ab.miff 20 . . ab %IMG7%magick ^ mlcl_face_mlc_ab.miff ^ %WEBSIZE% ^ mlcl_face_mlcl_ab_sm.miff The effect is subtle at small scale:
|
|
Process all Lab channels. call %PICTBAT%maxLocCol ^ mlcl_face.miff ^ mlcl_face_mlc.miff 20 %IMG7%magick ^ mlcl_face_mlc.miff ^ %WEBSIZE% ^ mlcl_face_mlcl_sm.miff |
|
Show a 1:1 crop of all Lab channels: %IMG7%magick ^ mlcl_face_mlc.miff ^ -crop 600x400+2800+2830 +repage ^ mlcl_eye_mlc.jpg |
As before, we can use %mlclAVG% as a mask to modulate the effect. We equalize the mask to get an even spread of the effect.
%IMG7%magick ^ mlcl_face.miff ^ mlcl_face_mlc.miff ^ ( %mlclAVG% -equalize ) ^ -compose Over -composite ^ %WEBSIZE% ^ mlcl_mod1.jpg |
From %SKIN_SRC%, an unpublished tool finds the bounding boxes for the eyes. This gives:
set leftEye=792x419+262+3157 set rightEye=1148x486+2585+2901
The script selCoordsBB.bat makes a mask, using the bounding boxes as gradient ellipses.
call %PICTBAT%selCoordsBB ^ mlcl_eyes_msk.miff ^ %ss_size% ^ "%leftEye% %rightEye%" %IMG7%magick ^ mlcl_eyes_msk.miff ^ %WEBSIZE% ^ mlcl_eyes_msk_sm.miff |
We can then use this mask to apply the effect to just the eyes:
%IMG7%magick ^ mlcl_face.miff ^ mlcl_face_mlc.miff ^ mlcl_eyes_msk.miff ^ -compose Over -composite ^ +write mlcl_eyes_comp_sm.miff ^ %WEBSIZE% ^ mlcl_eyes_comp_sm.miff |
For convenience, .bat scripts are also available in a single zip file. See Zipped BAT files.
rem From image %1, rem writes %2 with maximised local colour contrast rem (variation in L, a* and b*). rem %3 sigma to find the local mean. rem %4 sigma to find local maxima. rem %5 blend percentage rem %6 Lab or L or ab [default Lab] rem whether to maximize all L*a*b* channels, rem or just L*, rem or just a* and b*. rem %7 Post-process, eg -auto-level @rem @rem Assumes magick is HDRI. @rem @rem Reference: @rem http://im.snibgo.com/maxloccol.htm @if "%1"=="" findstr /B "rem @rem" %~f0 & exit /B 1 @setlocal enabledelayedexpansion @call echoOffSave call %PICTBAT%setInOut %1 mlc set INFILE=%~1 if not "%2"=="" if not "%2"=="." set OUTFILE=%2 set SIG1=%3 if "%SIG1%"=="." set SIG1= if "%SIG1%"=="" set SIG1=2 set SIG2=%4 if "%SIG2%"=="." set SIG2= if "%SIG2%"=="" set SIG2=%SIG1% set BLENDPC=%5 if "%BLENDPC%"=="." set BLENDPC= if "%BLENDPC%"=="" set BLENDPC=100 set CHANS=%6 if "%CHANS%"=="." set CHANS= if "%CHANS%"=="" set CHANS=Lab set POST_PROC=%7 if "%POST_PROC%"=="." set POST_PROC= set BASE=%~n1 echo BASE=[%BASE%] set TMPDIR=\temp\ set GRAY=%TMPDIR%mlcl_%BASE%_gray.miff set INLAB=%TMPDIR%mlcl_%BASE%_inlab.miff set BLR=%TMPDIR%mlcl_%BASE%_blr.miff set MINBLR=%TMPDIR%mlcl_%BASE%_minblr.miff set AVG=%TMPDIR%mlcl_%BASE%_minblr_avg.miff set DIV=%TMPDIR%mlcl_%BASE%_minblr_div.miff set MAXC=%TMPDIR%mlcl_%BASE%_maxc.miff set "sHDRI=-depth 32 -define compose:clamp^=off -define quantum:format^=floating-point" %IMG7%magick ^ %INFILE% ^ %sHDRI% ^ -colorspace Lab ^ -set colorspace sRGB ^ -channel GB -evaluate Subtract 50%% +channel ^ +write %INLAB% ^ ( +clone ^ -blur 0x%SIG1% ^ +write %BLR% ^ ) ^ -compose MinusSrc -composite ^ %MINBLR% for /F "usebackq" %%L in (`%IMG7%magick ^ %MINBLR% ^ %sHDRI% ^ -precision 19 ^ -evaluate Abs 0 ^ -format "maxAr=%%[fx:maxima.r]\nmaxAg=%%[fx:maxima.g]\nmaxAb=%%[fx:maxima.b]\n" ^ +write info: ^ -blur 0x%SIG2% ^ +write %AVG% ^ -format "maxBr=%%[fx:maxima.r]\nmaxBg=%%[fx:maxima.g]\nmaxBb=%%[fx:maxima.b]\n" ^ info:`) do set %%L for /F "usebackq" %%L in (`%IMG7%magick identify ^ -precision 19 ^ -format "multr=%%[fx:%maxAr%/%maxBr%]\nmultg=%%[fx:%maxAg%/%maxBg%]\nmultb=%%[fx:%maxAb%/%maxBb%]\n" xc:`) do set %%L echo maxAr=%maxAr% maxBr=%maxBr% multr=%multr% echo maxAg=%maxAg% maxBg=%maxBg% multg=%multg% echo maxAb=%maxAb% maxBb=%maxBb% multb=%multb% %IM7DEV%magick ^ %MINBLR% ^ %sHDRI% ^ ( %AVG% ^ -channel R -evaluate Multiply %multr% ^ -channel G -evaluate Multiply %multg% ^ -channel B -evaluate Multiply %multb% ^ +channel ^ ) ^ -compose DivideSrc -composite ^ -evaluate Divide 2 ^ -evaluate Add 50%% ^ -process 'oogbox' ^ %DIV% rem Next can't oogbox because a* and b* are -50% to +50%. %IMG7%magick ^ %BLR% ^ %sHDRI% ^ %DIV% ^ -compose Mathematics ^ -define compose:args=0,1.0,1.0,-0.5 ^ -composite ^ %MAXC% if /I %CHANS%==Lab ( echo %0: channels Lab set READ_FILES=^ %INLAB% ^ %MAXC% ) else if /I %CHANS%==L ( echo %0: channel L only set READ_FILES=^ %INLAB% ^ ^( +clone ^ -channel GB -separate +channel ^ ^( %MAXC% -channel R -separate +channel ^) ^ -insert 0 ^ -combine ^ ^) ) else if /I %CHANS%==ab ( echo %0: channels ab only set READ_FILES=^ %INLAB% ^ ^( +clone ^ -channel R -separate +channel ^ ^( %MAXC% -channel GB -separate +channel ^) ^ -combine ^ ^) ) else ( echo %0: Bad CHANS [%CHANS%] exit /B 1 ) echo READ_FILES: echo %READ_FILES% %IM7DEV%magick ^ %READ_FILES% ^ %sHDRI% ^ -compose blend -define compose:args=%BLENDPC% -composite ^ -set colorspace Lab ^ -channel GB -evaluate Add 50%% +channel ^ -process 'oogbox' ^ -colorspace sRGB ^ -process 'oogbox' ^ %POST_PROC% ^ %OUTFILE% call echoRestore @endlocal & set mlclOUTFILE=%OUTFILE%& set mlclAVG=%AVG%
All images on this page were created by the commands shown, using:
%IMG7%magick -version
Version: ImageMagick 7.1.0-42 Q16-HDRI x64 396d87c:20220709 https://imagemagick.org Copyright: (C) 1999 ImageMagick Studio LLC License: https://imagemagick.org/script/license.php Features: Cipher DPC HDRI OpenCL Delegates (built-in): bzlib cairo freetype gslib heic jng jp2 jpeg jxl lcms lqr lzma openexr pangocairo png ps raqm raw rsvg tiff webp xml zip zlib Compiler: Visual Studio 2022 (193231332)
%IM7DEV%magick -version
Version: ImageMagick 7.1.0-20 Q32-HDRI x86_64 2021-12-29 https://imagemagick.org Copyright: (C) 1999-2021 ImageMagick Studio LLC License: https://imagemagick.org/script/license.php Features: Cipher DPC HDRI Modules OpenMP(4.5) Delegates (built-in): bzlib cairo fontconfig fpx freetype jbig jng jpeg lcms ltdl lzma pangocairo png raqm rsvg tiff webp wmf x xml zip zlib Compiler: gcc (11.2)
To improve internet download speeds, some images may have been automatically converted (by ImageMagick, of course) from PNG or TIFF or MIFF to JPG.
Source file for this web page is maxloccol.h1. To re-create this web page, execute "procH1 maxloccol".
This page, including the images, is my copyright. Anyone is permitted to use or adapt any of the code, scripts or images for any purpose, including commercial use.
Anyone is permitted to re-publish this page, but only for non-commercial use.
Anyone is permitted to link to this page, including for commercial use.
Page version v1.0 25-April-2018.
Page created 09-Aug-2022 05:06:03.
Copyright © 2022 Alan Gibson.