Linux x64: ImageMagick 6.8.8-1 Q16
I need to read a raw image and split it into 16 pieces.
I need to overlay pieces 1 and 2, 3 and 4, etc. and tweak and label each group.
Then I need to convert everything into 1 final output image.
I wrote a bash script to do it but it runs a bit slow.
The single command below "works", needs no temporary files and is faster than the bash script, but I had to use the clone commands exactly the right number of times and hardcode the section names.
Is there a better way to loop in ImageMagick? Or a better way to do this?
(The real version is bigger and has more than the 8 sections in my example)
annotate="-gravity north -stroke #FFFF -fill white -strokewidth 1 -pointsize 15 -annotate 0"
bright="-brightness-contrast 50x50 -black-threshold 20%"
convert \
-size 512x2048 cmyk:test.raw -set colorspace Gray -separate -average -normalize -crop 512x256 +repage \
\( -clone 0 -crop 512x128 +repage -compose Plus -composite $bright $annotate "Section 1" \) -delete 0 \
\( -clone 0 -crop 512x128 +repage -compose Plus -composite $bright $annotate "Section 2" \) -delete 0 \
\( -clone 0 -crop 512x128 +repage -compose Plus -composite $bright $annotate "Section 3" \) -delete 0 \
\( -clone 0 -crop 512x128 +repage -compose Plus -composite $bright $annotate "Section 4" \) -delete 0 \
\( -clone 0 -crop 512x128 +repage -compose Plus -composite $bright $annotate "Section 5" \) -delete 0 \
\( -clone 0 -crop 512x128 +repage -compose Plus -composite $bright $annotate "Section 6" \) -delete 0 \
\( -clone 0 -crop 512x128 +repage -compose Plus -composite $bright $annotate "Section 7" \) -delete 0 \
\( -clone 0 -crop 512x128 +repage -compose Plus -composite $bright $annotate "Section 8" \) -delete 0 \
-append output.png
[Solved, use shell to loop] Loop/Repeat/For in ImageMagick?
[Solved, use shell to loop] Loop/Repeat/For in ImageMagick?
Last edited by kedlm on 2018-09-18T09:37:48-07:00, edited 1 time in total.
- fmw42
- Posts: 25562
- Joined: 2007-07-02T17:14:51-07:00
- Authentication code: 1152
- Location: Sunnyvale, California, USA
Re: Loop/Repeat/For in ImageMagick?
In Unix, you can do subshell processing to do what you need. That is indicated by the parens above and below the code. You basically do a loop over the previous created MPC file (memory mapped), which is fast reading multiple times, inside the subshell. You save to miff:- and then pipe the result to another convert to do the appending.
Here is a simple example. You can change your -crop as you have it and add your own annotate and bright.
Input:
Here is a simple example. You can change your -crop as you have it and add your own annotate and bright.
Input:
Code: Select all
num=`convert logo: -crop 4x2@ +repage +write tmp.mpc -format "%n\n" info: | head -n 1`
(
for ((i=0; i<num; i++)); do
echo >&2 "$i"
j=$((i+1))
convert tmp.mpc[$i] -gravity west -pointsize 18 -fill "green1" -font ubuntu -annotate +0+0 "Section $j" miff:-
done
) | convert - -append logo_result.png
-
- Posts: 12159
- Joined: 2010-01-23T23:01:33-07:00
- Authentication code: 1151
- Location: England, UK
Re: Loop/Repeat/For in ImageMagick?
I can't see any scope for increasing performance. IM doesn't have a looping construct to simplify the code. For jobs like this, I often write a script that contains a loop and builds the final command or script.
I would add "+repage" after the final "-append" because more recent versions of IM take the canvas size from the size of the first image.
"-annotate" can take metadata escapes shown on http://www.imagemagick.org/script/escape.php , so you can use "Section %p". Hence if you arrange to have a list of images, you can automatically annotate them from zero upwards. Add a dummy image at the start to number yours from one upwards.
You crop the 512x2048 image into 8 pieces, then crop each of those into 2 pieces, and "-compose Plus -composite" each pair. You might instead directly crop the 512x2048 image into 16 pieces. Then you could rearrange the order of the images in the list and insert a dummy "NULL:" image, so you have 17 images: the odd numbers, then NULL:, then the even numbers, Then use "-layers composite" to plus each pair. See http://www.imagemagick.org/script/comma ... php#layers
But this is messy. I suggest writing a script that contains a loop and builds the final command or script.
I would add "+repage" after the final "-append" because more recent versions of IM take the canvas size from the size of the first image.
"-annotate" can take metadata escapes shown on http://www.imagemagick.org/script/escape.php , so you can use "Section %p". Hence if you arrange to have a list of images, you can automatically annotate them from zero upwards. Add a dummy image at the start to number yours from one upwards.
You crop the 512x2048 image into 8 pieces, then crop each of those into 2 pieces, and "-compose Plus -composite" each pair. You might instead directly crop the 512x2048 image into 16 pieces. Then you could rearrange the order of the images in the list and insert a dummy "NULL:" image, so you have 17 images: the odd numbers, then NULL:, then the even numbers, Then use "-layers composite" to plus each pair. See http://www.imagemagick.org/script/comma ... php#layers
But this is messy. I suggest writing a script that contains a loop and builds the final command or script.
snibgo's IM pages: im.snibgo.com
Re: Loop/Repeat/For in ImageMagick?
Thanks for the quick answers!
@fmw42 that was very informative to learn a new way to handle temporary storage and sub shells
@snibgo I hadn't seen the metadata escapes and I added the last +repage; thanks
After some testing, just creating the long command in a for loop results in the simplest code, fastest run time, and no temporary storage on disk.
@fmw42 that was very informative to learn a new way to handle temporary storage and sub shells
@snibgo I hadn't seen the metadata escapes and I added the last +repage; thanks
After some testing, just creating the long command in a for loop results in the simplest code, fastest run time, and no temporary storage on disk.
- fmw42
- Posts: 25562
- Joined: 2007-07-02T17:14:51-07:00
- Authentication code: 1152
- Location: Sunnyvale, California, USA
Re: Loop/Repeat/For in ImageMagick?
If you add -scene 1 and use %s rather than %p, then you won't need the extra dummy image at the beginning. For example
Starts with Number 1 rather than Number 0 in the output frames.
Code: Select all
convert lena.jpg barn.jpg monet2.jpg mandril3.jpg -scene 1 -gravity center -pointsize 18 -annotate +0+0 "Number %s" test.gif
Re: Loop/Repeat/For in ImageMagick?
Good to know. I actually prefer it to start at 0 for the actual task.