Creating a Cleared Frame GIF Animation in the MagickWand API

The MagickWand interface is a new high-level C API interface to ImageMagick core methods. We discourage the use of the core methods and encourage the use of this API instead. Post MagickWand questions, bug reports, and suggestions to this forum.
garyb
Posts: 11
Joined: 2012-03-07T14:00:46-07:00
Authentication code: 8675308

Creating a Cleared Frame GIF Animation in the MagickWand API

Post by garyb »

Hi, I'm trying to use the MagickWand API in Objective-C/iOS to make a "Cleared Frame GIF Animation" in "ImageMagick 6.6.9-7 2011-05-02 Q8" but I have no idea where to begin... as seen at:

http://www.imagemagick.org/Usage/anim_basics/#cleared (With no pause seen in the background.)

I think I would need to use addImage to compile a bunch of transparent image frames (eg: PNGs) into a GIF and then somehow convert this gif to use my background image?

My main goal is to avoid animating the dither in the background between each frame. It looks like this method will give me just that, but again, not sure how to accomplish this with the MagickWand API. It kind of sucks that all the docs/examples are all in command-line mode. :(

Code: Select all

convert bunny_grass.gif \( bunny_anim.gif -repage 0x0+5+15\! \) \
            -coalesce -delete 0 -deconstruct -loop 0  bunny_bgnd.gif
So I guess to sum up, I would somehow need to re-create this using the MagickWand API. If anyone has any pointers or example code, that would be greatly appreciated!

Thanks,
Gary
el_supremo
Posts: 1015
Joined: 2005-03-21T21:16:57-07:00

Re: Creating a Cleared Frame GIF Animation in the MagickWand

Post by el_supremo »

I've worked out how to do the first stage of Anthony's example.
Perhaps this will give you a head start on the rest of it.
I'll post again if/when I figure out the -coalesce and -deconstruct.

Pete

Code: Select all

// This implements the command:
// convert bunny_grass.gif bunny_anim.gif -loop 0  bunny_on_grass.gif
// from Anthony's examples at: http://www.imagemagick.org/Usage/anim_basics/#cleared

#include <windows.h>
#include <wand/magick_wand.h>

void test_wand(void)
{
	MagickWand *mw = NULL;

	MagickWandGenesis();

	/* Create a wand */
	mw = NewMagickWand();

	/* Read the input image */
	if(MagickReadImage(mw,"bunny_grass.gif"));

	if(MagickReadImage(mw,"bunny_anim.gif"));

	// do "-loop 0"
	MagickSetOption(mw,"loop","0");

	/* write the images into one file */
	if(MagickWriteImages(mw,"bunny_on_grass.gif",MagickTrue));

	/* Tidy up */
	if(mw) mw = DestroyMagickWand(mw);

	MagickWandTerminus();
}
Sorry, my ISP shutdown all personal webspace so my MagickWand Examples in C is offline.
See my message in this topic for a link to a zip of all the files.
el_supremo
Posts: 1015
Joined: 2005-03-21T21:16:57-07:00

Re: Creating a Cleared Frame GIF Animation in the MagickWand

Post by el_supremo »

It wasn't quite as tricky as I thought. Here's the example with coalesce and deconstruct.
I had to use a MagickCore to get at the DeleteImages function.

@ Magick: Can a MagickWand version of DeleteImages be included in a new release - or have I missed (or forgotten) how to do this in MagickWand?

Pete

Code: Select all

// This implements the command:
// convert bunny_grass.gif ( bunny_anim.gif -repage 0x0+5+15! ) \
//            -coalesce -delete 0 -deconstruct -loop 0  bunny_bgnd.gif
// from Anthony's examples at: http://www.imagemagick.org/Usage/anim_basics/#cleared

#include <windows.h>
#include <wand/magick_wand.h>
// Need MagickCore for DeleteImages
#include <magick/MagickCore.h>
// and this is needed for the address of the image list (&aw->images)
#include <wand/magick-wand-private.h>
void test_wand(void)
{
	MagickWand *mw = NULL;
	MagickWand *aw = NULL;
	ExceptionInfo *exception;

	MagickWandGenesis();

	/* Create a wand */
	mw = NewMagickWand();

	/* Read the input image */
	if(MagickReadImage(mw,"bunny_grass.gif"));

//( bunny_anim.gif -repage 0x0+5+15\! )
	// We need a separate wand to do this bit in parentheses
	aw = NewMagickWand();
	if(MagickReadImage(aw,"bunny_anim.gif"));
	MagickResetImagePage(aw,"0x0+5+15!");

	// Now we have to add the images in the aw wand on to the end
	// of the mw wand.
	MagickAddImage(mw,aw);
	// We can now destroy the aw wand so that it can be used
	// for the next operation
	if(aw) aw = DestroyMagickWand(aw);

// -coalesce
	aw = MagickCoalesceImages(mw);
// delete 0
	DeleteImages(&aw->images,"0",exception);

	// Now free up the mw wand for the next step
	if(mw) mw = DestroyMagickWand(mw);

// -deconstruct
	mw = MagickDeconstructImages(aw);

// -loop 0
	MagickSetOption(mw,"loop","0");

	/* write the images into one file */
	if(MagickWriteImages(mw,"bunny_on_grass.gif",MagickTrue));

	/* Tidy up */
	if(mw) mw = DestroyMagickWand(mw);
	if(aw) aw = DestroyMagickWand(aw);
	MagickWandTerminus();
}
Sorry, my ISP shutdown all personal webspace so my MagickWand Examples in C is offline.
See my message in this topic for a link to a zip of all the files.
garyb
Posts: 11
Joined: 2012-03-07T14:00:46-07:00
Authentication code: 8675308

Re: Creating a Cleared Frame GIF Animation in the MagickWand

Post by garyb »

Thanks for the help!

I'll give that a shot. It couldn't actually find <wand/magick-wand-private.h> though. :( So in turn, DeleteImages(&aw->images, ...) isn't working unfortunately.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Creating a Cleared Frame GIF Animation in the MagickWand

Post by anthony »

MagickDeconstructImage() is actually just a alias for the Layers method "CompareAny"
however for overlay animations, you can use "CompareOverlay" instead which makes more sense.

"Deconstruct" as an operation should be depreciated.

Is their some reason you want an actual 'overlay' animation? (no transparency in any GIF frame?)

Note that if you do not mind transparency being used in the overlay images, For example something like the bunny animation produces in Transparency Optimization
http://www.imagemagick.org/Usage/anim_opt/#opt_trans
then the layers Optimize method can be used, as a general purpose optimizer. Their is just no guarantee that you will get a 'Overlay Animation'.

You may actually get a 'mixed disposal animation' as IM GIF optimization function thinks the result will be smaller (less pixels changed between each frame update). Note that that does not mean it is less pixels overall, or in fact a smaller file size, as that requires recursive optimization that could take a VERY long time!
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Creating a Cleared Frame GIF Animation in the MagickWand

Post by anthony »

garyb wrote:Thanks for the help!

I'll give that a shot. It couldn't actually find <wand/magick-wand-private.h> though. :( So in turn, DeleteImages(&aw->images, ...) isn't working unfortunately.
It is missing as it is 'private'. that is because DeleteImages is not MagickWand, but a lower level MagickCore library function.

Typical way of deleting images, is to destroy the old wand and create a new wand. Or use ClearmagickWand(), whcih is the same thing (I verified it in the code).

Of course any operational settings would also be lost. :-(



NOTE do not extract images and use MagickDestroyImage() as it is also incorrect wand usage, and may infact produce a segmentation fault. It should not be a public function!

That wand function should really take a MagickWand argument and destroy the current image from the wand, allowing you to iterate over the images destroying them. Perhaps a MagickDestroyAllImages() function would also be useful addition.

This was something I only recently discovered as I develop Imv7 Shell API. That API is already much more closely liked to MagickWand API by using a expanded form of MagickWand - a "MagickCLI Wand" in fact :-) -- Interesting times ahead for MagickWand!
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
el_supremo
Posts: 1015
Joined: 2005-03-21T21:16:57-07:00

Re: Creating a Cleared Frame GIF Animation in the MagickWand

Post by el_supremo »

I should have mentioned that I am using Version 6.7.3-3 Q16 which is a bit behind the times.

@Anthony: The "MagickCLI Wand" sounds very interesting. Looking forward to seeing it.

Pete
Sorry, my ISP shutdown all personal webspace so my MagickWand Examples in C is offline.
See my message in this topic for a link to a zip of all the files.
garyb
Posts: 11
Joined: 2012-03-07T14:00:46-07:00
Authentication code: 8675308

Re: Creating a Cleared Frame GIF Animation in the MagickWand

Post by garyb »

anthony wrote: Is their some reason you want an actual 'overlay' animation? (no transparency in any GIF frame?)

Note that if you do not mind transparency being used in the overlay images, For example something like the bunny animation produces in Transparency Optimization
http://www.imagemagick.org/Usage/anim_opt/#opt_trans
then the layers Optimize method can be used, as a general purpose optimizer. Their is just no guarantee that you will get a 'Overlay Animation'.

You may actually get a 'mixed disposal animation' as IM GIF optimization function thinks the result will be smaller (less pixels changed between each frame update). Note that that does not mean it is less pixels overall, or in fact a smaller file size, as that requires recursive optimization that could take a VERY long time!
I know it's kind of a lofty goal, but if there's another method that gives me the effect of a static background underneath frames, no jitter/animated in the background's dither between frames, is fast-ish to run and gives a fairly small file size, I'd love to hear it!! :) I don't neccessarily need transparency in the final GIF since each frame will have the background under them. I just saw this:
This is good enough for most purposes. For example by using the 'Dst_Over' composition method you could also place an image 'under' the animation as a static background.
From: http://www.imagemagick.org/Usage/anim_m ... mpose_draw which sounds good to me! So is it easy to run this command:

Code: Select all

convert script_k.gif  -repage 100x100+20+20\!   -coalesce \
              -draw 'image DstOver 0,0 0,0 "granite:"' \
          -layers Optimize   script_k_granite.gif
in the MagickWand API?
Question: I noticed this operates on a previously created GIF - "script_k.gif" - is there any way to do it all in one MagickWand session? (eg: create the GIF and at the same time overlay the frames on a background)
Question: Will it also have the weird 0-delay extra frame that I have to remove?

I *also* experimented with using:

Code: Select all

MagickOrderedPosterizeImage(wand, "o8x8,13")
but I found that a) there was still some animated dither between frames in some areas, and b) I like the look of the "regular" dithered image instead of the posterized dither.

Thank you so much for the help.
el_supremo
Posts: 1015
Joined: 2005-03-21T21:16:57-07:00

Re: Creating a Cleared Frame GIF Animation in the MagickWand

Post by el_supremo »

Typical way of deleting images, is to destroy the old wand
In this case we don't want to destroy all the images in the wand - only remove the first one. I'll have a look at doing it by iterating over the images and copying all but the first into a new wand.

To fix up the use of Deconstruct
change this:

Code: Select all

  mw = MagickDeconstructImages(aw);
to this:

Code: Select all

	mw = MagickCompareImageLayers(aw,CompareAnyLayer);

Pete
Sorry, my ISP shutdown all personal webspace so my MagickWand Examples in C is offline.
See my message in this topic for a link to a zip of all the files.
el_supremo
Posts: 1015
Joined: 2005-03-21T21:16:57-07:00

Re: Creating a Cleared Frame GIF Animation in the MagickWand

Post by el_supremo »

I've reworked my previous code so that it does not use MagickCore and it uses CompareImageLayers instead of Deconstruct.
The latest iteration of the code is in my MagickWand examples at:
http://members.shaw.ca/el.supremo/MagickWand/bunny.htm

Pete
Sorry, my ISP shutdown all personal webspace so my MagickWand Examples in C is offline.
See my message in this topic for a link to a zip of all the files.
garyb
Posts: 11
Joined: 2012-03-07T14:00:46-07:00
Authentication code: 8675308

Re: Creating a Cleared Frame GIF Animation in the MagickWand

Post by garyb »

el_supremo wrote:I've reworked my previous code so that it does not use MagickCore and it uses CompareImageLayers instead of Deconstruct.
The latest iteration of the code is in my MagickWand examples at:
http://members.shaw.ca/el.supremo/MagickWand/bunny.htm

Pete
Thanks for posting that Pete! Is there any other official MagickWand way to delete a frame at a specific index, rather than loop through the entire image sequence and copy out every frame except 0? Seems kind of silly/overhead.

Edit: Also, apparently MagickCompareImageLayers only works with "Image *images" instead of a MagickWand?

Thanks,
Gary
el_supremo
Posts: 1015
Joined: 2005-03-21T21:16:57-07:00

Re: Creating a Cleared Frame GIF Animation in the MagickWand

Post by el_supremo »

Is there any other official MagickWand way to delete a frame at a specific index
Not that I know of.
rather than loop through the entire image sequence and copy out every frame except 0? Seems kind of silly/overhead
The underlying images are in a doubly-linked list so it would seem to be much easier for IM to delete the images.
apparently MagickCompareImageLayers only works with "Image *images" instead of a MagickWand?
No, the first argument to that function is a MagickWand and it returns a MagickWand.

Pete
Sorry, my ISP shutdown all personal webspace so my MagickWand Examples in C is offline.
See my message in this topic for a link to a zip of all the files.
garyb
Posts: 11
Joined: 2012-03-07T14:00:46-07:00
Authentication code: 8675308

Re: Creating a Cleared Frame GIF Animation in the MagickWand

Post by garyb »

el_supremo wrote:
Is there any other official MagickWand way to delete a frame at a specific index
Not that I know of.
I found RemoveZeroDelayLayers but it looks like that's a MagickCore function. Oh well, just curious.
el_supremo wrote:
rather than loop through the entire image sequence and copy out every frame except 0? Seems kind of silly/overhead
The underlying images are in a doubly-linked list so it would seem to be much easier for IM to delete the images.
That went over my head, but if you say so, then sounds good to me! :)
el_supremo wrote:
apparently MagickCompareImageLayers only works with "Image *images" instead of a MagickWand?
No, the first argument to that function is a MagickWand and it returns a MagickWand.
No idea why I thought that! I must have been trying a different similarly-named function. Oops.

Anyway, thanks a ton!!

PS:
If I could pick your brain once more, any idea why this isn't working? http://www.wizards-toolkit.org/discours ... =6&t=20482
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Creating a Cleared Frame GIF Animation in the MagickWand

Post by anthony »

garyb wrote:I know it's kind of a lofty goal, but if there's another method that gives me the effect of a static background underneath frames, no jitter/animated in the background's dither between frames, is fast-ish to run and gives a fairly small file size, I'd love to hear it!! :) I don't neccessarily need transparency in the final GIF since each frame will have the background under them.
Either pre-dither the background before overlaying the image, especially with a fixed palette. OR use ordered-dither for the dithering.

Note dithering for small numbers of colors (or fixed palette) really needs a overhaul in IM. For example ordered dither with a user supplied palette would be a great addition! Unfortunately I have no time for it, though I do have links for it.
Question: I noticed this operates on a previously created GIF - "script_k.gif" - is there any way to do it all in one MagickWand session? (eg: create the GIF and at the same time overlay the frames on a background)
Question: Will it also have the weird 0-delay extra frame that I have to remove?
If you overlay their should be no 0-delay frame. And their is no reason the background animation (or static image) has to be external. What is needed however is that rather than a "null:" seperator image (required for CLI whcih only has one active Image List (or wand), the MagickWand API should be merging two separate wands! I designed the Core API to allow this, but I don't think who ever added it to the API is taking advantage of that!
I *also* experimented with using:

Code: Select all

MagickOrderedPosterizeImage(wand, "o8x8,13")
but I found that a) there was still some animated dither between frames in some areas, and b) I like the look of the "regular" dithered image instead of the posterized dither.
The problem is that it is a fixed mathematical palette and not one designed for the images! As for the existing dither, that could only mean their is color differences between the frames that the ordered dither is enhancing! Remove that difference (from due to saving to intermediate image) and it should go away.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Creating a Cleared Frame GIF Animation in the MagickWand

Post by anthony »

el_supremo wrote:
Is there any other official MagickWand way to delete a frame at a specific index
Not that I know of.
Definatally need to get MagickDeleteImage() function to delete current image from MagickWand! As well as a MagickDeleteAllImages() function. Depreciate the useless to the API function MagickDeleteImages()

I will added these changes to at least IMv7 Wand API, but will look at back-porting them the current IMv6 too.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
Post Reply