Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Creating an animated gif with GD

by punkish (Priest)
on Aug 21, 2010 at 22:23 UTC ( [id://856522]=perlquestion: print w/replies, xml ) Need Help??

punkish has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to create the simplest possible animated gif using GD, but I am failing. What am I doing wrong? Needless to say, making a static gif image works just fine. The animated gif just comes out black.

Update: I have successfully made an animated gif with Imager, but am still curious as to why GD doesn't work for me. On an additional note, there are several modules for working with images -- GD, Imager, PerlMagick, probably many more. Is there some comprehensive-ish comparison of the offerings out there?

use GD; my $img_width = 400; my $img_height = 300; my $cell_width = 100; my $cell_height = 100; my $num_of_years = 3; # Create a new, empty image my $img = GD::Image->new($img_width, $img_height); # Allocate some colors my $colors = colors($img); # Mark start of a new animation my $gifdata = $img->gifanimbegin; for (1 .. $num_of_years) { # Make a frame of right size my $frame = GD::Image->new($img->getBounds); image($frame, $img_width, $img_height, $cell_width, $cell_height, +$colors); # Add frame $gifdata .= $frame->gifanimadd; } # Finish the animated GIF $gifdata .= $img->gifanimend; open F, ">image.gif" or die $!; print F $img->gif(); close F; sub colors { my ($img) = @_; my @colors = (); for my $r (0 .. 7) { for my $g (0 .. 7) { for my $b (0 .. 7) { push @colors, $img->colorAllocate($r*32, $g*32, $b*32) +; } } } return \@colors; } sub image { my ($img, $img_width, $img_height, $cell_width, $cell_height, $col +ors) = @_; my $num_of_cells_in_x = ($img_width / $cell_width) - 1; my $num_of_cells_in_y = ($img_height / $cell_height) - 1; for my $y1 (0 .. $num_of_cells_in_y ) { my $ymin = $y1 * $cell_height; my $ymax = ($y1 * $cell_height) + $cell_height; for my $x1 (0 .. $num_of_cells_in_x ) { my $xmin = $x1 * $cell_width; my $xmax = ($x1 * $cell_width) + $cell_width; # Draw a filled rect of specified color my $color = $colors->[ int(rand( @$colors )) ]; $img->filledRectangle($xmin, $ymin, $xmax, $ymax, $color); } } return $img; }
--

when small people start casting long shadows, it is time to go to bed

Replies are listed 'Best First'.
Re: Creating an animated gif with GD
by BrowserUk (Patriarch) on Aug 22, 2010 at 02:39 UTC
    but am still curious as to why GD doesn't work for me.

    Because you're using it wrong :).

    First, you are accumulating the frames in  $gifdata .= $frame->gifanimadd;, but then you print just the header info from the image into the file: print F $img->gif();.

    You should be printing the accumulated headers and frame data to the file: print F $gifdata;

    That doesn't affect a complete fix though because you're also confusing what constitutes a frame and what a complete animation. That is, you appear to be drawing a complete set of moving rectangles into each frame, rather than one rectangle at a different position in each frame.

    You should also check that each frame, when viewed as a discrete image, actually displays what you think you are drawing in that frame..

    And finally, you need to ensure that all the colors you use in the frames, are added to the palette of the base image, before you capture the header with gifanimbegin()


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      First, you are accumulating the frames in $gifdata .= $frame->gifanimadd;, but then you print just the header info from the image into the file: print F $img->gif();. You should be printing the accumulated headers and frame data to the file: print F $gifdata;
      Silly me, of course, I was doing it wrong. It is all working now, many thanks. Oh, and GD is about an order of magnitude faster than Imager. This would make a significant difference when I work with real data... 100 years worth (iow, 100 frames) of a few hundred thousand to a couple of million cells.
      That doesn't affect a complete fix though because you're also confusing what constitutes a frame and what a complete animation. That is, you appear to be drawing a complete set of moving rectangles into each frame, rather than one rectangle at a different position in each frame.
      No, thankfully, I got that part right.

      Now I have to figure out whether an animated gif is appropriate for me (pretty universal readability... all browsers can), or if I should go the route of HTML5 video. What I would really like is a user-controllable scrub/scroll bar so the time-lapse can be changed to any time period. But, that is not a perl problem...

      Many thanks again.

      --

      when small people start casting long shadows, it is time to go to bed

        Is there any chance I could see the Imager version of the code?

        I'm curious about the performance difference.

Re: Creating an animated gif with GD
by zentara (Archbishop) on Aug 22, 2010 at 11:51 UTC
    there are several modules for working with images -- GD, Imager, PerlMagick, probably many more. Is there some comprehensive-ish comparison of the offerings out there?

    I usually use gifsicle for animated gifs. It works well. Then you can use any of GD, Imager or ImageMagick to make your frames, and feed them to gifsicle like

    system("gifsicle -lforever $my_stuffl*.gif > $my_stuff.anim.gif") ;
    for GD, try Text to animated pseudo-braille GIF and see Image::Magick GIF Animation Speed for ImageMagick usage.

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku
Re: Creating an animated gif with GD
by Khen1950fx (Canon) on Aug 22, 2010 at 07:23 UTC
    I tried a mix of GD and GD::Image::AnimatedGif. I used the sample from GD, but I kept it very simple. I just wanted the blue border of the red oval to expand and contract when I passed over it with my mouse. It's almost imperceptible, but it works.
    #!/usr/bin/perl use strict; use warnings; use GD; use GD::Image::AnimatedGif; my $im_width = 100; my $im_height = 100; my $im = new GD::Image($im_width, $im_height); my $white = $im->colorAllocate(255,255,255); my $black = $im->colorAllocate(0,0,255); my $red = $im->colorAllocate(255,0,0); my $blue = $im->colorAllocate(0,0,255); $im->rectangle(0,0,99,99,$black); $im->arc(50,50,95,75,0,360,$blue); $im->fill(50,50,$red); my $gifdata = $im->gifanimbegin; my $frame = GD::Image->new($im->getBounds); $gifdata = $frame->gifanimadd; my $loop = 0; my $speed = 82; $gifdata .= $im->gifanimend; print "Content-type: image/gif\n\n"; print $im->animated_gif($loop, $speed);

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://856522]
Approved by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others scrutinizing the Monastery: (2)
As of 2024-04-25 02:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found