Handling / creating a GIF animation with MagickWand
Posted: 2011-09-06T17:01:18-07:00
Well, actually it's not really like creating a GIF animation, but close...
I already have a GIF animation and most of the layers have transparency and so when displayed, each frame is composed with the previous layers, the first is a white background of the size of the overall image (I hope I am explaining this right ?).
In my code, I am just trying to reconstruct those layers to have the same GIF animation, but where all layers are completely defined (they have all the same size, no transparency...etc...).
Cutting the story short, here is my code :
///The problem I have at this point is that it seems that even though I am calling MagickNewImage at each loop, the result wand (reconstructed_wand) only has one image/layer in it.... ?///
(Edit) Actually, this is not correct, the MagickGetNumberImages reports the right number of images in the wand... (/edit)
Not sure I am calling the right API ? Also, if there is any comment on the rest, I am just starting with all this (parsing the string for the Identity does not seem the most efficient, but that's the best I have found...?)
Oh, and if it is important, here is the version I use :
Version: ImageMagick 6.6.2-6 2011-03-16 Q16 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2010 ImageMagick Studio LLC
Features: OpenMP
That's on Linux (Ubuntu 11.04).
Thanks
I already have a GIF animation and most of the layers have transparency and so when displayed, each frame is composed with the previous layers, the first is a white background of the size of the overall image (I hope I am explaining this right ?).
In my code, I am just trying to reconstruct those layers to have the same GIF animation, but where all layers are completely defined (they have all the same size, no transparency...etc...).
Cutting the story short, here is my code :
Code: Select all
void reconstruct(char *filename) {
MagickBooleanType status;
int num;
PixelIterator * iterator, * orig_iterator;
PixelWand ** pixels, ** orig_pixels;
PixelWand *bg_pxl_wnd;
size_t width;
size_t height;
int x,y,frame, tmp_frame;
int sx,sy, offset_x, offset_y;
char *identity;
char *pointer, *end_pointer, tmp[64];
unsigned int alpha;
PixelPacket color;
individual_layers = NewMagickWand();
status = MagickReadImage(individual_layers, filename);
if (status == MagickFalse) {
fprintf(stderr, "Could not open file %s\n", filename);
exit (-1);
}
num = MagickGetNumberImages(individual_layers);
num_frames = num;
width=MagickGetImageWidth(individual_layers);
height=MagickGetImageHeight(individual_layers);
bg_pxl_wnd = NewPixelWand();
PixelSetColor(bg_pxl_wnd, "white");
// reconstruct the different frames
reconstructed_images = NewMagickWand();
// for each frame of the final reconstructed image
for (frame = 0; frame < num; frame ++) {
fprintf(stderr, "reconstructing frame %d\n", frame);
MagickNewImage(reconstructed_images, width, height, bg_pxl_wnd);
MagickNextImage(reconstructed_images);
MagickResetIterator(individual_layers);
// go through all the previous frames
for (tmp_frame = 0; tmp_frame <= frame; tmp_frame ++) {
MagickNextImage(individual_layers);
// find the offset of the current layer
identity = MagickIdentifyImage(individual_layers);
// get the offset
pointer = strstr(identity, "Page geometry:");
end_pointer = strstr(pointer, "\n");
strncpy(tmp, pointer, end_pointer - pointer);
tmp[end_pointer-pointer]='\0';
sscanf(tmp, "Page geometry: %dx%d+%d+%d", &x,&y, &offset_x,&offset_y);
// get the size
pointer = strstr(identity, "Geometry:");
end_pointer = strstr(pointer, "\n");
strncpy(tmp, pointer, end_pointer - pointer);
tmp[end_pointer-pointer]='\0';
sscanf(tmp, "Geometry: %dx%d+%d+%d", &sx,&sy, &x,&y);
iterator = NewPixelRegionIterator(reconstructed_images, offset_x, offset_y, sx, sy);
orig_iterator = NewPixelIterator(individual_layers);
for (y=0; y<sy; y++) {
orig_pixels = PixelGetNextIteratorRow(orig_iterator, &sx);
pixels = PixelGetNextIteratorRow(iterator, &sx);
for (x=0; x<sx; x++) {
alpha = (unsigned int) (255*PixelGetAlpha(pixels[x]));
if (alpha == 0)
continue;
//fprintf(stderr, "Getting color of pixel %d,%d for reconstructing frame %d with frame %d, offset %d,%d, size %d,%d\n",
//x,y,frame, tmp_frame, offset_x, offset_y, sx, sy);
PixelGetQuantumColor(orig_pixels[x],&color);
PixelSetQuantumColor(pixels[x], &color);
}
}
PixelSyncIterator(iterator);
DestroyPixelIterator(iterator);
DestroyPixelIterator(orig_iterator);
}
}
//printf("Read %d layers in %s\n", MagickGetNumberImages(reconstructed_images), filename);
//MagickDisplayImages(reconstructed_images, "");
MagickWriteImage(reconstructed_images, "recon.gif");
}
(Edit) Actually, this is not correct, the MagickGetNumberImages reports the right number of images in the wand... (/edit)
Not sure I am calling the right API ? Also, if there is any comment on the rest, I am just starting with all this (parsing the string for the Identity does not seem the most efficient, but that's the best I have found...?)
Oh, and if it is important, here is the version I use :
Version: ImageMagick 6.6.2-6 2011-03-16 Q16 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2010 ImageMagick Studio LLC
Features: OpenMP
That's on Linux (Ubuntu 11.04).
Thanks