snibgo's ImageMagick pages

Cartoon and texture

An image can be deconstructed into a cartoon and texture.

An image can be deconstructed into a pair of images called a cartoon and texture.

image = cartoon + texture, f = u + v

The cartoon contains smoothly-changing gradients, and edges. So it contains low-frequency data. It also contains high-frequency data but only from the edges between colours. The texture image contains high frequency data except from the edges.

The requirement that the cartoon image should contain high-frequency edge detail but without high-frequency non-edge detail is difficult to satisfy.

Depending on the degree of smoothness and sharpness of the edges, the cartoon may resemble a watercolour painting.

From any original image and a cartoon, we can create the corresponding texture image:

%IM%convert ^
  ORIGINAL ^
  CARTOON ^
  -compose Mathematics ^
    -define compose:args=0,-1,1,0.5 ^
  -composite ^
  TEXTURE

This page builds on material in:

Sample input

set SRC=barbara_test.png
barbara_test.pngjpg

This image is from Directional Filters for Cartoon + Texture Image Decomposition, Antoni Buades, Jose-Luis Lisani, 2016. It is credited as a "standard test image". It has an abundance of fine detail in the patterned fabric. This image is not my copyright.

Method: -blur and -segment

A simple and quick method to obtain a flat-colour cartoon image is to blur the input image, then use one of IM's colour-reduction operations, such as "-segment".

%IM%convert -version

%IM%convert ^
  %SRC% ^
  -blur 0x4 ^
  +depth ^
  ct_blr.png
ct_blr.pngjpg
%IM%convert ^
  ct_blr.png ^
  -segment 10000x1.5 ^
  ct_blrseg.png
ct_blrseg.pngjpg

When choosing colours and allocating them, this method doesn't care where the edges are. The resulting cartoon image contains no gradients. Instead, it introduces edges within what were areas of smooth gradient.

Method: Buades et al

References:

This section implements the method described in the 2011 paper.

The result is a blend of the input image, and a blurred version of that image. (This immediately suggests the method has a problem: such blends are liable to ghosting effects.)

The paper uses a Local Total Variation, which is a blur of the slope. LTV is low where there is no detail; high where there is detail.

It also uses a Relative reduction rate of LTV, or lambda (λ), defined as:

          LTV(image) - LTV(blurred_image)
lambda = -------------------------------
                   LTV(image)

Where lambda is low, the cartoon will take data from the input image. Where lambda is high, the cartoon will take data from the blurred input. The cartoon (u) could then be:

u = λ * blurred_image + (1-λ) * image

However, rather than using lambda directly, it is modulated by a function, w(lambda).

w(lambda) = 0 where lambda < 0.25
          = 1 where lambda > 0.5
          = linear from 0 to 1 otherwise

The effect of w(lambda) is to narrow the blending between the image and its blur, reducing the ghosting problem.

So the cartoon is

u = W * blurred_image + (1-W) * image

where W = w(lambda).

The function w(lambda) is implemented in ImageMagick with "-level 25%,50%".

Typical value of sigma for blurs is 3 to 6.

The script cartTextBu.bat implements the algorithm.

call %PICTBAT%cartTextBu ^
  %SRC% ctx_XX1.png 4

This has created:

Cartoon image ctx_cart1.png:

ctx_cart1.png

Texture image ctx_text1.png:

ctx_text1.png

The method smooths non-edge areas in the cartoon, while leaving edges reasonably sharp. Buades and others have extended the technique to improve the edges but at the cost of complexity, eg taking the maximum output from 45 filters (at 8° intervals).

Method: erase edge pixels

This method is less mathematical. Results correspond better (I think) to the aesthetics of cartoons. The method is simply:

  1. Blur the image.
  2. Erase pixels at the edges.
  3. Fill the holes. ("Inpaint" them.)

This method invents pixel values at edges, so avoids the difficulty of excluding texture detail at edges.

We find edge pixels from the slope magnitude of the blurred image. This is a value that is lightest where the slope is steepest, ie at edges, but even the steepest slopes of a blurred image will be numerically low.

Methods of filing holes are shown in Filling holes. In this situation, pixels around each hole have roughly the same colour without any sudden jumps, so any hole-filler method will work. My preference is shiftFill.bat, which directly and quickly copies pixels from the edges into the holes, increasing the number copied at each sweep until all holes are filled. Where filling from opposite edges meet, it creates hard boundaries that can be softened by any desired amount.

Manually determine how much blur we need to remove unwanted detail.

set BLR_SIG=3.6

%IM%convert ^
  %SRC% ^
  -blur 0x%BLR_SIG% ^
  +depth ^
  ctx_b3.png
ctx_b3.png

Calculate the slope magnitude of the blurred image.

set smAUTO=0

call %PICTBAT%slopeMag ^
  ctx_b3.png ctx_bsm.miff

Slope magnitudes that haven't been auto-levelled are usually dark.

ctx_bsm.miffpng

Unsharpen with a modest radius but massive gain,
to virtually threshold the result.

Final blur and threshold smooths the boundaries.

%IM32f%convert ^
  ctx_bsm.miff ^
  -auto-level ^
  -unsharp 0x%BLR_SIG%+50+0 ^
  -blur 0x%BLR_SIG% ^
  -threshold 50%% ^
  ctx_edges.png

This has detected edges.

ctx_edges.png

Erase the edges from the blurred image.

%IM%convert ^
  ctx_b3.png ^
  ( ctx_edges.png -negate ) ^
  -compose CopyOpacity -composite ^
  ctx_holed.png
ctx_holed.png

Now we can use any hole-filling method. We show three different methods.

Fill in the holes by blurring for a soft effect.

call %PICTBAT%blurFill ^
  ctx_holed.png ^
  . ^
  ctx_fh_bf.png
ctx_fh_bf.png

Fill in the holes by shifting for a harder effect,
here slightly softened.

Very fast.

set sfPOST_PROC=-blur 0x0.5

call %PICTBAT%shiftFill ^
  ctx_holed.png ^
  . ^
  ctx_fh_sf.png
ctx_fh_sf.png

Fill in the holes by process module.

Much slower.

%IMDEV%convert ^
  ctx_holed.png ^
  -process ^
    'fillholes wr 1 lsr 10c als off v' ^
  ctx_fh_pm.png
ctx_fh_pm.png

From any cartoon image and the original, we can create the texture image.

%IM%convert ^
  %SRC% ^
  ctx_fh_sf.png ^
  -compose Mathematics ^
    -define compose:args=0,-1,1,0.5 ^
  -composite ^
  +depth ^
  ctx_fh_text.png

The texture image also includes edges,
because the edges invented by shiftFill.bat do not coincide with edges in the input image.

ctx_fh_text.png

From the edge mask, we can make a skeleton, possibly prune the stubs, perhaps mend broken lines, and dilate slightly (eg by blurring) to get an inked "outline" drawing.

%IM%convert ^
  ctx_edges.png ^
  -morphology Thinning:-1 skeleton ^
  -blur 0x0.5 ^
  -auto-level -negate ^
  ctx_skel.png
ctx_skel.png
%IM%convert ^
  ctx_fh_sf.png ^
  ctx_skel.png ^
  -alpha off ^
  -compose CopyOpacity -composite ^
  -background #400 ^
  -compose Over -layers Flatten ^
  ctx_drawn.png
ctx_drawn.png

We implement this as a script cartTextEep.bat. It creates outputs for the cartoon, texture, edges and skeleton.

The added lines emphasise problems, such as the "broken" forearm centre-bottom of the image, and where right-angles have been smoothed into curves.

For outline drawings, we could determine edges ignoring lightness, so considering just hue and saturation, or a* and b* of L*a*b*. This would avoid drawing lines where a shadow crosses an object.

The hole-filling process does not exactly mimic a skeleton, so the lines may not exactly coincide with the drawn edges. Instead, we could use the cartoon image as the basis of the lines.

Another interesting result comes from composing the blurred-and holed image over the original source, so the original shows only where the edges are. This is an extreme example of "adaptive smoothing". It preserves facial features fairly well, although the lip boundaries have been smoothed away.

%IM%convert ^
  %SRC% ^
  ctx_holed.png ^
  -composite ^
  ctx_smooth_non_edge.png
ctx_smooth_non_edge.png

Relaxation

For the above results, we have varied the source for the pixels at edges, but have always used the blurred source for the non-edge areas. Instead, we can choose a certain source for the edges and vary the source for the non-edges.

For example, we take the edge pixels from ctx_fh_sf.png, which populated them from shiftFill.bat.

%IM%convert ^
  ctx_fh_sf.png ^
  ctx_edges.png ^
  -compose CopyOpacity -composite ^
  ctx_sh_edge.png
ctx_sh_edge.png

This representation is similar to diffusion curves, but without the blur component. See:

We can fill this image, for example by blur or shift:

call %PICTBAT%blurFill ^
  ctx_sh_edge.png . ctx_sh_edge_bf.png
ctx_sh_edge_bf.png
call %PICTBAT%shiftFill ^
  ctx_sh_edge.png . ctx_sh_edge_sf.png
ctx_sh_edge_sf.png

The version filled by shift looks rough. We can use either as the first approximation for a relaxation fill (see Filling holes: relaxation):

call %PICTBAT%relaxFillMS ^
  ctx_sh_edge.png ctx_sh_edge_bf.png ^
  ctx_rf1.png

echo rfmsITER=%rfmsITER% 
rfmsITER=900 
ctx_rf1.png
call %PICTBAT%relaxFillMS ^
  ctx_sh_edge.png ctx_sh_edge_sf.png ^
  ctx_rf2.png

echo rfmsITER=%rfmsITER% 
rfmsITER=800 
ctx_rf2.png

The two results are similar. If we don't provide a first approximation relaxFillMS.bat will use a simple average of the unfilled image. We need to specify a high precision, i.e. a low RMSE difference. We will need many iterations, so we do a large number between tests.

call %PICTBAT%relaxFillMS ^
  ctx_sh_edge.png . ^
  ctx_rf3.png 0.0001 50

echo rfmsITER=%rfmsITER% 
rfmsITER=1600 
ctx_rf3.png

The result, between edges, is very smooth.

Yet another option is to take just the edges from the source image, then relax-fill between the edges.

%IM%convert ^
  %SRC% ^
  ctx_edges.png ^
  -alpha off ^
  -compose CopyOpacity -composite ^
  ctx_src_edges.png
ctx_src_edges.png
call %PICTBAT%relaxFillMS ^
  ctx_src_edges.png

echo rfmsITER=%rfmsITER% 
rfmsITER=1200 
ctx_src_edges_rfms.png

Other examples

We show the effect of different choices of sigma on different source images.

call %PICTBAT%cartTextEep ^
  toes.png ctx_t1_XX.png 1
ctx_t1_cart.pngjpg
call %PICTBAT%cartTextEep ^
  toes.png ctx_t2_XX.png 2
ctx_t2_cart.pngjpg
call %PICTBAT%cartTextEep ^
  toes.png ctx_t4_XX.png 4
ctx_t4_cart.pngjpg
call %PICTBAT%cartTextEep ^
  toes.png ctx_t8_XX.png 8
ctx_t8_cart.pngjpg
call %PICTBAT%cartTextEep ^
  toes.png ctx_t16_XX.png 16
ctx_t16_cart.pngjpg

 

set WEB_SIZE=-resize 600x600

set PH_SRC1=\pictures\20160623\AGA_2912_swim.tiff

if not exist ctx_ph_src1.miff %IM%convert ^
  %PH_SRC1% ^
  %WEB_SIZE% ^
  ctx_ph_src1.miff

if not exist ctx_ph_src1.miff goto error
ctx_ph_src1.miffjpg
call %PICTBAT%cartTextEep ^
  ctx_ph_src1.miff ^
  ctx_ph_src1a_XX.miff 2
ctx_ph_src1a_cart.miffjpg
call %PICTBAT%cartTextEep ^
  ctx_ph_src1.miff ^
  ctx_ph_src1b_XX.miff 4
ctx_ph_src1b_cart.miffjpg
call %PICTBAT%cartTextEep ^
  ctx_ph_src1.miff ^
  ctx_ph_src1c_XX.miff 8
ctx_ph_src1c_cart.miffjpg

 

set WEB_SIZE=-resize 600x600

set PH_SRC2=\pictures\20160623\AGA_2905_algq.tiff

if not exist ctx_ph_src2.miff %IM%convert ^
  %PH_SRC2% ^
  %WEB_SIZE% ^
  ctx_ph_src2.miff
ctx_ph_src2.miffjpg
call %PICTBAT%cartTextEep ^
  ctx_ph_src2.miff ^
  ctx_ph_src2a_XX.miff 2
ctx_ph_src2a_cart.miffjpg
call %PICTBAT%cartTextEep ^
  ctx_ph_src2.miff ^
  ctx_ph_src2b_XX.miff 4
ctx_ph_src2b_cart.miffjpg
call %PICTBAT%cartTextEep ^
  ctx_ph_src2.miff ^
  ctx_ph_src2c_XX.miff 8
ctx_ph_src2c_cart.miffjpg

Blending

Blending the input image with a cartoon gives pleasing results:

Not much cartoon.

%IM%convert ^
  %SRC% ^
  ctx_fh_sf.png ^
  -compose Blend ^
    -define compose:args=33 -composite ^
  +depth ^
  ctx_blnd0.png
ctx_blnd0.pngjpg

Mostly cartoon.

%IM%convert ^
  %SRC% ^
  ctx_fh_sf.png ^
  -compose Blend ^
    -define compose:args=67 -composite ^
  +depth ^
  ctx_blnd1.png
ctx_blnd1.pngjpg

Animations

With no blur (sigma=0), the cartoon is simply a copy of the input image. With a sufficiently large sigma, the cartoon is a solid colour. By animating the sigma value with animCartText.bat, we progressively simplify the cartoon and texture, etc. I prefer to assemble the animation in reverse, so we progressively build up the cartoon. The image grows, or becomes painted.

 call %PICTBAT%animCartText ^
  ctx_ph_src2.miff ctx_ph2_fr.miff 100 0.5 500

ctx_ph2_fr_cart.gif

ctx_ph2_fr_cart.gif

The blocky effect at the top may be a result of shiftFill factors, and may be curable.

Here is the skeleton growing:

ctx_ph2_fr_skel.gif

ctx_ph2_fr_skel.gif

Here are the edges forming, sliding into position:

ctx_ph2_fr_edges.gif

ctx_ph2_fr_edges.gif

That is unexpected but cool. How about negating that, so black lines form on a white background but make the white transparent, and paint the black lines over the cartoon?

ctx_ph2_fr_over.gif

ctx_ph2_fr_over.gif

Groovy, baby. Painting over the cartoon has concealed the blocky problem.

Future

I'd like a mechanism to automatcally choose the smallest satisfactory sigma. This might take a crop containing only the detail we want removed, and find the smallest sigma that causes no segmentation.

Frames from a video can each be procesed in this way, then reassembled into a movie.

Scripts

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

cartTextBu.bat

rem From input image %1,
rem makes cartoon and textures outputs
rem using technique of Buades et al.
rem %2 is output name, including XX, which will be substituted by cart or text.
rem such that input = cartoon + texture - 50%.
rem %3 is blur sigma.
rem
rem Future: allow for heavy blur.

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

@setlocal enabledelayedexpansion

@call echoOffSave

call %PICTBAT%setInOut %1 ctxb

set OUTFILE=%2
if "%OUTFILE%"=="." set OUTFILE=
if "%OUTFILE%"=="" set OUTFILE=%BASENAME%_ctx_XX%EXT%

set OUT_CART=%OUTFILE:XX=cart%
set OUT_TEXT=%OUTFILE:XX=text%

if "%OUT_CART%"=="%OUT_TEXT%" (
  echo Bad OUTFILE [%OUTFILE%] -- should contain XX
  exit /B 1
)

echo OUT_CART=%OUT_CART% OUT_TEXT=%OUT_TEXT%

set BLR_SIG=%3
if "%BLR_SIG%"=="." set BLR_SIG=
if "%BLR_SIG%"=="" set BLR_SIG=1

set BLR_SIG2=%4
if "%BLR_SIG2%"=="." set BLR_SIG2=
if "%BLR_SIG2%"=="" set BLR_SIG2=%BLR_SIG%

rem This works best with Q32 HDRI.

if "%IM32f%"=="" call %PICTBAT%setIm8.bat

set BLR_IMG=%OUTBASE%_ctx_blr.miff
set LTV_IMG=%OUTBASE%_ctx_ltv.miff
set LTV_BLR=%OUTBASE%_ctx_ltvblr.miff
set LAMBDA=%OUTBASE%_ctx_lambda.miff

%IM32f%convert ^
  %INFILE% ^
  -blur 0x%BLR_SIG% ^
  +depth ^
  %BLR_IMG%

call %PICTBAT%locTotVar %INFILE% %LTV_IMG% %BLR_SIG2%

call %PICTBAT%locTotVar %BLR_IMG% %LTV_BLR% %BLR_SIG2%

set sLEVEL=
set sLEVEL=-level 25%%,50%%

%IM32f%convert ^
  %LTV_IMG% +write mpr:LTVIMG ^
  %LTV_BLR% ^
  -compose MinusSrc -composite ^
  mpr:LTVIMG ^
  -compose DivideSrc -composite ^
  %sLEVEL% ^
  +depth ^
  %LAMBDA%

%IM32f%convert ^
  %INFILE% ^
  %BLR_IMG% ^
  %LAMBDA% ^
  -compose Over -composite ^
  +depth ^
  %OUT_CART%

%IM32f%convert ^
  %INFILE% ^
  %OUT_CART% ^
  -compose Mathematics -define compose:args=0,-1,1,0.5 -composite ^
  +depth ^
  %OUT_TEXT%

  
call echoRestore

endlocal

locTotVar.bat

rem From image %1,
rem makes %2 Local Total Variation, a blur of the slope.
rem %3 is sigma for blur.
rem
rem Future: allow for heavy blur.

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

@setlocal enabledelayedexpansion

@call echoOffSave

call %PICTBAT%setInOut %1 ltv

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

set BLR_SIG=%3
if "%BLR_SIG%"=="." set BLR_SIG=
if "%BLR_SIG%"=="" set BLR_SIG=1

rem This works best with Q32 HDRI.

if "%IM32f%"=="" call %PICTBAT%setIm8.bat

set smAUTO=0
call %PICTBAT%slopeMag %INFILE% %OUTFILE%

%IM32f%convert ^
  %OUTFILE% ^
  -blur 0x%BLR_SIG% ^
  +depth ^
  %OUTFILE%

call echoRestore

endlocal & set ltvOUTFILE=%OUTFILE%

cartTextEep.bat

rem From input image %1,
rem makes cartoon and textures outputs
rem using Erase Edge Pixel method.
rem %2 is output name, including XX, which will be substituted by cart, text, edges or skel.
rem such that input = cartoon + texture - 50%.
rem %3 is blur sigma.
rem
rem Future: allow for heavy blur.

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

@setlocal enabledelayedexpansion

@call echoOffSave

call %PICTBAT%setInOut %1 ctxb

set OUTFILE=%~2
if "%OUTFILE%"=="." set OUTFILE=
if "%OUTFILE%"=="" set OUTFILE=%BASENAME%_ctx_XX%EXT%

set OUT_CART="%OUTFILE:XX=cart%"
set OUT_TEXT="%OUTFILE:XX=text%"
set OUT_EDGES="%OUTFILE:XX=edges%"
set OUT_SKEL="%OUTFILE:XX=skel%"

if [%OUT_CART%]==[%OUT_TEXT%] (
  echo %0: Bad OUTFILE [%OUTFILE%] -- should contain XX
  exit /B 1
)

echo %0: OUT_CART=%OUT_CART% OUT_TEXT=%OUT_TEXT%

set BLR_SIG=%3
if "%BLR_SIG%"=="." set BLR_SIG=
if "%BLR_SIG%"=="" set BLR_SIG=1

set BLR_IMG=%BASENAME%_ctx_blr.miff
set SLOP_MAG=%BASENAME%_ctx_bsm.miff
set HOLED_MAG=%BASENAME%_ctx_holed.miff

%IM%convert ^
  %INFILE% ^
  -blur 0x%BLR_SIG% ^
  +depth ^
  %BLR_IMG%

set smAUTO=0

call %PICTBAT%slopeMag %BLR_IMG% %SLOP_MAG%

%IM32f%convert ^
  %SLOP_MAG% ^
  -auto-level ^
  -unsharp 0x%BLR_SIG%+50+0 ^
  -blur 0x%BLR_SIG% ^
  -threshold 50%% ^
  +depth ^
  %OUT_EDGES%

if ERRORLEVEL 1 exit /B 1

%IM%convert ^
  %BLR_IMG% ^
  ( %OUT_EDGES% -negate ) ^
  -compose CopyOpacity -composite ^
  %HOLED_MAG%

if ERRORLEVEL 1 exit /B 1

call %PICTBAT%shiftFill %HOLED_MAG% . %OUT_CART%

if ERRORLEVEL 1 exit /B 1

%IM%convert ^
  %INFILE% ^
  %OUT_CART% ^
  -compose Mathematics ^
    -define compose:args=0,-1,1,0.5 ^
  -composite ^
  +depth ^
  %OUT_TEXT%

if ERRORLEVEL 1 exit /B 1

%IM%convert ^
  %OUT_EDGES% ^
  -morphology Thinning:-1 skeleton ^
  -blur 0x0.5 ^
  -auto-level -negate ^
  %OUT_SKEL%

if ERRORLEVEL 1 exit /B 1

call echoRestore

endlocal

bigBlur.bat

rem From image %1 makes %2 with blur sigma %3 method %4
rem %3 is sigma. May have suffix 'c' or '%' for percentage or 'p' for proportion.
rem %4 is method:
rem   b blur
rem   r resize down then up
rem   a auto

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

@setlocal enabledelayedexpansion

rem @call echoOffSave

call %PICTBAT%setInOut %1 bb

set OUTFILE=%2
if "%OUTFILE%"=="." set OUTFILE=
if "%OUTFILE%"=="" set OUTFILE=%BASENAME%_%sioCODE%%EXT%

set BLR_SIG=%3
if "%BLR_SIG%"=="." set BLR_SIG=
if "%BLR_SIG%"=="" set BLR_SIG=3

set METH=%4
if "%METH%"=="." set METH=
if "%METH%"=="" set METH=a

set SIG_LAST=%BLR_SIG:~-1%

if "%SIG_LAST%"=="^%" set SIG_LAST=c

if /I "%SIG_LAST%"=="c" (

  for /F "usebackq" %%L in (`%IM%identify ^
    -format "nSIG=%%[fx:w*%BLR_SIG:~0,-1%/100]" ^
    %INFILE%`) do set %%L

) else if /I "%SIG_LAST%"=="p" (

  for /F "usebackq" %%L in (`%IM%identify ^
    -format "nSIG=%%[fx:w*%BLR_SIG:~0,-1%]" ^
    %INFILE%`) do set %%L

) else (
  set nSIG=%BLR_SIG%
)


if /I "%METH%"=="a" (

  for /F "usebackq" %%L in (`%IM%identify ^
    -format "IsSmall=%%[fx:%nSIG%<50?1:0]" ^
    %INFILE%`) do set %%L

  echo %0: nSIG=%nSIG% IsSmall=!IsSmall!

  set METH=r
  if !IsSmall!==1 set METH=b
)

set sRESIZE=
if /I "%METH%"=="b" (
  set sRESIZE=-blur 0x%nSIG%
) else if /I "%METH%"=="r" (

  for /F "usebackq" %%L in (`%IM%identify ^
    -format "WW=%%w\nHH=%%h\nRAT=%%[fx:50/%nSIG%]" ^
    %INFILE%`) do set %%L

  set sRESIZE=-resize !RAT!%% -resize "!WW!x!HH!^^^!"
)

echo %0: sRESIZE=%sRESIZE%

if /I not "%OUTFILE%"=="NULL:" %IM%convert ^
  %INFILE% ^
  %sRESIZE% ^
  %OUTFILE%

if ERRORLEVEL 1 exit /B 1

call echoRestore

endlocal & set bbOUTFILE=%OUTFILE%& set bbRESIZE=%sRESIZE%

animCartText.bat

rem Creates frames for animation of a cartoon and texture.
rem
rem %1 image to be turned onto cartoon + texture
rem %2 prefix and extension for frame files. Must _not_ include XX.
rem %3 number of frames [default 10].
rem %4 sigma for blur at start [default 0.5].
rem %5 sigma for blur at end [default 10].

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

@setlocal enabledelayedexpansion

@call echoOffSave

call %PICTBAT%setInOut %1 actx

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

for /F %%F in ("%OUTFILE%") do (
  set OUT_PREF=%%~dpnF
  set OUT_EXT=%%~xF
)

echo OUT_PREF=%OUT_PREF% OUT_EXT=%OUT_EXT%

set nFRAMES=%3
if "%nFRAMES%"=="." set nFRAMES=
if "%nFRAMES%"=="" set nFRAMES=10

set SIG_START=%4
if "%SIG_START%"=="." set SIG_START=
if "%SIG_START%"=="" set SIG_START=0.5

set SIG_END=%5
if "%SIG_END%"=="." set SIG_END=
if "%SIG_END%"=="" set SIG_END=10

call :clean

if "%IM32f%"=="" call %PICTBAT%setIm8.bat

set SIG=%SIG_START%
for /L %%I in (1,1,%nFRAMES%) do (
  echo %%I !SIG!

  set LZ=000000%%I
  set LZ=!LZ:~-6!

  call %PICTBAT%cartTextEep ^
    %INFILE% ^
    %OUT_PREF%_XX_!LZ!%EXT% !SIG!

  %IM%convert ^
    %OUT_PREF%_cart_!LZ!*%EXT% ^
    ^( %OUT_PREF%_edges_!LZ!*%EXT% ^
       -negate -transparent White ^
    ^) ^
    -compose Over -composite ^
    %OUT_PREF%_over_!LZ!%EXT%

  for /F "usebackq" %%L in (`%IM%identify ^
    -precision 19 ^
    -format "SIG=%%[fx:!SIG!*pow(%SIG_END%/%SIG_START%,1/(%nFRAMES%-1))]" ^
    xc:`) do set %%L
)


%IM%convert ^
  -loop 0 -delay 10 %OUT_PREF%_cart*%EXT% -reverse -duplicate 10 ^
  %OUT_PREF%_cart.gif

%IM%convert ^
  -loop 0 -delay 10 %OUT_PREF%_skel*%EXT% -reverse -duplicate 10 ^
  %OUT_PREF%_skel.gif

%IM%convert ^
  -loop 0 -delay 10 %OUT_PREF%_text*%EXT% -duplicate 10 ^
  %OUT_PREF%_text.gif

%IM%convert ^
  -loop 0 -delay 10 %OUT_PREF%_edges*%EXT% -reverse -duplicate 10 ^
  %OUT_PREF%_edges.gif

%IM%convert ^
  -loop 0 -delay 10 %OUT_PREF%_over*%EXT% -reverse -duplicate 10 ^
  %OUT_PREF%_over.gif

call :clean

call echoRestore

@endlocal

exit /B 0

:: -------------------------------------------------
:: Subroutine:

:clean
del %OUT_PREF%_skel_*%OUT_EXT%
del %OUT_PREF%_edges_*%OUT_EXT%
del %OUT_PREF%_cart_*%OUT_EXT%
del %OUT_PREF%_text_*%OUT_EXT%
del %OUT_PREF%_over_*%OUT_EXT%

exit /B 0

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 carttext.h1. To re-create this web page, run "procH1 carttext".


This page, including the images except where shown otherwise, 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 21-July-2016.

Page created 28-Jun-2017 14:12:04.

Copyright © 2017 Alan Gibson.