snibgo's ImageMagick pages

Power curve for shadow, mid and highlights

With four numbers, we can tweak the bottom, top and somewhere in the middle.

The script

We will demonstrate on the usual image:

set SRC=toes.png
toes.pngjpg

The script powSmh.bat creates a transformed image, and can also create a graph that shows the transformation in the usual way, with input along the x-axis and output along the y-axis.

With no parameters, we get no transformation.

call %PICTBAT%powSmh ^
  %SRC% psmh_t1.png . . psmh_t1_dbg.png 
 f:\prose\PICTURES>rem      (Y0, Y1, Y2), 
F:\pictures\powSmh: X1 = 0.5
F:\pictures\powSmh: Y0 = 0, Y1 = 0.5,  Y2 = 1
F:\pictures\powSmh: a = 1,  b = 0,  p = 1
F:\pictures\powSmh: xAtZero = -0
F:\pictures\powSmh: xAtOne = 1
psmh_t1.pngjpg
psmh_t1_dbg.png

Transform so input 0.6 becomes output 0.5 (0.6 => 0.5).

call %PICTBAT%powSmh ^
  %SRC% psmh_t2.png 0.6 . psmh_t2_dbg.png 
 f:\prose\PICTURES>rem      (Y0, Y1, Y2), 
F:\pictures\powSmh: X1 = 0.6
F:\pictures\powSmh: Y0 = 0, Y1 = 0.5,  Y2 = 1
F:\pictures\powSmh: a = 1,  b = 0,  p = 1.356915448856724
F:\pictures\powSmh: xAtZero = 0
F:\pictures\powSmh: xAtOne = 1
psmh_t2.pngjpg
psmh_t2_dbg.png

Transform so 0.5 => 0.4.

call %PICTBAT%powSmh ^
  %SRC% psmh_t3.png . ".,0.4,." psmh_t3_dbg.png 
 f:\prose\PICTURES>rem      (Y0, Y1, Y2), 
F:\pictures\powSmh: X1 = 0.5
F:\pictures\powSmh: Y0 = 0, Y1 = 0.4,  Y2 = 1
F:\pictures\powSmh: a = 1,  b = 0,  p = 1.321928094887362
F:\pictures\powSmh: xAtZero = 0
F:\pictures\powSmh: xAtOne = 1
psmh_t3.pngjpg
psmh_t3_dbg.png

Transform so 0.0 => 0.1, 0.5 => 0.4, 1.0 => 0.9.

call %PICTBAT%powSmh ^
  %SRC% psmh_t4.png . "0.1,0.4,0.9" psmh_t4_dbg.png 
 f:\prose\PICTURES>rem      (Y0, Y1, Y2), 
F:\pictures\powSmh: X1 = 0.5
F:\pictures\powSmh: Y0 = 0.1, Y1 = 0.4,  Y2 = 0.9
F:\pictures\powSmh: a = 0.8,  b = 0.1,  p = 1.415037499278844
F:\pictures\powSmh: xAtZero = -1.#IND
F:\pictures\powSmh: xAtOne = 1.086799011023172
psmh_t4.pngjpg
psmh_t4_dbg.png

Transform so 0.0 => -0.1, 0.5 => 0.4, 1.0 => 1.1.

call %PICTBAT%powSmh ^
  %SRC% psmh_t5.png . "-0.1,0.4,1.1" psmh_t5_dbg.png 
 f:\prose\PICTURES>rem      (Y0, Y1, Y2), 
F:\pictures\powSmh: X1 = 0.5
F:\pictures\powSmh: Y0 = -0.1, Y1 = 0.4,  Y2 = 1.1
F:\pictures\powSmh: a = 1.2,  b = -0.1,  p = 1.263034405833794
F:\pictures\powSmh: xAtZero = 0.139818503296633
F:\pictures\powSmh: xAtOne = 0.9334286593509811
psmh_t5.pngjpg
psmh_t5_dbg.png

We can have negative transformations, where y0 > y1 > y2:
0.0 => 1.1, 0.5 => 0.4, 1.0 => -0.1.

call %PICTBAT%powSmh ^
  %SRC% psmh_t6.png . "1.1,0.4,-0.1" psmh_t6_dbg.png 
 f:\prose\PICTURES>rem      (Y0, Y1, Y2), 
F:\pictures\powSmh: X1 = 0.5
F:\pictures\powSmh: Y0 = 1.1, Y1 = 0.4,  Y2 = -0.1
F:\pictures\powSmh: a = -1.2,  b = 1.1,  p = 0.7776075786635522
F:\pictures\powSmh: xAtZero = 0.8941370136942889
F:\pictures\powSmh: xAtOne = 0.04094280203134165
psmh_t6.pngjpg
psmh_t6_dbg.png

How does it work?

The general equation for output pixel values y from input pixel values x is:

y = a*xp + b

The algorithm is given three values of input x, and corresponding values of output y.

The three parameters p, a and b are calculated. Two of them are easy:

a = Y2 - Y0
b = Y0

Substituting into the general equation:

Y1 = (Y2 - Y0) * (X1)p + Y0

Rearranging:

(X1)p = (Y1 - Y0) / (Y2 - Y0)

p = log [(Y1 - Y0) / (Y2 - Y0)] 
              log (X1)

Now we have parameter p for "-evaluate Pow", and parameters a and b for "-function Polynomial".

To calculate where the line intersects y=0 and y=1:

y = a*xp + b

xp = (y - b) / a

x = ((y - b) / a)1/p

So, at y=0:

xatZero = (-b / a)1/p

And, at y=1:

xatOne = ((1 - b) / a)1/p

When -b or 1-b is negative, there is no intersection.

Lift, gamma, gain

The method shown on this page is very similar to Lift, Gamma, Gain functions in DaVinci Resolve and similar programs. However, in those programs the user tweaks the parameters that I call a, p and b. Changing any one of these parameters changes the entire image somewhat, though mostly at the bottom, middle and top respectively. So the user will often repeatedly adjust all three controls to get a desired effect.

Lift and gain correspond to TV or video monitor controls brightness and contrast.

In my version, the user directly supplies the three desired outputs for the bottom, middle and top, and the program calculates values for a, p and b.

Scripts

For convenience, .bat scripts are also available in a single zip file. See Zipped BAT files.

powSmh.bat

@rem Given %1 is an image,
@rem %2 is output file,
@rem %3 is an input mid-value, (X1)
@rem %4 is a set of quoted output shadow, mid and highlight values
rem      (Y0, Y1, Y2),
@rem all values typically 0.0 to 1.0.
@rem %5 if a filename, also writes debugging graph image.

@if "%1"=="" findstr /B "rem @rem" %~f0 & exit /B 1

@setlocal enabledelayedexpansion

@call echoOffSave

call %PICTBAT%setInOut %1 psmh

if not "%2"=="" if not "%2"=="." set OUTFILE=%2

set X1=%3
if "%X1%"=="." set X1=
if "%X1%"=="" set X1=0.5

set OUTVALS=%~4
if "%OUTVALS%"=="." set OUTVALS=
if "%OUTVALS%"=="" set OUTVALS=0,0.5,1.0

set DEBUG=%5
if "%DEBUG%"=="." set DEBUG=

for /F "tokens=1-3 delims=, " %%A in ("%OUTVALS%") do (
  set Y0=%%A
  set Y1=%%B
  set Y2=%%C
)

if "%Y0%"=="." set Y0=
if "%Y0%"=="" set Y0=0

if "%Y2%"=="." set Y2=
if "%Y2%"=="" set Y2=1

if "%Y1%"=="." set Y1=
if "%Y1%"=="" set Y1=((%Y0%)+(%Y2%))/2.0

set FMT=^
Y0=%%[fx:%Y0%]\n^
Y1=%%[fx:%Y1%]\n^
Y2=%%[fx:%Y2%]

for /F "usebackq" %%L in (`%IM%identify ^
  -precision 16 ^
  -format "%FMT%" ^
  xc:`) do set %%L

echo %0: X1 = %X1%
echo %0: Y0 = %Y0%, Y1 = %Y1%,  Y2 = %Y2%

set b=%Y0%

set FMT=^
a=%%[fx:%Y2%-(%Y0%)]\n^
p=%%[fx:log((%Y1%-(%Y0%))/(%Y2%-(%Y0%)))/log(%X1%)]

for /F "usebackq" %%L in (`%IM%identify ^
  -precision 16 ^
  -format "%FMT%" ^
  xc:`) do set %%L

echo %0: a = %a%,  b = %b%,  p = %p%

set FMT=^
xAtZero=%%[fx:pow(-(%b%)/(%a%),1/(%p%))]\n^
xAtOne=%%[fx:pow((1-%b%)/(%a%),1/(%p%))]\n

for /F "usebackq" %%L in (`%IM%identify ^
  -precision 16 ^
  -format "%FMT%" ^
  xc:`) do set %%L

echo %0: xAtZero = %xAtZero%
echo %0: xAtOne = %xAtOne%



%IM%convert ^
  %INFILE% ^
  -evaluate Pow %p% ^
  -function Polynomial %a%,%b% ^
  %OUTFILE%

if not "%DEBUG%"=="" (
  %IM%convert ^
    -size 1x256 gradient: -rotate 90 ^
    -evaluate Pow %p% ^
    -function Polynomial %a%,%b% ^
    %DEBUG%

  call %PICTBAT%graphLineCol %DEBUG% . . 0 %DEBUG%
)


call echoRestore

@endlocal & set psmhOUTFILE=%OUTFILE%

All images on this page were created by the commands shown, using:

%IM%identify -version
Version: ImageMagick 6.9.5-3 Q16 x86 2016-07-22 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2015 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Visual C++: 180040629
Features: Cipher DPC Modules OpenMP 
Delegates (built-in): bzlib cairo flif freetype jng jp2 jpeg lcms lqr openexr pangocairo png ps rsvg tiff webp xml zlib

To improve internet download speeds, some images may have been automatically converted (by ImageMagick, of course) from PNG to JPG.

Source file for this web page is powsmh.h1. To re-create this web page, execute "procH1 powsmh".


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 9-November-2017.

Page created 06-Dec-2017 22:22:57.

Copyright © 2017 Alan Gibson.