MagickCore / CloneImage & Animated GIFs
Posted: 2013-03-18T18:45:03-07:00
Hi,
I can't seem to be able to fully/deep clone an image that contains multiple images (eg animated GIFs). Looking at MagickCore/Image.c/CloneImage, I see that if the 'detach' parameter is true, it simply drops the additional images in the sequence ( clone_image->next=NewImageList(); ). If the 'detach' parameter is false, it provides a reference to the original image's 'next' property ( clone_image->next=image->next; ). If the original image is disposed at a later time, and then the clone image is used/modified, an access exception is generated (or something along those lines...)
Other code which relies on CloneImage, like Magick++ Image.modifyImage() method, results in dropping the sequential images. For example, the following Magick++ code would corrupt an animated gif (not tested):
Magick::Image img("animated.gif");
img.modifyImage();
img.write("animated.2.gif");
Here is my Magick++ workaround, hopefully something like this can be built into the core methods:
Finally, it would be nice if there was a const-friendly Image.write method; I have to jump through hoops to maintain const-correctness when I use IM -- done via unnecessary cloning
Thanks!
I can't seem to be able to fully/deep clone an image that contains multiple images (eg animated GIFs). Looking at MagickCore/Image.c/CloneImage, I see that if the 'detach' parameter is true, it simply drops the additional images in the sequence ( clone_image->next=NewImageList(); ). If the 'detach' parameter is false, it provides a reference to the original image's 'next' property ( clone_image->next=image->next; ). If the original image is disposed at a later time, and then the clone image is used/modified, an access exception is generated (or something along those lines...)
Other code which relies on CloneImage, like Magick++ Image.modifyImage() method, results in dropping the sequential images. For example, the following Magick++ code would corrupt an animated gif (not tested):
Magick::Image img("animated.gif");
img.modifyImage();
img.write("animated.2.gif");
Here is my Magick++ workaround, hopefully something like this can be built into the core methods:
Code: Select all
Magick::Image clone_magickimg( const Magick::Image& img )
{
MagickCore::ExceptionInfo ex;
GetExceptionInfo( &ex );
MagickCore::Image* cpy = CloneImage( img.constImage(), 0, 0, to_magickbool( true ), &ex );
if ( cpy == NULL )
{
assert( false );
DestroyExceptionInfo( &ex );
return Magick::Image();
}
// multi-page/animated gif support
MagickCore::Image *next = img.constImage()->next,
*parent = cpy;
while ( next != NULL )
{
parent->next = CloneImage( next, 0, 0, to_magickbool( true ), &ex );
if ( parent->next == NULL ) // error on clone
{
assert( false );
DestroyImage( cpy );
DestroyExceptionInfo( &ex );
return Magick::Image();
}
parent = parent->next;
next = next->next;
}; // while
DestroyExceptionInfo( &ex );
return std::move( Magick::Image( cpy ) );
} // clone_magickimg
Thanks!