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.
blah.
%IM%convert ^ \pictures\20140522\AGA_1798_ssd_ehb2.tiff ^ -resize x480 ^ pnt_street.png set SRC=pnt_street.png |
Videos are silent, 480 pixels high, and generally:
%IM%convert ^ %SRC% ^ -colorspace Gray -equalize ^ pnt_st_gr.png |
|
call %PICTBAT%slopeMag %SRC% %IM%convert ^ pnt_street_sm.png ^ -colorspace Gray -equalize ^ pnt_st_sm.png |
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 |
|
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 |
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_h.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: |
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_h.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: |
Make a video with this mask.
call %PICTBAT%mPntVideo ^ %SRC% ^ pnt_street_sm_n2.png ^ Black ^ 250 10 ^ pnt_sm22 |
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.
|
|
%IM%convert ^ pnt_draw.png ^ -level 0,60%% ^ 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 |
The sequence might be in order of greatest-detail, or from a central point outwards, or ... .
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:
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]
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.
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
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
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
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.