Page 1 of 1

slow execution: stack of images with shadows

Posted: 2014-01-09T10:31:01-07:00
by ladiko
I want to create a stack or deck of six images with shadows (the shadow is shifted +10+10) under each image and a transparent background. each image is slightly shifted, so it looks like a stack of cards. right now i use a quite inefficient way by loading each image two times, once for the image itself and a second time for the shadow. Maybe someone knows a better way. the whole process takes around 8 seconds on a core i3 desktop pc, which i guess could be at least reduced to 4s.

So to create some sample images, i use the following command, which creates red.jpg, yellow.jpg, orange.jpg, green.jpg, brown.jpg and orange.jpg, each 2152x1416 pixels.

Code: Select all

for COLOUR in red blue yellow orange green brown ; do \
	convert -size 2152x1416 xc:${COLOUR} -fill ${COLOUR} -draw "rectangle 0,0 2152,1416" ${COLOUR}.jpg ; done
So here is what i do with these images right now:

Code: Select all

convert -size 772x407 xc:transparent  \
    \( red.jpg -geometry 400x264+372+37 -background black -shadow 60x5 \) -composite \
    red.jpg -geometry 400x264+362+27 -composite \
    \( blue.jpg -geometry 405x267+324+61 -background black -shadow 60x5 \) -composite \
    blue.jpg -geometry 405x267+314+51 -composite \
    \( yellow.jpg -geometry 397x262+286+96 -background black -shadow 60x5 \) -composite \
    yellow.jpg -geometry 397x262+276+86 -composite \
    \( brown.jpg -geometry 411x271+211+126 -background black -shadow 60x5 \) -composite \
    brown.jpg -geometry 411x271+221+136 -composite \
    \( green.jpg -geometry 440x290+140+101 -background black -shadow 60x5 \) -composite \
    green.jpg -geometry 440x290+130+91 -composite \
    \( orange.jpg -geometry 522x344+15+15 -background black -shadow 60x5 \) -composite \
    orange.jpg -geometry 522x344+5+5 -composite \
    composite_out.png
The result looks like that (click on the preview image):
Image

I tried something like the following, but didnt figure out how to create a shadow without loading the original image a second time, rather than drawing a black rectangle and create a shadow from it:

Code: Select all

convert -size 767x401 xc:skyblue \
	-draw "rectangle 324,61 400,264" -background black -shadow 60x4+4+4 \
	-draw "image over 314,51 400,264 red.jpg" -composite \
    composite_out.png

Re: slow execution: stack of images with shadows

Posted: 2014-01-09T11:09:30-07:00
by snibgo
I strongly suggest you don't use jpg for these intermediates saves. It's an awful format for solid colour.

If you use clone and swap, then you won't need to read each image twice.

Re: slow execution: stack of images with shadows

Posted: 2014-01-09T11:46:14-07:00
by ladiko
Hello snibgo,

thank you for your suggestions.

These are just sample images for demonstration purposes here. For my real aim, i'm using photos instead of solid colour images. I already played around with +clone and +swap like it's explained here and here, but it seems like i miss something, because it's not much faster and creates strange pictures:
Image

Code: Select all

convert -size 772x407 xc:transparent  \
    red.jpg -geometry 400x264+362+27 \( +clone -background black -shadow 60x5 \) +swap -composite \
    blue.jpg -geometry 405x267+314+51 \( +clone -background black -shadow 60x5 \) +swap -composite \
    yellow.jpg -geometry 397x262+276+86 \( +clone -background black -shadow 60x5 \) +swap -composite \
    brown.jpg -geometry 411x271+221+136 \( +clone -background black -shadow 60x5 \) +swap -composite \
    green.jpg -geometry 440x290+130+91 \( +clone -background black -shadow 60x5 \) +swap -composite \
    orange.jpg -geometry 522x344+5+5 \( +clone -background black -shadow 60x5 \) +swap -composite \
    composite_out.png
Seems like it only composits the shadows, but leaves out the images.

btw.:
execution time on Xubuntu 12.04.3 with 2GB RAM and a Intel Celeron 847E @ 1.10GHz:

Code: Select all

user@machine:~$ time for COLOUR in red blue yellow orange green brown ; do \
>    convert -size 2152x1416 xc:${COLOUR} -fill ${COLOUR} -draw "rectangle 0,0 2152,1416" ${COLOUR}.jpg ; done

real    0m5.019s
user    0m8.808s
sys     0m0.248s

user@machine:~$ time convert -size 772x407 xc:transparent  \
>     red.jpg -geometry 400x264+362+27 \( +clone -background black -shadow 60x5 \) +swap -composite \
>     blue.jpg -geometry 405x267+314+51 \( +clone -background black -shadow 60x5 \) +swap -composite \
>     yellow.jpg -geometry 397x262+276+86 \( +clone -background black -shadow 60x5 \) +swap -composite \
>     brown.jpg -geometry 411x271+221+136 \( +clone -background black -shadow 60x5 \) +swap -composite \
>     green.jpg -geometry 440x290+130+91 \( +clone -background black -shadow 60x5 \) +swap -composite \
>     orange.jpg -geometry 522x344+5+5 \( +clone -background black -shadow 60x5 \) +swap -composite \
>     composite_out.png

real    0m39.800s
user    1m18.032s
sys     0m0.472s

user@machine:~$ time convert -size 772x407 xc:transparent  \
>     red.jpg -geometry 400x264+362+27 \( +clone -background black -shadow 60x5 \) +swap -composite \
>     blue.jpg -geometry 405x267+314+51 \( +clone -background black -shadow 60x5 \) +swap -composite \
>     yellow.jpg -geometry 397x262+276+86 \( +clone -background black -shadow 60x5 \) +swap -composite \
>     brown.jpg -geometry 411x271+221+136 \( +clone -background black -shadow 60x5 \) +swap -composite \
>     green.jpg -geometry 440x290+130+91 \( +clone -background black -shadow 60x5 \) +swap -composite \
>     orange.jpg -geometry 522x344+5+5 \( +clone -background black -shadow 60x5 \) +swap -composite \
>     composite_out.png

real    0m39.812s
user    1m18.104s
sys     0m0.424s

Re: slow execution: stack of images with shadows

Posted: 2014-01-09T13:43:35-07:00
by snibgo
"-composite" uses 2 images, or 3 if 3 are on the stack. When 3 are on the stack, the third is used as a mask. Look at your first "-composite": you have 3 images (xc:transparent, red.jpg, and red.jpg cloned. You swap the last 2, so red.jpg is used as a mask.

You almost have it right. You can composite red.jpg with its shadow, then composite the result on xc:transparent. Then move on to blue: composite blue.jpg with its shadow, and composite the result to the image so far.

Re: slow execution: stack of images with shadows

Posted: 2014-01-10T05:38:01-07:00
by ladiko
Thanks for your hint. I tried several ways of rearranging the command order and structuring them with brackets, but it didnt work. I'm clueless, now.

Re: slow execution: stack of images with shadows

Posted: 2014-01-10T06:29:58-07:00
by snibgo
Here's one way. Windows script:

Code: Select all

convert -size 215x141 xc:red red.png
convert -size 215x141 xc:blue blue.png
convert -size 215x141 xc:yellow yellow.png

convert ^
  ( red.png ^
    ( -clone 0 -background black -shadow 60x5 ) ^
    +swap -composite +repage ^
  ) ^
  ( blue.png ^
    ( -clone 0 -background black -shadow 60x5 ) ^
    +swap -composite +repage -repage -15+10 ^
  ) ^
  ( yellow.png ^
    ( -clone 0 -background black -shadow 60x5 ) ^
    +swap -composite +repage -repage -40+25 ^
  ) ^
  -background none ^
  -layers merge ^
  +repage ^
  rs.png
When creating the cards, xc:{colour} is all I need. No need to also draw a rectangle.

At the end of the main convert, I will "merge" the cards together. This automatically make the canvas just large enough. I use a transparent ("none") background. You might prefer a colour. To create offsets with "-layers", we need "-repage". If I used "composite" I would need "-geometry".

Each card follows the same pattern: read the card, clone it to make the shadow, swap and composite so the shadow is under (not over) the card.

"+repage" removes the page data created by the shadow, and each "-repage" adds page data back in, giving offsets relative to the first card.

Each card plus its shadow is a unit, with an offset. So we have three of these. "-layers merge" creates an image from the three images. The final "+repage" removes offset data.

If you want the final output to be larger, you could use "-extent" near the end.

People who are accustomed to interactive graphics programs often start off with a blank canvas. With ImageMagick this is rarely required and usually adds complications.

Re: slow execution: stack of images with shadows

Posted: 2014-01-14T08:31:44-07:00
by ladiko
Hello snibgo,

i got the required result and it's 5 times faster than the command i began with:

Code: Select all

convert \
	\( red.jpg -resize 400x264 \( -clone 0 -background black -shadow 80x5 \) +swap -composite -repage +362+27 \) \
	\( blue.jpg -resize 405x267 \( -clone 0 -background black -shadow 80x5 \) +swap -composite -repage +314+51 \) \
	\( yellow.jpg -resize 397x262 \( -clone 0 -background black -shadow 80x5 \) +swap -composite -repage +276+86 \) \
	\( brown.jpg -resize 411x271 \( -clone 0 -background black -shadow 80x5 \) +swap -composite -repage +221+126 \) \
	\( green.jpg -resize 440x290 \( -clone 0 -background black -shadow 80x5 \) +swap -composite -repage +130+91 \) \
	\( orange.jpg -resize 522x344 \( -clone 0 -background black -shadow 80x5 \) +swap -composite \) \
	-background none -layers merge composite_out.png
Thank you very much for your help and explanations. Still imagemagick is overwhelming for me.