Mercurial > hg > xemacs-beta
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, ¤t_background, PNG_GAMMA_SCREEN, | 3134 png_set_background (png_ptr, ¤t_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 |