diff --git a/Changes b/Changes index 219f088d9..b5badc952 100644 --- a/Changes +++ b/Changes @@ -8,6 +8,7 @@ - fix Transform::Proj4 tests and build (#498 #499) - thanks @shawnlaffan - t_linear stores iunit ounit itype otype - IO::FITS no longer writes COMMENT header with "HASH(0x...)" +- add IO::GD::write_gif_anim for better GIF animation in Demos/harness 2.093 2024-09-29 - PDL.set_datatype now doesn't physicalise input, PDL.convert_type does diff --git a/Demos/harness b/Demos/harness index f72239f10..fb48d27d1 100644 --- a/Demos/harness +++ b/Demos/harness @@ -1,5 +1,6 @@ use strict; use warnings; use PDL; +use PDL::IO::GD; # for write_gif_anim, bigger file but nicer looking use PDL::Demos; use File::Path qw(mkpath); use File::Spec::Functions qw(catdir catfile splitpath updir); @@ -109,7 +110,7 @@ for (@infos) { if (@this_imgs > 1) { my $multiframe = cat(map rpic($_), @this_imgs); my $vidfile = catfile($outdir, "vid-".++$vidcounter.".gif"); - $multiframe->wmpeg($vidfile); + $multiframe->write_gif_anim($vidfile, 0, 10); unlink @this_imgs; delete @seen_img{@this_imgs}; # may reappear with new content @this_imgs = $vidfile; diff --git a/IO/GD/GD.pd b/IO/GD/GD.pd index 90078fc6c..481f335eb 100644 --- a/IO/GD/GD.pd +++ b/IO/GD/GD.pd @@ -396,6 +396,53 @@ loop(i) %{ EOC ); +pp_def( 'write_gif_anim', + Pars => 'img(c=3,x,y,n)', + GenericTypes => ['B'], + OtherPars => 'char* filename; int Loops; int Delay', + OtherParsDefaults => {Loops=>0, Delay=>4}, + NoPthread => 1, + Doc => <<'EOF', +=for ref + +Writes an image cube to a file as an animated GIF. + +RGB dimension is first. y=0 is at bottom. 0 loops = infinite (default). +Delay in 100ths of a second, default 4. +EOF + Code => <<'EOF', +FILE *fh = fopen($COMP(filename), "wb"); +if (!fh) $CROAK("Error opening %s\n", $COMP(filename)); +gdImagePtr im = gdImageCreateTrueColor($SIZE(x), $SIZE(y)), im_prev = NULL; +if (!im) $CROAK("Error creating gdImage\n"); +loop (n=0:1) %{ + loop (y,x) %{ + gdImageSetPixel(im, x, $SIZE(y)-1-y, + gdImageColorResolve(im, $img(c=>0), $img(c=>1), $img(c=>2)) + ); + %} +%} +gdImageGifAnimBegin(im, fh, 0, $COMP(Loops)); +gdImageGifAnimAdd(im, fh, 1, 0, 0, $COMP(Delay), gdDisposalNone, im_prev); +im_prev = im; +loop (n=1) %{ + im = gdImageCreateTrueColor($SIZE(x), $SIZE(y)); + if (!im) $CROAK("Error creating gdImage\n"); + loop (y,x) %{ + gdImageSetPixel(im, x, $SIZE(y)-1-y, + gdImageColorResolve(im, $img(c=>0), $img(c=>1), $img(c=>2)) + ); + %} + gdImageGifAnimAdd(im, fh, 1, 0, 0, $COMP(Delay), gdDisposalNone, im_prev); + gdImageDestroy(im_prev); + im_prev = im; +%} +gdImageDestroy(im_prev); +gdImageGifAnimEnd(fh); +fclose(fh); +EOF +); + pp_addxs( <<'ENDXS' ); void _gdImageDestroy( im )