Page 1 of 1

how to avoid blinking in a gif with infinite loop

Posted: 2015-03-12T16:03:46-07:00
by konstantin00
Hi folks,

Just started out with ImageMagick. I'm trying to create a bobble head effect with the following command:

body.png is a headless body.
head.png is just the head for the body.

Code: Select all

convert -dispose none -delay 0 \
body.png \
-dispose previous -delay 0 \
-page +0+0 head.png \
-dispose previous -delay 5 \
-page +0+0 head.png \
-page +2+5 head.png \
-page +0+10 head.png \
-page +2+15 head.png \
-page +0+10 head.png \
-page +2+5 head.png \
-page +0+0 head.png \
-page +2+5 head.png \
-page +0+10 head.png \
-page +2+15 head.png \
-page +0+10 head.png \
-page +2+5 head.png \
-page +0+0 head.png \
-page +2+5 head.png \
-page +0+10 head.png \
-page +2+15 head.png \
-page +0+10 head.png \
-page +2+5 head.png \
-page +0+0 head.png \
-page +2+5 head.png \
-page +0+10 head.png \
-page +2+15 head.png \
-page +0+10 head.png \
-page +2+5 head.png \
-loop 0 output.gif
  1. When the gif first loads or when the gif is done with a loop iteration, it "blinks" with white space of where the head is supposed to be, so it's very jarring. Any thoughts on how to prevent this?
  2. Any ideas on how to add rotation to the head?
  3. Any thoughts on improving this code to be more efficient?
Thank you!

Re: how to avoid blinking in a gif with infinite loop

Posted: 2015-03-12T16:19:43-07:00
by snibgo
Your first frame contains just the body. Is this what you mean by the "white space where the head is supposed to be"? Then make the first frame both the body and the head, something like:

Code: Select all

( body.png head.png -composite )

Re: how to avoid blinking in a gif with infinite loop

Posted: 2015-03-13T08:09:23-07:00
by konstantin00
Ok but I need the head to disappear when the bobbling begins

Re: how to avoid blinking in a gif with infinite loop

Posted: 2015-03-13T08:23:09-07:00
by snibgo
There are many ways of doing this. See "animation" under http://www.imagemagick.org/Usage/

I always do animation by making every frame as I want it to look. So every frame would have one body, and one head in the required position. (I would use clone or MPR: so I don't need to read the files for every frame.) Than "-layers optimize" at the end works out the differences.

But I'm not an animation expert.

Re: how to avoid blinking in a gif with infinite loop

Posted: 2015-03-13T10:42:23-07:00
by konstantin00
Thank you for the ideas, but I'm a little confused.
I don't want the body to move at all.
The head needs to "bobble" up and down with a slight rotation back and forth.

How would I utilize +clone here? That moves both the body and the head down 200px and when i explode the GIF, it just shows all the frames being the same (shifted down 200px)

Code: Select all

convert body.png head.png -geometry +0+0 -composite \
\( +clone -page +0+50 \) \
\( +clone -page +0+100 \) \
\( +clone -page +0+150 \) \
\( +clone -page +0+200 \) \
-loop 0 output.gif

Re: how to avoid blinking in a gif with infinite loop

Posted: 2015-03-13T10:46:41-07:00
by snibgo
Please provide your body.png and head.png. You can put the somewhere like dropbox.com and paste the URLs here.

Re: how to avoid blinking in a gif with infinite loop

Posted: 2015-03-13T11:02:24-07:00
by konstantin00
body: http://104.130.236.196/body.png
head: http://104.130.236.196/head.png

The images are both 400x400 to make it easy to offset the head. The head has a transparent background.

Re: how to avoid blinking in a gif with infinite loop

Posted: 2015-03-13T11:05:14-07:00
by konstantin00
And using the code from the first comment

Code: Select all

convert -dispose none -delay 0 \
body.png \
-dispose previous -delay 0 \
-page +0+0 head.png \
-dispose previous -delay 5 \
-page +0+0 head.png \
-page +2+5 head.png \
-page +0+10 head.png \
-page +2+15 head.png \
-page +0+10 head.png \
-page +2+5 head.png \
-page +0+0 head.png \
-page +2+5 head.png \
-page +0+10 head.png \
-page +2+15 head.png \
-page +0+10 head.png \
-page +2+5 head.png \
-page +0+0 head.png \
-page +2+5 head.png \
-page +0+10 head.png \
-page +2+15 head.png \
-page +0+10 head.png \
-page +2+5 head.png \
-page +0+0 head.png \
-page +2+5 head.png \
-page +0+10 head.png \
-page +2+15 head.png \
-page +0+10 head.png \
-page +2+5 head.png \
-loop 0 output.gif
I get the following GIF: http://104.130.236.196/output.gif

Re: how to avoid blinking in a gif with infinite loop

Posted: 2015-03-13T12:02:58-07:00
by snibgo
This is how I would do it. I start by filling in the body transparency with white.

EDIT: This is Windows BAT syntax. Adjust for Unix bash.

Code: Select all

convert ^
  body.png -background White -flatten  ^
  head.png ^
  ( -clone 0-1 -composite ) ^
  ( -clone 0-1 -geometry +2+5 -composite ) ^
  ( -clone 0-1 -geometry +0+10 -composite ) ^
  ( -clone 0-1 -geometry +2+15 -composite ) ^
  ( -clone 0-1 -geometry +0+10 -composite ) ^
  ( -clone 0-1 -geometry +2+5 -composite ) ^
  -delete 0-1 ^
  -layers optimize ^
  -loop 0 ^
  bodyhead.gif
Image

We can rotate the head of each frame. I take the centre of the head to be at (185,130). I rotate by 5 degrees, then 10, etc.

Code: Select all

convert ^
  body.png -background White -flatten  ^
  head.png ^
  ( -clone 0-1 -composite ) ^
  ( -clone 0-1 ( -clone 1 -distort SRT 185,130,1,5 ) -swap 1,2 +delete -geometry +2+5 -composite ) ^
  ( -clone 0-1 ( -clone 1 -distort SRT 185,130,1,10 ) -swap 1,2 +delete -geometry +0+10 -composite ) ^
  ( -clone 0-1 ( -clone 1 -distort SRT 185,130,1,15 ) -swap 1,2 +delete -geometry +2+15 -composite ) ^
  ( -clone 0-1 ( -clone 1 -distort SRT 185,130,1,10 ) -swap 1,2 +delete -geometry +0+10 -composite ) ^
  ( -clone 0-1 ( -clone 1 -distort SRT 185,130,1,5 ) -swap 1,2 +delete -geometry +2+5 -composite ) ^
  -delete 0-1 ^
  -layers optimize ^
  -loop 0 ^
  bodyhead2.gif
Image

Re: how to avoid blinking in a gif with infinite loop

Posted: 2015-03-13T13:27:42-07:00
by konstantin00
I have a lot to learn with Imagemagick. Just so I understand your code, I'm going to try to explain it myself:

Code: Select all

convert ^
  body.png -background White -flatten  ^
  head.png ^
  ( -clone 0-1 -composite ) ^
  ( -clone 0-1 -geometry +2+5 -composite ) ^
  ( -clone 0-1 -geometry +0+10 -composite ) ^
  ( -clone 0-1 -geometry +2+15 -composite ) ^
  ( -clone 0-1 -geometry +0+10 -composite ) ^
  ( -clone 0-1 -geometry +2+5 -composite ) ^
  -delete 0-1 ^
  -layers optimize ^
  -loop 0 ^
  bodyhead.gif
  • Set the background color of body.png to white and flatten the image to remove the transparency.
  • Add the head as a new layer.
  • Clone the first two images (0-1) as a composite single image.
  • Clone the first two images (0-1) with offset +2+5 applied to the "source" (which is the head or the 1 in 0-1 part of clone command) and composite it as a single image.
  • Clone the first two images (0-1) with offset +0+10 applied to the "source" (which is the head or the 1 in 0-1 part of clone command) and composite it as a single image.
  • Clone the first two images (0-1) with offset +2+15 applied to the "source" (which is the head or the 1 in 0-1 part of clone command) and composite it as a single image.
  • Clone the first two images (0-1) with offset +0+10 applied to the "source" (which is the head or the 1 in 0-1 part of clone command) and composite it as a single image.
  • Clone the first two images (0-1) with offset +2+5 applied to the "source" (which is the head or the 1 in 0-1 part of clone command) and composite it as a single image.
  • Delete the first two images that were created in line #2-3, which is the headless body and then the body with the head.
  • Optimize the layers and loop indefinitely and save to bodyhead.gif

Re: how to avoid blinking in a gif with infinite loop

Posted: 2015-03-13T13:32:07-07:00
by konstantin00
Also I added

Code: Select all

-set delay 5
to speed up the "bobbling"

Re: how to avoid blinking in a gif with infinite loop

Posted: 2015-03-13T13:41:20-07:00
by konstantin00
And thank you snibgo for all your help!

Re: how to avoid blinking in a gif with infinite loop

Posted: 2015-03-13T14:33:18-07:00
by snibgo
konstantin00 wrote:Just so I understand your code, I'm going to try to explain it myself: ...
Yes, your explanation is correct.

My code to also rotate the head does this:

Code: Select all

  ( -clone 0-1 ( -clone 1 -distort SRT 185,130,1,10 ) -swap 1,2 +delete -geometry +0+10 -composite ) ^
-clone 0-1 start a new list, with a copy of body and head

( -clone 1 start a new nested list, with just the head

-distort SRT 185,130,1,10 apply ScaleRotateTranslate distortion to this head. See http://www.imagemagick.org/script/comma ... hp#distort I use the SRT version with 4 arguments: X,Y,Scale,Angle. X,Y gives the centre of the rotation. Scale is 1, which means don't change the scale. 10 is the angle in degrees for the rotation.

) end the sublist. Now the list contains 3 entries, numbered 0 to 2: body, head and rotated head.

-swap 1,2 +delete I swap the head and the rotated head, then delete the last entry, which is the unrotated head. Instead of "-swap 1,2 +delete", I could have just had "-delete 1". Why didn't I? Because I'm stupid.

-geometry +0+10 -composite ) As before, we composite the (rotated) head over the body.


I'm not an expert at animation. My method builds each frame separately, and keeps each one in memory, before "-layers optimize" finds the differences. So my method is simple, and I find it easy to understand. However, it can probably be done using the method in your first code, where you give each frame only as a difference. That method should be faster and use less memory.

Re: how to avoid blinking in a gif with infinite loop

Posted: 2015-03-13T22:28:30-07:00
by snibgo
The "empty-head" may the zero-delay problem, which Anthony discusses the on http://www.imagemagick.org/Usage/anim_basics/#zero

I tried making an animation with just delta frames:

Code: Select all

convert ^
  -dispose Previous -delay 5 ^
  head.png ^
  -duplicate 40 ^
  -distort SRT "185,130,1,0,185,%%[fx:x=t>20?40-t:t;130+x*x*270/400]" ^
  -dispose None -delay 0 ^
  ( body.png -background White -flatten ) ^
  -insert 0 ^
  -loop 0 ^
  bodyhead3.gif
Image

It didn't work properly, on Firefox. So I tried again, using the deltas to make each frame in full, then "-layers-optimize" to make the deltas again:

Code: Select all

convert ^
  -delay 5 ^
  head.png ^
  -duplicate 40 ^
  -distort SRT "185,130,1,0,185,%%[fx:x=t>20?40-t:t;130+x*x*270/400]" ^
  null: ^
  ( body.png -background White -flatten ) ^
  -compose DstOver -layers composite ^
  +write bh3.png ^
  -layers optimize ^
  -loop 0 ^
  bodyhead4.gif
Yes, that works fine.
Image