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 
ssl_src.pngjpg

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=^
LUTMIN=%%[fx:minima]\n^
LUTMEAN=%%[fx:mean]\n^
LUTMEANPC=%%[fx:mean*100]\n^
LUTMAX=%%[fx:maxima]\n

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

echo LUTMIN=%LUTMIN% LUTMEAN=%LUTMEAN% LUTMEANPC=%LUTMEANPC% LUTMAX=%LUTMAX% 
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,0,black,^
0,%%[fx:h-1],white ^
  ) ^
  ( +clone ^
    -fill #888 ^
    -colorize 100 ^
  ) ^
  -combine ^
  %SRC% ^
  +swap ^
  -compose Distort -composite ^
  -resize "%LUTMEANPC%x100%%^!" ^
  ssl_distlut1.png
ssl_distlut1.png

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

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

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 ^
  ssl_lut2.miff

Apply just the horizontal slut:

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

Apply just the vertical slut:

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

Apply both sluts:

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

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 ^
  ssl_lutlv.miff

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
ssl_scr4.pngjpg

Scripts

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

speMagLut.bat

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

@setlocal

@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% ^
  %OUTFILE%

call echoRestore

@endlocal

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 http://www.imagemagick.org
Copyright: © 1999-2018 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
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.