snibgo's ImageMagick pages

Painting

We can use IM to gradually paint a picture. The result is a sequence of frames that may be combined into an animated GIF or part of a video sequence. The image is slowly revealed.

In the good old days, internet connections were pieces of wet string and images took a long time to download. We watched them gradually build on the screen. This was like observing a painter building a picture, especially when the using progressive JPEG.

Sample images

blah.

%IM%convert ^
  \pictures\20140522\AGA_1798_ssd_ehb2.tiff ^
  -resize x480 ^
  pnt_street.png

set SRC=pnt_street.png
pnt_street.pngjpg

General techniques

Videos are silent, 480 pixels high, and generally:

Mask reveal

%IM%convert ^
  %SRC% ^
  -colorspace Gray -equalize ^
  pnt_st_gr.png
pnt_st_gr.png
call %PICTBAT%slopeMag %SRC%

%IM%convert ^
  pnt_street_sm.png ^
  -colorspace Gray -equalize ^
  pnt_st_sm.png
pnt_st_sm.pngjpg

From the image and the two masks, we can make videos that reveal the image according to each mask.

call %PICTBAT%mPntVideo ^
  %SRC% ^
  pnt_st_gr.png ^
  Black ^
  250 10 ^
  pnt_gr

call %PICTBAT%pntMaskReveal ^
  %SRC% ^
  pnt_st_gr.png ^
  %TEMP%\pnt_gr Black 250

del %TEMP%\pnt_gr2*.png 2>nul

call %PICTBAT%mFrLink %TEMP%\pnt_gr %TEMP%\pnt_gr2 .png 0 0 0 10

call %PICTBAT%mFrLink %TEMP%\pnt_gr %TEMP%\pnt_gr2 .png 0 249 10

call %PICTBAT%mFrLink %TEMP%\pnt_gr %TEMP%\pnt_gr2 .png 249 249 260 10

call %PICTBAT%mFrLink %TEMP%\pnt_gr %TEMP%\pnt_gr2 .png 249 0 270

call %PICTBAT%mFrLink %TEMP%\pnt_gr %TEMP%\pnt_gr2 .png 0 0 520 10

del pnt_gr.mpg 2>nul
%IM%ffmpeg -i %TEMP%\pnt_gr2_%%06d.png -q 4 pnt_gr.mpg
call %PICTBAT%mPntVideo ^
  %SRC% ^
  pnt_st_sm.png ^
  Black ^
  250 10 ^
  pnt_sm

In the second example, the painting of the sky isn't smooth. For some frames there is no painting, then many pixels are painted in a single frame. The histogram of the mask explains the problem:

%IM%convert ^
  pnt_st_sm.png ^
  ( +clone -unique-colors -write info: +delete ) ^
  -define histogram:unique-colors=false ^
  -write histogram:mpr:HIST +delete ^
  mpr:HIST ^
  -bordercolor Blue -border 2 ^
  pnt_st_sm_h.png 
pnt_st_sm.png PNG 39257x1 39257x1+0+0 16-bit Gray 0.000u 0:00.026
pnt_st_sm_h.png

Before the equalise, the problem is even more obvious:

%IM%convert ^
  pnt_street_sm.png ^
  ( +clone -unique-colors -write info: +delete ) ^
  -define histogram:unique-colors=false ^
  -write histogram:mpr:HIST +delete ^
  mpr:HIST ^
  -bordercolor Blue -border 2 ^
  pnt_street_sm_h.png 
pnt_street_sm.png PNG 48524x1 48524x1+0+0 16-bit Gray 0.000u 0:00.003
pnt_street_sm_h.png

To overcome the problem, we can add noise. We blur the noise to get a more painterly effect. We need more noise where the mask is dark.

%IM%convert ^
  pnt_street_sm.png ^
  ( -clone 0 ^
    -fill Gray50 -colorize 100 ^
    +noise Gaussian ^
    -blur 0x5 ^
    -colorspace Gray ^
    -solarize 50%% ^
    -level 50%%,0 ^
    -auto-level ^
    -write n.png ^
  ) ^
  ( -clone 0 -negate ) ^
  -delete 0 ^
  -compose Multiply -composite ^
  -evaluate Multiply 0.25 ^
  nc.png

%IM%convert ^
  n.png ^
  ( +clone -unique-colors -write info: +delete ) ^
  -define histogram:unique-colors=false ^
  -write histogram:mpr:HIST +delete ^
  mpr:HIST ^
  -bordercolor Blue -border 2 ^
  n_h.png 
n.png PNG 1191x1 1191x1+0+0 16-bit Gray 0.000u 0:00.000

n.png:

n.png

n_h.png:

n_h.png

nc.png:

nc.png

Add the noise to the mask:

%IM%convert ^
  pnt_street_sm.png ^
  nc.png ^
  -compose Add -composite ^
  -equalize ^
  pnt_street_sm_n.png

%IM%convert ^
  pnt_street_sm_n.png ^
  ( +clone -unique-colors -write info: +delete ) ^
  -define histogram:unique-colors=false ^
  -write histogram:mpr:HIST +delete ^
  mpr:HIST ^
  -bordercolor Blue -border 2 ^
  n_h2.png 
n2.png PNG 57926x1 57926x1+0+0 16-bit Gray 0.000u 0:00.004

pnt_street_sm_n.png:

pnt_street_sm_n.pngjpg n_h2.png

The histogram of this revised mask is flat, as we want it. Make a video with this mask.

call %PICTBAT%mPntVideo ^
  %SRC% ^
  pnt_street_sm_n.png ^
  Black ^
  250 10 ^
  pnt_sm2

The result is satisfactory.

An alternative to adding noise is to add a portion of the original image.

%IM%convert ^
  pnt_street_sm.png ^
  ( %SRC% ^
    -colorspace Gray ^
    -auto-level ^
    -write n2.png ^
  ) ^
  ( -clone 0 -negate ) ^
  -delete 0 ^
  -compose Multiply -composite ^
  -evaluate Multiply 0.25 ^
  nc2.png

%IM%convert ^
  n2.png ^
  ( +clone -unique-colors -write info: +delete ) ^
  -define histogram:unique-colors=false ^
  -write histogram:mpr:HIST +delete ^
  mpr:HIST ^
  -bordercolor Blue -border 2 ^
  n2_h.png 
n2.png PNG 57926x1 57926x1+0+0 16-bit Gray 0.000u 0:00.004

n2.png:

n2.png

n2_h.png:

n2_h.png

nc2.png:

nc2.png

Add the the darkened image to the mask:

%IM%convert ^
  pnt_street_sm.png ^
  nc2.png ^
  -compose Add -composite ^
  -equalize ^
  pnt_street_sm_n2.png

%IM%convert ^
  pnt_street_sm_n2.png ^
  ( +clone -unique-colors -write info: +delete ) ^
  -define histogram:unique-colors=false ^
  -write histogram:mpr:HIST +delete ^
  mpr:HIST ^
  -bordercolor Blue -border 2 ^
  n2_h2.png 
pnt_street_sm_n2.png PNG 34903x1 34903x1+0+0 16-bit Gray 0.016u 0:00.003

pnt_street_sm_n2.png:

pnt_street_sm_n2.png n2_h2.png

Make a video with this mask.

call %PICTBAT%mPntVideo ^
  %SRC% ^
  pnt_street_sm_n2.png ^
  Black ^
  250 10 ^
  pnt_sm22

Line drawings

Eg 20140522\AGA_1798_ssd.tiff

How do we simulate the action of a pen tracing the lines? We need to break loops at junctions.

The negated slope-magnitude makes an plausible drawing.

%IM%convert ^
  pnt_street_sm.png ^
  -negate ^
  pnt_draw.png

The lines are good.
The tones (eg below the car) are less good.

pnt_draw.png
%IM%convert ^
  pnt_draw.png ^
  -level 0,60%% ^
  pnt_draw2.png
pnt_draw2.png

We negate to make a mask, and use this to make a video.

%IM%convert ^
  pnt_draw2.png ^
  -negate ^
  pnt_draw2n.png

call %PICTBAT%mPntVideo ^
  pnt_draw2.png ^
  pnt_draw2n.png ^
  White ^
  250 10 ^
  pnt_dr2

Simplifying colour

The sequence might be in order of greatest-detail, or from a central point outwards, or ... .

Successive resolutions

We can paint the entire image in a single colour. Then divide the image into four rectangle and paint each one. Keep going until we are at the single-pixel level. This mechanical process isn't visually interesting, and the final result is, of course, simply the input image.

The final result is more interesting when it retains traces of the painting process. The process is more interesting (and faster) when it concentrates the painting on important areas. These areas should be painted at finer resolutions, and after the coarser resolutions. We might identify the important areas by:

Painting a video

So far, we have used a single image to make multiple images. But we can use a sequence of images as the input. The revelation method may use one of the above techniques, or be related to the motion captured by the video.

[youtube=PmBx5Zo8KZo] [youtube=YaOOmaGzx0g] [youtube=0JS5uXGa4_c]

Scripts

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

Make a gif from frames with given prefix (dir\name).

Make a video from frames with given prefix (dir\name).

mPntVideo.bat isn't a general-purpose script, but one specially writen for this page.

mPntVideo.bat

rem From image %1 and mask %2, make video that reveals the image.
rem %3 is initial colour
rem %4 is number of frames in revelation
rem %5 is number of frames to pause
rem %6 is identifying string
rem
rem This creates: pause, revelation, pause, derevelation, pause.

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

@setlocal

rem @call echoOffSave

set INFILE=%1
set EXT=%~x1
set MASK=%2

set nREVEL=%4
if "%nREVEL%"=="" set nREVEL=100

set nPAUSE=%5
if "%nPAUSE%"=="" set nPAUSE=10

set ID_STR=%6
if "%ID_STR%"=="" set ID_STR=mpv

set ID_STR2=%ID_STR%_v2

set VIDEO=%ID_STR%.mpg

set TMPDIR=%TEMP%\pnt
if not exist %TMPDIR% md %TMPDIR%

set /A nREVELm1=%nREVEL%-1

del %TMPDIR%\%ID_STR%_*%EXT%

call %PICTBAT%pntMaskReveal ^
  %INFILE% ^
  %MASK% ^
  %TMPDIR%\%ID_STR% %3 %nREVEL%

del %TMPDIR%\%ID_STR2%*.png 2>nul

call %PICTBAT%mFrLink ^
  %TMPDIR%\%ID_STR% ^
  %TMPDIR%\%ID_STR2% %EXT% ^
  0 0 0 %nPAUSE%

set /A NEXT=%nPAUSE%

call %PICTBAT%mFrLink ^
  %TMPDIR%\%ID_STR% ^
  %TMPDIR%\%ID_STR2% %EXT% ^
  0 %nREVELm1% %NEXT%

set /A NEXT+=%nREVEL%

call %PICTBAT%mFrLink ^
  %TMPDIR%\%ID_STR% ^
  %TMPDIR%\%ID_STR2% %EXT% ^
  %nREVELm1% %nREVELm1% %NEXT% %nPAUSE%

set /A NEXT+=%nPAUSE%

call %PICTBAT%mFrLink ^
  %TMPDIR%\%ID_STR% ^
  %TMPDIR%\%ID_STR2% %EXT% ^
  %nREVELm1% 0 %NEXT%

set /A NEXT+=%nREVEL%

call %PICTBAT%mFrLink ^
  %TMPDIR%\%ID_STR% ^
  %TMPDIR%\%ID_STR2% %EXT% ^
  0 0 %NEXT% %nPAUSE%

set /A NEXT+=%nPAUSE%


del /q %VIDEO%
%IM%ffmpeg -an -r 25 -i %TMPDIR%\%ID_STR2%_%%06d%EXT% -q 4 -r 25 %VIDEO%


call echoRestore

endlocal

pntMaskReveal.bat

rem From image %1, mask %2, prefix %3, initial colour %4, %5 frames >=2,
rem makes frames of image revealed by the mask.
@rem
@rem First frame will be entirely initial colour;
@rem last frame will be entirely image.
@rem
@rem Also uses:
@rem   pmrOVERLAP
@rem

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

@setlocal

@call echoOffSave


set INFILE=%1
set EXT=%~x1
set MASK=%2
set PREFIX=%3
set INIT_COL=%4
set nFRAMES=%5

if %nFRAMES% LSS 2 exit /B 1

set /A nFRAMESm1=%nFRAMES%-1

set EXTPREF=
if /I %EXT%==.png set EXTPREF=PNG24:

for /F "usebackq" %%L in (`%IM%identify ^
  -format "INTVL=%%[fx:100/%nFRAMESm1%]\nINTVL_2=%%[fx:50/%nFRAMESm1%]" ^
  xc:`) do set %%L

for /L %%i in (0,1,%nFRAMESm1%) do (

  set LZ=00000%%i
  set LZ=!LZ:~-6!

  for /F "usebackq" %%L in (`%IM%identify ^
    -format "THRESHpc=%%[fx:100-%INTVL%*%%i]\nLEV1=%%[fx:100-%INTVL%*(%%i+0.5)]\nLEV2=%%[fx:100-%INTVL%*(%%i-0.5)]" ^
    xc:`) do set %%L

  echo %%i !LZ! THRESHpc=!THRESHpc! LEV1=!LEV1! LEV2=!LEV2!

  if %%i==0 (
    set THRESH=-evaluate set 0
  ) else if %%i==%nFRAMESm1% (
    set THRESH=-evaluate set 100%%
  ) else (
    set THRESH=-level !LEV1!,!LEV2!%%
  )

  %IM%convert ^
    %INFILE% ^
    ^( +clone -fill %INIT_COL% -colorize 100 ^) ^
    +swap ^
    ^( %MASK% ^
      !THRESH! ^
    ^) ^
    -composite ^
    -type Truecolor ^
    %EXTPREF%%PREFIX%_!LZ!%EXT%
)


call echoRestore

endlocal

mFrLink.bat

rem Make frame links.
@rem %1 is source prefix
@rem %2 is destination prefix
@rem %3 is extension eg .png
@rem %4 is first src frame num
@rem %5 is last src frame num (can be <= first)
@rem %6 is first dest frame num
@rem %7 is optional repetitions of action (default 1)

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

@setlocal

@call echoOffSave

set EXT=%3

set STEP=1
if %5 LSS %4 set STEP=-1

set OUT_NUM=%6

set N_REPS=%7
if "%N_REPS%"=="" set N_REPS=1

for /L %%r in (1,1,%N_REPS%) do (

  for /L %%i in (%4,%STEP%,%5) do (

    set LZIN=00000%%i
    set LZIN=!LZIN:~-6!

    set LZOUT=00000!OUT_NUM!
    set LZOUT=!LZOUT:~-6!

    mklink /H %2_!LZOUT!%EXT% %1_!LZIN!%EXT% >nul
    if ERRORLEVEL 1 exit /B 1

    set /A OUT_NUM+=1
  )
)

call echoRestore

@endlocal

delFr.bat

rem Delete frames.
@rem
@rem %1 is prefix
@rem %2 is extension eg png
@rem %3 is first frame to delete
@rem %4 is last frame to delete

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

@setlocal

@call echoOffSave


set STEP=1
if %4 LSS %3 set STEP=-1


for /L %%i in (%3,%STEP%,%4) do (

  set LZIN=00000%%i
  set LZIN=!LZIN:~-6!

  del %1_!LZIN!.%2 2>nul
)



call echoRestore

endlocal

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

%IM%identify -version
Version: ImageMagick 6.9.1--6 Q16 x64 2015-06-20 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2015 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Features: Cipher DPC Modules OpenMP 
Delegates (built-in): bzlib cairo freetype jng jp2 jpeg lcms lqr openexr pangocairo png ps rsvg tiff webp xml zlib

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


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-July-2014.

Page created 18-Jul-2015 22:51:26.

Copyright © 2015 Alan Gibson.