mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-30 08:09:04 +00:00
New image functions adapted to Emacs conventions.
(png_load, tiff_load, jpeg_load, gif_load): Always GCPRO local variable `file'.
This commit is contained in:
parent
bc28370787
commit
5ad6a5fb89
@ -1,3 +1,9 @@
|
||||
1999-12-31 Gerd Moellmann <gerd@gnu.org>
|
||||
|
||||
* xfns.c: New image functions adapted to Emacs conventions.
|
||||
(png_load, tiff_load, jpeg_load, gif_load): Always GCPRO local
|
||||
variable `file'.
|
||||
|
||||
1999-12-31 William M. Perry <wmperry@aventail.com>
|
||||
|
||||
* xfns.c (jpeg_format): Added the :data keyword
|
||||
|
566
src/xfns.c
566
src/xfns.c
@ -7941,7 +7941,7 @@ enum png_keyword_index
|
||||
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 @@ png_image_p (object)
|
||||
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 @@ my_png_warning (png_ptr, msg)
|
||||
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? */
|
||||
};
|
||||
|
||||
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;
|
||||
/* 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_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,58 +8068,59 @@ png_load (f, img)
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
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))
|
||||
{
|
||||
/* 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;
|
||||
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,
|
||||
my_png_error, my_png_warning);
|
||||
@ -8160,9 +8165,9 @@ png_load (f, img)
|
||||
|
||||
/* 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 @@ png_load (f, img)
|
||||
/* 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 @@ enum jpeg_keyword_index
|
||||
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 @@ jpeg_image_p (object)
|
||||
|
||||
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 @@ our_skip_input_data (cinfo, num_bytes)
|
||||
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 @@ jpeg_memory_src (cinfo, data, len)
|
||||
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 @@ jpeg_load (f, img)
|
||||
/* 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 @@ jpeg_load (f, img)
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
/* If we already have an XImage, free that. */
|
||||
x_destroy_x_image (ximg);
|
||||
|
||||
/* Free pixmap and colors. */
|
||||
x_clear_image (f, img);
|
||||
/* 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 @@ jpeg_load (f, img)
|
||||
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;
|
||||
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;
|
||||
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);
|
||||
/* 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);
|
||||
}
|
||||
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 ();
|
||||
/* 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 @@ enum tiff_keyword_index
|
||||
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 @@ tiff_image_p (object)
|
||||
|| (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;
|
||||
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.
|
||||
|
||||
/* 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;
|
||||
}
|
||||
tiff_memory_source;
|
||||
|
||||
static size_t tiff_read_from_memory(thandle_t data, tdata_t buf, tsize_t size)
|
||||
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;
|
||||
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)
|
||||
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;
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tiff_mmap_memory(thandle_t data, tdata_t *pbase, toff_t *psize)
|
||||
static int
|
||||
tiff_mmap_memory (data, pbase, psize)
|
||||
thandle_t data;
|
||||
tdata_t *pbase;
|
||||
toff_t *psize;
|
||||
{
|
||||
/* It is already _IN_ memory. */
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tiff_unmap_memory(thandle_t data, tdata_t base, toff_t size)
|
||||
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)
|
||||
static toff_t
|
||||
tiff_size_of_memory (data)
|
||||
thandle_t data;
|
||||
{
|
||||
return(((tiff_memory_source *) data)->len);
|
||||
return ((tiff_memory_source *) data)->len;
|
||||
}
|
||||
|
||||
/* Load TIFF image IMG for use on frame F. Value is non-zero if
|
||||
@ -8928,51 +8966,53 @@ tiff_load (f, img)
|
||||
|
||||
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 @@ enum gif_keyword_index
|
||||
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 @@ gif_image_p (object)
|
||||
|| (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;
|
||||
}
|
||||
gif_memory_source;
|
||||
|
||||
static int gif_read_from_memory(GifFileType *file, GifByteType *buf, int len)
|
||||
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;
|
||||
if (len > src->len - src->index)
|
||||
return -1;
|
||||
|
||||
memcpy(buf, src->bytes + src->index, len);
|
||||
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 @@ gif_load (f, img)
|
||||
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user