snibgo's ImageMagick pages

Specify scaling by LUTs

Stretch/shrink controlled by a Nx1 image.

IM can readily stretch or shrink an entire image in just the x-direction, eg with "-resize 130x100%". We might want to vary the left-right scaling at different positions along the width. If the input image has a width WW pixels, we create a WWx1 image with values that represent the scales to be applied to the columns. We call this WWx1 image a "slut", a scaling look-up table. The process converts the slut into an absolute displacement map, and applies it to the source image.

The identity slut that causes no change in scale has all values at 100%. Values higher than 100% will stretch; values lower than 100% will shrink.

With this method, the pixels in one column are all scaled in the x-direction by the same amount, which is specified in the slut. If we want different horizontal scales within each single column, a method such as Displacement by masked SRT can be used.

We can distort in the y-direction with the same process.

Scripts on this page assume that the version of ImageMagick in %IM7DEV% is V7 and has been built with various process modules. See Process modules.

Sample input

For the source, we use an image with a grid so we can see what is happening.

set SRC=ssl_src.png

call %PICTBAT%gridOver ^
  toes.png %SRC% 10 10 1 yellow

for /F "usebackq" %%L in (`%IMG7%magick ^
  %SRC% ^
  -format "WW=%%w\nHH=%%h\n" ^
  info:`) do set %%L

echo WW=%WW% HH=%HH% 
WW=267 HH=233 

Worked example

The sample image is 267 pixels wide. Suppose we want to distort it horizontally so that:

We make the look-up table with those values. As some values exceed 100% of QuantumRange, we must save this in a floating-point format.

set FMT=^

for /F "usebackq" %%L in (`%IM7DEV%magick ^
  -size 53x1 "xc:gray(100%%)" ^
  -size 53x1 "xc:gray(200%%)" ^
  -size 107x1 "gradient:gray(200%%)-gray(50%%)" ^
  -size 54x1 "xc:gray(50%%)" ^
  +append +repage ^
  -precision 16 ^
  -format "%FMT%" ^
  +write info: ^
  -define "quantum:format=floating-point" -depth 32 ^
  ssl_lut1.miff`) do set %%L

LUTMIN=0.5 LUTMEAN=1.197565543071161 LUTMEANPC=119.7565543071161 LUTMAX=2 

The percentages of gray represent the required scales.

The minimum and maximum values are as we expect. The mean value tells us the overall scaling -- how much the overall image needs to change.

We process the Nx1 slut:

The process modules cumulhisto and invclut were written to process histograms and cluts, but can be used here without problems. The slut can be made or modified with a method shown in the Clut cookbook.

%IM7DEV%magick ^
  ssl_lut1.miff ^
  -process 'cumulhisto norm' ^
  -auto-level ^
  -process 'invclut' ^
  -auto-level ^
  -scale "%WW%x%HH%^!" ^
  ( +clone ^
    -sparse-color bilinear ^
0,%%[fx:h-1],white ^
  ) ^
  ( +clone ^
    -fill #888 ^
    -colorize 100 ^
  ) ^
  -combine ^
  %SRC% ^
  +swap ^
  -compose Distort -composite ^
  -resize "%LUTMEANPC%x100%%^!" ^

A flicker-gif shows how we have distorted the source image:

%IMG7%magick ^
  -delay 50 -dispose Previous ^
  ssl_distlut1.png ssl_src.png ^

The quality might be improved if we resized the image and slut at the start, instead of resizing the result at the end.

If we divide all the slut values by a constant, the displacement map will be the same but the slut mean and hence the overall resizing will be different.

We have applied one slut to all the input rows. We could apply different sluts, but we couldn't then resize because the means of each slut will generally be different. Hence, the scales won't be absolute, and a given scale will generally have different effects on different rows.

For the vertical displacement, we have used an identity map. Instead, we could use another slut to vary the scales in the y-direction.

The script speMagLut.bat

The script speMagLut.bat takes an input image and sluts for the horizontal and vertical directions, and does the work.

We create a slut for the vertical dimension:

%IMG7%magick ^
  -size %HH%x1 ^
  gradient:White-Black ^

Apply just the horizontal slut:

call %PICTBAT%speMagLut ^
  toes.png ssl_lut1.miff . ^

Apply just the vertical slut:

call %PICTBAT%speMagLut ^
  toes.png . ssl_lut2.miff ^

Apply both sluts:

call %PICTBAT%speMagLut ^
  toes.png ssl_lut1.miff ssl_lut2.miff ^

We can make sluts from aspects of the source image, such as the average intensity of columns and rows so we have greatest magnification where the image is lightest.

-sigmoidal-contrast exagerates the effect, and -blur reduces abrupt transitions.

%IMG7%magick ^
  toes.png ^
  -colorspace Gray ^
  ( +clone ^
    -scale "x1^!" ^
    -sigmoidal-contrast 5x50%% ^
    -blur 0x3 ^
    -write ssl_lutlh.miff ^
    +delete ^
  ) ^
  -scale "1x^!" ^
  -sigmoidal-contrast 5x50%% ^
  -blur 0x3 ^
  -rotate -90 ^

We set each scale to 100 percent instead of using the default "auto".

call %PICTBAT%speMagLut ^
  toes.png ssl_lutlh.miff ssl_lutlv.miff ^
  ssl_scr4.png ^
  100 100


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


rem %1 input image to be distorted (WWxHH pixels)
rem %2 horizontal slut, WWx1 pixels
rem %3 vertical slut, HHx1 pixels
rem %4 output filename
rem %5 horizontal percentage scale or "auto"
rem %6 vertical percentage scale or "auto"

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


@call echoOffSave

call %PICTBAT%setInOut %1 sml

set HSLUT=%~2
if "%HSLUT%"=="." set HSLUT=

set VSLUT=%~3
if "%VSLUT%"=="." set VSLUT=

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

set HSCALE=%5
if "%HSCALE%"=="." set HSCALE=
if "%HSCALE%"=="" set HSCALE=auto

set VSCALE=%6
if "%VSCALE%"=="." set VSCALE=
if "%VSCALE%"=="" set VSCALE=auto

if "%HSLUT%"=="" (
  set HS=-size %%[WW]x1 xc: -set option:HMEANPC 100 -sparse-color Bilinear 0,0,Black,%%[fx:w-1],0,White
) else (
  set HS=%HSLUT% -set option:HMEANPC %%[fx:mean*100] -process 'cumulhisto norm' -auto-level -process 'invclut' -auto-level

if "%VSLUT%"=="" (
  set VS=-size %%[HH]x1 xc: -set option:VMEANPC 100 -sparse-color Bilinear 0,0,Black,%%[fx:w-1],0,White
) else (
  set VS=%VSLUT% -set option:VMEANPC %%[fx:mean*100] -process 'cumulhisto norm' -auto-level -process 'invclut' -auto-level

echo HS=%HS%

if %HSCALE%==auto (
  set HSC=%%[HMEANPC]
) else (
  set HSC=%HSCALE%

if %VSCALE%==auto (
  set VSC=%%[VMEANPC]
) else (
  set VSC=%VSCALE%

set RESZ=
if not %HSC%==100 set RESZ=-resize "%HSC%x%VSC%%%^!"
if not %VSC%==100 set RESZ=-resize "%HSC%x%VSC%%%^!"

%IM7DEV%magick ^
  %INFILE% ^
  -set option:WW %%w ^
  -set option:HH %%h ^
  ( %HS% ^
    -scale "%%[WW]x%%[HH]^!" ^
  ) ^
  ( %VS% ^
    -rotate 90 ^
    -scale "%%[WW]x%%[HH]^!" ^
  ) ^
  ( +clone ^
    -fill #888 -colorize 100 ^
  ) ^
  ( -clone 1-3 ^
    -combine ^
  ) ^
  -delete 1-3 ^
  -compose Distort -composite ^
  %RESZ% ^

call echoRestore


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

%IM7DEV%magick identify -version
Version: ImageMagick 7.0.7-28 Q32 x86_64 2018-12-09
Copyright: © 1999-2018 ImageMagick Studio LLC
Features: Cipher DPC HDRI Modules OpenMP 
Delegates (built-in): bzlib cairo fftw fontconfig fpx freetype jbig jng jpeg lcms ltdl lzma pangocairo png rsvg tiff webp wmf x 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 spemaglut.h1. To re-create this web page, execute "procH1 spemaglut".

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 10-July-2019.

Page created 12-Jul-2019 12:36:18.

Copyright © 2019 Alan Gibson.