Sometimes a photograph needs more "zing", more "pop". Aesthetic decisions are difficult to quantify and harder to automate, but here are some tools aimed at large images derived from raw camera files.
The following operations are performed on the full-size image, approx 5000x7500 pixels. For presentation on this web page, three images are shown:
Set up initial conditions:
set ZP_SRC=AGA_1434_gms.tiff set RESIZE=-resize 500x500 set CROP=-crop 400x500+1930+2300 +repage
An ImageMagick bug in version 6.9.1-6 causes "histogram:" images to be of MIFF format, even though they are named ".PNG". See bug report Histogram images. So I use an older version of IM for that task:
set IMH=%IMG691%
The script for doing this is not (yet) published, so this cookbook starts with an image that already has a "correct" gamma.
%IMG7%magick ^ %ZP_SRC% ^ ( +clone ^ %RESIZE% ^ -write zp_src_sm.jpg ^ +delete ) ^ %CROP% zp_src_sm_cr.jpg %IMG7%magick ^ AGA_1434_gms.tiff ^ -define histogram:unique-colors=false ^ histogram:AGA_1434_hist.png call %PICTBAT%stats %ZP_SRC% min=0 max=1 mean=0.370564 SD=0.0949998 satMin=0 satMax=0.27509 satMean=0.0367565 satSD=0.021548 propWhite=0 |
Pixel values are present from zero to one, so auto-level will do nothing. But the image has very few dark or light pixels, also evidenced from the low standard deviation (0.095) and the histogram is mostly scrunched up in the middle.
We can apply quick and simple processing: linear-stretch, auto-gamma, increase saturation; unsharp:
%IMG7%magick ^ %ZP_SRC% ^ -linear-stretch 0.01x0.01%% ^ -auto-gamma ^ -modulate 100,250,100 ^ -unsharp 0x1 ^ -write zp_satun.tiff ^ ( +clone ^ %RESIZE% ^ -write zp_satun.jpg ^ +delete ) ^ %CROP% zp_satun_cr.jpg %IMG7%magick ^ zp_satun.tiff ^ -define histogram:unique-colors=false ^ histogram:zp_satun_hist.png call %PICTBAT%stats zp_satun.tiff min=0 max=1 mean=0.485442 SD=0.185361 satMin=0 satMax=1 satMean=0.162045 satSD=0.0849977 propWhite=2.8572e-05 |
The histogram shows that some pixels have clipped, at both ends.
The GMS image above has a low standard deviation (low contrast), and we can increase it to any value we want. The script sigSetSd.bat iterates to find a solution, so it isn't fast. The script can be run on a small version of the image with little loss of accuracy.
(A much faster process module is now available for this. See Process modules: set mean and standard deviation, and the Set mean and stddev page.)
call %PICTBAT%sigSetSd %ZP_SRC% MEAN echo %sssOPTION% -sigmoidal-contrast 7.10773,37.0563969% %IMG7%magick ^ %ZP_SRC% ^ %sssOPTION% ^ -write zp_ssd.tiff ^ ( +clone ^ %RESIZE% ^ -write zp_ssd.jpg ^ +delete ) ^ %CROP% zp_ssd_cr.jpg %IMG7%magick ^ zp_ssd.tiff ^ -define histogram:unique-colors=false ^ histogram:zp_ssd_hist.png Use this as the source for following operations. set ZP_SRC2=zp_ssd.tiff call %PICTBAT%stats %ZP_SRC% min=0 max=1 mean=0.370564 SD=0.0949998 satMin=0 satMax=0.27509 satMean=0.0367565 satSD=0.021548 propWhite=0 |
Sigmoidal-contrast of 7.09 is a fairly heavy increase. The steepest increase is at tone=37%. The SD has increased to the required value. The mean has also increased, towards 0.5.
Where this increases contrast, it also increases saturation. If we want to avoid this, we can perform sigmoidal-contrast on just the lightness.
%IMG7%magick ^ %ZP_SRC% ^ -colorspace Lab -channel R ^ %sssOPTION% ^ +channel -colorspace sRGB ^ -write zp_ssdl.tiff ^ ( +clone ^ %RESIZE% ^ -write zp_ssdl.jpg ^ +delete ) ^ %CROP% zp_ssdl_cr.jpg %IMG7%magick ^ zp_ssdl.tiff ^ -define histogram:unique-colors=false ^ histogram:zp_ssdl_hist.png call %PICTBAT%stats zp_ssdl.tiff min=0 max=1 mean=0.494226 SD=0.171846 satMin=0 satMax=0.276844 satMean=0.0388487 satSD=0.0230612 propWhite=0 |
Equalising the histogram can be useful to see detail in highlights and shadows. The result has a mean of about 0.5, and a standard-deviation of about 0.2889 (which is usually a big increase, for photographs). By itself, the result is usually unattractive.
%IMG7%magick ^ %ZP_SRC% ^ -equalize ^ -write zp_equ.tiff ^ ( +clone ^ %RESIZE% ^ -write zp_equ.jpg ^ +delete ) ^ %CROP% zp_equ_cr.jpg %IMG7%magick ^ zp_equ.tiff ^ -define histogram:unique-colors=false ^ histogram:zp_equ_hist.png call %PICTBAT%stats zp_equ.tiff min=0 max=1 mean=0.482264 SD=0.282403 satMin=0 satMax=0.87747 satMean=0.135663 satSD=0.104407 propWhite=7.48707e-06 |
As with SSD, where the contrast is increased, so is the saturation.
The simple equalisation has clipped both ends. We can reduce or eliminate this.
set eqshDEBUG=1 call %PICTBAT%equSlope %ZP_SRC% 20 55 8 90 zp_equs.tiff set eqshDEBUG= %IMG7%magick ^ zp_equs.tiff ^ ( +clone ^ %RESIZE% ^ -write zp_equs.jpg ^ +delete ) ^ %CROP% zp_equs_cr.jpg %IMG7%magick ^ zp_equs.tiff ^ -define histogram:unique-colors=false ^ histogram:zp_equs_hist.png call %PICTBAT%stats zp_equs.tiff min=0 max=1 mean=0.487966 SD=0.240535 satMin=0 satMax=0.747921 satMean=0.115586 satSD=0.0889999 propWhite=0 |
Blending an equalisation with the source is more attractive. A 50% blend is often good.
%IMG7%magick ^ %ZP_SRC% ^ ( +clone -equalize ) ^ -compose blend -define compose:args=50 -composite ^ -write zp_equb.tiff ^ ( +clone ^ %RESIZE% ^ -write zp_equb.jpg ^ +delete ) ^ %CROP% zp_equb_cr.jpg %IMG7%magick ^ zp_equb.tiff ^ -define histogram:unique-colors=false ^ histogram:zp_equb_hist.png call %PICTBAT%stats zp_equb.tiff min=0 max=1 mean=0.426414 SD=0.187682 satMin=0 satMax=0.570703 satMean=0.0862097 satSD=0.0609256 propWhite=0 |
An alternative to blending is the limit the contrast-shift caused by the equalisation, using the script eqLimit.bat from my page Process modules: equalisation. Here, I limit the contrast-shift to (mean + 1*SD).
call %PICTBAT%eqLimit %ZP_SRC% 1 . . zp_equc.tiff %IMG7%magick ^ zp_equc.tiff ^ ( +clone ^ %RESIZE% ^ -write zp_equc.jpg ^ +delete ) ^ %CROP% zp_equc_cr.jpg %IMG7%magick ^ zp_equc.tiff ^ -define histogram:unique-colors=false ^ histogram:zp_equc_hist.png call %PICTBAT%stats zp_equc.tiff min=0 max=1 mean=0.437378 SD=0.258051 satMin=0 satMax=0.792721 satMean=0.105077 satSD=0.0687336 propWhite=1.75065e-05 |
Blending 50% of the equalisation with the source limits the shift of all the pixels equally. By contrast, eqLimit.bat limits the shift to a certain maximum, while increasing the shift of other pixels. So eqLimit.bat results in a wider spreading of the overall histogram, while retaining the peaks. The result is less flat, more lively, than the 50% blend of equalisation and source.
The script exHvyBlr.bat is like unsharp masking, but with much heavier blur.
call %PICTBAT%exHvyBlr %ZP_SRC2% 0.5 150 %IMG7%magick ^ zp_ssd_ehb.tiff ^ ( +clone ^ %RESIZE% ^ -write zp_ehb.jpg ^ +delete ) ^ %CROP% zp_ehb_cr.jpg %IMG7%magick ^ zp_ssd_ehb.tiff ^ -define histogram:unique-colors=false ^ histogram:zp_ssd_ehb_hist.png call %PICTBAT%stats zp_ssd_ehb.tiff min=0 max=1 mean=0.468946 SD=0.192001 satMin=0 satMax=0.7075 satMean=0.0728775 satSD=0.0470818 propWhite=0.00217447 |
Highlights have clipped badly. Local contrast has increased. Unfortunately, this has made the background people more distracting.
The script lbdMask.bat shows where there is detail. The mask is white where there is detail and black where there isn't. This approximates to what is in focus, but skin tone that has little detail shows as black.
call %PICTBAT%lbdMask %ZP_SRC2% %IMG7%magick ^ zp_ssd_lbdm.tiff ^ -write zp_lbdm.tiff ^ ( +clone ^ %RESIZE% ^ -write zp_lbdm.jpg ^ +delete ) ^ %CROP% zp_lbdm_cr.jpg |
(See Details, details for alternative methods of identifying detail.)
We can use the LBD mask to sharpen the sharp objects and further blur the unsharp objects, by composing the EHB sharp version over a blurred version.
%IMG7%magick ^ %ZP_SRC2% ^ -blur 0x20 ^ zp_ssd_ehb.tiff ^ zp_ssd_lbdm.tiff ^ -composite ^ -write zp_sus.tiff ^ ( +clone ^ %RESIZE% ^ -write zp_sus.jpg ^ +delete ) ^ %CROP% zp_sus_cr.jpg %IMG7%magick ^ zp_sus.tiff ^ -define histogram:unique-colors=false ^ histogram:zp_sus_hist.png call %PICTBAT%stats zp_sus.tiff min=0 max=1 mean=0.466803 SD=0.173657 satMin=0 satMax=0.7075 satMean=0.0672174 satSD=0.0423363 propWhite=0.000151448 |
Distant grass and people are blurred. Foreground skin is also blurred, removing texture but also removing the boundary between skin and unfocused grass (top-right of crop). Most donkey fur is sharpened, but individual strands top-right are blurred away. We could reduce these side-effects by enlarging the white areas of the mask with morphology dilate, or another method.
The effect is similar to both IM operations "-adaptive-sharpen" and "adaptive-blur". My method is slower, but I have total control over the "adaptive" part.
The histogram shows that some pixels have clipped, at both ends.
The operations have increased saturation, but we could boost it more:
%IMG7%magick ^ zp_sus.tiff ^ -modulate 100,200,100 ^ -write zp_sus_sat.tiff ^ ( +clone ^ %RESIZE% ^ -write zp_sus_sat.jpg ^ +delete ) ^ %CROP% zp_sus_sat_cr.jpg %IMG7%magick ^ zp_sus.tiff ^ -define histogram:unique-colors=false ^ histogram:zp_sus_sat_hist.png call %PICTBAT%stats zp_sus_sat.tiff min=0 max=1 mean=0.469168 SD=0.182104 satMin=0 satMax=1 satMean=0.13441 satSD=0.0845872 propWhite=0.000151448 |
Compare the quick-and-easy (zp_satun.jpg) and more complicated version (zp_sus_sat.jpg) side by side:
The second version is, to my eyes, vastly superior. Compared to the first image, the second:
See the pages Adaptive auto level and gamma and [Adaptive] Contrast-limited equalisation.
We don't need to keep all those huge tiff files, so delete them.
del zp_lbdm.tiff del zp_satun.tiff del zp_ssd.tiff del zp_ssd_ehb.tiff del zp_ssd_lbdm.tiff del zp_ssdl.tiff del zp_equ.tiff del zp_equb.tiff del zp_equc.tiff rem del zp_sus.tiff ... keep this one
For convenience, .bat scripts are also available in a single zip file. See Zipped BAT files.
@rem Updated: @rem 26-July-2022 for IM 7. @for /F "usebackq" %%L in (`%IMG7%magick ^ %* ^ -format "statMIN=%%[fx:minima]\nstatMAX=%%[fx:maxima]\nstatMEAN=%%[fx:mean]\nstatSD=%%[fx:standard_deviation]\n" ^ -write info: ^ ^( +clone ^ -colorspace HCL ^ -format "statSatMin=%%[fx:minima.g]\nstatSatMax=%%[fx:maxima.g]\nstatSatMean=%%[fx:mean.g]\nstatSatSD=%%[fx:standard_deviation.g]\n" ^ -write info: ^ +delete ^ ^) ^ -fill #000 +opaque #fff -format "statPropWhite=%%[fx:mean]" ^ info:`) do @set %%L @echo min=%statMIN% max=%statMAX% mean=%statMEAN% SD=%statSD% @echo satMin=%statSatMin% satMax=%statSatMax% satMean=%statSatMean% satSD=%statSatSd% @echo propWhite=%statPropWhite%
This finds the contrast parameter of the "sigmoidal-contrast" operation, and the "+" or "-" sign, that gives a required standard deviation (SD). It doesn't try to maximise the SD, because increasing contrast always increases SD, until we have a black-and-white image.
A required input to this script is the mid-point of the sigmoid. (This is the steepest part of a "-" curve, or the shallowest part of a "+" curve.) In practice, setting the mid-point to the mean of the image often works well, so this is an input option.
The default goal SD is 0.166667. Initial guesses for the contrast are 0.0000001 and 30.
From two guesses, the script finds the SD that results from each contrast setting. Then it starts looping. In each loop, it finds the geometric mean of the two guessed contrasts, and the SD from that contrast. Now we have calculated three SDs. The required SD is between either the first two or the last two. We discard the worst result, leaving us two guesses for the contrast.
Continue looping until we have converged: two contrasts are equal, or two SDs are equal, within the desired precision.
rem For image %1, finds the +/-sigmoidal-contrast that makes the standard deviation a given goal. rem %2 is required mid-point for sigmoidal-contrast, as percentage, eg "50". rem Or "mean" to use the mean of the image. @rem @rem Will use: @rem sssGOAL_SD default 0.166667 @rem sssPRECISION default "-precision 6" @rem @rem sssDIRECTION "incOnly", "decOnly" or "both". @rem For "incOnly", has goal of only increasing SD. If current SD >= goal, does nothing (and returns sssALREADY_CLOSE=1). @rem For "decOnly", has goal of only decreasing SD. If current SD <= goal, does nothing (and returns sssALREADY_CLOSE=1). @rem For "both", has goal of increasing or decreasing SD as required. @rem @rem Returns: @rem sssFALSE_RESULT = 0 (okay) or 1 (algorithm failed). @rem sssALREADY_CLOSE = 0 or 1 @rem sssOPTION = "+sigmoidal-contrast %sssCONTRAST%,%sssMID_PT%" or @rem "-sigmoidal-contrast %sssCONTRAST%,%sssMID_PT%" or @rem "" (when already close) @rem sssCONTRAST, sssMID_PT @rem @rem When decreasing contrast, the algorithm can fail when the current SD is high; @rem the image is mostly black and white, @rem with few mid-tones to be shifted by "+sigmoidal-contrast". @rem @rem Updated: @rem 26-July-2022 for IM v7. @rem @if "%2"=="" findstr /B "rem @rem" %~f0 & exit /B 1 @setlocal enabledelayedexpansion @call echoOffSave set INFILE=%1 set MID_PT=%2 if "%MID_PT%"=="" set MID_PT=30 set GOAL_SD=%sssGOAL_SD% if "%GOAL_SD%"=="" set GOAL_SD=0.166667 set CON0=0.0000001 set CON2=30 set PRECISION=%sssPRECISION% if "%PRECISION%"=="" set PRECISION=-precision 6 set DIRECTION=%sssDIRECTION% if "%DIRECTION%"=="" set DIRECTION=both set MAX_PREC=9 set TMP_IN=\temp\sss.miff if /I "%MID_PT%"=="mean" for /F "usebackq" %%L ^ in (`%IMG7%magick ^ %INFILE% ^ +write %TMP_IN% ^ -precision %MAX_PREC% ^ -format "MID_PT=%%[fx:100*mean]" info:`) ^ do set %%L echo %0: MID_PT=%MID_PT% rem Are we already close? for /F "usebackq" %%L ^ in (`%IMG7%magick ^ %TMP_IN% ^ -precision %MAX_PREC% ^ ^( +clone -format "SDcur=%%[fx:standard_deviation]\n" -write info: +delete ^) ^ ^( +clone +sigmoidal-contrast %CON0%x%MID_PT%%% -format "SDdec=%%[fx:standard_deviation]\n" -write info: +delete ^) ^ -sigmoidal-contrast %CON0%x%MID_PT%%% -format "SDinc=%%[fx:standard_deviation]\n" info:`) ^ do set %%L for /F "usebackq" %%L ^ in (`%IMG7%magick identify ^ -format "ALREADY_CLOSE=%%[fx:%SDdec%<=%GOAL_SD%&&%GOAL_SD%<=%SDinc%]\nNEED_DEC=%%[fx:%GOAL_SD%<%SDdec%]" ^ xc:`) ^ do set %%L if %NEED_DEC%==1 if /I %DIRECTION%==incOnly set ALREADY_CLOSE=1 if %NEED_DEC%==0 if /I %DIRECTION%==decOnly set ALREADY_CLOSE=1 if %ALREADY_CLOSE%==1 ( set FINISHED=1 set FALSE_RESULT=0 set OPTION= goto finished ) if %NEED_DEC%==1 ( set SIG_SIGN=+ set tmpCon=%CON0% set CON0=%CON2% set CON2=!tmpCon! ) else ( set SIG_SIGN=- ) echo %0: SIG_SIGN=%SIG_SIGN% for /F "usebackq" %%L ^ in (`%IMG7%magick ^ %TMP_IN% ^ -precision %MAX_PREC% ^ ^( +clone %SIG_SIGN%sigmoidal-contrast %CON0%x%MID_PT%%% -format "SD0=%%[fx:standard_deviation]\n" -write info: +delete ^) ^ %SIG_SIGN%sigmoidal-contrast %CON2%x%MID_PT%%% ^ -format "SD2=%%[fx:standard_deviation]" ^ info:`) ^ do set %%L for /F "usebackq" %%L ^ in (`%IMG7%magick identify ^ -format "FALSE_RESULT=%%[fx:%SD0%>=%GOAL_SD%||%SD2%<=%GOAL_SD%]" ^ xc:`) ^ do set %%L echo %0: SD0=%SD0% SD2=%SD2% FALSE_RESULT=%FALSE_RESULT% set FINISHED=%FALSE_RESULT% if %FINISHED%==1 goto finished set nIter=0 :loop if %CON0%==%CON2% set FINISHED=1 for /F "usebackq" %%L ^ in (`%IMG7%magick identify ^ %PRECISION% ^ -format "CON1=%%[fx:sqrt(%CON0%*%CON2%)]" ^ xc:`) ^ do set %%L if %CON0%==%CON1% set FINISHED=1 if %CON1%==%CON2% set FINISHED=1 for /F "usebackq" %%L ^ in (`%IMG7%magick ^ %TMP_IN% ^ %PRECISION% ^ %SIG_SIGN%sigmoidal-contrast %CON1%x%MID_PT%%% ^ -format "SD1=%%[fx:standard_deviation]" ^ info:`) ^ do set %%L for /F "usebackq" %%L ^ in (`%IMG7%magick identify ^ -format "signDiff=%%[fx:%SD1%<%GOAL_SD%?-1:%SD1%>%GOAL_SD%]" ^ xc:`) ^ do set %%L echo %0: CON0=%CON0% CON1=%CON1% CON2=%CON2% echo %0: SD0=%SD0% SD1=%SD1% SD2=%SD2% rem echo %0: signDiff=%signDiff% if %signDiff%==0 ( set FINISHED=1 ) else if %SD0%==%SD1% ( set FINISHED=1 ) else if %SD1%==%SD2% ( set FINISHED=1 ) else if %signDiff%==-1 ( set CON0=%CON1% set SD0=%SD1% ) else ( set CON2=%CON1% set SD2=%SD1% ) @set /A nIter+=1 if %FINISHED%==0 goto loop echo %0: nIter=%nIter% if %ALREADY_CLOSE%==0 ( set OPTION=%SIG_SIGN%sigmoidal-contrast %CON1%,%MID_PT%%% ) :finished call echoRestore endlocal & ^ set sssFALSE_RESULT=%FALSE_RESULT%& ^ set sssCONTRAST=%CON1%& ^ set sssMID_PT=%MID_PT%& ^ set sssALREADY_CLOSE=%ALREADY_CLOSE%& ^ set sssOPTION=%OPTION% set sss exit /B 0
rem From image %1, rem make contrast-limited histogram-equalised (with iterative redistribution) version. @rem @rem Optional parameters: @rem %2 is limiting factor SD_FACT, so limit = mean + SD_FACT * standard_deviation. @rem Default 1. @rem %3 is percentage lift for shadows. Maximum < 100. Default 0, no lift. @rem %4 is percentage drop for highlights. Maximum < 100. Default 0, no drop. @rem %5 is output file, or null: for no output. @rem @rem Can also use: @rem eqlDEBUG if 1, also creates curve histograms. @rem eqlDIFF_LIMIT iteration stops when the count redistributed is less than this percentage. @rem Set to a value >= 100 to prevent iteration. @rem Default 1.0. @rem eqlSUPPRESS_OUT if 1, suppresses output. @rem @rem Updated: @rem 26-July-2022 for IM v7. @rem @if "%1"=="" findstr /B "rem @rem" %~f0 & exit /B 1 @setlocal enabledelayedexpansion @call echoOffSave call %PICTBAT%setInOut %1 eql set SD_FACT=%2 if "%SD_FACT%"=="." set SD_FACT= if "%SD_FACT%"=="" set SD_FACT=1 set LIFT_SHADOW_PC=%3 if "%LIFT_SHADOW_PC%"=="." set LIFT_SHADOW_PC= if "%LIFT_SHADOW_PC%"=="" set LIFT_SHADOW_PC=0 set DROP_HIGHLIGHT_PC=%4 if "%DROP_HIGHLIGHT_PC%"=="." set DROP_HIGHLIGHT_PC= if "%DROP_HIGHLIGHT_PC%"=="" set DROP_HIGHLIGHT_PC=0 if not "%5"=="" set OUTFILE=%5 if "%5"=="" ( set EQL_BASE=%~n1_%sioCODE% ) else ( set EQL_BASE=%~n5_%sioCODE% ) if "%eqlDIFF_LIMIT%"=="" set eqlDIFF_LIMIT=1 set TMPEXT=miff for /F "usebackq" %%L in (`cygpath %TEMP%`) do set CYGTEMP=%%L %IM7DEV%magick ^ %INFILE% ^ -colorspace Lab -channel R -separate -set colorspace sRGB ^ -process 'mkhisto norm' ^ %CYGTEMP%\%EQL_BASE%_gch.%TMPEXT% if ERRORLEVEL 1 exit /B 1 for /F "usebackq" %%L in (`%IMG7%magick ^ %TEMP%\%EQL_BASE%_gch.%TMPEXT% ^ -precision 15 ^ -format "histcap=%%[fx:(mean+%SD_FACT%*standard_deviation)*100]" ^ info:`) do set %%L echo %0: histcap=%histcap% set nIter=0 :loop %IM7DEV%magick ^ %CYGTEMP%\%EQL_BASE%_gch.%TMPEXT% ^ -channel RGB ^ -evaluate Min %histcap%%% ^ +channel ^ %CYGTEMP%\%EQL_BASE%_gchc_cap.%TMPEXT% for /F "usebackq" %%L in (`%IMG7%magick ^ %TEMP%\%EQL_BASE%_gch.%TMPEXT% ^ %TEMP%\%EQL_BASE%_gchc_cap.%TMPEXT% ^ -compose MinusSrc -composite ^ -precision 15 ^ -format "MeanDiffPC=%%[fx:mean*100]" ^ info:`) do set %%L echo %0: MeanDiffPC=%MeanDiffPC% %IM7DEV%magick ^ %CYGTEMP%\%EQL_BASE%_gch.%TMPEXT% ^ -channel RGB ^ -evaluate Min %histcap%%% ^ +channel ^ -evaluate Add %MeanDiffPC%%% ^ %CYGTEMP%\%EQL_BASE%_gch.%TMPEXT% for /F "usebackq" %%L in (`%IMG7%magick identify ^ -format "DO_LOOP=%%[fx:%MeanDiffPC%>%eqlDIFF_LIMIT%?1:0]" ^ xc:`) do set %%L rem If max(eql_gch) > histcap + epsilon, repeat. rem OR rem if %MeanDiffPC% > epsilon, repeat set /A nIter+=1 if %DO_LOOP%==1 goto loop echo %0: nIter=%nIter% if %LIFT_SHADOW_PC%==0 if %DROP_HIGHLIGHT_PC%==0 %IM7DEV%magick ^ %CYGTEMP%\%EQL_BASE%_gch.%TMPEXT% ^ -auto-level ^ %CYGTEMP%\%EQL_BASE%_gch.%TMPEXT% if %LIFT_SHADOW_PC%==0 goto skipShad set WX=0 rem In following, "-blur" should really be "decomb". set DECOMB=-blur 0x1 for /F "usebackq tokens=2 delims=:, " %%A in (`%IM7DEV%magick ^ %CYGTEMP%\%EQL_BASE%_gch.%TMPEXT% ^ -auto-level ^ +write %CYGTEMP%\%EQL_BASE%_gch.%TMPEXT% ^ %DECOMB% ^ -threshold %LIFT_SHADOW_PC%%% ^ -process onewhite ^ NULL: 2^>^&1`) do set WX=%%A rem %0: echo WX=%WX% if "%WX%"=="none" ( %IMG7%magick ^ %TEMP%\%EQL_BASE%_gch.%TMPEXT% ^ -fill #fff -colorize 100 ^ %TEMP%\%EQL_BASE%_gch.%TMPEXT% ) else if not %WX%==0 %IM7DEV%magick ^ %CYGTEMP%\%EQL_BASE%_gch.%TMPEXT% ^ -size %WX%x1 xc:gray(%LIFT_SHADOW_PC%%%) ^ -gravity West -composite ^ %CYGTEMP%\%EQL_BASE%_gch.%TMPEXT% :skipShad if %DROP_HIGHLIGHT_PC%==0 goto skipHigh set WX=0 rem In following, "-blur" should really be "decomb". set DECOMB=-blur 0x1 for /F "usebackq tokens=2 delims=:, " %%A in (`%IM7DEV%magick ^ %CYGTEMP%\%EQL_BASE%_gch.%TMPEXT% ^ -auto-level ^ +write %CYGTEMP%\%EQL_BASE%_gch.%TMPEXT% ^ %DECOMB% ^ -threshold %DROP_HIGHLIGHT_PC%%% ^ -flop ^ -process onewhite ^ NULL: 2^>^&1`) do set WX=%%A rem %0: echo WX=%WX% if "%WX%"=="none" ( %IMG7%magick ^ %TEMP%\%EQL_BASE%_gch.%TMPEXT% ^ -fill #fff -colorize 100 ^ %TEMP%\%EQL_BASE%_gch.%TMPEXT% ) else if not %WX%==0 %IM7DEV%magick ^ %CYGTEMP%\%EQL_BASE%_gch.%TMPEXT% ^ -size %WX%x1 xc:gray(%DROP_HIGHLIGHT_PC%%%) ^ -gravity East -composite ^ %CYGTEMP%\%EQL_BASE%_gch.%TMPEXT% :skipHigh %IM7DEV%magick ^ %CYGTEMP%\%EQL_BASE%_gch.%TMPEXT% ^ -process 'cumulhisto norm' ^ %CYGTEMP%\%EQL_BASE%_gchc_clhe_red.%TMPEXT% if /I "%OUTFILE%" NEQ "null:" if not "%eqlSUPPRESS_OUT%"=="1" %IMG7%magick ^ %INFILE% ^ %TEMP%\%EQL_BASE%_gchc_clhe_red.%TMPEXT% ^ -clut ^ %OUTFILE% if "%eqlDEBUG%"=="1" ( call %PICTBAT%graphLineCol %TEMP%\%EQL_BASE%_gch.%TMPEXT% . . 0 %EQL_BASE%_gch.png call %PICTBAT%graphLineCol %TEMP%\%EQL_BASE%_gchc_cap.%TMPEXT% . . 0 %EQL_BASE%_gchc_cap.png call %PICTBAT%graphLineCol %TEMP%\%EQL_BASE%_gchc_clhe_red.%TMPEXT% . . 0 %EQL_BASE%_gchc_clhe_red.png ) call echoRestore @endlocal & set eqlOUTFILE=%OUTFILE% &set eqlCLUT=%TEMP%\%EQL_BASE%_gchc_clhe_red.%TMPEXT%
rem Extrapolate away from heavy blur. Increases local contrast. rem A bit like tone-mapping, HDR, High Dynamic Range. @rem @rem %2 is resize amount (inverse of blur radius) as percentage of image size. @rem Small amounts (0.1-5) spread impact over large area. [0.5] @rem Large amounts (25-100) give unsharp mask. @rem %3 is extrapolation as percentage. @rem 0 is blur; 100 is no effect (unchanged image), 150 is subtle, 15000 is massive. @rem %4, if given, is output filename. @rem @rem See also hvyBlrDiff.bat @rem @rem Updated: @rem 26-July-2022 for IM v7. @rem @if "%1"=="" findstr /B "rem @rem" %~f0 & exit /B 1 @setlocal @call echoOffSave call %PICTBAT%setInOut %1 ehb set BLUR_PC=%2 if "%BLUR_PC%"=="." set BLUR_PC= if "%BLUR_PC%"=="" set BLUR_PC=0.5 set BLEND_PC=%3 if "%BLEND_PC%"=="." set BLEND_PC= if "%BLEND_PC%"=="" set BLEND_PC=200 if not "%4"=="" set OUTFILE=%4 FOR /F "usebackq" %%L IN (`%IMG7%magick identify -format "WW=%%w\nHH=%%h" %INFILE%`) DO set %%L %IMG7%magick ^ %INFILE% ^ ^( +clone ^ -resize %BLUR_PC%%% -resize "%WW%x%HH%^!" ^ ^) ^ +swap ^ -compose Blend -define compose:args=%BLEND_PC% -composite ^ %OUTFILE% call echoRestore @endlocal & set ehbOUTFILE=%OUTFILE%
rem Makes a mask from LBD, difference from light blur resulting in monochrome RMS. rem White or light where there is detail; black or dark where there isn't. rem rem %2 is blur sigma in pixels. @rem @rem See also ltBlrDiff. @rem @rem Updated: @rem 26-July-2022 for IM v7. @rem @if "%1"=="" findstr /B "rem @rem" %~f0 & exit /B 1 @setlocal @call echoOffSave call %PICTBAT%setInOut %1 lbdm set BLUR_SIG=%2 if "%BLUR_SIG%"=="" set BLUR_SIG=4 %IMG7%magick ^ %INFILE% ^ ^( +clone -blur 0x%BLUR_SIG% ^) ^ -compose Difference -composite ^ -grayscale RMS ^ -auto-level ^ -auto-gamma ^ -blur 0x20 ^ -contrast-stretch 25x25%% ^ %OUTFILE% call echoRestore @endlocal
All images on this page were created by the commands shown, using:
%IMG7%magick -version
Version: ImageMagick 7.1.0-49 Q16-HDRI x64 7a3f3f1:20220924 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 (193331630)
Source file for this web page is zingph.h1. To re-create this web page, execute "procH1 zingph".
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 4-Mar-2014.
Page created 26-Nov-2022 00:25:36.
Copyright © 2022 Alan Gibson.