Page 1 of 2

Any chance to improve the performace of this "-compose" cmd?

Posted: 2008-06-19T05:06:11-07:00
by Da_Vinci
Hi guys,

I hope you can help me out. :(

I have a black image (about 500x500px) which I create with

Code: Select all

convert -size 500x500 xc:black black_canvas.png
On this image I need to "stamp" dozens of copies one(!) single other image.

The stamp image looks like this:
Image

Right now I run this command in a loop with varying geometry values:

Code: Select all

convert black_canvas.png stamp_pic.png -compose screen -geometry +123+456 -composite black_canvas.png
I tried it with a loop for about 60 stamps. Took it 15sec to apply them. :shock:

But I will most likely need to have the chance to stamp up to several hundred instances of stamp_pic.png onto black_canvas.png.

I got a slight improvement by "stamping" it multiple times per command using something like:

Code: Select all

convert black_canvas.png \
stamp_pic.png -compose screen -geometry +123+456 -composite \
stamp_pic.png -compose screen -geometry +789+123 . . . -composite \
. . . \
black_canvas.png
But neither do I know how many "-compose" actions are allowed per command nor did it improve the performance seriously in any way.

What would you recommend me to do here?
(this is gonna be part of a small PHP project of mine)
(the "screen" blend mode is quite important btw.)

Re: Any chance to improve the performace of this "-compose" cmd?

Posted: 2008-06-19T05:45:08-07:00
by Bonzo
From one of my webpages:
Resize one image into different sizes in one line of code.
Two different methods: The first uses the built im method of saving an image into the memory
The second uses +clone. On the image I used the first method was 0.1sec slower to create the 4 different sized images.
With the first method using mpr: the same image can be used in any number of scripts without reading it in again. You can also create more than one image in the memory by giving it a different "name".

<?php
exec("convert print2.jpg -write mpr:image +delete \( mpr:image -thumbnail x480 -write mpr_480.jpg \) \( mpr:image -thumbnail x250 -write mpr_250.jpg \) \( mpr:image -thumbnail x100 -write mpr_100.jpg \) \( mpr:image -thumbnail 64x64! -write mpr_64.jpg \) ");

exec("convert print2.jpg \( +clone -thumbnail x480 -write clone_480.jpg +delete \) \( +clone -thumbnail x250 -write clone_250.jpg +delete \) \( +clone -thumbnail x100 -write clone_100.jpg +delete \) -thumbnail 64x64! clone_64.jpg ");
?>
You should be able to adapt this code and see if it has any speed improvements or can you create the image you are placing on your background to have e.g. 4 images in a square and then you need to place it on the background 1/4 of the times ?

Re: Any chance to improve the performace of this "-compose" cmd?

Posted: 2008-06-19T06:14:52-07:00
by Da_Vinci
Not sure if this is what I need.

I'm not looking for some kind of tiling. :?
I have three things:
1. A black canvas image of about 500x500.
2. A smaller stamp image:
Image
3. A list of coordinates at which I need to have a stamp each. (coords are kind of randomly seeded)

Also the stamps need to have a blend mode of "screen".

Does the "+clone" allow me to compose one image several times at varying geometries while reading it just once?
If yes, could you give me a hint on how to do that? I couldn't find any comparable snippet.
Well, I did find this:

Code: Select all

\( +clone \) -compose screen -flatten \
But how do I know which image it's gonna clone?

Btw, is there some general limit for the length of a command?

Re: Any chance to improve the performace of this "-compose" cmd?

Posted: 2008-06-19T07:56:37-07:00
by Da_Vinci
Changing this:

Code: Select all

convert black_canvas.png stamp_pic.png -compose screen -geometry +123+456 -composite black_canvas.png
To this

Code: Select all

composite stamp_pic.png -compose screen -geometry +123+456 black_canvas.png black_canvas.png
made the execution 2x faster. :D

Well, … would one of you be so kind to show me how to read that stamp_pic.png just once while composing it multiple times? I have no clue :?
Additionally it would be awesome if I could also make the stamp_pic.png slightly transculent before flattening.

I searched http://www.imagemagick.org/Usage/compose/#over for help but couldn't find anything related. :(
I also couldn't come up with any solution of my own :(

Re: Any chance to improve the performace of this "-compose" cmd?

Posted: 2008-06-19T09:57:31-07:00
by Bonzo
Another small problem Da_Vinci your second example "composite" only works with 2 images.

Whats this like for speed?

Code: Select all

exec("convert conejt8.png -write mpr:image +delete -size 500x500 xc:black mpr:image -compose screen -geometry +123+356 -composite mpr:image -compose screen -geometry +223+156 -composite mpr:image -compose screen -geometry +100+222 -composite output.png");
EDIT: I forgot to say I am generating the black background as well. replace -size 500x500 xc:black with black_canvas.png

Re: Any chance to improve the performace of this "-compose" cmd?

Posted: 2008-06-19T10:44:54-07:00
by fmw42
try the following for a fixed number of composites

convert stamp_pic.png black_canvas.png \
\( -clone 1 -clone 0 -compose screen -geometry +100+100 -composite \) -delete 1 \
\( -clone 1 -clone 0 -compose screen -geometry +200+200 -composite \) -delete 1 \
\( -clone 1 -clone 0 -compose screen -geometry +300+300 -composite \) -delete 1 \
-delete 0 black_canvas1.png

or

convert \( stamp_pic.png -write mpr:image \) black_canvas.png \
\( -clone 1 mpr:image -compose screen -geometry +100+100 -composite \) -delete 1 \
\( -clone 1 mpr:image -compose screen -geometry +200+200 -composite \) -delete 1 \
\( -clone 1 mpr:image -compose screen -geometry +300+300 -composite \) -delete 1 \
-delete 0 black_canvas2.png

However, in PHP, you can make a string with all the composite lines that you need to do (if it is not too long for PHP) and then bring the string in. For example,

str="\( -clone 1 mpr:image -compose screen -geometry +100+100 -composite \) -delete 1 \
\( -clone 1 mpr:image -compose screen -geometry +200+200 -composite \) -delete 1 \
\( -clone 1 mpr:image -compose screen -geometry +300+300 -composite \) -delete 1 \"

convert \( stamp_pic.png -write mpr:image \) black_canvas.png \
$str -delete 0 black_canvas2.png

You can create the string in a PHP loop also.

You can also do the following (in bash Unix terminal) with a memory mapped disk file. (You will have to convert to PHP equivalent). This may speed your loops up.

tmp1A="./stamp_1_$$.mpc"
tmp1B="./stamp_1_$$.cache"
tmp2A="./stamp_2_$$.mpc"
tmp2B="./stamp_2_$$.cache"
trap "rm -f $tmp1A $tmp1B $tmp2A $tmp2B; exit 0" 0
trap "rm -f $tmp1A $tmp1B $tmp2A $tmp2B; exit 1" 1 2 3 15
convert stamp_pic.png $tmp1A
convert black_canvas.png $tmp2A
i=1
num=3
geom1="+100+100"
geom2="+200+200"
geom3="+300+300"
while [ $i -le $num ]; do
eval convert $tmp2A $tmp1A -compose screen -geometry \$geom$i -composite $tmp2A
i=`expr $i + 1`
done
convert $tmp2A black_canvas3.png
exit 0

But at least you can do the looping over any number of locations.

see
http://www.imagemagick.org/Usage/files/#mpc
http://www.imagemagick.org/Usage/files/#mpr
http://www.imagemagick.org/Usage/basics/#image_seq

Re: Any chance to improve the performace of this "-compose" cmd?

Posted: 2008-06-19T11:09:01-07:00
by Da_Vinci
Thanks a lot for your replies! :o

Unfortunately all three versions return a black image.

Here is the code I used (matches the last version by fmw42):

Code: Select all

convert \( assets/stamp.png -write mpr:image \) assets/canvas.png \( -clone 1 mpr:image -compose screen -geometry +118+89 -composite \) -delete 1 \( -clone 1 mpr:image -compose screen -geometry +112+106 -composite \) -delete 1 -delete 0 assets/heatmap/canvas.png 

Re: Any chance to improve the performace of this "-compose" cmd?

Posted: 2008-06-19T11:20:05-07:00
by fmw42
All I can say is try my example. It works for me. The only other issue might be your use of paths to your files. Either move them all the same directory or try absolute paths from root.

See also my additional method using memory mapped disk files. More complicated, but you can loop.

But first get your path issue worked out.

Also what version of IM are you using? Is it old?

Re: Any chance to improve the performace of this "-compose" cmd?

Posted: 2008-06-19T11:57:56-07:00
by Da_Vinci
Da_Vinci wrote:Thanks a lot for your replies! :o

Unfortunately all three versions return a black image.

Here is the code I used (matches the last version by fmw42):

Code: Select all

convert \( assets/stamp.png -write mpr:image \) assets/canvas.png \( -clone 1 mpr:image -compose screen -geometry +118+89 -composite \) -delete 1 \( -clone 1 mpr:image -compose screen -geometry +112+106 -composite \) -delete 1 -delete 0 assets/heatmap/canvas.png 
Okay, I got it working! Some stupid typo :? broke it :(
Now let's see which method is the fastest :D

Re: Any chance to improve the performace of this "-compose" cmd?

Posted: 2008-06-19T13:23:00-07:00
by fmw42
please report back as I for one am interested in your results to see if they agree with what I had found in an old timing example between using clone and mpr. I did not time my last method using mpc.

Re: Any chance to improve the performace of this "-compose" cmd?

Posted: 2008-06-19T14:18:55-07:00
by Da_Vinci
fmw42 wrote:please report back as I for one am interested in your results to see if they agree with what I had found in an old timing example between using clone and mpr. I did not time my last method using mpc.
Clone did better for me. (8secs vs. 12secs for 333 stamps)

It's still pretty damn slow for what I'd need it. :? Using the unix shell mght not be suitable for my needs as the project is going to be an open source CodeIgniter framework. Thus compatibility is a must.
Every stamp represents a click on a heatmap like what you know from crazyegg.com.
Lousy 333 clicks per heatmap is unfortunately just unrealistic :(

Re: Any chance to improve the performace of this "-compose" cmd?

Posted: 2008-06-19T18:39:02-07:00
by anthony
Note that -clone is faster than reading the image multiple times as it reduces the IO, and the image data is not duplicated in memory until an image is modified (which it never is in this case), reducing the memory footprint.

But you may be able to use -layers for faster behaviour.

convert -background black canvas.png \
\( stamp.png -repage +118+89 \) \
\( +clone -repage +112+106 \) \
\( +clone -repage +112+106 \) \
\( +clone -repage +123+456 \) \
-compose screen -layers flatten canvas_new.png

this generates a lot of 'layers' then composes each layer with 'screen' onto the background, in a fast loop. A 'black' background ensures the first 'layer' is kept as is.


How does this perform compared to -clone -geometry -composite

Can you give a final summery of the various techniques in terms of speed for multiple images (say 100 composites). I will place this summery online in IM examples, "Layering Images".

Re: Any chance to improve the performace of this "-compose" cmd?

Posted: 2008-06-19T18:47:36-07:00
by fmw42
strangely, a while back I did some quick timings and also found that the clone method was faster than the mpr method

Anthony - that is a neat approach!!!

Re: Any chance to improve the performace of this "-compose" cmd?

Posted: 2008-06-19T21:39:35-07:00
by anthony
Thanks. That is the power of layers.

However using virtual-canvas offsets mean you can not position things with gravity effects. Gravity has no meaning to the virtual canvas and layering.

On the other hand, which I created the multi-image sequence composition (-layers composite), I made sure you could use gravity to offset the whole overlay (source) sequence, while retaing virtual canvas offsets within the sequence. It was a real pain, but it means you can merge two animations with internal offsets, together with a general gravity effected composition -geometry offset.

Yes. geometry is a completely seperate 'offset' to that of the virtual canvas. -composite only uses gemetry, while layer merging (flatten,mosaic,merge) uses canvas offsets.

Only the -layer composite method allows the use of BOTH simultaneously!

Re: Any chance to improve the performace of this "-compose" cmd?

Posted: 2008-06-20T07:03:29-07:00
by Da_Vinci
anthony wrote:Note that -clone is faster than reading the image multiple times as it reduces the IO, and the image data is not duplicated in memory until an image is modified (which it never is in this case), reducing the memory footprint.

But you may be able to use -layers for faster behaviour.

convert -background black canvas.png \
\( stamp.png -repage +118+89 \) \
\( +clone -repage +112+106 \) \
\( +clone -repage +112+106 \) \
\( +clone -repage +123+456 \) \
-compose screen -layers flatten canvas_new.png

this generates a lot of 'layers' then composes each layer with 'screen' onto the background, in a fast loop. A 'black' background ensures the first 'layer' is kept as is.


How does this perform compared to -clone -geometry -composite

Can you give a final summery of the various techniques in terms of speed for multiple images (say 100 composites). I will place this summery online in IM examples, "Layering Images".
Okay, I'll do that.

But unfortunately the latest "+clone -repage" code returns nothing but a black canvas.

Also you're applying a black background. This might be a problem for me. :(
I need to have the option "screen" the stamp with different strengths onto the canvas.

This is what I do right now:
First create the canvas:

Code: Select all

convert -size 454x461 xc:black assets/heatmap/heat_maps/057bb100.png
Then I have the cone ("stamp") image which is located at "assets/heatmap/cone.png".
I apply black with a given strength to reduce the screen effect and write it into a temporary file "assets/heatmap/cone_adjusted.png":

Code: Select all

convert assets/heatmap/cone.png -resize 30x30 -fill black -colorize 40% assets/heatmap/cone_adjusted.png
Then I have an array of coordinates for each strength, which then get stamped:

Code: Select all

convert -background black assets/heatmap/heat_maps/057bb100.png \
\( assets/heatmap/cone_adjusted.png -repage +181+180 \) \
\( +clone -repage +370+161 \) \
-compose screen -layers flatten assets/heatmap/heat_maps/057bb100.png
After running this last command I proceed with the array for another strength, create a new temporary cone for it and loop the "screening" for its coords.

# # # # #

In short what I need could be expressed as such:
I need to create a black canvas with dimensions 475x873 and get the cone image stamped on it:
- at (23x67, 75x789, 76x297, 256x91) with an opacity (or what I called "strength") of 40%
- at (91x37, 57x92, 10x24, 2x35) with an opacity (or what I called "strength") of 20%
- and at (2x74, 87x36, 37x16, 46x24) with an opacity (or what I called "strength") of 90%

This is the whole idea. I assume there's even a fast way to combine all this into one single command with one. I'm just too new to IM to find it on my own and thus depend on your help :? :(
So I'm glad I can at least do something in return for all great and provide you with some speed comparison statistics. :)