diff options
| author | Chong Yidong | 2011-08-21 22:34:23 -0400 |
|---|---|---|
| committer | Chong Yidong | 2011-08-21 22:34:23 -0400 |
| commit | e013fb340c50dd99676ccc4552fd6aae2e319aa8 (patch) | |
| tree | dc391443df091476c5607e196b0a1658175a3525 /src/image.c | |
| parent | 138c0212ac4bc4708210ba4b3e0a4fad00a4dc5f (diff) | |
| download | emacs-e013fb340c50dd99676ccc4552fd6aae2e319aa8.tar.gz emacs-e013fb340c50dd99676ccc4552fd6aae2e319aa8.zip | |
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
Diffstat (limited to 'src/image.c')
| -rw-r--r-- | src/image.c | 54 |
1 files changed, 29 insertions, 25 deletions
diff --git a/src/image.c b/src/image.c index d1091aec6f3..65be22b087a 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -7139,7 +7139,6 @@ gif_load (struct frame *f, struct image *img) | |||
| 7139 | ColorMapObject *gif_color_map; | 7139 | ColorMapObject *gif_color_map; |
| 7140 | unsigned long pixel_colors[256]; | 7140 | unsigned long pixel_colors[256]; |
| 7141 | GifFileType *gif; | 7141 | GifFileType *gif; |
| 7142 | int image_height, image_width; | ||
| 7143 | gif_memory_source memsrc; | 7142 | gif_memory_source memsrc; |
| 7144 | Lisp_Object specified_bg = image_spec_value (img->spec, QCbackground, NULL); | 7143 | Lisp_Object specified_bg = image_spec_value (img->spec, QCbackground, NULL); |
| 7145 | Lisp_Object specified_file = image_spec_value (img->spec, QCfile, NULL); | 7144 | Lisp_Object specified_file = image_spec_value (img->spec, QCfile, NULL); |
| @@ -7216,19 +7215,13 @@ gif_load (struct frame *f, struct image *img) | |||
| 7216 | } | 7215 | } |
| 7217 | } | 7216 | } |
| 7218 | 7217 | ||
| 7219 | img->corners[TOP_CORNER] = gif->SavedImages[idx].ImageDesc.Top; | 7218 | width = img->width = gif->SWidth; |
| 7220 | img->corners[LEFT_CORNER] = gif->SavedImages[idx].ImageDesc.Left; | 7219 | height = img->height = gif->SHeight; |
| 7221 | image_height = gif->SavedImages[idx].ImageDesc.Height; | ||
| 7222 | img->corners[BOT_CORNER] = img->corners[TOP_CORNER] + image_height; | ||
| 7223 | image_width = gif->SavedImages[idx].ImageDesc.Width; | ||
| 7224 | img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + image_width; | ||
| 7225 | 7220 | ||
| 7226 | width = img->width = max (gif->SWidth, | 7221 | img->corners[TOP_CORNER] = gif->SavedImages[0].ImageDesc.Top; |
| 7227 | max (gif->Image.Left + gif->Image.Width, | 7222 | img->corners[LEFT_CORNER] = gif->SavedImages[0].ImageDesc.Left; |
| 7228 | img->corners[RIGHT_CORNER])); | 7223 | img->corners[BOT_CORNER] = img->corners[TOP_CORNER] + height; |
| 7229 | height = img->height = max (gif->SHeight, | 7224 | img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + width; |
| 7230 | max (gif->Image.Top + gif->Image.Height, | ||
| 7231 | img->corners[BOT_CORNER])); | ||
| 7232 | 7225 | ||
| 7233 | if (!check_image_size (f, width, height)) | 7226 | if (!check_image_size (f, width, height)) |
| 7234 | { | 7227 | { |
| @@ -7283,6 +7276,10 @@ gif_load (struct frame *f, struct image *img) | |||
| 7283 | unsigned char *raster = (unsigned char *) subimage->RasterBits; | 7276 | unsigned char *raster = (unsigned char *) subimage->RasterBits; |
| 7284 | int transparency_color_index = -1; | 7277 | int transparency_color_index = -1; |
| 7285 | int disposal = 0; | 7278 | int disposal = 0; |
| 7279 | int subimg_width = subimage->ImageDesc.Width; | ||
| 7280 | int subimg_height = subimage->ImageDesc.Height; | ||
| 7281 | int subimg_top = subimage->ImageDesc.Top; | ||
| 7282 | int subimg_left = subimage->ImageDesc.Left; | ||
| 7286 | 7283 | ||
| 7287 | /* Find the Graphic Control Extension block for this sub-image. | 7284 | /* Find the Graphic Control Extension block for this sub-image. |
| 7288 | Extract the disposal method and transparency color. */ | 7285 | Extract the disposal method and transparency color. */ |
| @@ -7306,6 +7303,13 @@ gif_load (struct frame *f, struct image *img) | |||
| 7306 | if (j == 0) | 7303 | if (j == 0) |
| 7307 | disposal = 2; | 7304 | disposal = 2; |
| 7308 | 7305 | ||
| 7306 | /* For disposal == 0, the spec says "No disposal specified. The | ||
| 7307 | decoder is not required to take any action." In practice, it | ||
| 7308 | seems we need to treat this like "keep in place", see e.g. | ||
| 7309 | http://upload.wikimedia.org/wikipedia/commons/3/37/Clock.gif */ | ||
| 7310 | if (disposal == 0) | ||
| 7311 | disposal = 1; | ||
| 7312 | |||
| 7309 | /* Allocate subimage colors. */ | 7313 | /* Allocate subimage colors. */ |
| 7310 | memset (pixel_colors, 0, sizeof pixel_colors); | 7314 | memset (pixel_colors, 0, sizeof pixel_colors); |
| 7311 | gif_color_map = subimage->ImageDesc.ColorMap; | 7315 | gif_color_map = subimage->ImageDesc.ColorMap; |
| @@ -7333,34 +7337,34 @@ gif_load (struct frame *f, struct image *img) | |||
| 7333 | int row, pass; | 7337 | int row, pass; |
| 7334 | 7338 | ||
| 7335 | for (y = 0, row = interlace_start[0], pass = 0; | 7339 | for (y = 0, row = interlace_start[0], pass = 0; |
| 7336 | y < image_height; | 7340 | y < subimg_height; |
| 7337 | y++, row += interlace_increment[pass]) | 7341 | y++, row += interlace_increment[pass]) |
| 7338 | { | 7342 | { |
| 7339 | if (row >= image_height) | 7343 | if (row >= subimg_height) |
| 7340 | { | 7344 | { |
| 7341 | row = interlace_start[++pass]; | 7345 | row = interlace_start[++pass]; |
| 7342 | while (row >= image_height) | 7346 | while (row >= subimg_height) |
| 7343 | row = interlace_start[++pass]; | 7347 | row = interlace_start[++pass]; |
| 7344 | } | 7348 | } |
| 7345 | 7349 | ||
| 7346 | for (x = 0; x < image_width; x++) | 7350 | for (x = 0; x < subimg_width; x++) |
| 7347 | { | 7351 | { |
| 7348 | int c = raster[y * image_width + x]; | 7352 | int c = raster[y * subimg_width + x]; |
| 7349 | if (transparency_color_index != c || disposal != 1) | 7353 | if (transparency_color_index != c || disposal != 1) |
| 7350 | XPutPixel (ximg, x + img->corners[LEFT_CORNER], | 7354 | XPutPixel (ximg, x + subimg_left, row + subimg_top, |
| 7351 | row + img->corners[TOP_CORNER], pixel_colors[c]); | 7355 | pixel_colors[c]); |
| 7352 | } | 7356 | } |
| 7353 | } | 7357 | } |
| 7354 | } | 7358 | } |
| 7355 | else | 7359 | else |
| 7356 | { | 7360 | { |
| 7357 | for (y = 0; y < image_height; ++y) | 7361 | for (y = 0; y < subimg_height; ++y) |
| 7358 | for (x = 0; x < image_width; ++x) | 7362 | for (x = 0; x < subimg_width; ++x) |
| 7359 | { | 7363 | { |
| 7360 | int c = raster[y * image_width + x]; | 7364 | int c = raster[y * subimg_width + x]; |
| 7361 | if (transparency_color_index != c || disposal != 1) | 7365 | if (transparency_color_index != c || disposal != 1) |
| 7362 | XPutPixel (ximg, x + img->corners[LEFT_CORNER], | 7366 | XPutPixel (ximg, x + subimg_left, y + subimg_top, |
| 7363 | y + img->corners[TOP_CORNER], pixel_colors[c]); | 7367 | pixel_colors[c]); |
| 7364 | } | 7368 | } |
| 7365 | } | 7369 | } |
| 7366 | } | 7370 | } |