comparison src/glyphs-x.c @ 265:8efd647ea9ca r20-5b31

Import from CVS: tag r20-5b31
author cvs
date Mon, 13 Aug 2007 10:25:37 +0200
parents 11cf20601dec
children 966663fcf606
comparison
equal deleted inserted replaced
264:682d2a9d41a5 265:8efd647ea9ca
33 GIF/JPEG support added by Ben Wing for 19.14 33 GIF/JPEG support added by Ben Wing for 19.14
34 PNG support added by Bill Perry for 19.14 34 PNG support added by Bill Perry for 19.14
35 Improved GIF/JPEG support added by Bill Perry for 19.14 35 Improved GIF/JPEG support added by Bill Perry for 19.14
36 Cleanup/simplification of error handling by Ben Wing for 19.14 36 Cleanup/simplification of error handling by Ben Wing for 19.14
37 Pointer/icon overhaul, more restructuring by Ben Wing for 19.14 37 Pointer/icon overhaul, more restructuring by Ben Wing for 19.14
38 GIF support changed to external GIFlib 3.1 by Jareth Hein for 20.5
39 Many changes for color work and optimizations by Jareth Hein for 20.5
40 Switch of GIF/JPEG/PNG to new EImage intermediate code by Jareth Hein for 20.5
41 TIFF code by Jareth Hein for 20.5
38 42
39 TODO: 43 TODO:
40 Convert images.el to C and stick it in here? 44 Convert images.el to C and stick it in here?
41 */ 45 */
42 46
51 #include "buffer.h" 55 #include "buffer.h"
52 #include "frame.h" 56 #include "frame.h"
53 #include "insdel.h" 57 #include "insdel.h"
54 #include "opaque.h" 58 #include "opaque.h"
55 59
60 #include "imgproc.h"
61
56 #include "sysfile.h" 62 #include "sysfile.h"
57 63
58 #ifdef HAVE_PNG 64 #ifdef HAVE_PNG
59 #ifdef __cplusplus 65 #ifdef __cplusplus
60 extern "C" { 66 extern "C" {
68 #endif 74 #endif
69 #ifdef FILE_CODING 75 #ifdef FILE_CODING
70 #include "file-coding.h" 76 #include "file-coding.h"
71 #endif 77 #endif
72 78
73 #define LISP_DEVICE_TO_X_SCREEN(dev) \ 79 #if INTBITS == 32
74 XDefaultScreenOfDisplay (DEVICE_X_DISPLAY (XDEVICE (dev))) 80 # define FOUR_BYTE_TYPE unsigned int
81 #elif LONGBITS == 32
82 # define FOUR_BYTE_TYPE unsigned long
83 #elif SHORTBITS == 32
84 # define FOUR_BYTE_TYPE unsigned short
85 #else
86 #error What kind of strange-ass system are we running on?
87 #endif
88
89 #define LISP_DEVICE_TO_X_SCREEN(dev) XDefaultScreenOfDisplay (DEVICE_X_DISPLAY (XDEVICE (dev)))
75 90
76 DEFINE_IMAGE_INSTANTIATOR_FORMAT (xbm); 91 DEFINE_IMAGE_INSTANTIATOR_FORMAT (xbm);
77 Lisp_Object Qxbm; 92 Lisp_Object Qxbm;
78 93
79 Lisp_Object Q_mask_file, Q_mask_data, Q_hotspot_x, Q_hotspot_y; 94 Lisp_Object Q_mask_file, Q_mask_data, Q_hotspot_x, Q_hotspot_y;
128 143
129 144
130 /************************************************************************/ 145 /************************************************************************/
131 /* image instance methods */ 146 /* image instance methods */
132 /************************************************************************/ 147 /************************************************************************/
148
149 /************************************************************************/
150 /* convert from a series of RGB triples to an XImage formated for the */
151 /* proper display */
152 /************************************************************************/
153 XImage *EImage2XImage(Lisp_Object device, int width, int height, unsigned char *pic,
154 unsigned long **pixtbl, int *pixcount, int *npixels)
155 {
156 Display *dpy;
157 Colormap cmap;
158 Visual *vis;
159 XImage *outimg;
160 int depth, bitmap_pad, byte_cnt, i, j;
161 int rd,gr,bl,q;
162 unsigned char *data, *ip, *dp;
163 quant_table *qtable;
164 union {
165 FOUR_BYTE_TYPE val;
166 char cp[4];
167 } conv;
168
169 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
170 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
171 vis = DEVICE_X_VISUAL (XDEVICE(device));
172 depth = DEVICE_X_DEPTH(XDEVICE(device));
173
174 if (vis->class == PseudoColor) {
175 /* Quantize the image and get a histogram while we're at it.
176 Do this first to save memory */
177 qtable = EImage_build_quantable(pic, width, height, 256);
178 if (qtable == NULL) return NULL;
179 }
180
181 bitmap_pad = ((depth > 16) ? 32 :
182 (depth > 8) ? 16 :
183 8);
184 byte_cnt = bitmap_pad >> 3;
185
186 outimg = XCreateImage (dpy, vis,
187 depth, ZPixmap, 0, 0, width, height,
188 bitmap_pad, 0);
189 if (!outimg) return NULL;
190
191 data = (unsigned char *) xmalloc (outimg->bytes_per_line * height);
192 if (!data) {
193 XDestroyImage(outimg);
194 return NULL;
195 }
196 outimg->data = data;
197
198 if (vis->class == PseudoColor) {
199 unsigned long pixarray[256];
200 int n;
201 /* use our quantize table to allocate the colors */
202 *pixcount = 32;
203 *pixtbl = xnew_array (unsigned long, *pixcount);
204 *npixels = 0;
205
206 /* ### should implement a sort by popularity to assure proper allocation */
207 n = *npixels;
208 for (i = 0; i < qtable->num_active_colors; i++) {
209 XColor color;
210 int res;
211
212 color.red = qtable->rm[i] ? qtable->rm[i] << 8 : 0;
213 color.green = qtable->gm[i] ? qtable->gm[i] << 8 : 0;
214 color.blue = qtable->bm[i] ? qtable->bm[i] << 8 : 0;
215 color.flags = DoRed | DoGreen | DoBlue;
216 res = allocate_nearest_color (dpy, cmap, vis, &color);
217 if (res > 0 && res < 3)
218 {
219 DO_REALLOC(*pixtbl, *pixcount, n+1, unsigned long);
220 (*pixtbl)[n] = color.pixel;
221 n++;
222 }
223 pixarray[i] = color.pixel;
224 }
225 *npixels = n;
226 ip = pic;
227 for (i = 0; i < height; i++) {
228 dp = data + (i * outimg->bytes_per_line);
229 for (j = 0; j < width; j++) {
230 rd = *ip++;
231 gr = *ip++;
232 bl = *ip++;
233 conv.val = pixarray[QUANT_GET_COLOR(qtable,rd,gr,bl)];
234 #ifdef WORDS_BIGENDIAN
235 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
236 #else
237 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q];
238 #endif
239 }
240 }
241 xfree(qtable);
242 } else {
243 unsigned long rshift,gshift,bshift,rbits,gbits,bbits,junk;
244 junk = vis->red_mask;
245 rshift = 0;
246 while ((junk & 0x1) == 0) {
247 junk = junk >> 1;
248 rshift ++;
249 }
250 rbits = 0;
251 while (junk != 0) {
252 junk = junk >> 1;
253 rbits++;
254 }
255 junk = vis->green_mask;
256 gshift = 0;
257 while ((junk & 0x1) == 0) {
258 junk = junk >> 1;
259 gshift ++;
260 }
261 gbits = 0;
262 while (junk != 0) {
263 junk = junk >> 1;
264 gbits++;
265 }
266 junk = vis->blue_mask;
267 bshift = 0;
268 while ((junk & 0x1) == 0) {
269 junk = junk >> 1;
270 bshift ++;
271 }
272 bbits = 0;
273 while (junk != 0) {
274 junk = junk >> 1;
275 bbits++;
276 }
277 ip = pic;
278 for (i = 0; i < height; i++) {
279 dp = data + (i * outimg->bytes_per_line);
280 for (j = 0; j < width; j++) {
281 if (rbits > 8)
282 rd = *ip++ << (rbits - 8);
283 else
284 rd = *ip++ >> (8 - rbits);
285 if (gbits > 8)
286 gr = *ip++ << (gbits - 8);
287 else
288 gr = *ip++ >> (8 - gbits);
289 if (bbits > 8)
290 bl = *ip++ << (bbits - 8);
291 else
292 bl = *ip++ >> (8 - bbits);
293
294 conv.val = (rd << rshift) | (gr << gshift) | (bl << bshift);
295 #ifdef WORDS_BIGENDIAN
296 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
297 #else
298 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q];
299 #endif
300 }
301 }
302 }
303 return outimg;
304 }
305
306
133 307
134 static void 308 static void
135 x_print_image_instance (struct Lisp_Image_Instance *p, 309 x_print_image_instance (struct Lisp_Image_Instance *p,
136 Lisp_Object printcharfun, 310 Lisp_Object printcharfun,
137 int escapeflag) 311 int escapeflag)
338 if (XrmGetResource (XtDatabase (display), 512 if (XrmGetResource (XtDatabase (display),
339 "bitmapFilePath", "BitmapFilePath", &type, &value) 513 "bitmapFilePath", "BitmapFilePath", &type, &value)
340 && !strcmp (type, "String")) 514 && !strcmp (type, "String"))
341 Vx_bitmap_file_path = decode_env_path (0, (char *) value.addr); 515 Vx_bitmap_file_path = decode_env_path (0, (char *) value.addr);
342 Vx_bitmap_file_path = nconc2 (Vx_bitmap_file_path, 516 Vx_bitmap_file_path = nconc2 (Vx_bitmap_file_path,
343 (list1 (build_string (BITMAPDIR)))); 517 (decode_path (BITMAPDIR)));
344 } 518 }
345 519
346 { 520 {
347 Lisp_Object found; 521 Lisp_Object found;
348 if (locate_file (Vx_bitmap_file_path, name, "", &found, R_OK) < 0) 522 if (locate_file (Vx_bitmap_file_path, name, "", &found, R_OK) < 0)
438 free_alist (alist); 612 free_alist (alist);
439 RETURN_UNGCPRO (result); 613 RETURN_UNGCPRO (result);
440 } 614 }
441 } 615 }
442 616
617 #if 0
443 static void 618 static void
444 write_lisp_string_to_temp_file (Lisp_Object string, char *filename_out) 619 write_lisp_string_to_temp_file (Lisp_Object string, char *filename_out)
445 { 620 {
446 Lisp_Object instream, outstream; 621 Lisp_Object instream, outstream;
447 Lstream *istr, *ostr; 622 Lstream *istr, *ostr;
448 char tempbuf[1024]; /* some random amount */ 623 char tempbuf[1024]; /* some random amount */
449 int fubar = 0; 624 int fubar = 0;
450 FILE *tmpfil; 625 FILE *tmpfil;
451 static Extbyte_dynarr *conversion_out_dynarr = NULL; 626 static Extbyte_dynarr *conversion_out_dynarr;
452 Bytecount bstart, bend; 627 Bytecount bstart, bend;
453 struct gcpro gcpro1, gcpro2; 628 struct gcpro gcpro1, gcpro2;
454 #ifdef FILE_CODING 629 #ifdef FILE_CODING
455 Lisp_Object conv_out_stream; 630 Lisp_Object conv_out_stream;
456 Lstream *costr; 631 Lstream *costr;
537 712
538 if (fubar) 713 if (fubar)
539 report_file_error ("Writing temp file", 714 report_file_error ("Writing temp file",
540 list1 (build_string (filename_out))); 715 list1 (build_string (filename_out)));
541 } 716 }
717 #endif
542 718
543 719
544 /************************************************************************/ 720 /************************************************************************/
545 /* cursor functions */ 721 /* cursor functions */
546 /************************************************************************/ 722 /************************************************************************/
1801 Colormap cmap; 1977 Colormap cmap;
1802 /* Stream that we need to close */ 1978 /* Stream that we need to close */
1803 FILE *instream; 1979 FILE *instream;
1804 /* Object that holds state info for JPEG decoding */ 1980 /* Object that holds state info for JPEG decoding */
1805 struct jpeg_decompress_struct *cinfo_ptr; 1981 struct jpeg_decompress_struct *cinfo_ptr;
1982 /* EImage data */
1983 unsigned char *eimage;
1806 /* Pixels to keep around while the image is active */ 1984 /* Pixels to keep around while the image is active */
1807 unsigned long *pixels; 1985 unsigned long *pixels;
1808 int npixels; 1986 int npixels, pixcount;
1809 /* Client-side image structure */ 1987 /* Client-side image structure */
1810 XImage *ximage; 1988 XImage *ximage;
1811 /* Tempfile to remove */ 1989 /* Tempfile to remove */
1990 #ifdef USE_TEMP_FILES_FOR_JPEG_IMAGES
1812 char tempfile[50]; 1991 char tempfile[50];
1813 int tempfile_needs_to_be_removed; 1992 int tempfile_needs_to_be_removed;
1993 #endif
1814 }; 1994 };
1815 1995
1816 static Lisp_Object 1996 static Lisp_Object
1817 jpeg_instantiate_unwind (Lisp_Object unwind_obj) 1997 jpeg_instantiate_unwind (Lisp_Object unwind_obj)
1818 { 1998 {
1824 jpeg_destroy_decompress (data->cinfo_ptr); 2004 jpeg_destroy_decompress (data->cinfo_ptr);
1825 2005
1826 if (data->instream) 2006 if (data->instream)
1827 fclose (data->instream); 2007 fclose (data->instream);
1828 2008
1829 if (data->tempfile_needs_to_be_removed) 2009 if (data->eimage) xfree (data->eimage);
1830 unlink (data->tempfile);
1831 2010
1832 if (data->npixels > 0) 2011 if (data->npixels > 0)
1833 {
1834 XFreeColors (data->dpy, data->cmap, data->pixels, data->npixels, 0L); 2012 XFreeColors (data->dpy, data->cmap, data->pixels, data->npixels, 0L);
2013 if (data->pixcount)
1835 xfree (data->pixels); 2014 xfree (data->pixels);
1836 }
1837 2015
1838 if (data->ximage) 2016 if (data->ximage)
1839 { 2017 {
1840 if (data->ximage->data) 2018 if (data->ximage->data)
1841 { 2019 {
1842 xfree (data->ximage->data); 2020 xfree (data->ximage->data);
1843 data->ximage->data = 0; 2021 data->ximage->data = 0;
1844 } 2022 }
1845 XDestroyImage (data->ximage); 2023 XDestroyImage (data->ximage);
1846 } 2024 }
2025 #if USE_TEMP_FILES_FOR_JPEG_IMAGES
2026 if (data->tempfile_needs_to_be_removed)
2027 unlink (data->tempfile);
2028 #endif
1847 2029
1848 return Qnil; 2030 return Qnil;
1849 } 2031 }
1850 2032
1851 /* 2033 /*
1980 int dest_mask, Lisp_Object domain) 2162 int dest_mask, Lisp_Object domain)
1981 { 2163 {
1982 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); 2164 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1983 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); 2165 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1984 Display *dpy; 2166 Display *dpy;
1985 Screen *scr;
1986 Colormap cmap; 2167 Colormap cmap;
1987 Visual *vis; 2168 Visual *vis;
1988 /* It is OK for the unwind data to be local to this function, 2169 /* It is OK for the unwind data to be local to this function,
1989 because the unwind-protect is always executed when this 2170 because the unwind-protect is always executed when this
1990 stack frame is still valid. */ 2171 stack frame is still valid. */
2003 2184
2004 if (!DEVICE_X_P (XDEVICE (device))) 2185 if (!DEVICE_X_P (XDEVICE (device)))
2005 signal_simple_error ("Not an X device", device); 2186 signal_simple_error ("Not an X device", device);
2006 2187
2007 dpy = DEVICE_X_DISPLAY (XDEVICE (device)); 2188 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
2008 scr = DefaultScreenOfDisplay (dpy);
2009 cmap = DEVICE_X_COLORMAP (XDEVICE(device)); 2189 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
2010 vis = DEVICE_X_VISUAL (XDEVICE(device)); 2190 vis = DEVICE_X_VISUAL (XDEVICE(device));
2011 2191
2012 /* Step -1: First record our unwind-protect, which will clean up after 2192 /* Step -1: First record our unwind-protect, which will clean up after
2013 any exit, normal or not */ 2193 any exit, normal or not */
2096 * (a) suspension is not possible with the stdio data source, and 2276 * (a) suspension is not possible with the stdio data source, and
2097 * (b) we passed TRUE to reject a tables-only JPEG file as an error. 2277 * (b) we passed TRUE to reject a tables-only JPEG file as an error.
2098 * See libjpeg.doc for more info. 2278 * See libjpeg.doc for more info.
2099 */ 2279 */
2100 2280
2281 #if 0
2101 /* Step 4: set parameters for decompression. */ 2282 /* Step 4: set parameters for decompression. */
2102 2283
2103 /* We request that the JPEG file be automatically quantized into 2284 if (vis->class == PseudoColor)
2104 8-bit color in case it's not already (many JPEGs are stored in 2285 {
2105 24-bit color). "Two-pass quantize" means that the colormap 2286
2106 is determined on-the-fly for this particular image rather than 2287 /* We request that the JPEG file be automatically quantized into
2107 quantizing to a supplied colormap. We can get away with this 2288 8-bit color in case it's not already (many JPEGs are stored in
2108 because we then use allocate_nearest_color(). 2289 24-bit color). "Two-pass quantize" means that the colormap
2109 2290 is determined on-the-fly for this particular image rather than
2110 #### Note of course that this is not the most color-effective 2291 quantizing to a supplied colormap. We can get away with this
2111 way of doing things -- we could quantize an image that has 2292 because we then use allocate_nearest_color().
2112 lots of very similar colors, and eat up the colormap with these 2293
2113 (useless to other images) colors. Unfortunately I don't think 2294 #### Note of course that this is not the most color-effective
2114 there's any "general" way of maximizing the overall image 2295 way of doing things -- we could quantize an image that has
2115 quality of lots of images, given that we don't know the 2296 lots of very similar colors, and eat up the colormap with these
2116 colors of the images until we come across each one. Best we 2297 (useless to other images) colors. Unfortunately I don't think
2117 could do would be various sorts of heuristics, which I don't 2298 there's any "general" way of maximizing the overall image
2118 feel like dealing with now. A better scheme would be the 2299 quality of lots of images, given that we don't know the
2119 way things are done under MS Windows, where the colormap is 2300 colors of the images until we come across each one. Best we
2120 dynamically adjusted for various applications; but that kind 2301 could do would be various sorts of heuristics, which I don't
2121 of thing would have to be provided by X, which it isn't. */ 2302 feel like dealing with now. A better scheme would be the
2122 2303 way things are done under MS Windows, where the colormap is
2123 cinfo.quantize_colors = TRUE; 2304 dynamically adjusted for various applications; but that kind
2124 cinfo.two_pass_quantize = TRUE; 2305 of thing would have to be provided by X, which it isn't. */
2125 cinfo.colormap = NULL; 2306
2126 2307 cinfo.quantize_colors = TRUE;
2308 cinfo.two_pass_quantize = TRUE;
2309 cinfo.colormap = NULL;
2310 }
2311
2127 /* Step 5: Start decompressor */ 2312 /* Step 5: Start decompressor */
2128 2313
2129 jpeg_start_decompress (&cinfo); 2314 jpeg_start_decompress (&cinfo);
2130 /* We can ignore the return value since suspension is not possible 2315 /* We can ignore the return value since suspension is not possible
2131 * with the stdio data source. 2316 * with the stdio data source.
2132 */ 2317 */
2133 2318
2134 /* At this point we know the size of the image and the colormap. */ 2319 /* At this point we know the size of the image and the colormap. */
2135 2320
2136 /* Step 5.33: Allocate the colors */ 2321 /* Step 5.33: Allocate the colors */
2137 { 2322 if (vis->class == PseudoColor) {
2138 int i; 2323 int i;
2139 2324 unwind.pixcount = 32;
2140 /* Just in case the image contains out-of-range pixels, we go 2325 unwind.pixels = xnew_array (unsigned long, unwind.pixcount);
2141 ahead and allocate space for all of them. */ 2326 unwind.npixels = 0;
2142 unwind.pixels = xnew_array (unsigned long, 256);
2143 unwind.npixels = cinfo.actual_number_of_colors;
2144
2145 for (i = 0; i < 256; i++)
2146 unwind.pixels[i] = 0; /* Use a reasonable color for out of range. */
2147 2327
2148 /* Allocate pixels for the various colors. */ 2328 /* Allocate pixels for the various colors. */
2149 for (i = 0; i < unwind.npixels; i++) 2329 for (i = 0; i < cinfo.actual_number_of_colors; i++)
2150 { 2330 {
2151 XColor color; 2331 XColor color;
2152 int ri, gi, bi; 2332 int ri, gi, bi, res;
2153 2333
2154 ri = 0; 2334 ri = 0;
2155 gi = cinfo.out_color_components > 1 ? 1 : 0; 2335 gi = cinfo.out_color_components > 1 ? 1 : 0;
2156 bi = cinfo.out_color_components > 2 ? 2 : 0; 2336 bi = cinfo.out_color_components > 2 ? 2 : 0;
2157 2337
2161 color.red = cinfo.colormap[ri] ? cinfo.colormap[ri][i] << 8 : 0; 2341 color.red = cinfo.colormap[ri] ? cinfo.colormap[ri][i] << 8 : 0;
2162 color.green = cinfo.colormap[gi] ? cinfo.colormap[gi][i] << 8 : 0; 2342 color.green = cinfo.colormap[gi] ? cinfo.colormap[gi][i] << 8 : 0;
2163 color.blue = cinfo.colormap[bi] ? cinfo.colormap[bi][i] << 8 : 0; 2343 color.blue = cinfo.colormap[bi] ? cinfo.colormap[bi][i] << 8 : 0;
2164 color.flags = DoRed | DoGreen | DoBlue; 2344 color.flags = DoRed | DoGreen | DoBlue;
2165 2345
2166 allocate_nearest_color (dpy, cmap, vis, &color); 2346 res = allocate_nearest_color (dpy, cmap, vis, &color);
2167 unwind.pixels[i] = color.pixel; 2347 if (res > 0 && res < 3)
2348 {
2349 DO_REALLOC(unwind.pixels, unwind.pixcount, unwind.npixels+1, unsigned long);
2350 unwind.pixels[unwind.npixels] = color.pixel;
2351 unwind.npixels++;
2352 }
2168 } 2353 }
2169 } 2354 }
2170 2355
2171 /* Step 5.66: Create the image */ 2356 /* Step 5.66: Create the image */
2172 { 2357 {
2180 /* first get bitmap_pad (from XPM) */ 2365 /* first get bitmap_pad (from XPM) */
2181 bitmap_pad = ((depth > 16) ? 32 : 2366 bitmap_pad = ((depth > 16) ? 32 :
2182 (depth > 8) ? 16 : 2367 (depth > 8) ? 16 :
2183 8); 2368 8);
2184 2369
2185 unwind.ximage = XCreateImage (dpy, DefaultVisualOfScreen (scr), 2370 unwind.ximage = XCreateImage (dpy, vis, depth, ZPixmap, 0, 0, width, height,
2186 depth, ZPixmap, 0, 0, width, height,
2187 bitmap_pad, 0); 2371 bitmap_pad, 0);
2188 2372
2189 if (!unwind.ximage) 2373 if (!unwind.ximage)
2190 signal_simple_error ("Unable to create X image struct", instantiator); 2374 signal_simple_error ("Unable to create X image struct", instantiator);
2191 2375
2239 was compiled with 12-bit samples -- #### 2423 was compiled with 12-bit samples -- ####
2240 We should deal with this possibility) */ 2424 We should deal with this possibility) */
2241 unwind.pixels[(unsigned char) row_buffer[0][i]]); 2425 unwind.pixels[(unsigned char) row_buffer[0][i]]);
2242 } 2426 }
2243 } 2427 }
2244 2428 #else
2429 {
2430 /* Step 4: set parameters for decompression. */
2431
2432 /* Now that we're using EImages, use the default of all data in 24bit color.
2433 The backend routine will take care of any necessary reductions. */
2434
2435 /* Step 5: Start decompressor */
2436 jpeg_start_decompress (&cinfo);
2437
2438 /* Step 6: Read in the data and put into EImage format (8bit RGB triples)*/
2439
2440 unwind.eimage = (unsigned char*) xmalloc (cinfo.output_width * cinfo.output_height * 3);
2441 if (!unwind.eimage)
2442 signal_simple_error("Unable to allocate enough memory for image", instantiator);
2443
2444 {
2445 JSAMPARRAY row_buffer; /* Output row buffer */
2446 JSAMPLE *jp;
2447 int row_stride; /* physical row width in output buffer */
2448 unsigned char *op = unwind.eimage;
2449
2450 /* We may need to do some setup of our own at this point before reading
2451 * the data. After jpeg_start_decompress() we have the correct scaled
2452 * output image dimensions available
2453 * We need to make an output work buffer of the right size.
2454 */
2455 /* JSAMPLEs per row in output buffer. */
2456 row_stride = cinfo.output_width * cinfo.output_components;
2457 /* Make a one-row-high sample array that will go away when done
2458 with image */
2459 row_buffer = ((*cinfo.mem->alloc_sarray)
2460 ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1));
2461
2462 /* Here we use the library's state variable cinfo.output_scanline as the
2463 * loop counter, so that we don't have to keep track ourselves.
2464 */
2465 while (cinfo.output_scanline < cinfo.output_height)
2466 {
2467 int i;
2468
2469 /* jpeg_read_scanlines expects an array of pointers to scanlines.
2470 * Here the array is only one element long, but you could ask for
2471 * more than one scanline at a time if that's more convenient.
2472 */
2473 (void) jpeg_read_scanlines (&cinfo, row_buffer, 1);
2474 jp = row_buffer[0];
2475 for (i = 0; i < cinfo.output_width; i++) {
2476 int clr;
2477 #if (BITS_IN_JSAMPLE == 8)
2478 for (clr = 0; clr < 3; clr++)
2479 *op++ = (unsigned char)*jp++;
2480 #else /* other option is 12 */
2481 for (clr = 0; clr < 3; clr++)
2482 *op++ = (unsigned char)(*jp++ >> 4);
2483 #endif
2484 }
2485 }
2486 unwind.ximage = EImage2XImage (device, cinfo.output_width, cinfo.output_height, unwind.eimage,
2487 &unwind.pixels, &unwind.pixcount, &unwind.npixels);
2488 if (!unwind.ximage)
2489 signal_simple_error("JPEG conversion failed", instantiator);
2490 }
2491 }
2492
2493 #endif
2245 /* Step 6.5: Create the pixmap and set up the image instance */ 2494 /* Step 6.5: Create the pixmap and set up the image instance */
2246 init_image_instance_from_x_image (ii, unwind.ximage, dest_mask, 2495 init_image_instance_from_x_image (ii, unwind.ximage, dest_mask,
2247 unwind.pixels, unwind.npixels, 2496 unwind.pixels, unwind.npixels,
2248 instantiator); 2497 instantiator);
2249 2498
2258 2507
2259 Now that we've succeeded, we don't want the pixels 2508 Now that we've succeeded, we don't want the pixels
2260 freed right now. They're kept around in the image instance 2509 freed right now. They're kept around in the image instance
2261 structure until it's destroyed. */ 2510 structure until it's destroyed. */
2262 unwind.npixels = 0; 2511 unwind.npixels = 0;
2512 unwind.pixcount = 0;
2263 2513
2264 /* This will clean up everything else. */ 2514 /* This will clean up everything else. */
2265 unbind_to (speccount, Qnil); 2515 unbind_to (speccount, Qnil);
2266 } 2516 }
2267 2517
2268 #endif /* HAVE_JPEG */ 2518 #endif /* HAVE_JPEG */
2269 2519
2270 #ifdef HAVE_GIF 2520 #ifdef HAVE_GIF
2271 2521 /* #define USE_TEMP_FILES_FOR_GIF_IMAGES */
2272 /********************************************************************** 2522 /**********************************************************************
2273 * GIF * 2523 * GIF *
2274 **********************************************************************/ 2524 **********************************************************************/
2275 2525
2276 #include "gif_lib.h" /* This is in our own source tree */ 2526 #include <gif_lib.h>
2277 2527
2278 static void 2528 static void
2279 gif_validate (Lisp_Object instantiator) 2529 gif_validate (Lisp_Object instantiator)
2280 { 2530 {
2281 file_or_data_must_be_present (instantiator); 2531 file_or_data_must_be_present (instantiator);
2299 2549
2300 struct gif_unwind_data 2550 struct gif_unwind_data
2301 { 2551 {
2302 Display *dpy; 2552 Display *dpy;
2303 Colormap cmap; 2553 Colormap cmap;
2554 unsigned char *eimage;
2304 /* Object that holds the decoded data from a GIF file */ 2555 /* Object that holds the decoded data from a GIF file */
2305 GifFileType *giffile; 2556 GifFileType *giffile;
2306 /* Pixels to keep around while the image is active */ 2557 /* Pixels to keep around while the image is active */
2307 unsigned long *pixels; 2558 unsigned long *pixels;
2308 int npixels; 2559 int npixels, pixcount;
2309 /* Client-side image structure */ 2560 /* Client-side image structure */
2310 XImage *ximage; 2561 XImage *ximage;
2562 #ifdef USE_TEMP_FILES_FOR_GIF_IMAGES
2311 /* Tempfile to remove */ 2563 /* Tempfile to remove */
2312 char tempfile[50]; 2564 char tempfile[50];
2313 int tempfile_needs_to_be_removed; 2565 int tempfile_needs_to_be_removed;
2566 #endif
2314 }; 2567 };
2315 2568
2316 static Lisp_Object 2569 static Lisp_Object
2317 gif_instantiate_unwind (Lisp_Object unwind_obj) 2570 gif_instantiate_unwind (Lisp_Object unwind_obj)
2318 { 2571 {
2319 struct gif_unwind_data *data = 2572 struct gif_unwind_data *data =
2320 (struct gif_unwind_data *) get_opaque_ptr (unwind_obj); 2573 (struct gif_unwind_data *) get_opaque_ptr (unwind_obj);
2321 2574
2322 free_opaque_ptr (unwind_obj); 2575 free_opaque_ptr (unwind_obj);
2323 if (data->giffile) 2576 if (data->giffile)
2324 DGifCloseFile (data->giffile); 2577 {
2578 DGifCloseFile (data->giffile);
2579 GifFree(data->giffile);
2580 }
2581 if (data->eimage) xfree(data->eimage);
2582 #ifdef USE_TEMP_FILES_FOR_GIF_IMAGES
2325 if (data->tempfile_needs_to_be_removed) 2583 if (data->tempfile_needs_to_be_removed)
2326 unlink (data->tempfile); 2584 unlink (data->tempfile);
2585 #endif
2327 if (data->npixels > 0) 2586 if (data->npixels > 0)
2328 { 2587 XFreeColors (data->dpy, data->cmap, data->pixels, data->npixels, 0L);
2329 XFreeColors (data->dpy, data->cmap, data->pixels, data->npixels, 0L); 2588 if (data->pixcount > 0)
2330 xfree (data->pixels); 2589 xfree (data->pixels);
2331 }
2332 if (data->ximage) 2590 if (data->ximage)
2333 { 2591 {
2334 if (data->ximage->data) 2592 if (data->ximage->data)
2335 { 2593 {
2336 xfree (data->ximage->data); 2594 xfree (data->ximage->data);
2340 } 2598 }
2341 2599
2342 return Qnil; 2600 return Qnil;
2343 } 2601 }
2344 2602
2603 #ifndef USE_TEMP_FILES_FOR_GIF_IMAGES
2604 typedef struct gif_memory_storage
2605 {
2606 Extbyte *bytes; /* The data */
2607 Extcount len; /* How big is it? */
2608 int index; /* Where are we? */
2609 } gif_memory_storage;
2610
2611 static size_t gif_read_from_memory(GifByteType *buf, size_t size, VoidPtr data)
2612 {
2613 gif_memory_storage *mem = (gif_memory_storage*)data;
2614
2615 if (size > (mem->len - mem->index))
2616 return -1;
2617 memcpy(buf, mem->bytes + mem->index, size);
2618 mem->index = mem->index + size;
2619 return size;
2620 }
2621
2622 static int gif_memory_close(VoidPtr data)
2623 {
2624 return 0;
2625 }
2626
2627 #endif
2628 struct gif_error_struct
2629 {
2630 char *err_str; /* return the error string */
2631 jmp_buf setjmp_buffer; /* for return to caller */
2632 };
2633
2634 static void gif_error_func(CONST char *err_str, VoidPtr error_ptr)
2635 {
2636 struct gif_error_struct *error_data = (struct gif_error_struct*)error_ptr;
2637
2638 /* return to setjmp point */
2639 error_data->err_str = err_str;
2640 longjmp (error_data->setjmp_buffer, 1);
2641 }
2642
2345 static void 2643 static void
2346 gif_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, 2644 gif_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2347 Lisp_Object pointer_fg, Lisp_Object pointer_bg, 2645 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2348 int dest_mask, Lisp_Object domain) 2646 int dest_mask, Lisp_Object domain)
2349 { 2647 {
2350 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); 2648 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2351 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); 2649 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2352 Display *dpy; 2650 Display *dpy;
2353 Screen *scr;
2354 Colormap cmap; 2651 Colormap cmap;
2355 Visual *vis; 2652 Visual *vis;
2356 /* It is OK for the unwind data to be local to this function, 2653 /* It is OK for the unwind data to be local to this function,
2357 because the unwind-protect is always executed when this 2654 because the unwind-protect is always executed when this
2358 stack frame is still valid. */ 2655 stack frame is still valid. */
2359 struct gif_unwind_data unwind; 2656 struct gif_unwind_data unwind;
2360 int speccount = specpdl_depth (); 2657 int speccount = specpdl_depth ();
2361 2658 #ifndef USE_TEMP_FILES_FOR_GIF_IMAGES
2659 gif_memory_storage mem_struct;
2660 struct gif_error_struct gif_err;
2661 Extbyte *bytes;
2662 Extcount len;
2663 #endif
2362 if (!DEVICE_X_P (XDEVICE (device))) 2664 if (!DEVICE_X_P (XDEVICE (device)))
2363 signal_simple_error ("Not an X device", device); 2665 signal_simple_error ("Not an X device", device);
2364 2666
2365 dpy = DEVICE_X_DISPLAY (XDEVICE (device)); 2667 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
2366 scr = DefaultScreenOfDisplay (dpy);
2367 cmap = DEVICE_X_COLORMAP (XDEVICE(device)); 2668 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
2368 vis = DEVICE_X_VISUAL (XDEVICE(device)); 2669 vis = DEVICE_X_VISUAL (XDEVICE(device));
2369 2670
2370 memset (&unwind, 0, sizeof (unwind)); 2671 memset (&unwind, 0, sizeof (unwind));
2371 unwind.dpy = dpy; 2672 unwind.dpy = dpy;
2372 unwind.cmap = cmap; 2673 unwind.cmap = cmap;
2373 record_unwind_protect (gif_instantiate_unwind, make_opaque_ptr (&unwind)); 2674 record_unwind_protect (gif_instantiate_unwind, make_opaque_ptr (&unwind));
2374 2675
2375 /* 1. Now decode the data. */ 2676 /* 1. Now decode the data. */
2376 2677
2377 /* #### The GIF routines currently require that you read from a file,
2378 so write out to a temp file. We should change this. */
2379 { 2678 {
2380 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); 2679 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
2381 2680
2382 assert (!NILP (data)); 2681 assert (!NILP (data));
2383 2682
2683 if (!(unwind.giffile = GifSetup()))
2684 signal_simple_error ("Insufficent memory to instantiate GIF image", instantiator);
2685
2686 /* set up error facilities */
2687 if (setjmp(gif_err.setjmp_buffer)) {
2688 /* An error was signaled. No clean up is needed, as unwind handles that
2689 for us. Just pass the error along. */
2690 Lisp_Object errstring;
2691 errstring = build_string (gif_err.err_str);
2692 signal_simple_error_2 ("GIF decoding error", errstring, instantiator);
2693 }
2694 GifSetErrorFunc(unwind.giffile, (Gif_error_func)gif_error_func, (VoidPtr)&gif_err);
2695
2696 #ifdef USE_TEMP_FILES_FOR_GIF_IMAGES
2384 write_lisp_string_to_temp_file (data, unwind.tempfile); 2697 write_lisp_string_to_temp_file (data, unwind.tempfile);
2385 unwind.tempfile_needs_to_be_removed = 1; 2698 unwind.tempfile_needs_to_be_removed = 1;
2386 2699 DGifOpenFileName (unwind.giffile, unwind.tempfile);
2700 #else
2701 GET_STRING_BINARY_DATA_ALLOCA (data, bytes, len);
2702 mem_struct.bytes = bytes;
2703 mem_struct.len = len;
2704 mem_struct.index = 0;
2705 GifSetReadFunc(unwind.giffile, gif_read_from_memory, (VoidPtr)&mem_struct);
2706 GifSetCloseFunc(unwind.giffile, gif_memory_close, (VoidPtr)&mem_struct);
2707 DGifInitRead(unwind.giffile);
2708 #endif
2387 /* Then slurp the image into memory, decoding along the way. 2709 /* Then slurp the image into memory, decoding along the way.
2388 The result is the image in a simple one-byte-per-pixel 2710 The result is the image in a simple one-byte-per-pixel
2389 format (#### the GIF routines only support 8-bit GIFs, 2711 format (#### the GIF routines only support 8-bit GIFs,
2390 it appears). */ 2712 it appears). */
2391 unwind.giffile = DGifOpenFileName (unwind.tempfile); 2713 DGifSlurp (unwind.giffile);
2392 if (unwind.giffile == NULL)
2393 {
2394 gif_decode_error:
2395 signal_simple_error ("Unable to decode GIF",
2396 build_string (EmacsPrintGifError ()));
2397 }
2398 /* DGifSlurp() doesn't handle interlaced files. */
2399 /* Actually, it does, sort of. It just sets the Interlace flag
2400 and stores RasterBits in interlaced order. We handle that below. */
2401 if (DGifSlurp (unwind.giffile) != GIF_OK)
2402 goto gif_decode_error;
2403 } 2714 }
2404 2715
2716 #if 0
2405 /* 2. Now allocate the colors for the image. */ 2717 /* 2. Now allocate the colors for the image. */
2406 { 2718 {
2407 int i; 2719 int i;
2408 ColorMapObject *cmo = unwind.giffile->SColorMap; 2720 ColorMapObject *cmo = unwind.giffile->SColorMap;
2409 /* Just in case the image contains out-of-range pixels, we go 2721 /* Just in case the image contains out-of-range pixels, we go
2410 ahead and allocate space for all of them. */ 2722 ahead and allocate space for all of them. */
2411 unwind.pixels = xnew_array (unsigned long, 256); 2723 unwind.pixels = xnew_array (unsigned long, 256);
2412 unwind.npixels = cmo->ColorCount; 2724 unwind.npixels = 0;
2413 2725
2414 for (i = 0; i < 256; i++) 2726 for (i = 0; i < 256; i++)
2415 unwind.pixels[i] = 0; /* Use a reasonable color for out of range. */ 2727 unwind.pixels[i] = 0; /* Use a reasonable color for out of range. */
2416 2728
2417 /* Allocate pixels for the various colors. */ 2729 /* Allocate pixels for the various colors. */
2418 for (i = 0; i < cmo->ColorCount; i++) 2730 for (i = 0; i < cmo->ColorCount; i++)
2419 { 2731 {
2732 int res;
2420 XColor color; 2733 XColor color;
2421 2734
2422 color.red = cmo->Colors[i].Red << 8; 2735 color.red = cmo->Colors[i].Red << 8;
2423 color.green = cmo->Colors[i].Green << 8; 2736 color.green = cmo->Colors[i].Green << 8;
2424 color.blue = cmo->Colors[i].Blue << 8; 2737 color.blue = cmo->Colors[i].Blue << 8;
2425 color.flags = DoRed | DoGreen | DoBlue; 2738 color.flags = DoRed | DoGreen | DoBlue;
2426 2739
2427 allocate_nearest_color (dpy, cmap, vis, &color); 2740 res = allocate_nearest_color (dpy, cmap, vis, &color);
2428 unwind.pixels[i] = color.pixel; 2741 if (res > 0 && res < 3)
2742 {
2743 unwind.pixels[unwind.npixels] = color.pixel;
2744 unwind.npixels++;
2745 }
2429 } 2746 }
2430 } 2747 }
2431 2748
2432 /* 3. Now create the image */ 2749 /* 3. Now create the image */
2433 { 2750 {
2497 RasterBits[i * width + j])]); 2814 RasterBits[i * width + j])]);
2498 2815
2499 row += interlace ? InterlacedJumps[pass] : 1; 2816 row += interlace ? InterlacedJumps[pass] : 1;
2500 } 2817 }
2501 } 2818 }
2502 2819 #else
2820 /* 3. Now create the EImage */
2821 {
2822 ColorMapObject *cmo = unwind.giffile->SColorMap;
2823 int height = unwind.giffile->SHeight;
2824 int width = unwind.giffile->SWidth;
2825 int i, j, row, pass, interlace;
2826 unsigned char *eip;
2827 /* interlaced gifs have rows in this order:
2828 0, 8, 16, ..., 4, 12, 20, ..., 2, 6, 10, ..., 1, 3, 5, ... */
2829 static int InterlacedOffset[] = { 0, 4, 2, 1 };
2830 static int InterlacedJumps[] = { 8, 8, 4, 2 };
2831
2832 unwind.eimage = (unsigned char*) xmalloc (width * height * 3);
2833 if (!unwind.eimage)
2834 signal_simple_error("Unable to allocate enough memory for image", instantiator);
2835
2836 /* write the data in EImage format (8bit RGB triples) */
2837
2838 /* Note: We just use the first image in the file and ignore the rest.
2839 We check here that that image covers the full "screen" size.
2840 I don't know whether that's always the case.
2841 -dkindred@cs.cmu.edu */
2842 if (unwind.giffile->SavedImages[0].ImageDesc.Height != height
2843 || unwind.giffile->SavedImages[0].ImageDesc.Width != width
2844 || unwind.giffile->SavedImages[0].ImageDesc.Left != 0
2845 || unwind.giffile->SavedImages[0].ImageDesc.Top != 0)
2846 signal_simple_error ("First image in GIF file is not full size",
2847 instantiator);
2848
2849 interlace = unwind.giffile->SavedImages[0].ImageDesc.Interlace;
2850 pass = 0;
2851 row = interlace ? InterlacedOffset[pass] : 0;
2852 eip = unwind.eimage;
2853 for (i = 0; i < height; i++)
2854 {
2855 if (interlace && row >= height)
2856 row = InterlacedOffset[++pass];
2857 eip = unwind.eimage + (row * width * 3);
2858 for (j = 0; j < width; j++) {
2859 unsigned char pixel = unwind.giffile->SavedImages[0].RasterBits[(i * width) + j];
2860 *eip++ = cmo->Colors[pixel].Red;
2861 *eip++ = cmo->Colors[pixel].Green;
2862 *eip++ = cmo->Colors[pixel].Blue;
2863 }
2864 row += interlace ? InterlacedJumps[pass] : 1;
2865 }
2866 unwind.ximage = EImage2XImage (device, width, height, unwind.eimage,
2867 &unwind.pixels, &unwind.pixcount, &unwind.npixels);
2868 if (!unwind.ximage)
2869 signal_simple_error("GIF conversion failed", instantiator);
2870 }
2871 #endif
2503 /* 4. Now create the pixmap and set up the image instance */ 2872 /* 4. Now create the pixmap and set up the image instance */
2504 init_image_instance_from_x_image (ii, unwind.ximage, dest_mask, 2873 init_image_instance_from_x_image (ii, unwind.ximage, dest_mask,
2505 unwind.pixels, unwind.npixels, 2874 unwind.pixels, unwind.npixels,
2506 instantiator); 2875 instantiator);
2507 /* Now that we've succeeded, we don't want the pixels 2876 /* Now that we've succeeded, we don't want the pixels
2508 freed right now. They're kept around in the image instance 2877 freed right now. They're kept around in the image instance
2509 structure until it's destroyed. */ 2878 structure until it's destroyed. */
2510 unwind.npixels = 0; 2879 unwind.npixels = 0;
2880 unwind.pixcount = 0;
2511 unbind_to (speccount, Qnil); 2881 unbind_to (speccount, Qnil);
2512 } 2882 }
2513 2883
2514 #endif /* HAVE_GIF */ 2884 #endif /* HAVE_GIF */
2515 2885
2536 png_possible_dest_types (void) 2906 png_possible_dest_types (void)
2537 { 2907 {
2538 return IMAGE_COLOR_PIXMAP_MASK; 2908 return IMAGE_COLOR_PIXMAP_MASK;
2539 } 2909 }
2540 2910
2541 #if !defined (USE_TEMP_FILES_FOR_PNG_IMAGES) && (PNG_LIBPNG_VER >= 87) 2911 #ifndef USE_TEMP_FILES_FOR_PNG_IMAGES
2542 struct png_memory_storage 2912 struct png_memory_storage
2543 { 2913 {
2544 Extbyte *bytes; /* The data */ 2914 Extbyte *bytes; /* The data */
2545 Extcount len; /* How big is it? */ 2915 Extcount len; /* How big is it? */
2546 int index; /* Where are we? */ 2916 int index; /* Where are we? */
2547 }; 2917 };
2548 2918
2549 static void png_read_from_memory(png_structp png_ptr, png_bytep data, 2919 static void png_read_from_memory(png_structp png_ptr, png_bytep data,
2550 png_uint_32 length) 2920 png_size_t length)
2551 { 2921 {
2552 struct png_memory_storage *tbr = 2922 struct png_memory_storage *tbr =
2553 (struct png_memory_storage *) png_get_io_ptr (png_ptr); 2923 (struct png_memory_storage *) png_get_io_ptr (png_ptr);
2554 2924
2555 if (length > (tbr->len - tbr->index)) 2925 if (length > (tbr->len - tbr->index))
2556 png_error (png_ptr, (png_const_charp) "Read Error"); 2926 png_error (png_ptr, (png_const_charp) "Read Error");
2557 memcpy(data,tbr->bytes + tbr->index,length); 2927 memcpy(data,tbr->bytes + tbr->index,length);
2558 tbr->index = tbr->index + length; 2928 tbr->index = tbr->index + length;
2559 } 2929 }
2560 #endif /* !USE_TEMP_FILES_FOR_PNG_IMAGESS || PNG_LIBPNG_VER >= 87 */ 2930 #endif /* !USE_TEMP_FILES_FOR_PNG_IMAGES */
2931
2932 struct png_error_struct
2933 {
2934 CONST char *err_str;
2935 jmp_buf setjmp_buffer; /* for return to caller */
2936 };
2937
2938 /* jh 98/03/12 - #### AARRRGH! libpng includes jmp_buf inside its own
2939 structure, and there are cases where the size can be different from
2940 between inside the libarary, and inside the code! To do an end run
2941 around this, use our own error functions, and don't rely on things
2942 passed in the png_ptr to them. This is an ugly hack and must
2943 go away when the lisp engine is threaded! */
2944 static struct png_error_struct png_err_stct;
2945
2946 static void png_error_func(png_structp png_ptr, png_const_charp message)
2947 {
2948 png_err_stct.err_str = message;
2949 longjmp (png_err_stct.setjmp_buffer, 1);
2950 }
2951
2952 static void png_warning_func(png_structp png_ptr, png_const_charp message)
2953 {
2954 warn_when_safe (Qpng, Qinfo, "%s", message);
2955 }
2561 2956
2562 struct png_unwind_data 2957 struct png_unwind_data
2563 { 2958 {
2564 Display *dpy; 2959 Display *dpy;
2565 Colormap cmap; 2960 Colormap cmap;
2566 FILE *instream; 2961 FILE *instream;
2567 png_struct *png_ptr; 2962 unsigned char *eimage;
2568 png_info *info_ptr; 2963 png_structp png_ptr;
2964 png_infop info_ptr;
2569 unsigned long *pixels; 2965 unsigned long *pixels;
2570 int npixels; 2966 int npixels, pixcount;
2571 XImage *ximage; 2967 XImage *ximage;
2968 #ifdef USE_TEMP_FILES_FOR_PNG_IMAGESS
2572 char tempfile[50]; 2969 char tempfile[50];
2573 int tempfile_needs_to_be_removed; 2970 int tempfile_needs_to_be_removed;
2971 #endif
2574 }; 2972 };
2575 2973
2576 static Lisp_Object 2974 static Lisp_Object
2577 png_instantiate_unwind (Lisp_Object unwind_obj) 2975 png_instantiate_unwind (Lisp_Object unwind_obj)
2578 { 2976 {
2579 struct png_unwind_data *data = 2977 struct png_unwind_data *data =
2580 (struct png_unwind_data *) get_opaque_ptr (unwind_obj); 2978 (struct png_unwind_data *) get_opaque_ptr (unwind_obj);
2581 2979
2582 free_opaque_ptr (unwind_obj); 2980 free_opaque_ptr (unwind_obj);
2583 if (data->png_ptr) 2981 if (data->png_ptr)
2584 png_read_destroy (data->png_ptr, data->info_ptr, (png_info *) NULL); 2982 png_destroy_read_struct (&(data->png_ptr), &(data->info_ptr), (png_infopp)NULL);
2585 if (data->instream) 2983 if (data->instream)
2586 fclose (data->instream); 2984 fclose (data->instream);
2587 if (data->tempfile_needs_to_be_removed)
2588 unlink (data->tempfile);
2589 if (data->npixels > 0) 2985 if (data->npixels > 0)
2590 { 2986 XFreeColors (data->dpy, data->cmap, data->pixels, data->npixels, 0L);
2591 XFreeColors (data->dpy, data->cmap, data->pixels, data->npixels, 0L); 2987 if (data->pixcount > 0)
2592 xfree (data->pixels); 2988 xfree (data->pixels);
2593 } 2989
2594 2990 if (data->eimage)
2991 xfree (data->eimage);
2595 if (data->ximage) 2992 if (data->ximage)
2596 { 2993 {
2597 if (data->ximage->data) 2994 if (data->ximage->data)
2598 { 2995 {
2599 xfree (data->ximage->data); 2996 xfree (data->ximage->data);
2600 data->ximage->data = 0; 2997 data->ximage->data = 0;
2601 } 2998 }
2602 XDestroyImage (data->ximage); 2999 XDestroyImage (data->ximage);
2603 } 3000 }
2604 3001 #ifdef USE_TEMP_FILES_FOR_PNG_IMAGES
3002 if (data->tempfile_needs_to_be_removed)
3003 unlink (data->tempfile);
3004 #endif
2605 return Qnil; 3005 return Qnil;
2606 } 3006 }
2607
2608 /* This doesn't appear to be used. */
2609 #if 0
2610 #define get_png_val(p) _get_png_val (&(p), info_ptr.bit_depth)
2611 png_uint_16
2612 _get_png_val (png_byte **pp, int bit_depth)
2613 {
2614 png_uint_16 c = 0;
2615
2616 if (bit_depth == 16) {
2617 c = (*((*pp)++)) << 8;
2618 }
2619 c |= (*((*pp)++));
2620
2621 return c;
2622 }
2623 #endif
2624 3007
2625 static void 3008 static void
2626 png_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, 3009 png_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2627 Lisp_Object pointer_fg, Lisp_Object pointer_bg, 3010 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2628 int dest_mask, Lisp_Object domain) 3011 int dest_mask, Lisp_Object domain)
2634 Visual *vis; 3017 Visual *vis;
2635 struct png_unwind_data unwind; 3018 struct png_unwind_data unwind;
2636 int speccount = specpdl_depth (); 3019 int speccount = specpdl_depth ();
2637 3020
2638 /* PNG variables */ 3021 /* PNG variables */
2639 png_struct *png_ptr; 3022 png_structp png_ptr;
2640 png_info *info_ptr; 3023 png_infop info_ptr;
2641 3024
2642 if (!DEVICE_X_P (XDEVICE (device))) 3025 if (!DEVICE_X_P (XDEVICE (device)))
2643 signal_simple_error ("Not an X device", device); 3026 signal_simple_error ("Not an X device", device);
2644 3027
2645 dpy = DEVICE_X_DISPLAY (XDEVICE (device)); 3028 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
2646 cmap = DEVICE_X_COLORMAP (XDEVICE(device)); 3029 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
2647 vis = DEVICE_X_VISUAL (XDEVICE(device)); 3030 vis = DEVICE_X_VISUAL (XDEVICE(device));
2648 3031
2649 png_ptr = xnew (png_struct); 3032 /* Initialize all PNG structures */
2650 info_ptr = xnew (png_info); 3033 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (void*)&png_err_stct,
2651 3034 png_error_func, png_warning_func);
3035 if (!png_ptr)
3036 signal_simple_error("Error obtaining memory for png_read", instantiator);
3037 info_ptr = png_create_info_struct(png_ptr);
3038 if (!info_ptr)
3039 {
3040 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
3041 signal_simple_error("Error obtaining memory for png_read", instantiator);
3042 }
3043
2652 memset (&unwind, 0, sizeof (unwind)); 3044 memset (&unwind, 0, sizeof (unwind));
2653 unwind.png_ptr = png_ptr; 3045 unwind.png_ptr = png_ptr;
2654 unwind.info_ptr = info_ptr; 3046 unwind.info_ptr = info_ptr;
2655 unwind.dpy = dpy; 3047 unwind.dpy = dpy;
2656 unwind.cmap = cmap; 3048 unwind.cmap = cmap;
2659 3051
2660 /* This code is a mixture of stuff from Ben's GIF/JPEG stuff from 3052 /* This code is a mixture of stuff from Ben's GIF/JPEG stuff from
2661 this file, example.c from the libpng 0.81 distribution, and the 3053 this file, example.c from the libpng 0.81 distribution, and the
2662 pngtopnm sources. -WMP- 3054 pngtopnm sources. -WMP-
2663 */ 3055 */
2664 #if defined (USE_TEMP_FILES_FOR_PNG_IMAGES) || (PNG_LIBPNG_VER < 87) 3056 /* It has been further modified to handle the API changes for 0.96,
2665 /* Write out to a temp file - we really should take the time to 3057 and is no longer usable for previous versions. jh
2666 write appropriate memory bound IO stuff, but I am just trying 3058 */
2667 to get the stupid thing working right now.
2668 */
2669 {
2670 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
2671
2672 assert (!NILP (data));
2673
2674 write_lisp_string_to_temp_file (data, unwind.tempfile);
2675 unwind.tempfile_needs_to_be_removed = 1;
2676
2677 if ((unwind.instream = fopen (unwind.tempfile, "rb")) == NULL)
2678 report_file_error ("Opening PNG temp file",
2679 list1 (build_string (unwind.tempfile)));
2680 }
2681 #else
2682 /* Nothing */
2683 #endif
2684 3059
2685 /* Set the jmp_buf reurn context for png_error ... if this returns !0, then 3060 /* Set the jmp_buf reurn context for png_error ... if this returns !0, then
2686 we ran into a problem somewhere, and need to clean up after ourselves. */ 3061 we ran into a problem somewhere, and need to clean up after ourselves. */
2687 if (setjmp (png_ptr->jmpbuf)) 3062 if (setjmp (png_err_stct.setjmp_buffer))
2688 { 3063 {
2689 /* Am I doing enough here? I think so, since most things happen 3064 /* Something blew up: just display the error (cleanup happens in the unwind) */
2690 in png_unwind */ 3065 signal_simple_error_2 ("Error decoding PNG",
2691 png_read_destroy (png_ptr, info_ptr, (png_info *) NULL); 3066 build_string(png_err_stct.err_str),
2692 signal_simple_error ("Error decoding PNG", instantiator); 3067 instantiator);
2693 } 3068 }
2694
2695 /* Initialize all PNG structures */
2696 png_info_init (info_ptr);
2697 png_read_init (png_ptr);
2698 3069
2699 /* Initialize the IO layer and read in header information */ 3070 /* Initialize the IO layer and read in header information */
2700 #if defined (USE_TEMP_FILES_FOR_PNG_IMAGES) || (PNG_LIBPNG_VER < 87)
2701 png_init_io (png_ptr, unwind.instream);
2702 #else
2703 { 3071 {
2704 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); 3072 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
2705 Extbyte *bytes; 3073 Extbyte *bytes;
2706 Extcount len; 3074 Extcount len;
2707 struct png_memory_storage tbr; /* Data to be read */ 3075 struct png_memory_storage tbr; /* Data to be read */
2708 3076
2709 assert (!NILP (data)); 3077 assert (!NILP (data));
2710 3078
2711 /* #### This is a definite problem under Mule due to the amount of 3079 /* #### This is a definite problem under Mule due to the amount of
2712 stack data it might allocate. Need to be able to convert and 3080 stack data it might allocate. Need to think about using Lstreams */
2713 write out to a file. */
2714 GET_STRING_BINARY_DATA_ALLOCA (data, bytes, len); 3081 GET_STRING_BINARY_DATA_ALLOCA (data, bytes, len);
2715 tbr.bytes = bytes; 3082 tbr.bytes = bytes;
2716 tbr.len = len; 3083 tbr.len = len;
2717 tbr.index = 0; 3084 tbr.index = 0;
2718 png_set_read_fn(png_ptr,(void *) &tbr, png_read_from_memory); 3085 png_set_read_fn(png_ptr,(void *) &tbr, png_read_from_memory);
2719 } 3086 }
2720 #endif
2721 3087
2722 png_read_info (png_ptr, info_ptr); 3088 png_read_info (png_ptr, info_ptr);
2723 3089
3090 #if 0
2724 /* set up the transformations you want. Note that these are 3091 /* set up the transformations you want. Note that these are
2725 all optional. Only call them if you want them */ 3092 all optional. Only call them if you want them */
2726 /* tell libpng to strip 16 bit depth files down to 8 bits */ 3093 /* tell libpng to strip 16 bit depth files down to 8 bits */
2727 if (info_ptr->bit_depth == 16) 3094 if (info_ptr->bit_depth == 16)
2728 png_set_strip_16 (png_ptr); 3095 png_set_strip_16 (png_ptr);
2741 png_byte *png_pixels; 3108 png_byte *png_pixels;
2742 png_byte **row_pointers; 3109 png_byte **row_pointers;
2743 png_color static_color_cube[216]; 3110 png_color static_color_cube[216];
2744 3111
2745 /* Wow, allocate all the memory. Truly, exciting. */ 3112 /* Wow, allocate all the memory. Truly, exciting. */
2746 unwind.pixels = xnew_array (unsigned long, 256); 3113 unwind.pixcount = 32;
3114 unwind.pixels = xnew_array (unsigned long, unwind.pixcount);
2747 png_pixels = xnew_array (png_byte, linesize * height); 3115 png_pixels = xnew_array (png_byte, linesize * height);
2748 row_pointers = xnew_array (png_byte *, height); 3116 row_pointers = xnew_array (png_byte *, height);
2749 3117
2750 for (y = 0; y < 256; y++)
2751 unwind.pixels[y] = 0;
2752 for (y = 0; y < height; y++) 3118 for (y = 0; y < height; y++)
2753 row_pointers[y] = png_pixels + (linesize * y); 3119 row_pointers[y] = png_pixels + (linesize * y);
2754 3120
2755 /* #### This is where we should handle transparency, but I am unsure of 3121 /* #### This is where we should handle transparency, but I am unsure of
2756 how exactly to get that information right now, in a safe manner. */ 3122 how exactly to get that information right now, in a safe manner. */
2768 png_set_background (png_ptr, &current_background, PNG_GAMMA_SCREEN, 3134 png_set_background (png_ptr, &current_background, PNG_GAMMA_SCREEN,
2769 0, 1.0); 3135 0, 1.0);
2770 } 3136 }
2771 #endif 3137 #endif
2772 3138
2773 if ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || 3139 if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
2774 (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) 3140 (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
3141 (vis->class == PseudoColor))
2775 { 3142 {
2776 if (!(info_ptr->valid & PNG_INFO_PLTE)) 3143 if (!(info_ptr->valid & PNG_INFO_PLTE))
2777 { 3144 {
2778 for (y = 0; y < 216; y++) 3145 for (y = 0; y < 216; y++)
2779 { 3146 {
2794 png_read_end (png_ptr, info_ptr); 3161 png_read_end (png_ptr, info_ptr);
2795 3162
2796 /* Ok, now we go and allocate all the colors */ 3163 /* Ok, now we go and allocate all the colors */
2797 if (info_ptr->valid & PNG_INFO_PLTE) 3164 if (info_ptr->valid & PNG_INFO_PLTE)
2798 { 3165 {
2799 unwind.npixels = info_ptr->num_palette; 3166 unwind.npixels = 0;
2800 for (y = 0; y < unwind.npixels; y++) 3167 for (y = 0; y < info_ptr->num_palette; y++)
2801 { 3168 {
3169 int res;
2802 color.red = info_ptr->palette[y].red << 8; 3170 color.red = info_ptr->palette[y].red << 8;
2803 color.green = info_ptr->palette[y].green << 8; 3171 color.green = info_ptr->palette[y].green << 8;
2804 color.blue = info_ptr->palette[y].blue << 8; 3172 color.blue = info_ptr->palette[y].blue << 8;
2805 color.flags = DoRed | DoGreen | DoBlue; 3173 color.flags = DoRed | DoGreen | DoBlue;
2806 allocate_nearest_color (dpy, cmap, vis, &color); 3174 res = allocate_nearest_color (dpy, cmap, vis, &color);
2807 unwind.pixels[y] = color.pixel; 3175 if (res > 0 && res < 3)
3176 {
3177 DO_REALLOC(unwind.pixels, unwind.pixcount, unwind.npixels+1, unsigned long);
3178 unwind.pixels[unwind.npixels] = color.pixel;
3179 unwind.npixels++;
3180 }
2808 } 3181 }
2809 } 3182 }
2810 else 3183 else
2811 { 3184 {
2812 unwind.npixels = 216; 3185 unwind.npixels = 0;
2813 for (y = 0; y < 216; y++) 3186 for (y = 0; y < 216; y++)
2814 { 3187 {
3188 int res;
2815 color.red = static_color_cube[y].red << 8; 3189 color.red = static_color_cube[y].red << 8;
2816 color.green = static_color_cube[y].green << 8; 3190 color.green = static_color_cube[y].green << 8;
2817 color.blue = static_color_cube[y].blue << 8; 3191 color.blue = static_color_cube[y].blue << 8;
2818 color.flags = DoRed|DoGreen|DoBlue; 3192 color.flags = DoRed|DoGreen|DoBlue;
2819 allocate_nearest_color (dpy, cmap, vis, &color); 3193 res = allocate_nearest_color (dpy, cmap, vis, &color);
2820 unwind.pixels[y] = color.pixel; 3194 if (res > 0 && res < 3)
3195 {
3196 unwind.pixels[unwind.npixels] = color.pixel;
3197 unwind.npixels++;
3198 }
2821 } 3199 }
2822 } 3200 }
2823 3201
2824 #ifdef PNG_SHOW_COMMENTS 3202 #ifdef PNG_SHOW_COMMENTS
2825 /* #### 3203 /* ####
2875 } 3253 }
2876 3254
2877 xfree (row_pointers); 3255 xfree (row_pointers);
2878 xfree (png_pixels); 3256 xfree (png_pixels);
2879 } 3257 }
3258 #else
3259 {
3260 int height = info_ptr->height;
3261 int width = info_ptr->width;
3262 int y;
3263 unsigned char **row_pointers;
3264
3265 /* Wow, allocate all the memory. Truly, exciting. */
3266 unwind.eimage = xnew_array_and_zero (unsigned char, width * height * 3);
3267 /* libpng expects that the image buffer passed in contains a
3268 picture to draw on top of if the png has any transparencies.
3269 This could be a good place to pass that in... */
3270
3271 row_pointers = xnew_array (png_byte *, height);
3272
3273 for (y = 0; y < height; y++)
3274 row_pointers[y] = unwind.eimage + (width * 3 * y);
3275
3276 /* Now that we're using EImage, ask for 8bit RGB triples for any type
3277 of image*/
3278 /* convert palatte images to full RGB */
3279 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3280 png_set_expand(png_ptr);
3281 /* send grayscale images to RGB too */
3282 if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY ||
3283 info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
3284 png_set_gray_to_rgb(png_ptr);
3285 /* we can't handle alpha values */
3286 if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
3287 png_set_strip_alpha(png_ptr);
3288 /* rip out any transparancy layers/colors */
3289 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
3290 png_set_expand(png_ptr);
3291 png_set_strip_alpha(png_ptr);
3292 }
3293 /* tell libpng to strip 16 bit depth files down to 8 bits */
3294 if (info_ptr->bit_depth == 16)
3295 png_set_strip_16 (png_ptr);
3296 /* if the image is < 8 bits, pad it out */
3297 if (info_ptr->bit_depth < 8) {
3298 if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3299 png_set_expand(png_ptr);
3300 else
3301 png_set_packing (png_ptr);
3302 }
3303
3304 #if 1 /* tests? or permanent? */
3305 {
3306 /* if the png specifies a background chunk, go ahead and
3307 use it */
3308 png_color_16 my_background, *image_background;
3309
3310 /* ### how do I get the background of the current frame? */
3311 my_background.red = 0x7fff;
3312 my_background.green = 0x7fff;
3313 my_background.blue = 0x7fff;
3314
3315 if (png_get_bKGD(png_ptr, info_ptr, &image_background))
3316 png_set_background(png_ptr, image_background,
3317 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
3318 else
3319 png_set_background(png_ptr, &my_background,
3320 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
3321 }
3322 #endif
3323 png_read_image (png_ptr, row_pointers);
3324 png_read_end (png_ptr, info_ptr);
3325
3326 #ifdef PNG_SHOW_COMMENTS
3327 /* ####
3328 * I turn this off by default now, because the !%^@#!% comments
3329 * show up every time the image is instantiated, which can get
3330 * really really annoying. There should be some way to pass this
3331 * type of data down into the glyph code, where you can get to it
3332 * from lisp anyway. - WMP
3333 */
3334 {
3335 int i;
3336
3337 for (i = 0 ; i < info_ptr->num_text ; i++)
3338 {
3339 /* How paranoid do I have to be about no trailing NULLs, and
3340 using (int)info_ptr->text[i].text_length, and strncpy and a temp
3341 string somewhere? */
3342
3343 warn_when_safe (Qpng, Qinfo, "%s - %s",
3344 info_ptr->text[i].key,
3345 info_ptr->text[i].text);
3346 }
3347 }
3348 #endif
3349
3350 xfree (row_pointers);
3351 unwind.ximage = EImage2XImage (device, width, height, unwind.eimage,
3352 &unwind.pixels, &unwind.pixcount, &unwind.npixels);
3353 if (!unwind.ximage)
3354 signal_simple_error("PNG conversion failed", instantiator);
3355 }
3356 #endif
2880 3357
2881 init_image_instance_from_x_image (ii, unwind.ximage, dest_mask, 3358 init_image_instance_from_x_image (ii, unwind.ximage, dest_mask,
2882 unwind.pixels, unwind.npixels, 3359 unwind.pixels, unwind.npixels,
2883 instantiator); 3360 instantiator);
2884 3361
2885 /* This will clean up everything else. */ 3362 /* This will clean up everything else. */
2886 unwind.npixels = 0; 3363 unwind.npixels = 0;
3364 unwind.pixcount = 0;
2887 unbind_to (speccount, Qnil); 3365 unbind_to (speccount, Qnil);
2888 } 3366 }
2889 3367
2890 #endif /* HAVE_PNG */ 3368 #endif /* HAVE_PNG */
2891 3369
2892 3370
2893 #ifdef HAVE_TIFF 3371 #ifdef HAVE_TIFF
3372 #include "tiffio.h"
2894 3373
2895 /********************************************************************** 3374 /**********************************************************************
2896 * TIFF * 3375 * TIFF *
2897 **********************************************************************/ 3376 **********************************************************************/
2898 static void 3377 static void
2902 } 3381 }
2903 3382
2904 static Lisp_Object 3383 static Lisp_Object
2905 tiff_normalize (Lisp_Object inst, Lisp_Object console_type) 3384 tiff_normalize (Lisp_Object inst, Lisp_Object console_type)
2906 { 3385 {
2907 signal_simple_error ("No TIFF support yet", inst); 3386 return simple_image_type_normalize (inst, console_type, Qtiff);
2908 return Qnil;
2909 } 3387 }
2910 3388
2911 static int 3389 static int
2912 tiff_possible_dest_types (void) 3390 tiff_possible_dest_types (void)
2913 { 3391 {
2914 return IMAGE_COLOR_PIXMAP_MASK; 3392 return IMAGE_COLOR_PIXMAP_MASK;
3393 }
3394
3395 struct tiff_unwind_data
3396 {
3397 Display *dpy;
3398 Colormap cmap;
3399 unsigned char *eimage;
3400 /* Object that holds the decoded data from a TIFF file */
3401 TIFF *tiff;
3402 /* Pixels to keep around while the image is active */
3403 unsigned long *pixels;
3404 int npixels,pixcount;
3405 /* Client-side image structure */
3406 XImage *ximage;
3407 };
3408
3409 static Lisp_Object
3410 tiff_instantiate_unwind (Lisp_Object unwind_obj)
3411 {
3412 struct tiff_unwind_data *data =
3413 (struct tiff_unwind_data *) get_opaque_ptr (unwind_obj);
3414
3415 free_opaque_ptr (unwind_obj);
3416 if (data->tiff)
3417 {
3418 TIFFClose(data->tiff);
3419 }
3420 if (data->eimage)
3421 xfree(data->eimage);
3422 if (data->npixels > 0)
3423 XFreeColors (data->dpy, data->cmap, data->pixels, data->npixels, 0L);
3424 if (data->pixcount)
3425 xfree (data->pixels);
3426 if (data->ximage)
3427 {
3428 if (data->ximage->data)
3429 {
3430 xfree (data->ximage->data);
3431 data->ximage->data = 0;
3432 }
3433 XDestroyImage (data->ximage);
3434 }
3435
3436 return Qnil;
3437 }
3438
3439 typedef struct tiff_memory_storage
3440 {
3441 Extbyte *bytes; /* The data */
3442 Extcount len; /* How big is it? */
3443 int index; /* Where are we? */
3444 } tiff_memory_storage;
3445
3446 static size_t tiff_memory_read(thandle_t data, tdata_t buf, tsize_t size)
3447 {
3448 tiff_memory_storage *mem = (tiff_memory_storage*)data;
3449
3450 if (size > (mem->len - mem->index))
3451 return -1;
3452 memcpy(buf, mem->bytes + mem->index, size);
3453 mem->index = mem->index + size;
3454 return size;
3455 }
3456
3457 static size_t tiff_memory_write(thandle_t data, tdata_t buf, tsize_t size)
3458 {
3459 abort();
3460 }
3461
3462 static toff_t tiff_memory_seek(thandle_t data, toff_t off, int whence)
3463 {
3464 tiff_memory_storage *mem = (tiff_memory_storage*)data;
3465 int newidx;
3466 switch(whence) {
3467 case SEEK_SET:
3468 newidx = off;
3469 break;
3470 case SEEK_END:
3471 newidx = mem->len + off;
3472 break;
3473 case SEEK_CUR:
3474 newidx = mem->index + off;
3475 break;
3476 default:
3477 fprintf(stderr,"Eh? invalid seek mode in tiff_memory_seek\n");
3478 return -1;
3479 }
3480
3481 if ((newidx > mem->len) || (newidx < 0))
3482 return -1;
3483
3484 mem->index = newidx;
3485 return newidx;
3486 }
3487
3488 static int tiff_memory_close(thandle_t data)
3489 {
3490 return 0;
3491 }
3492
3493 static int tiff_map_noop(thandle_t data, tdata_t* pbase, toff_t* psize)
3494 {
3495 return 0;
3496 }
3497
3498 static void tiff_unmap_noop(thandle_t data, tdata_t pbase, toff_t psize)
3499 {
3500 return;
3501 }
3502
3503 static toff_t tiff_memory_size(thandle_t data)
3504 {
3505 tiff_memory_storage *mem = (tiff_memory_storage*)data;
3506 return mem->len;
3507 }
3508
3509 struct tiff_error_struct
3510 {
3511 #if HAVE_VSNPRINTF
3512 char err_str[256];
3513 #else
3514 char err_str[1024]; /* return the error string */
3515 #endif
3516 jmp_buf setjmp_buffer; /* for return to caller */
3517 };
3518
3519 /* jh 98/03/12 - ###This struct for passing data to the error functions
3520 is an ugly hack caused by the fact that libtiff (as of v3.4) doesn't
3521 have any place to store error func data. This should be rectified
3522 before XEmacs gets threads! */
3523 static struct tiff_error_struct tiff_err_data;
3524
3525 static void tiff_error_func(CONST char *module, CONST char *fmt, ...)
3526 {
3527 va_list vargs;
3528
3529 va_start (vargs, fmt);
3530 #if HAVE_VSNPRINTF
3531 vsnprintf(tiff_err_data.err_str, 255, fmt, vargs);
3532 #else
3533 /* pray this doesn't overflow... */
3534 vsprintf(tiff_err_data.err_str, fmt, vargs);
3535 #endif
3536 va_end(vargs);
3537 /* return to setjmp point */
3538 longjmp (tiff_err_data.setjmp_buffer, 1);
3539 }
3540
3541 static void tiff_warning_func(CONST char *module, CONST char *fmt, ...)
3542 {
3543 va_list vargs;
3544 #if HAVE_VSNPRINTF
3545 char warn_str[256];
3546 #else
3547 char warn_str[1024];
3548 #endif
3549
3550 va_start (vargs, fmt);
3551 #if HAVE_VSNPRINTF
3552 vsnprintf(warn_str, 255, fmt, vargs);
3553 #else
3554 vsprintf(warn_str, fmt, vargs);
3555 #endif
3556 va_end(vargs);
3557 warn_when_safe (Qtiff, Qinfo, "%s - %s",
3558 module, warn_str);
2915 } 3559 }
2916 3560
2917 static void 3561 static void
2918 tiff_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, 3562 tiff_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2919 Lisp_Object pointer_fg, Lisp_Object pointer_bg, 3563 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2920 int dest_mask, Lisp_Object domain) 3564 int dest_mask, Lisp_Object domain)
2921 { 3565 {
2922 abort (); 3566 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
3567 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
3568 Colormap cmap;
3569 Display *dpy;
3570 tiff_memory_storage mem_struct;
3571 /* It is OK for the unwind data to be local to this function,
3572 because the unwind-protect is always executed when this
3573 stack frame is still valid. */
3574 struct tiff_unwind_data unwind;
3575 int speccount = specpdl_depth ();
3576
3577 if (!DEVICE_X_P (XDEVICE (device)))
3578 signal_simple_error ("Not an X device", device);
3579
3580 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
3581 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
3582
3583 memset (&unwind, 0, sizeof (unwind));
3584 unwind.dpy = dpy;
3585 unwind.cmap = cmap;
3586 record_unwind_protect (tiff_instantiate_unwind, make_opaque_ptr (&unwind));
3587
3588 /* set up error facilities */
3589 if (setjmp(tiff_err_data.setjmp_buffer)) {
3590 /* An error was signaled. No clean up is needed, as unwind handles that
3591 for us. Just pass the error along. */
3592 Lisp_Object errstring;
3593 errstring = build_string (tiff_err_data.err_str);
3594 signal_simple_error_2 ("TIFF decoding error", errstring, instantiator);
3595 }
3596 TIFFSetErrorHandler((TIFFErrorHandler)tiff_error_func);
3597 TIFFSetWarningHandler((TIFFErrorHandler)tiff_warning_func);
3598 {
3599 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
3600 Extbyte *bytes;
3601 Extcount len;
3602
3603 uint32 width, height;
3604 uint32 *raster;
3605 unsigned char *ep;
3606
3607 assert (!NILP (data));
3608
3609 /* #### This is a definite problem under Mule due to the amount of
3610 stack data it might allocate. Think about Lstreams... */
3611 GET_STRING_BINARY_DATA_ALLOCA (data, bytes, len);
3612 mem_struct.bytes = bytes;
3613 mem_struct.len = len;
3614 mem_struct.index = 0;
3615
3616 unwind.tiff = TIFFClientOpen("memfile", "r", &mem_struct,
3617 (TIFFReadWriteProc)tiff_memory_read,
3618 (TIFFReadWriteProc)tiff_memory_write,
3619 tiff_memory_seek, tiff_memory_close, tiff_memory_size,
3620 tiff_map_noop, tiff_unmap_noop);
3621 if (!unwind.tiff)
3622 signal_simple_error ("Insufficent memory to instantiate TIFF image", instantiator);
3623
3624 TIFFGetField(unwind.tiff, TIFFTAG_IMAGEWIDTH, &width);
3625 TIFFGetField(unwind.tiff, TIFFTAG_IMAGELENGTH, &height);
3626 unwind.eimage = xmalloc(width * height * 3);
3627
3628 /* ### This is little more than proof-of-concept/function testing.
3629 It needs to be reimplimented via scanline reads for both memory
3630 compactness. */
3631 raster = (uint32*) _TIFFmalloc(width * height * sizeof (uint32));
3632 if (raster != NULL) {
3633 int i,j;
3634 uint32 *rp;
3635 ep = unwind.eimage;
3636 rp = raster;
3637 if (TIFFReadRGBAImage(unwind.tiff, width, height, raster, 0)) {
3638 for (i = height - 1; i >= 0; i--) {
3639 /* This is to get around weirdness in the libtiff library where properly
3640 made TIFFs will come out upside down. libtiff bug or jhod-brainlock? */
3641 rp = raster + (i * width);
3642 for (j = 0; j < width; j++) {
3643 *ep++ = (unsigned char)TIFFGetR(*rp);
3644 *ep++ = (unsigned char)TIFFGetG(*rp);
3645 *ep++ = (unsigned char)TIFFGetB(*rp);
3646 rp++;
3647 }
3648 }
3649 }
3650 _TIFFfree(raster);
3651 } else
3652 signal_simple_error ("Unable to allocate memory for TIFFReadRGBA", instantiator);
3653
3654 unwind.ximage = EImage2XImage (device, width, height, unwind.eimage,
3655 &unwind.pixels, &unwind.pixcount, &unwind.npixels);
3656 if (!unwind.ximage)
3657 signal_simple_error("TIFF conversion failed", instantiator);
3658 }
3659 /* Now create the pixmap and set up the image instance */
3660 init_image_instance_from_x_image (ii, unwind.ximage, dest_mask,
3661 unwind.pixels, unwind.npixels,
3662 instantiator);
3663 /* Now that we've succeeded, we don't want the pixels
3664 freed right now. They're kept around in the image instance
3665 structure until it's destroyed. */
3666 unwind.npixels = 0;
3667 unwind.pixcount = 0;
3668 unbind_to (speccount, Qnil);
2923 } 3669 }
2924 3670
2925 #endif /* HAVE_TIFF */ 3671 #endif /* HAVE_TIFF */
2926 3672
2927 3673