Mercurial > emacs
changeset 27060:4960164efd1c
New image functions adapted to Emacs conventions.
(png_load, tiff_load, jpeg_load, gif_load): Always GCPRO local
variable `file'.
author | Gerd Moellmann <gerd@gnu.org> |
---|---|
date | Fri, 31 Dec 1999 16:46:22 +0000 |
parents | 6bb2a4a0413e |
children | 414002a326d9 |
files | src/xfns.c |
diffstat | 1 files changed, 325 insertions(+), 279 deletions(-) [+] |
line wrap: on
line diff
--- a/src/xfns.c Fri Dec 31 15:54:44 1999 +0000 +++ b/src/xfns.c Fri Dec 31 16:46:22 1999 +0000 @@ -7941,7 +7941,7 @@ static struct image_keyword png_format[PNG_LAST] = { {":type", IMAGE_SYMBOL_VALUE, 1}, - {":data", IMAGE_STRING_VALUE, 0}, + {":data", IMAGE_STRING_VALUE, 0}, {":file", IMAGE_STRING_VALUE, 0}, {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0}, @@ -7977,12 +7977,9 @@ return 0; /* Must specify either the :data or :file keyword. This should - ** probably be moved up into parse_image_spec, since it seems to be - ** a general requirement. - */ - if (!fmt[PNG_FILE].count && !fmt[PNG_DATA].count) - return 0; - return 1; + probably be moved up into parse_image_spec, since it seems to be + a general requirement. */ + return fmt[PNG_FILE].count || fmt[PNG_DATA].count; } @@ -8009,27 +8006,34 @@ image_error ("PNG warning: %s", build_string (msg), Qnil); } -/* Memory source for PNG decoding. Originally written for XEmacs by - William Perry <wmperry@gnu.org>, who has paperwork on file, and so - it is safe to use. */ +/* Memory source for PNG decoding. */ + struct png_memory_storage { - unsigned char *bytes; /* The data */ - size_t len; /* How big is it? */ - int index; /* Where are we? */ + unsigned char *bytes; /* The data */ + size_t len; /* How big is it? */ + int index; /* Where are we? */ }; + +/* Function set as reader function when reading PNG image from memory. + PNG_PTR is a pointer to the PNG control structure. Copy LENGTH + bytes from the input to DATA. */ + static void -png_read_from_memory(png_structp png_ptr, png_bytep data, - png_size_t length) -{ - struct png_memory_storage *tbr = - (struct png_memory_storage *) png_get_io_ptr (png_ptr); - - if (length > (tbr->len - tbr->index)) - png_error (png_ptr, (png_const_charp) "Read Error"); - memcpy (data,tbr->bytes + tbr->index,length); - tbr->index = tbr->index + length; +png_read_from_memory (png_ptr, data, length) + png_structp png_ptr; + png_bytep data; + png_size_t length; +{ + struct png_memory_storage *tbr + = (struct png_memory_storage *) png_get_io_ptr (png_ptr); + + if (length > tbr->len - tbr->index) + png_error (png_ptr, "Read error"); + + bcopy (tbr->bytes + tbr->index, data, length); + tbr->index = tbr->index + length; } /* Load PNG image IMG for use on frame F. Value is non-zero if @@ -8064,57 +8068,58 @@ /* Find out what file to load. */ specified_file = image_spec_value (img->spec, QCfile, NULL); specified_data = image_spec_value (img->spec, QCdata, NULL); + file = Qnil; + GCPRO1 (file); if (NILP (specified_data)) + { + file = x_find_image_file (specified_file); + if (!STRINGP (file)) { - file = x_find_image_file (specified_file); - GCPRO1 (file); - if (!STRINGP (file)) - { - image_error ("Cannot find image file %s", specified_file, Qnil); - UNGCPRO; - return 0; - } - - /* Open the image file. */ - fp = fopen (XSTRING (file)->data, "rb"); - if (!fp) - { - image_error ("Cannot open image file %s", file, Qnil); - UNGCPRO; - fclose (fp); - return 0; - } - - /* Check PNG signature. */ - if (fread (sig, 1, sizeof sig, fp) != sizeof sig - || !png_check_sig (sig, sizeof sig)) - { - image_error ("Not a PNG file: %s", file, Qnil); - UNGCPRO; - fclose (fp); - return 0; - } + image_error ("Cannot find image file %s", specified_file, Qnil); + UNGCPRO; + return 0; + } + + /* Open the image file. */ + fp = fopen (XSTRING (file)->data, "rb"); + if (!fp) + { + image_error ("Cannot open image file %s", file, Qnil); + UNGCPRO; + fclose (fp); + return 0; } - else + + /* Check PNG signature. */ + if (fread (sig, 1, sizeof sig, fp) != sizeof sig + || !png_check_sig (sig, sizeof sig)) { - /* Read from memory */ - tbr.bytes = XSTRING (specified_data)->data; - tbr.len = STRING_BYTES (XSTRING (specified_data)); - tbr.index = 0; - - /* Chekc PNG signature */ - if ((tbr.len < sizeof(sig)) || - !png_check_sig (tbr.bytes, sizeof(sig))) - { - image_error ("Not a PNG file: %s", file, Qnil); - UNGCPRO; - return 0; - } - - /* Need to skip past the signature */ - tbr.bytes += sizeof(sig); + image_error ("Not a PNG file: %s", file, Qnil); + UNGCPRO; + fclose (fp); + return 0; } + } + else + { + /* Read from memory. */ + tbr.bytes = XSTRING (specified_data)->data; + tbr.len = STRING_BYTES (XSTRING (specified_data)); + tbr.index = 0; + + /* Check PNG signature. */ + if (tbr.len < sizeof sig + || !png_check_sig (tbr.bytes, sizeof sig)) + { + image_error ("Not a PNG file: %s", file, Qnil); + UNGCPRO; + return 0; + } + + /* Need to skip past the signature. */ + tbr.bytes += sizeof (sig); + } /* Initialize read and info structs for PNG lib. */ png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, @@ -8160,9 +8165,9 @@ /* Read image info. */ if (!NILP (specified_data)) - png_set_read_fn (png_ptr,(void *) &tbr, png_read_from_memory); + png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory); else - png_init_io (png_ptr, fp); + png_init_io (png_ptr, fp); png_set_sig_bytes (png_ptr, sizeof sig); png_read_info (png_ptr, info_ptr); @@ -8272,8 +8277,11 @@ /* Read the entire image. */ png_read_image (png_ptr, rows); png_read_end (png_ptr, info_ptr); - if (fp) fclose (fp); - fp = NULL; + if (fp) + { + fclose (fp); + fp = NULL; + } BLOCK_INPUT; @@ -8421,7 +8429,7 @@ static struct image_keyword jpeg_format[JPEG_LAST] = { {":type", IMAGE_SYMBOL_VALUE, 1}, - {":data", IMAGE_STRING_VALUE, 0}, + {":data", IMAGE_STRING_VALUE, 0}, {":file", IMAGE_STRING_VALUE, 0}, {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0}, @@ -8454,7 +8462,7 @@ if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg) || (fmt[JPEG_ASCENT].count - && XFASTINT (fmt[JPEG_ASCENT].value) > 100)) + && XFASTINT (fmt[JPEG_ASCENT].value) > 100)) return 0; /* Must specify either the :data or :file keyword. This should @@ -8523,10 +8531,7 @@ if (src) { if (num_bytes > src->bytes_in_buffer) - { - ERREXIT (cinfo, JERR_INPUT_EOF); - /*NOTREACHED*/ - } + ERREXIT (cinfo, JERR_INPUT_EOF); src->bytes_in_buffer -= num_bytes; src->next_input_byte += num_bytes; @@ -8576,6 +8581,7 @@ src->next_input_byte = data; } + /* Load image IMG for use on frame F. Patterned after example.c from the JPEG lib. */ @@ -8600,12 +8606,13 @@ /* Open the JPEG file. */ specified_file = image_spec_value (img->spec, QCfile, NULL); specified_data = image_spec_value (img->spec, QCdata, NULL); + file = Qnil; + GCPRO1 (file); /* Reading from :data takes precedence. */ if (NILP (specified_data)) { file = x_find_image_file (specified_file); - GCPRO1 (file); if (!STRINGP (file)) { image_error ("Cannot find image file %s", specified_file, Qnil); @@ -8622,38 +8629,38 @@ } } - /* Customize libjpeg's error handling to call my_error_exit - when an error is detected. This function will perform - a longjmp. */ + /* Customize libjpeg's error handling to call my_error_exit when an + error is detected. This function will perform a longjmp. */ mgr.pub.error_exit = my_error_exit; cinfo.err = jpeg_std_error (&mgr.pub); if ((rc = setjmp (mgr.setjmp_buffer)) != 0) { - if (rc == 1) - { - /* Called from my_error_exit. Display a JPEG error. */ - char buffer[JMSG_LENGTH_MAX]; - cinfo.err->format_message ((j_common_ptr) &cinfo, buffer); - image_error ("Error reading JPEG file `%s': %s", file, - build_string (buffer)); - } + if (rc == 1) + { + /* Called from my_error_exit. Display a JPEG error. */ + char buffer[JMSG_LENGTH_MAX]; + cinfo.err->format_message ((j_common_ptr) &cinfo, buffer); + image_error ("Error reading JPEG file `%s': %s", file, + build_string (buffer)); + } /* Close the input file and destroy the JPEG object. */ - if (fp) fclose (fp); + if (fp) + fclose (fp); jpeg_destroy_decompress (&cinfo); - BLOCK_INPUT; + BLOCK_INPUT; - /* If we already have an XImage, free that. */ - x_destroy_x_image (ximg); - - /* Free pixmap and colors. */ - x_clear_image (f, img); + /* If we already have an XImage, free that. */ + x_destroy_x_image (ximg); + + /* Free pixmap and colors. */ + x_clear_image (f, img); - UNBLOCK_INPUT; - UNGCPRO; - return 0; + UNBLOCK_INPUT; + UNGCPRO; + return 0; } /* Create the JPEG decompression object. Let it read from fp. @@ -8681,63 +8688,64 @@ if (!x_create_x_image_and_pixmap (f, file, width, height, 0, &ximg, &img->pixmap)) { - UNBLOCK_INPUT; - longjmp (mgr.setjmp_buffer, 2); + UNBLOCK_INPUT; + longjmp (mgr.setjmp_buffer, 2); } /* Allocate colors. When color quantization is used, - cinfo.actual_number_of_colors has been set with the number of - colors generated, and cinfo.colormap is a two-dimensional array - of color indices in the range 0..cinfo.actual_number_of_colors. - No more than 255 colors will be generated. */ + cinfo.actual_number_of_colors has been set with the number of + colors generated, and cinfo.colormap is a two-dimensional array + of color indices in the range 0..cinfo.actual_number_of_colors. + No more than 255 colors will be generated. */ { - int i, ir, ig, ib; - - if (cinfo.out_color_components > 2) - ir = 0, ig = 1, ib = 2; - else if (cinfo.out_color_components > 1) - ir = 0, ig = 1, ib = 0; - else - ir = 0, ig = 0, ib = 0; - - /* Use the color table mechanism because it handles colors that - cannot be allocated nicely. Such colors will be replaced with - a default color, and we don't have to care about which colors - can be freed safely, and which can't. */ - init_color_table (); - colors = (unsigned long *) alloca (cinfo.actual_number_of_colors - * sizeof *colors); + int i, ir, ig, ib; + + if (cinfo.out_color_components > 2) + ir = 0, ig = 1, ib = 2; + else if (cinfo.out_color_components > 1) + ir = 0, ig = 1, ib = 0; + else + ir = 0, ig = 0, ib = 0; + + /* Use the color table mechanism because it handles colors that + cannot be allocated nicely. Such colors will be replaced with + a default color, and we don't have to care about which colors + can be freed safely, and which can't. */ + init_color_table (); + colors = (unsigned long *) alloca (cinfo.actual_number_of_colors + * sizeof *colors); - for (i = 0; i < cinfo.actual_number_of_colors; ++i) - { - /* Multiply RGB values with 255 because X expects RGB values - in the range 0..0xffff. */ - int r = cinfo.colormap[ir][i] << 8; - int g = cinfo.colormap[ig][i] << 8; - int b = cinfo.colormap[ib][i] << 8; - colors[i] = lookup_rgb_color (f, r, g, b); - } - - /* Remember those colors actually allocated. */ - img->colors = colors_in_color_table (&img->ncolors); - free_color_table (); + for (i = 0; i < cinfo.actual_number_of_colors; ++i) + { + /* Multiply RGB values with 255 because X expects RGB values + in the range 0..0xffff. */ + int r = cinfo.colormap[ir][i] << 8; + int g = cinfo.colormap[ig][i] << 8; + int b = cinfo.colormap[ib][i] << 8; + colors[i] = lookup_rgb_color (f, r, g, b); + } + + /* Remember those colors actually allocated. */ + img->colors = colors_in_color_table (&img->ncolors); + free_color_table (); } /* Read pixels. */ row_stride = width * cinfo.output_components; buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE, - row_stride, 1); + row_stride, 1); for (y = 0; y < height; ++y) { - jpeg_read_scanlines (&cinfo, buffer, 1); - for (x = 0; x < cinfo.output_width; ++x) - XPutPixel (ximg, x, y, colors[buffer[0][x]]); + jpeg_read_scanlines (&cinfo, buffer, 1); + for (x = 0; x < cinfo.output_width; ++x) + XPutPixel (ximg, x, y, colors[buffer[0][x]]); } /* Clean up. */ jpeg_finish_decompress (&cinfo); jpeg_destroy_decompress (&cinfo); - if (fp) fclose (fp); + if (fp) + fclose (fp); /* Put the image into the pixmap. */ x_put_x_image (f, ximg, img->pixmap, width, height); @@ -8787,7 +8795,7 @@ static struct image_keyword tiff_format[TIFF_LAST] = { {":type", IMAGE_SYMBOL_VALUE, 1}, - {":data", IMAGE_STRING_VALUE, 0}, + {":data", IMAGE_STRING_VALUE, 0}, {":file", IMAGE_STRING_VALUE, 0}, {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0}, @@ -8821,91 +8829,121 @@ || (fmt[TIFF_ASCENT].count && XFASTINT (fmt[TIFF_ASCENT].value) > 100)) return 0; + /* Must specify either the :data or :file keyword. This should - ** probably be moved up into parse_image_spec, since it seems to be - ** a general requirement. - */ - if (!fmt[TIFF_FILE].count && !fmt[TIFF_DATA].count) - return 0; - return 1; -} - -/* Reading from a memory buffer for TIFF images - Based on the PNG memory source, but we have to provide a lot of - extra functions. Blah. + probably be moved up into parse_image_spec, since it seems to be + a general requirement. */ + return fmt[TIFF_FILE].count || fmt[TIFF_DATA].count; +} + + +/* Reading from a memory buffer for TIFF images Based on the PNG + memory source, but we have to provide a lot of extra functions. + Blah. We really only need to implement read and seek, but I am not convinced that the TIFF library is smart enough not to destroy itself if we only hand it the function pointers we need to - override. */ -typedef struct { + override. */ + +typedef struct +{ unsigned char *bytes; size_t len; int index; -} tiff_memory_source; - -static size_t tiff_read_from_memory(thandle_t data, tdata_t buf, tsize_t size) -{ - tiff_memory_source *src = (tiff_memory_source *)data; +} +tiff_memory_source; + +static size_t +tiff_read_from_memory (data, buf, size) + thandle_t data; + tdata_t buf; + tsize_t size; +{ + tiff_memory_source *src = (tiff_memory_source *) data; if (size > src->len - src->index) - return (size_t) -1; - memcpy(buf, src->bytes + src->index, size); + return (size_t) -1; + bcopy (src->bytes + src->index, buf, size); src->index += size; return size; } -static size_t tiff_write_from_memory(thandle_t data, tdata_t buf, tsize_t size) +static size_t +tiff_write_from_memory (data, buf, size) + thandle_t data; + tdata_t buf; + tsize_t size; { return (size_t) -1; } -static toff_t tiff_seek_in_memory(thandle_t data, toff_t off, int whence) -{ - tiff_memory_source *src = (tiff_memory_source *)data; +static toff_t +tiff_seek_in_memory (data, off, whence) + thandle_t data; + toff_t off; + int whence; +{ + tiff_memory_source *src = (tiff_memory_source *) data; int idx; switch (whence) - { - case SEEK_SET: /* Go from beginning of source */ - idx = off; - break; - case SEEK_END: /* Go from end of source */ - idx = src->len + off; - break; - case SEEK_CUR: /* Go from current position */ - idx = src->index + off; - break; - default: /* Invalid `whence' */ - return(-1); - } - if ((idx > src->len) || (idx < 0)) - return -1; + { + case SEEK_SET: /* Go from beginning of source. */ + idx = off; + break; + + case SEEK_END: /* Go from end of source. */ + idx = src->len + off; + break; + + case SEEK_CUR: /* Go from current position. */ + idx = src->index + off; + break; + + default: /* Invalid `whence'. */ + return -1; + } + + if (idx > src->len || idx < 0) + return -1; + src->index = idx; return src->index; } -static int tiff_close_memory(thandle_t data) +static int +tiff_close_memory (data) + thandle_t data; { /* NOOP */ - return(0); -} - -static int tiff_mmap_memory(thandle_t data, tdata_t *pbase, toff_t *psize) + return 0; +} + +static int +tiff_mmap_memory (data, pbase, psize) + thandle_t data; + tdata_t *pbase; + toff_t *psize; { /* It is already _IN_ memory. */ - return(0); -} - -static void tiff_unmap_memory(thandle_t data, tdata_t base, toff_t size) + return 0; +} + +static void +tiff_unmap_memory (data, base, size) + thandle_t data; + tdata_t base; + toff_t size; { /* We don't need to do this. */ - return; -} - -static toff_t tiff_size_of_memory(thandle_t data) -{ - return(((tiff_memory_source *) data)->len); +} + +static toff_t +tiff_size_of_memory (data) + thandle_t data; +{ + return ((tiff_memory_source *) data)->len; } /* Load TIFF image IMG for use on frame F. Value is non-zero if @@ -8928,51 +8966,53 @@ specified_file = image_spec_value (img->spec, QCfile, NULL); specified_data = image_spec_value (img->spec, QCdata, NULL); + file = Qnil; + GCPRO1 (file); if (NILP (specified_data)) + { + /* Read from a file */ + file = x_find_image_file (specified_file); + if (!STRINGP (file)) { - /* Read from a file */ - file = x_find_image_file (specified_file); - GCPRO1 (file); - if (!STRINGP (file)) - { - image_error ("Cannot find image file %s", file, Qnil); - UNGCPRO; - return 0; - } + image_error ("Cannot find image file %s", file, Qnil); + UNGCPRO; + return 0; + } - /* Try to open the image file. */ - tiff = TIFFOpen (XSTRING (file)->data, "r"); - if (tiff == NULL) - { - image_error ("Cannot open `%s'", file, Qnil); - UNGCPRO; - return 0; - } - } - else + /* Try to open the image file. */ + tiff = TIFFOpen (XSTRING (file)->data, "r"); + if (tiff == NULL) { - /* Memory source! */ - memsrc.bytes = XSTRING (specified_data)->data; - memsrc.len = STRING_BYTES (XSTRING (specified_data)); - memsrc.index = 0; - - tiff = TIFFClientOpen ("memory_source", "r", &memsrc, - (TIFFReadWriteProc)tiff_read_from_memory, - (TIFFReadWriteProc)tiff_write_from_memory, - tiff_seek_in_memory, - tiff_close_memory, - tiff_size_of_memory, - tiff_mmap_memory, - tiff_unmap_memory); - - if (!tiff) - { - image_error ("Cannot open memory source `%s'. ", specified_data, Qnil); - UNGCPRO; - return 0; - } + image_error ("Cannot open `%s'", file, Qnil); + UNGCPRO; + return 0; } + } + else + { + /* Memory source! */ + memsrc.bytes = XSTRING (specified_data)->data; + memsrc.len = STRING_BYTES (XSTRING (specified_data)); + memsrc.index = 0; + + tiff = TIFFClientOpen ("memory_source", "r", &memsrc, + (TIFFReadWriteProc) tiff_read_from_memory, + (TIFFReadWriteProc) tiff_write_from_memory, + tiff_seek_in_memory, + tiff_close_memory, + tiff_size_of_memory, + tiff_mmap_memory, + tiff_unmap_memory); + + if (!tiff) + { + image_error ("Cannot open memory source `%s'. ", + specified_data, Qnil); + UNGCPRO; + return 0; + } + } /* Get width and height of the image, and allocate a raster buffer of width x height 32-bit values. */ @@ -9078,7 +9118,7 @@ static struct image_keyword gif_format[GIF_LAST] = { {":type", IMAGE_SYMBOL_VALUE, 1}, - {":data", IMAGE_STRING_VALUE, 0}, + {":data", IMAGE_STRING_VALUE, 0}, {":file", IMAGE_STRING_VALUE, 0}, {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0}, @@ -9113,36 +9153,41 @@ || (fmt[GIF_ASCENT].count && XFASTINT (fmt[GIF_ASCENT].value) > 100)) return 0; + /* Must specify either the :data or :file keyword. This should - ** probably be moved up into parse_image_spec, since it seems to be - ** a general requirement. - */ - if (!fmt[GIF_FILE].count && !fmt[GIF_DATA].count) - return 0; - return 1; + probably be moved up into parse_image_spec, since it seems to be + a general requirement. */ + return fmt[GIF_FILE].count || fmt[GIF_DATA].count; } /* Reading a GIF image from memory Based on the PNG memory stuff to a certain extent. */ -typedef struct { +typedef struct +{ unsigned char *bytes; size_t len; int index; -} gif_memory_source; - -static int gif_read_from_memory(GifFileType *file, GifByteType *buf, int len) +} +gif_memory_source; + +static int +gif_read_from_memory (file, buf, len) + GifFileType *file; + GifByteType *buf; + int len; { gif_memory_source *src = (gif_memory_source *) file->UserData; - if (len > (src->len - src->index)) - return -1; - - memcpy(buf, src->bytes + src->index, len); + if (len > src->len - src->index) + return -1; + + bcopy (src->bytes + src->index, buf, len); src->index += len; return len; } + /* Load GIF image IMG for use on frame F. Value is non-zero if successful. */ @@ -9165,42 +9210,43 @@ specified_file = image_spec_value (img->spec, QCfile, NULL); specified_data = image_spec_value (img->spec, QCdata, NULL); + file = Qnil; + GCPRO1 (file); if (NILP (specified_data)) + { + file = x_find_image_file (specified_file); + if (!STRINGP (file)) { - file = x_find_image_file (specified_file); - GCPRO1 (file); - if (!STRINGP (file)) - { - image_error ("Cannot find image file %s", specified_file, Qnil); - UNGCPRO; - return 0; - } + image_error ("Cannot find image file %s", specified_file, Qnil); + UNGCPRO; + return 0; + } - /* Open the GIF file. */ - gif = DGifOpenFileName (XSTRING (file)->data); - if (gif == NULL) - { - image_error ("Cannot open `%s'", file, Qnil); - UNGCPRO; - return 0; - } - } - else + /* Open the GIF file. */ + gif = DGifOpenFileName (XSTRING (file)->data); + if (gif == NULL) { - /* Read from memory! */ - memsrc.bytes = XSTRING (specified_data)->data; - memsrc.len = STRING_BYTES (XSTRING (specified_data)); - memsrc.index = 0; - - gif = DGifOpen(&memsrc, gif_read_from_memory); - if (!gif) - { - image_error ("Cannot open memory source `%s'",specified_data, Qnil); - UNGCPRO; - return 0; - } + image_error ("Cannot open `%s'", file, Qnil); + UNGCPRO; + return 0; } + } + else + { + /* Read from memory! */ + memsrc.bytes = XSTRING (specified_data)->data; + memsrc.len = STRING_BYTES (XSTRING (specified_data)); + memsrc.index = 0; + + gif = DGifOpen(&memsrc, gif_read_from_memory); + if (!gif) + { + image_error ("Cannot open memory source `%s'",specified_data, Qnil); + UNGCPRO; + return 0; + } + } /* Read entire contents. */ rc = DGifSlurp (gif);