1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-21 12:03:55 -08:00

Fix animated gif segfault and frame clearing bug.

* src/image.c (gif_load): Don't assume that each subimage has the same
dimensions as the base image.  Handle disposal method that is
"undefined" by the gif spec.

Fixes: debbugs:9335
This commit is contained in:
Chong Yidong 2011-08-21 22:34:23 -04:00
parent 138c0212ac
commit e013fb340c
2 changed files with 35 additions and 25 deletions

View file

@ -1,3 +1,9 @@
2011-08-22 Chong Yidong <cyd@stupidchicken.com>
* image.c (gif_load): Don't assume that each subimage has the same
dimensions as the base image. Handle disposal method that is
"undefined" by the gif spec (Bug#9335).
2011-08-20 Chong Yidong <cyd@stupidchicken.com>
* eval.c (Fsignal): Handle `debug' symbol in error handler (Bug#9329).

View file

@ -7139,7 +7139,6 @@ gif_load (struct frame *f, struct image *img)
ColorMapObject *gif_color_map;
unsigned long pixel_colors[256];
GifFileType *gif;
int image_height, image_width;
gif_memory_source memsrc;
Lisp_Object specified_bg = image_spec_value (img->spec, QCbackground, NULL);
Lisp_Object specified_file = image_spec_value (img->spec, QCfile, NULL);
@ -7216,19 +7215,13 @@ gif_load (struct frame *f, struct image *img)
}
}
img->corners[TOP_CORNER] = gif->SavedImages[idx].ImageDesc.Top;
img->corners[LEFT_CORNER] = gif->SavedImages[idx].ImageDesc.Left;
image_height = gif->SavedImages[idx].ImageDesc.Height;
img->corners[BOT_CORNER] = img->corners[TOP_CORNER] + image_height;
image_width = gif->SavedImages[idx].ImageDesc.Width;
img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + image_width;
width = img->width = gif->SWidth;
height = img->height = gif->SHeight;
width = img->width = max (gif->SWidth,
max (gif->Image.Left + gif->Image.Width,
img->corners[RIGHT_CORNER]));
height = img->height = max (gif->SHeight,
max (gif->Image.Top + gif->Image.Height,
img->corners[BOT_CORNER]));
img->corners[TOP_CORNER] = gif->SavedImages[0].ImageDesc.Top;
img->corners[LEFT_CORNER] = gif->SavedImages[0].ImageDesc.Left;
img->corners[BOT_CORNER] = img->corners[TOP_CORNER] + height;
img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + width;
if (!check_image_size (f, width, height))
{
@ -7283,6 +7276,10 @@ gif_load (struct frame *f, struct image *img)
unsigned char *raster = (unsigned char *) subimage->RasterBits;
int transparency_color_index = -1;
int disposal = 0;
int subimg_width = subimage->ImageDesc.Width;
int subimg_height = subimage->ImageDesc.Height;
int subimg_top = subimage->ImageDesc.Top;
int subimg_left = subimage->ImageDesc.Left;
/* Find the Graphic Control Extension block for this sub-image.
Extract the disposal method and transparency color. */
@ -7306,6 +7303,13 @@ gif_load (struct frame *f, struct image *img)
if (j == 0)
disposal = 2;
/* For disposal == 0, the spec says "No disposal specified. The
decoder is not required to take any action." In practice, it
seems we need to treat this like "keep in place", see e.g.
http://upload.wikimedia.org/wikipedia/commons/3/37/Clock.gif */
if (disposal == 0)
disposal = 1;
/* Allocate subimage colors. */
memset (pixel_colors, 0, sizeof pixel_colors);
gif_color_map = subimage->ImageDesc.ColorMap;
@ -7333,34 +7337,34 @@ gif_load (struct frame *f, struct image *img)
int row, pass;
for (y = 0, row = interlace_start[0], pass = 0;
y < image_height;
y < subimg_height;
y++, row += interlace_increment[pass])
{
if (row >= image_height)
if (row >= subimg_height)
{
row = interlace_start[++pass];
while (row >= image_height)
while (row >= subimg_height)
row = interlace_start[++pass];
}
for (x = 0; x < image_width; x++)
for (x = 0; x < subimg_width; x++)
{
int c = raster[y * image_width + x];
int c = raster[y * subimg_width + x];
if (transparency_color_index != c || disposal != 1)
XPutPixel (ximg, x + img->corners[LEFT_CORNER],
row + img->corners[TOP_CORNER], pixel_colors[c]);
XPutPixel (ximg, x + subimg_left, row + subimg_top,
pixel_colors[c]);
}
}
}
else
{
for (y = 0; y < image_height; ++y)
for (x = 0; x < image_width; ++x)
for (y = 0; y < subimg_height; ++y)
for (x = 0; x < subimg_width; ++x)
{
int c = raster[y * image_width + x];
int c = raster[y * subimg_width + x];
if (transparency_color_index != c || disposal != 1)
XPutPixel (ximg, x + img->corners[LEFT_CORNER],
y + img->corners[TOP_CORNER], pixel_colors[c]);
XPutPixel (ximg, x + subimg_left, y + subimg_top,
pixel_colors[c]);
}
}
}