Mercurial > hg > xemacs-beta
comparison src/glyphs-x.c @ 290:c9fe270a4101 r21-0b43
Import from CVS: tag r21-0b43
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:36:47 +0200 |
parents | e11d67e05968 |
children | 70ad99077275 |
comparison
equal
deleted
inserted
replaced
289:6e6992ccc4b6 | 290:c9fe270a4101 |
---|---|
59 | 59 |
60 #include "imgproc.h" | 60 #include "imgproc.h" |
61 | 61 |
62 #include "sysfile.h" | 62 #include "sysfile.h" |
63 | 63 |
64 #ifdef HAVE_PNG | |
65 #ifdef __cplusplus | |
66 extern "C" { | |
67 #endif | |
68 #include <png.h> | |
69 #ifdef __cplusplus | |
70 } | |
71 #endif | |
72 #else | |
73 #include <setjmp.h> | 64 #include <setjmp.h> |
74 #endif | 65 |
75 #ifdef FILE_CODING | 66 #ifdef FILE_CODING |
76 #include "file-coding.h" | 67 #include "file-coding.h" |
77 #endif | 68 #endif |
78 | |
79 #undef HAVE_PNG | |
80 #undef HAVE_TIFF | |
81 #undef HAVE_JPEG | |
82 #undef HAVE_GIF | |
83 | 69 |
84 #if INTBITS == 32 | 70 #if INTBITS == 32 |
85 # define FOUR_BYTE_TYPE unsigned int | 71 # define FOUR_BYTE_TYPE unsigned int |
86 #elif LONGBITS == 32 | 72 #elif LONGBITS == 32 |
87 # define FOUR_BYTE_TYPE unsigned long | 73 # define FOUR_BYTE_TYPE unsigned long |
94 #define LISP_DEVICE_TO_X_SCREEN(dev) XDefaultScreenOfDisplay (DEVICE_X_DISPLAY (XDEVICE (dev))) | 80 #define LISP_DEVICE_TO_X_SCREEN(dev) XDefaultScreenOfDisplay (DEVICE_X_DISPLAY (XDEVICE (dev))) |
95 | 81 |
96 #ifdef HAVE_XFACE | 82 #ifdef HAVE_XFACE |
97 DEFINE_IMAGE_INSTANTIATOR_FORMAT (xface); | 83 DEFINE_IMAGE_INSTANTIATOR_FORMAT (xface); |
98 Lisp_Object Qxface; | 84 Lisp_Object Qxface; |
99 #endif | |
100 | |
101 #ifdef HAVE_TIFF | |
102 DEFINE_IMAGE_INSTANTIATOR_FORMAT (tiff); | |
103 Lisp_Object Qtiff; | |
104 #endif | |
105 | |
106 #ifdef HAVE_JPEG | |
107 DEFINE_IMAGE_INSTANTIATOR_FORMAT (jpeg); | |
108 Lisp_Object Qjpeg; | |
109 #endif | |
110 | |
111 #ifdef HAVE_GIF | |
112 DEFINE_IMAGE_INSTANTIATOR_FORMAT (gif); | |
113 Lisp_Object Qgif; | |
114 #endif | |
115 | |
116 #ifdef HAVE_PNG | |
117 DEFINE_IMAGE_INSTANTIATOR_FORMAT (png); | |
118 Lisp_Object Qpng; | |
119 #endif | 85 #endif |
120 | 86 |
121 DEFINE_IMAGE_INSTANTIATOR_FORMAT (cursor_font); | 87 DEFINE_IMAGE_INSTANTIATOR_FORMAT (cursor_font); |
122 Lisp_Object Qcursor_font; | 88 Lisp_Object Qcursor_font; |
123 | 89 |
1497 } | 1463 } |
1498 | 1464 |
1499 #endif /* HAVE_XPM */ | 1465 #endif /* HAVE_XPM */ |
1500 | 1466 |
1501 | 1467 |
1502 #ifdef HAVE_JPEG | |
1503 | |
1504 /********************************************************************** | |
1505 * JPEG * | |
1506 **********************************************************************/ | |
1507 | |
1508 #ifdef __cplusplus | |
1509 extern "C" { | |
1510 #endif | |
1511 #include <jpeglib.h> | |
1512 #include <jerror.h> | |
1513 #ifdef __cplusplus | |
1514 } | |
1515 #endif | |
1516 | |
1517 /*#define USE_TEMP_FILES_FOR_JPEG_IMAGES 1*/ | |
1518 static void | |
1519 jpeg_validate (Lisp_Object instantiator) | |
1520 { | |
1521 file_or_data_must_be_present (instantiator); | |
1522 } | |
1523 | |
1524 static Lisp_Object | |
1525 jpeg_normalize (Lisp_Object inst, Lisp_Object console_type) | |
1526 { | |
1527 return simple_image_type_normalize (inst, console_type, Qjpeg); | |
1528 } | |
1529 | |
1530 static int | |
1531 jpeg_possible_dest_types (void) | |
1532 { | |
1533 return IMAGE_COLOR_PIXMAP_MASK; | |
1534 } | |
1535 | |
1536 /* To survive the otherwise baffling complexity of making sure | |
1537 everything gets cleaned up in the presence of an error, we | |
1538 use an unwind_protect(). */ | |
1539 | |
1540 struct jpeg_unwind_data | |
1541 { | |
1542 Display *dpy; | |
1543 Colormap cmap; | |
1544 /* Stream that we need to close */ | |
1545 FILE *instream; | |
1546 /* Object that holds state info for JPEG decoding */ | |
1547 struct jpeg_decompress_struct *cinfo_ptr; | |
1548 /* EImage data */ | |
1549 unsigned char *eimage; | |
1550 /* Pixels to keep around while the image is active */ | |
1551 unsigned long *pixels; | |
1552 int npixels, pixcount; | |
1553 /* Client-side image structure */ | |
1554 XImage *ximage; | |
1555 /* Tempfile to remove */ | |
1556 #ifdef USE_TEMP_FILES_FOR_JPEG_IMAGES | |
1557 char tempfile[50]; | |
1558 int tempfile_needs_to_be_removed; | |
1559 #endif | |
1560 }; | |
1561 | |
1562 static Lisp_Object | |
1563 jpeg_instantiate_unwind (Lisp_Object unwind_obj) | |
1564 { | |
1565 struct jpeg_unwind_data *data = | |
1566 (struct jpeg_unwind_data *) get_opaque_ptr (unwind_obj); | |
1567 | |
1568 free_opaque_ptr (unwind_obj); | |
1569 if (data->cinfo_ptr) | |
1570 jpeg_destroy_decompress (data->cinfo_ptr); | |
1571 | |
1572 if (data->instream) | |
1573 fclose (data->instream); | |
1574 | |
1575 if (data->eimage) xfree (data->eimage); | |
1576 | |
1577 if (data->npixels > 0) | |
1578 XFreeColors (data->dpy, data->cmap, data->pixels, data->npixels, 0L); | |
1579 if (data->pixcount) | |
1580 xfree (data->pixels); | |
1581 | |
1582 if (data->ximage) | |
1583 { | |
1584 if (data->ximage->data) | |
1585 { | |
1586 xfree (data->ximage->data); | |
1587 data->ximage->data = 0; | |
1588 } | |
1589 XDestroyImage (data->ximage); | |
1590 } | |
1591 #if USE_TEMP_FILES_FOR_JPEG_IMAGES | |
1592 if (data->tempfile_needs_to_be_removed) | |
1593 unlink (data->tempfile); | |
1594 #endif | |
1595 | |
1596 return Qnil; | |
1597 } | |
1598 | |
1599 /* | |
1600 * ERROR HANDLING: | |
1601 * | |
1602 * The JPEG library's standard error handler (jerror.c) is divided into | |
1603 * several "methods" which you can override individually. This lets you | |
1604 * adjust the behavior without duplicating a lot of code, which you might | |
1605 * have to update with each future release. | |
1606 * | |
1607 * Our example here shows how to override the "error_exit" method so that | |
1608 * control is returned to the library's caller when a fatal error occurs, | |
1609 * rather than calling exit() as the standard error_exit method does. | |
1610 * | |
1611 * We use C's setjmp/longjmp facility to return control. This means that the | |
1612 * routine which calls the JPEG library must first execute a setjmp() call to | |
1613 * establish the return point. We want the replacement error_exit to do a | |
1614 * longjmp(). But we need to make the setjmp buffer accessible to the | |
1615 * error_exit routine. To do this, we make a private extension of the | |
1616 * standard JPEG error handler object. (If we were using C++, we'd say we | |
1617 * were making a subclass of the regular error handler.) | |
1618 * | |
1619 * Here's the extended error handler struct: | |
1620 */ | |
1621 | |
1622 struct my_jpeg_error_mgr | |
1623 { | |
1624 struct jpeg_error_mgr pub; /* "public" fields */ | |
1625 jmp_buf setjmp_buffer; /* for return to caller */ | |
1626 }; | |
1627 | |
1628 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61) | |
1629 METHODDEF(void) | |
1630 #else | |
1631 METHODDEF void | |
1632 #endif | |
1633 our_init_source (j_decompress_ptr cinfo) | |
1634 { | |
1635 } | |
1636 | |
1637 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61) | |
1638 METHODDEF(boolean) | |
1639 #else | |
1640 METHODDEF boolean | |
1641 #endif | |
1642 our_fill_input_buffer (j_decompress_ptr cinfo) | |
1643 { | |
1644 /* Insert a fake EOI marker */ | |
1645 struct jpeg_source_mgr *src = cinfo->src; | |
1646 static JOCTET buffer[2]; | |
1647 | |
1648 buffer[0] = (JOCTET) 0xFF; | |
1649 buffer[1] = (JOCTET) JPEG_EOI; | |
1650 | |
1651 src->next_input_byte = buffer; | |
1652 src->bytes_in_buffer = 2; | |
1653 return TRUE; | |
1654 } | |
1655 | |
1656 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61) | |
1657 METHODDEF(void) | |
1658 #else | |
1659 METHODDEF void | |
1660 #endif | |
1661 our_skip_input_data (j_decompress_ptr cinfo, long num_bytes) | |
1662 { | |
1663 struct jpeg_source_mgr *src = NULL; | |
1664 | |
1665 src = (struct jpeg_source_mgr *) cinfo->src; | |
1666 | |
1667 if (!src) | |
1668 { | |
1669 return; | |
1670 } else if (num_bytes > src->bytes_in_buffer) | |
1671 { | |
1672 ERREXIT(cinfo, JERR_INPUT_EOF); | |
1673 /*NOTREACHED*/ | |
1674 } | |
1675 | |
1676 src->bytes_in_buffer -= num_bytes; | |
1677 src->next_input_byte += num_bytes; | |
1678 } | |
1679 | |
1680 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61) | |
1681 METHODDEF(void) | |
1682 #else | |
1683 METHODDEF void | |
1684 #endif | |
1685 our_term_source (j_decompress_ptr cinfo) | |
1686 { | |
1687 } | |
1688 | |
1689 typedef struct | |
1690 { | |
1691 struct jpeg_source_mgr pub; | |
1692 } our_jpeg_source_mgr; | |
1693 | |
1694 static void | |
1695 jpeg_memory_src (j_decompress_ptr cinfo, JOCTET *data, unsigned int len) | |
1696 { | |
1697 struct jpeg_source_mgr *src; | |
1698 | |
1699 if (cinfo->src == NULL) | |
1700 { /* first time for this JPEG object? */ | |
1701 cinfo->src = (struct jpeg_source_mgr *) | |
1702 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, | |
1703 sizeof(our_jpeg_source_mgr)); | |
1704 src = (struct jpeg_source_mgr *) cinfo->src; | |
1705 src->next_input_byte = data; | |
1706 } | |
1707 src = (struct jpeg_source_mgr *) cinfo->src; | |
1708 src->init_source = our_init_source; | |
1709 src->fill_input_buffer = our_fill_input_buffer; | |
1710 src->skip_input_data = our_skip_input_data; | |
1711 src->resync_to_restart = jpeg_resync_to_restart; /* use default method */ | |
1712 src->term_source = our_term_source; | |
1713 src->bytes_in_buffer = len; | |
1714 src->next_input_byte = data; | |
1715 } | |
1716 | |
1717 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61) | |
1718 METHODDEF(void) | |
1719 #else | |
1720 METHODDEF void | |
1721 #endif | |
1722 my_jpeg_error_exit (j_common_ptr cinfo) | |
1723 { | |
1724 /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ | |
1725 struct my_jpeg_error_mgr *myerr = (struct my_jpeg_error_mgr *) cinfo->err; | |
1726 | |
1727 /* Return control to the setjmp point */ | |
1728 longjmp (myerr->setjmp_buffer, 1); | |
1729 } | |
1730 | |
1731 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61) | |
1732 METHODDEF(void) | |
1733 #else | |
1734 METHODDEF void | |
1735 #endif | |
1736 my_jpeg_output_message (j_common_ptr cinfo) | |
1737 { | |
1738 char buffer[JMSG_LENGTH_MAX]; | |
1739 | |
1740 /* Create the message */ | |
1741 (*cinfo->err->format_message) (cinfo, buffer); | |
1742 warn_when_safe (Qjpeg, Qinfo, "%s", buffer); | |
1743 } | |
1744 | |
1745 /* The code in this routine is based on example.c from the JPEG library | |
1746 source code and from gif_instantiate() */ | |
1747 static void | |
1748 jpeg_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
1749 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
1750 int dest_mask, Lisp_Object domain) | |
1751 { | |
1752 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
1753 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
1754 Display *dpy; | |
1755 Colormap cmap; | |
1756 Visual *vis; | |
1757 /* It is OK for the unwind data to be local to this function, | |
1758 because the unwind-protect is always executed when this | |
1759 stack frame is still valid. */ | |
1760 struct jpeg_unwind_data unwind; | |
1761 int speccount = specpdl_depth (); | |
1762 | |
1763 /* This struct contains the JPEG decompression parameters and pointers to | |
1764 * working space (which is allocated as needed by the JPEG library). | |
1765 */ | |
1766 struct jpeg_decompress_struct cinfo; | |
1767 /* We use our private extension JPEG error handler. | |
1768 * Note that this struct must live as long as the main JPEG parameter | |
1769 * struct, to avoid dangling-pointer problems. | |
1770 */ | |
1771 struct my_jpeg_error_mgr jerr; | |
1772 | |
1773 if (!DEVICE_X_P (XDEVICE (device))) | |
1774 signal_simple_error ("Not an X device", device); | |
1775 | |
1776 dpy = DEVICE_X_DISPLAY (XDEVICE (device)); | |
1777 cmap = DEVICE_X_COLORMAP (XDEVICE(device)); | |
1778 vis = DEVICE_X_VISUAL (XDEVICE(device)); | |
1779 | |
1780 /* Step -1: First record our unwind-protect, which will clean up after | |
1781 any exit, normal or not */ | |
1782 | |
1783 xzero (unwind); | |
1784 unwind.dpy = dpy; | |
1785 unwind.cmap = cmap; | |
1786 record_unwind_protect (jpeg_instantiate_unwind, make_opaque_ptr (&unwind)); | |
1787 | |
1788 #ifdef USE_TEMP_FILES_FOR_JPEG_IMAGES | |
1789 /* Step 0: Write out to a temp file. | |
1790 | |
1791 The JPEG routines require you to read from a file unless | |
1792 you provide your own special input handlers, which I don't | |
1793 feel like doing. */ | |
1794 { | |
1795 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
1796 | |
1797 assert (!NILP (data)); | |
1798 | |
1799 write_lisp_string_to_temp_file (data, unwind.tempfile); | |
1800 unwind.tempfile_needs_to_be_removed = 1; | |
1801 | |
1802 /* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that | |
1803 * requires it in order to read binary files. | |
1804 */ | |
1805 | |
1806 if ((unwind.instream = fopen (unwind.tempfile, "r")) == NULL) | |
1807 report_file_error ("Opening JPEG temp file", | |
1808 list1 (build_string (unwind.tempfile))); | |
1809 } | |
1810 #endif | |
1811 | |
1812 /* Step 1: allocate and initialize JPEG decompression object */ | |
1813 | |
1814 /* We set up the normal JPEG error routines, then override error_exit. */ | |
1815 cinfo.err = jpeg_std_error (&jerr.pub); | |
1816 jerr.pub.error_exit = my_jpeg_error_exit; | |
1817 jerr.pub.output_message = my_jpeg_output_message; | |
1818 | |
1819 /* Establish the setjmp return context for my_error_exit to use. */ | |
1820 if (setjmp (jerr.setjmp_buffer)) | |
1821 { | |
1822 /* If we get here, the JPEG code has signaled an error. | |
1823 * We need to clean up the JPEG object, close the input file, and return. | |
1824 */ | |
1825 | |
1826 { | |
1827 Lisp_Object errstring; | |
1828 char buffer[JMSG_LENGTH_MAX]; | |
1829 | |
1830 /* Create the message */ | |
1831 (*cinfo.err->format_message) ((j_common_ptr) &cinfo, buffer); | |
1832 errstring = build_string (buffer); | |
1833 | |
1834 signal_image_error_2 ("JPEG decoding error", | |
1835 errstring, instantiator); | |
1836 } | |
1837 } | |
1838 | |
1839 /* Now we can initialize the JPEG decompression object. */ | |
1840 jpeg_create_decompress (&cinfo); | |
1841 unwind.cinfo_ptr = &cinfo; | |
1842 | |
1843 /* Step 2: specify data source (eg, a file) */ | |
1844 | |
1845 #ifdef USE_TEMP_FILES_FOR_JPEG_IMAGES | |
1846 jpeg_stdio_src (&cinfo, unwind.instream); | |
1847 #else | |
1848 { | |
1849 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
1850 CONST Extbyte *bytes; | |
1851 Extcount len; | |
1852 | |
1853 /* #### This is a definite problem under Mule due to the amount of | |
1854 stack data it might allocate. Need to be able to convert and | |
1855 write out to a file. */ | |
1856 GET_STRING_BINARY_DATA_ALLOCA (data, bytes, len); | |
1857 jpeg_memory_src (&cinfo, (JOCTET *) bytes, len); | |
1858 } | |
1859 #endif | |
1860 | |
1861 /* Step 3: read file parameters with jpeg_read_header() */ | |
1862 | |
1863 jpeg_read_header (&cinfo, TRUE); | |
1864 /* We can ignore the return value from jpeg_read_header since | |
1865 * (a) suspension is not possible with the stdio data source, and | |
1866 * (b) we passed TRUE to reject a tables-only JPEG file as an error. | |
1867 * See libjpeg.doc for more info. | |
1868 */ | |
1869 | |
1870 #if 0 | |
1871 /* Step 4: set parameters for decompression. */ | |
1872 | |
1873 if (vis->class == PseudoColor) | |
1874 { | |
1875 | |
1876 /* We request that the JPEG file be automatically quantized into | |
1877 8-bit color in case it's not already (many JPEGs are stored in | |
1878 24-bit color). "Two-pass quantize" means that the colormap | |
1879 is determined on-the-fly for this particular image rather than | |
1880 quantizing to a supplied colormap. We can get away with this | |
1881 because we then use allocate_nearest_color(). | |
1882 | |
1883 #### Note of course that this is not the most color-effective | |
1884 way of doing things -- we could quantize an image that has | |
1885 lots of very similar colors, and eat up the colormap with these | |
1886 (useless to other images) colors. Unfortunately I don't think | |
1887 there's any "general" way of maximizing the overall image | |
1888 quality of lots of images, given that we don't know the | |
1889 colors of the images until we come across each one. Best we | |
1890 could do would be various sorts of heuristics, which I don't | |
1891 feel like dealing with now. A better scheme would be the | |
1892 way things are done under MS Windows, where the colormap is | |
1893 dynamically adjusted for various applications; but that kind | |
1894 of thing would have to be provided by X, which it isn't. */ | |
1895 | |
1896 cinfo.quantize_colors = TRUE; | |
1897 cinfo.two_pass_quantize = TRUE; | |
1898 cinfo.colormap = NULL; | |
1899 } | |
1900 | |
1901 /* Step 5: Start decompressor */ | |
1902 | |
1903 jpeg_start_decompress (&cinfo); | |
1904 /* We can ignore the return value since suspension is not possible | |
1905 * with the stdio data source. | |
1906 */ | |
1907 | |
1908 /* At this point we know the size of the image and the colormap. */ | |
1909 | |
1910 /* Step 5.33: Allocate the colors */ | |
1911 if (vis->class == PseudoColor) | |
1912 { | |
1913 int i; | |
1914 unwind.pixcount = 32; | |
1915 unwind.pixels = xnew_array (unsigned long, unwind.pixcount); | |
1916 unwind.npixels = 0; | |
1917 | |
1918 /* Allocate pixels for the various colors. */ | |
1919 for (i = 0; i < cinfo.actual_number_of_colors; i++) | |
1920 { | |
1921 XColor color; | |
1922 int ri, gi, bi, res; | |
1923 | |
1924 ri = 0; | |
1925 gi = cinfo.out_color_components > 1 ? 1 : 0; | |
1926 bi = cinfo.out_color_components > 2 ? 2 : 0; | |
1927 | |
1928 /* Ok... apparently, an entry of cinfo.colormap can be NULL if | |
1929 there are no bits of that color in the image. How incredibly | |
1930 gross. Wouldn't it be nice to have exceptions!? */ | |
1931 color.red = cinfo.colormap[ri] ? cinfo.colormap[ri][i] << 8 : 0; | |
1932 color.green = cinfo.colormap[gi] ? cinfo.colormap[gi][i] << 8 : 0; | |
1933 color.blue = cinfo.colormap[bi] ? cinfo.colormap[bi][i] << 8 : 0; | |
1934 color.flags = DoRed | DoGreen | DoBlue; | |
1935 | |
1936 res = allocate_nearest_color (dpy, cmap, vis, &color); | |
1937 if (res > 0 && res < 3) | |
1938 { | |
1939 DO_REALLOC(unwind.pixels, unwind.pixcount, unwind.npixels+1, unsigned long); | |
1940 unwind.pixels[unwind.npixels] = color.pixel; | |
1941 unwind.npixels++; | |
1942 } | |
1943 } | |
1944 } | |
1945 | |
1946 /* Step 5.66: Create the image */ | |
1947 { | |
1948 int height = cinfo.output_height; | |
1949 int width = cinfo.output_width; | |
1950 int depth; | |
1951 int bitmap_pad; | |
1952 | |
1953 depth = DEVICE_X_DEPTH(XDEVICE(device)); | |
1954 | |
1955 /* first get bitmap_pad (from XPM) */ | |
1956 bitmap_pad = ((depth > 16) ? 32 : | |
1957 (depth > 8) ? 16 : | |
1958 8); | |
1959 | |
1960 unwind.ximage = XCreateImage (dpy, vis, depth, ZPixmap, 0, 0, width, height, | |
1961 bitmap_pad, 0); | |
1962 | |
1963 if (!unwind.ximage) | |
1964 signal_image_error ("Unable to create X image struct", instantiator); | |
1965 | |
1966 /* now that bytes_per_line must have been set properly alloc data */ | |
1967 unwind.ximage->data = | |
1968 (char *) xmalloc (unwind.ximage->bytes_per_line * height); | |
1969 } | |
1970 | |
1971 /* Step 6: Read in the data and put into image */ | |
1972 { | |
1973 JSAMPARRAY row_buffer; /* Output row buffer */ | |
1974 int row_stride; /* physical row width in output buffer */ | |
1975 | |
1976 /* We may need to do some setup of our own at this point before reading | |
1977 * the data. After jpeg_start_decompress() we have the correct scaled | |
1978 * output image dimensions available, as well as the output colormap | |
1979 * if we asked for color quantization. | |
1980 * In this example, we need to make an output work buffer of the right size. | |
1981 */ | |
1982 /* JSAMPLEs per row in output buffer. | |
1983 Since we asked for quantized output, cinfo.output_components | |
1984 will always be 1. */ | |
1985 row_stride = cinfo.output_width * cinfo.output_components; | |
1986 /* Make a one-row-high sample array that will go away when done | |
1987 with image */ | |
1988 row_buffer = ((*cinfo.mem->alloc_sarray) | |
1989 ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1)); | |
1990 | |
1991 /* Here we use the library's state variable cinfo.output_scanline as the | |
1992 * loop counter, so that we don't have to keep track ourselves. | |
1993 */ | |
1994 while (cinfo.output_scanline < cinfo.output_height) | |
1995 { | |
1996 int i; | |
1997 int scanline = cinfo.output_scanline; | |
1998 | |
1999 /* jpeg_read_scanlines expects an array of pointers to scanlines. | |
2000 * Here the array is only one element long, but you could ask for | |
2001 * more than one scanline at a time if that's more convenient. | |
2002 */ | |
2003 jpeg_read_scanlines (&cinfo, row_buffer, 1); | |
2004 | |
2005 for (i = 0; i < (int) cinfo.output_width; i++) | |
2006 XPutPixel (unwind.ximage, i, scanline, | |
2007 /* Let's make sure we avoid getting bit like | |
2008 what happened for GIF's. It's probably the | |
2009 case that JSAMPLE's are unsigned chars as | |
2010 opposed to chars, but you never know. | |
2011 | |
2012 (They could even be shorts if the library | |
2013 was compiled with 12-bit samples -- #### | |
2014 We should deal with this possibility) */ | |
2015 unwind.pixels[(unsigned char) row_buffer[0][i]]); | |
2016 } | |
2017 } | |
2018 #else | |
2019 { | |
2020 /* Step 4: set parameters for decompression. */ | |
2021 | |
2022 /* Now that we're using EImages, use the default of all data in 24bit color. | |
2023 The backend routine will take care of any necessary reductions. */ | |
2024 | |
2025 /* Step 5: Start decompressor */ | |
2026 jpeg_start_decompress (&cinfo); | |
2027 | |
2028 /* Step 6: Read in the data and put into EImage format (8bit RGB triples)*/ | |
2029 | |
2030 unwind.eimage = (unsigned char*) xmalloc (cinfo.output_width * cinfo.output_height * 3); | |
2031 if (!unwind.eimage) | |
2032 signal_image_error("Unable to allocate enough memory for image", instantiator); | |
2033 | |
2034 { | |
2035 JSAMPARRAY row_buffer; /* Output row buffer */ | |
2036 JSAMPLE *jp; | |
2037 int row_stride; /* physical row width in output buffer */ | |
2038 unsigned char *op = unwind.eimage; | |
2039 | |
2040 /* We may need to do some setup of our own at this point before reading | |
2041 * the data. After jpeg_start_decompress() we have the correct scaled | |
2042 * output image dimensions available | |
2043 * We need to make an output work buffer of the right size. | |
2044 */ | |
2045 /* JSAMPLEs per row in output buffer. */ | |
2046 row_stride = cinfo.output_width * cinfo.output_components; | |
2047 /* Make a one-row-high sample array that will go away when done | |
2048 with image */ | |
2049 row_buffer = ((*cinfo.mem->alloc_sarray) | |
2050 ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1)); | |
2051 | |
2052 /* Here we use the library's state variable cinfo.output_scanline as the | |
2053 * loop counter, so that we don't have to keep track ourselves. | |
2054 */ | |
2055 while (cinfo.output_scanline < cinfo.output_height) | |
2056 { | |
2057 int i; | |
2058 | |
2059 /* jpeg_read_scanlines expects an array of pointers to scanlines. | |
2060 * Here the array is only one element long, but you could ask for | |
2061 * more than one scanline at a time if that's more convenient. | |
2062 */ | |
2063 (void) jpeg_read_scanlines (&cinfo, row_buffer, 1); | |
2064 jp = row_buffer[0]; | |
2065 for (i = 0; i < cinfo.output_width; i++) | |
2066 { | |
2067 int clr; | |
2068 #if (BITS_IN_JSAMPLE == 8) | |
2069 for (clr = 0; clr < 3; clr++) | |
2070 *op++ = (unsigned char)*jp++; | |
2071 #else /* other option is 12 */ | |
2072 for (clr = 0; clr < 3; clr++) | |
2073 *op++ = (unsigned char)(*jp++ >> 4); | |
2074 #endif | |
2075 } | |
2076 } | |
2077 unwind.ximage = convert_EImage_to_XImage (device, cinfo.output_width, cinfo.output_height, unwind.eimage, | |
2078 &unwind.pixels, &unwind.pixcount, &unwind.npixels); | |
2079 if (!unwind.ximage) | |
2080 signal_image_error("JPEG conversion failed", instantiator); | |
2081 } | |
2082 } | |
2083 | |
2084 #endif | |
2085 /* Step 6.5: Create the pixmap and set up the image instance */ | |
2086 init_image_instance_from_x_image (ii, unwind.ximage, dest_mask, | |
2087 cmap, unwind.pixels, unwind.npixels, | |
2088 instantiator); | |
2089 | |
2090 /* Step 7: Finish decompression */ | |
2091 | |
2092 jpeg_finish_decompress (&cinfo); | |
2093 /* We can ignore the return value since suspension is not possible | |
2094 * with the stdio data source. | |
2095 */ | |
2096 | |
2097 /* And we're done! | |
2098 | |
2099 Now that we've succeeded, we don't want the pixels | |
2100 freed right now. They're kept around in the image instance | |
2101 structure until it's destroyed. */ | |
2102 unwind.npixels = 0; | |
2103 unwind.pixcount = 0; | |
2104 | |
2105 /* This will clean up everything else. */ | |
2106 unbind_to (speccount, Qnil); | |
2107 } | |
2108 | |
2109 #endif /* HAVE_JPEG */ | |
2110 | |
2111 #ifdef HAVE_GIF | |
2112 /* #define USE_TEMP_FILES_FOR_GIF_IMAGES */ | |
2113 /********************************************************************** | |
2114 * GIF * | |
2115 **********************************************************************/ | |
2116 | |
2117 #include <gif_lib.h> | |
2118 | |
2119 static void | |
2120 gif_validate (Lisp_Object instantiator) | |
2121 { | |
2122 file_or_data_must_be_present (instantiator); | |
2123 } | |
2124 | |
2125 static Lisp_Object | |
2126 gif_normalize (Lisp_Object inst, Lisp_Object console_type) | |
2127 { | |
2128 return simple_image_type_normalize (inst, console_type, Qgif); | |
2129 } | |
2130 | |
2131 static int | |
2132 gif_possible_dest_types (void) | |
2133 { | |
2134 return IMAGE_COLOR_PIXMAP_MASK; | |
2135 } | |
2136 | |
2137 /* To survive the otherwise baffling complexity of making sure | |
2138 everything gets cleaned up in the presence of an error, we | |
2139 use an unwind_protect(). */ | |
2140 | |
2141 struct gif_unwind_data | |
2142 { | |
2143 Display *dpy; | |
2144 Colormap cmap; | |
2145 unsigned char *eimage; | |
2146 /* Object that holds the decoded data from a GIF file */ | |
2147 GifFileType *giffile; | |
2148 /* Pixels to keep around while the image is active */ | |
2149 unsigned long *pixels; | |
2150 int npixels, pixcount; | |
2151 /* Client-side image structure */ | |
2152 XImage *ximage; | |
2153 #ifdef USE_TEMP_FILES_FOR_GIF_IMAGES | |
2154 /* Tempfile to remove */ | |
2155 char tempfile[50]; | |
2156 int tempfile_needs_to_be_removed; | |
2157 #endif | |
2158 }; | |
2159 | |
2160 static Lisp_Object | |
2161 gif_instantiate_unwind (Lisp_Object unwind_obj) | |
2162 { | |
2163 struct gif_unwind_data *data = | |
2164 (struct gif_unwind_data *) get_opaque_ptr (unwind_obj); | |
2165 | |
2166 free_opaque_ptr (unwind_obj); | |
2167 if (data->giffile) | |
2168 { | |
2169 DGifCloseFile (data->giffile); | |
2170 GifFree(data->giffile); | |
2171 } | |
2172 if (data->eimage) xfree(data->eimage); | |
2173 #ifdef USE_TEMP_FILES_FOR_GIF_IMAGES | |
2174 if (data->tempfile_needs_to_be_removed) | |
2175 unlink (data->tempfile); | |
2176 #endif | |
2177 if (data->npixels > 0) | |
2178 XFreeColors (data->dpy, data->cmap, data->pixels, data->npixels, 0L); | |
2179 if (data->pixcount > 0) | |
2180 xfree (data->pixels); | |
2181 if (data->ximage) | |
2182 { | |
2183 if (data->ximage->data) | |
2184 { | |
2185 xfree (data->ximage->data); | |
2186 data->ximage->data = 0; | |
2187 } | |
2188 XDestroyImage (data->ximage); | |
2189 } | |
2190 | |
2191 return Qnil; | |
2192 } | |
2193 | |
2194 #ifndef USE_TEMP_FILES_FOR_GIF_IMAGES | |
2195 typedef struct gif_memory_storage | |
2196 { | |
2197 Extbyte *bytes; /* The data */ | |
2198 Extcount len; /* How big is it? */ | |
2199 int index; /* Where are we? */ | |
2200 } gif_memory_storage; | |
2201 | |
2202 static size_t | |
2203 gif_read_from_memory(GifByteType *buf, size_t size, VoidPtr data) | |
2204 { | |
2205 gif_memory_storage *mem = (gif_memory_storage*)data; | |
2206 | |
2207 if (size > (mem->len - mem->index)) | |
2208 return -1; | |
2209 memcpy(buf, mem->bytes + mem->index, size); | |
2210 mem->index = mem->index + size; | |
2211 return size; | |
2212 } | |
2213 | |
2214 static int | |
2215 gif_memory_close(VoidPtr data) | |
2216 { | |
2217 return 0; | |
2218 } | |
2219 | |
2220 #endif | |
2221 struct gif_error_struct | |
2222 { | |
2223 CONST char *err_str; /* return the error string */ | |
2224 jmp_buf setjmp_buffer; /* for return to caller */ | |
2225 }; | |
2226 | |
2227 static void | |
2228 gif_error_func(CONST char *err_str, VoidPtr error_ptr) | |
2229 { | |
2230 struct gif_error_struct *error_data = (struct gif_error_struct*)error_ptr; | |
2231 | |
2232 /* return to setjmp point */ | |
2233 error_data->err_str = err_str; | |
2234 longjmp (error_data->setjmp_buffer, 1); | |
2235 } | |
2236 | |
2237 static void | |
2238 gif_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
2239 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
2240 int dest_mask, Lisp_Object domain) | |
2241 { | |
2242 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
2243 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
2244 Display *dpy; | |
2245 Colormap cmap; | |
2246 Visual *vis; | |
2247 /* It is OK for the unwind data to be local to this function, | |
2248 because the unwind-protect is always executed when this | |
2249 stack frame is still valid. */ | |
2250 struct gif_unwind_data unwind; | |
2251 int speccount = specpdl_depth (); | |
2252 #ifndef USE_TEMP_FILES_FOR_GIF_IMAGES | |
2253 gif_memory_storage mem_struct; | |
2254 struct gif_error_struct gif_err; | |
2255 Extbyte *bytes; | |
2256 Extcount len; | |
2257 #endif | |
2258 if (!DEVICE_X_P (XDEVICE (device))) | |
2259 signal_simple_error ("Not an X device", device); | |
2260 | |
2261 dpy = DEVICE_X_DISPLAY (XDEVICE (device)); | |
2262 cmap = DEVICE_X_COLORMAP (XDEVICE(device)); | |
2263 vis = DEVICE_X_VISUAL (XDEVICE(device)); | |
2264 | |
2265 xzero (unwind); | |
2266 unwind.dpy = dpy; | |
2267 unwind.cmap = cmap; | |
2268 record_unwind_protect (gif_instantiate_unwind, make_opaque_ptr (&unwind)); | |
2269 | |
2270 /* 1. Now decode the data. */ | |
2271 | |
2272 { | |
2273 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
2274 | |
2275 assert (!NILP (data)); | |
2276 | |
2277 if (!(unwind.giffile = GifSetup())) | |
2278 signal_image_error ("Insufficent memory to instantiate GIF image", instantiator); | |
2279 | |
2280 /* set up error facilities */ | |
2281 if (setjmp(gif_err.setjmp_buffer)) | |
2282 { | |
2283 /* An error was signaled. No clean up is needed, as unwind handles that | |
2284 for us. Just pass the error along. */ | |
2285 Lisp_Object errstring; | |
2286 errstring = build_string (gif_err.err_str); | |
2287 signal_image_error_2 ("GIF decoding error", errstring, instantiator); | |
2288 } | |
2289 GifSetErrorFunc(unwind.giffile, (Gif_error_func)gif_error_func, (VoidPtr)&gif_err); | |
2290 | |
2291 #ifdef USE_TEMP_FILES_FOR_GIF_IMAGES | |
2292 write_lisp_string_to_temp_file (data, unwind.tempfile); | |
2293 unwind.tempfile_needs_to_be_removed = 1; | |
2294 DGifOpenFileName (unwind.giffile, unwind.tempfile); | |
2295 #else | |
2296 GET_STRING_BINARY_DATA_ALLOCA (data, bytes, len); | |
2297 mem_struct.bytes = bytes; | |
2298 mem_struct.len = len; | |
2299 mem_struct.index = 0; | |
2300 GifSetReadFunc(unwind.giffile, gif_read_from_memory, (VoidPtr)&mem_struct); | |
2301 GifSetCloseFunc(unwind.giffile, gif_memory_close, (VoidPtr)&mem_struct); | |
2302 DGifInitRead(unwind.giffile); | |
2303 #endif | |
2304 /* Then slurp the image into memory, decoding along the way. | |
2305 The result is the image in a simple one-byte-per-pixel | |
2306 format (#### the GIF routines only support 8-bit GIFs, | |
2307 it appears). */ | |
2308 DGifSlurp (unwind.giffile); | |
2309 } | |
2310 | |
2311 #if 0 | |
2312 /* 2. Now allocate the colors for the image. */ | |
2313 { | |
2314 int i; | |
2315 ColorMapObject *cmo = unwind.giffile->SColorMap; | |
2316 /* Just in case the image contains out-of-range pixels, we go | |
2317 ahead and allocate space for all of them. */ | |
2318 unwind.pixels = xnew_array (unsigned long, 256); | |
2319 unwind.npixels = 0; | |
2320 | |
2321 for (i = 0; i < 256; i++) | |
2322 unwind.pixels[i] = 0; /* Use a reasonable color for out of range. */ | |
2323 | |
2324 /* Allocate pixels for the various colors. */ | |
2325 for (i = 0; i < cmo->ColorCount; i++) | |
2326 { | |
2327 int res; | |
2328 XColor color; | |
2329 | |
2330 color.red = cmo->Colors[i].Red << 8; | |
2331 color.green = cmo->Colors[i].Green << 8; | |
2332 color.blue = cmo->Colors[i].Blue << 8; | |
2333 color.flags = DoRed | DoGreen | DoBlue; | |
2334 | |
2335 res = allocate_nearest_color (dpy, cmap, vis, &color); | |
2336 if (res > 0 && res < 3) | |
2337 { | |
2338 unwind.pixels[unwind.npixels] = color.pixel; | |
2339 unwind.npixels++; | |
2340 } | |
2341 } | |
2342 } | |
2343 | |
2344 /* 3. Now create the image */ | |
2345 { | |
2346 int height = unwind.giffile->SHeight; | |
2347 int width = unwind.giffile->SWidth; | |
2348 int depth; | |
2349 int bitmap_pad; | |
2350 int i, j, row, pass, interlace; | |
2351 /* interlaced gifs have rows in this order: | |
2352 0, 8, 16, ..., 4, 12, 20, ..., 2, 6, 10, ..., 1, 3, 5, ... */ | |
2353 static int InterlacedOffset[] = { 0, 4, 2, 1 }; | |
2354 static int InterlacedJumps[] = { 8, 8, 4, 2 }; | |
2355 | |
2356 depth = DEVICE_X_DEPTH(XDEVICE(device)); | |
2357 | |
2358 /* first get bitmap_pad (from XPM) */ | |
2359 bitmap_pad = ((depth > 16) ? 32 : | |
2360 (depth > 8) ? 16 : | |
2361 8); | |
2362 | |
2363 unwind.ximage = XCreateImage (dpy, vis, | |
2364 depth, ZPixmap, 0, 0, width, height, | |
2365 bitmap_pad, 0); | |
2366 | |
2367 if (!unwind.ximage) | |
2368 signal_image_error ("Unable to create X image struct", instantiator); | |
2369 | |
2370 /* now that bytes_per_line must have been set properly alloc data */ | |
2371 unwind.ximage->data = | |
2372 (char *) xmalloc (unwind.ximage->bytes_per_line * height); | |
2373 | |
2374 /* write the data -- | |
2375 #### XPutPixel() is a client-side-only function but could | |
2376 still be slow. Another possibility is to just convert to | |
2377 XPM format and use the Xpm routines, which optimize this | |
2378 stuff; but it's doubtful that this will be faster in the | |
2379 long run, what with all the XPM overhead. If this proves | |
2380 to be a bottleneck here, maybe we should just copy the | |
2381 optimization routines from XPM (they're in turn mostly | |
2382 copied from the Xlib source code). */ | |
2383 | |
2384 /* Note: We just use the first image in the file and ignore the rest. | |
2385 We check here that that image covers the full "screen" size. | |
2386 I don't know whether that's always the case. | |
2387 -dkindred@cs.cmu.edu */ | |
2388 if (unwind.giffile->SavedImages[0].ImageDesc.Height != height | |
2389 || unwind.giffile->SavedImages[0].ImageDesc.Width != width | |
2390 || unwind.giffile->SavedImages[0].ImageDesc.Left != 0 | |
2391 || unwind.giffile->SavedImages[0].ImageDesc.Top != 0) | |
2392 signal_image_error ("First image in GIF file is not full size", | |
2393 instantiator); | |
2394 | |
2395 interlace = unwind.giffile->SavedImages[0].ImageDesc.Interlace; | |
2396 pass = 0; | |
2397 row = interlace ? InterlacedOffset[pass] : 0; | |
2398 for (i = 0; i < height; i++) | |
2399 { | |
2400 if (interlace && row >= height) | |
2401 row = InterlacedOffset[++pass]; | |
2402 | |
2403 for (j = 0; j < width; j++) | |
2404 XPutPixel (unwind.ximage, j, row, | |
2405 unwind.pixels[(unsigned char) | |
2406 /* incorrect signed declaration | |
2407 of RasterBits[] */ | |
2408 (unwind.giffile->SavedImages[0]. | |
2409 RasterBits[i * width + j])]); | |
2410 | |
2411 row += interlace ? InterlacedJumps[pass] : 1; | |
2412 } | |
2413 } | |
2414 #else | |
2415 /* 3. Now create the EImage */ | |
2416 { | |
2417 ColorMapObject *cmo = unwind.giffile->SColorMap; | |
2418 int height = unwind.giffile->SHeight; | |
2419 int width = unwind.giffile->SWidth; | |
2420 int i, j, row, pass, interlace; | |
2421 unsigned char *eip; | |
2422 /* interlaced gifs have rows in this order: | |
2423 0, 8, 16, ..., 4, 12, 20, ..., 2, 6, 10, ..., 1, 3, 5, ... */ | |
2424 static int InterlacedOffset[] = { 0, 4, 2, 1 }; | |
2425 static int InterlacedJumps[] = { 8, 8, 4, 2 }; | |
2426 | |
2427 unwind.eimage = (unsigned char*) xmalloc (width * height * 3); | |
2428 if (!unwind.eimage) | |
2429 signal_image_error("Unable to allocate enough memory for image", instantiator); | |
2430 | |
2431 /* write the data in EImage format (8bit RGB triples) */ | |
2432 | |
2433 /* Note: We just use the first image in the file and ignore the rest. | |
2434 We check here that that image covers the full "screen" size. | |
2435 I don't know whether that's always the case. | |
2436 -dkindred@cs.cmu.edu */ | |
2437 if (unwind.giffile->SavedImages[0].ImageDesc.Height != height | |
2438 || unwind.giffile->SavedImages[0].ImageDesc.Width != width | |
2439 || unwind.giffile->SavedImages[0].ImageDesc.Left != 0 | |
2440 || unwind.giffile->SavedImages[0].ImageDesc.Top != 0) | |
2441 signal_image_error ("First image in GIF file is not full size", | |
2442 instantiator); | |
2443 | |
2444 interlace = unwind.giffile->SavedImages[0].ImageDesc.Interlace; | |
2445 pass = 0; | |
2446 row = interlace ? InterlacedOffset[pass] : 0; | |
2447 eip = unwind.eimage; | |
2448 for (i = 0; i < height; i++) | |
2449 { | |
2450 if (interlace && row >= height) | |
2451 row = InterlacedOffset[++pass]; | |
2452 eip = unwind.eimage + (row * width * 3); | |
2453 for (j = 0; j < width; j++) | |
2454 { | |
2455 unsigned char pixel = unwind.giffile->SavedImages[0].RasterBits[(i * width) + j]; | |
2456 *eip++ = cmo->Colors[pixel].Red; | |
2457 *eip++ = cmo->Colors[pixel].Green; | |
2458 *eip++ = cmo->Colors[pixel].Blue; | |
2459 } | |
2460 row += interlace ? InterlacedJumps[pass] : 1; | |
2461 } | |
2462 unwind.ximage = convert_EImage_to_XImage (device, width, height, unwind.eimage, | |
2463 &unwind.pixels, &unwind.pixcount, &unwind.npixels); | |
2464 if (!unwind.ximage) | |
2465 signal_image_error("GIF conversion failed", instantiator); | |
2466 } | |
2467 #endif | |
2468 /* 4. Now create the pixmap and set up the image instance */ | |
2469 init_image_instance_from_x_image (ii, unwind.ximage, dest_mask, | |
2470 cmap, unwind.pixels, unwind.npixels, | |
2471 instantiator); | |
2472 /* Now that we've succeeded, we don't want the pixels | |
2473 freed right now. They're kept around in the image instance | |
2474 structure until it's destroyed. */ | |
2475 unwind.npixels = 0; | |
2476 unwind.pixcount = 0; | |
2477 unbind_to (speccount, Qnil); | |
2478 } | |
2479 | |
2480 #endif /* HAVE_GIF */ | |
2481 | |
2482 | |
2483 #ifdef HAVE_PNG | |
2484 /* #define USE_TEMP_FILES_FOR_PNG_IMAGES 1 */ | |
2485 | |
2486 /********************************************************************** | |
2487 * PNG * | |
2488 **********************************************************************/ | |
2489 static void | |
2490 png_validate (Lisp_Object instantiator) | |
2491 { | |
2492 file_or_data_must_be_present (instantiator); | |
2493 } | |
2494 | |
2495 static Lisp_Object | |
2496 png_normalize (Lisp_Object inst, Lisp_Object console_type) | |
2497 { | |
2498 return simple_image_type_normalize (inst, console_type, Qpng); | |
2499 } | |
2500 | |
2501 static int | |
2502 png_possible_dest_types (void) | |
2503 { | |
2504 return IMAGE_COLOR_PIXMAP_MASK; | |
2505 } | |
2506 | |
2507 #ifndef USE_TEMP_FILES_FOR_PNG_IMAGES | |
2508 struct png_memory_storage | |
2509 { | |
2510 CONST Extbyte *bytes; /* The data */ | |
2511 Extcount len; /* How big is it? */ | |
2512 int index; /* Where are we? */ | |
2513 }; | |
2514 | |
2515 static void | |
2516 png_read_from_memory(png_structp png_ptr, png_bytep data, | |
2517 png_size_t length) | |
2518 { | |
2519 struct png_memory_storage *tbr = | |
2520 (struct png_memory_storage *) png_get_io_ptr (png_ptr); | |
2521 | |
2522 if (length > (tbr->len - tbr->index)) | |
2523 png_error (png_ptr, (png_const_charp) "Read Error"); | |
2524 memcpy (data,tbr->bytes + tbr->index,length); | |
2525 tbr->index = tbr->index + length; | |
2526 } | |
2527 #endif /* !USE_TEMP_FILES_FOR_PNG_IMAGES */ | |
2528 | |
2529 struct png_error_struct | |
2530 { | |
2531 CONST char *err_str; | |
2532 jmp_buf setjmp_buffer; /* for return to caller */ | |
2533 }; | |
2534 | |
2535 /* jh 98/03/12 - #### AARRRGH! libpng includes jmp_buf inside its own | |
2536 structure, and there are cases where the size can be different from | |
2537 between inside the libarary, and inside the code! To do an end run | |
2538 around this, use our own error functions, and don't rely on things | |
2539 passed in the png_ptr to them. This is an ugly hack and must | |
2540 go away when the lisp engine is threaded! */ | |
2541 static struct png_error_struct png_err_stct; | |
2542 | |
2543 static void | |
2544 png_error_func (png_structp png_ptr, png_const_charp msg) | |
2545 { | |
2546 png_err_stct.err_str = msg; | |
2547 longjmp (png_err_stct.setjmp_buffer, 1); | |
2548 } | |
2549 | |
2550 static void | |
2551 png_warning_func (png_structp png_ptr, png_const_charp msg) | |
2552 { | |
2553 warn_when_safe (Qpng, Qinfo, "%s", msg); | |
2554 } | |
2555 | |
2556 struct png_unwind_data | |
2557 { | |
2558 Display *dpy; | |
2559 Colormap cmap; | |
2560 FILE *instream; | |
2561 unsigned char *eimage; | |
2562 png_structp png_ptr; | |
2563 png_infop info_ptr; | |
2564 unsigned long *pixels; | |
2565 int npixels, pixcount; | |
2566 XImage *ximage; | |
2567 #ifdef USE_TEMP_FILES_FOR_PNG_IMAGESS | |
2568 char tempfile[50]; | |
2569 int tempfile_needs_to_be_removed; | |
2570 #endif | |
2571 }; | |
2572 | |
2573 static Lisp_Object | |
2574 png_instantiate_unwind (Lisp_Object unwind_obj) | |
2575 { | |
2576 struct png_unwind_data *data = | |
2577 (struct png_unwind_data *) get_opaque_ptr (unwind_obj); | |
2578 | |
2579 free_opaque_ptr (unwind_obj); | |
2580 if (data->png_ptr) | |
2581 png_destroy_read_struct (&(data->png_ptr), &(data->info_ptr), (png_infopp)NULL); | |
2582 if (data->instream) | |
2583 fclose (data->instream); | |
2584 if (data->npixels > 0) | |
2585 XFreeColors (data->dpy, data->cmap, data->pixels, data->npixels, 0L); | |
2586 if (data->pixcount > 0) | |
2587 xfree (data->pixels); | |
2588 | |
2589 if (data->eimage) | |
2590 xfree (data->eimage); | |
2591 if (data->ximage) | |
2592 { | |
2593 if (data->ximage->data) | |
2594 { | |
2595 xfree (data->ximage->data); | |
2596 data->ximage->data = 0; | |
2597 } | |
2598 XDestroyImage (data->ximage); | |
2599 } | |
2600 #ifdef USE_TEMP_FILES_FOR_PNG_IMAGES | |
2601 if (data->tempfile_needs_to_be_removed) | |
2602 unlink (data->tempfile); | |
2603 #endif | |
2604 return Qnil; | |
2605 } | |
2606 | |
2607 static void | |
2608 png_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
2609 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
2610 int dest_mask, Lisp_Object domain) | |
2611 { | |
2612 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
2613 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
2614 Display *dpy; | |
2615 Colormap cmap; | |
2616 Visual *vis; | |
2617 struct png_unwind_data unwind; | |
2618 int speccount = specpdl_depth (); | |
2619 | |
2620 /* PNG variables */ | |
2621 png_structp png_ptr; | |
2622 png_infop info_ptr; | |
2623 | |
2624 if (!DEVICE_X_P (XDEVICE (device))) | |
2625 signal_simple_error ("Not an X device", device); | |
2626 | |
2627 dpy = DEVICE_X_DISPLAY (XDEVICE (device)); | |
2628 cmap = DEVICE_X_COLORMAP (XDEVICE(device)); | |
2629 vis = DEVICE_X_VISUAL (XDEVICE(device)); | |
2630 | |
2631 /* Initialize all PNG structures */ | |
2632 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, (void*)&png_err_stct, | |
2633 png_error_func, png_warning_func); | |
2634 if (!png_ptr) | |
2635 signal_image_error ("Error obtaining memory for png_read", instantiator); | |
2636 info_ptr = png_create_info_struct (png_ptr); | |
2637 if (!info_ptr) | |
2638 { | |
2639 png_destroy_read_struct (&png_ptr, (png_infopp)NULL, (png_infopp)NULL); | |
2640 signal_image_error ("Error obtaining memory for png_read", instantiator); | |
2641 } | |
2642 | |
2643 xzero (unwind); | |
2644 unwind.png_ptr = png_ptr; | |
2645 unwind.info_ptr = info_ptr; | |
2646 unwind.dpy = dpy; | |
2647 unwind.cmap = cmap; | |
2648 | |
2649 record_unwind_protect (png_instantiate_unwind, make_opaque_ptr (&unwind)); | |
2650 | |
2651 /* This code is a mixture of stuff from Ben's GIF/JPEG stuff from | |
2652 this file, example.c from the libpng 0.81 distribution, and the | |
2653 pngtopnm sources. -WMP- | |
2654 */ | |
2655 /* It has been further modified to handle the API changes for 0.96, | |
2656 and is no longer usable for previous versions. jh | |
2657 */ | |
2658 | |
2659 /* Set the jmp_buf reurn context for png_error ... if this returns !0, then | |
2660 we ran into a problem somewhere, and need to clean up after ourselves. */ | |
2661 if (setjmp (png_err_stct.setjmp_buffer)) | |
2662 { | |
2663 /* Something blew up: just display the error (cleanup happens in the unwind) */ | |
2664 signal_image_error_2 ("Error decoding PNG", | |
2665 build_string(png_err_stct.err_str), | |
2666 instantiator); | |
2667 } | |
2668 | |
2669 /* Initialize the IO layer and read in header information */ | |
2670 { | |
2671 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
2672 CONST Extbyte *bytes; | |
2673 Extcount len; | |
2674 struct png_memory_storage tbr; /* Data to be read */ | |
2675 | |
2676 assert (!NILP (data)); | |
2677 | |
2678 /* #### This is a definite problem under Mule due to the amount of | |
2679 stack data it might allocate. Need to think about using Lstreams */ | |
2680 GET_STRING_BINARY_DATA_ALLOCA (data, bytes, len); | |
2681 tbr.bytes = bytes; | |
2682 tbr.len = len; | |
2683 tbr.index = 0; | |
2684 png_set_read_fn (png_ptr,(void *) &tbr, png_read_from_memory); | |
2685 } | |
2686 | |
2687 png_read_info (png_ptr, info_ptr); | |
2688 | |
2689 #if 0 | |
2690 /* set up the transformations you want. Note that these are | |
2691 all optional. Only call them if you want them */ | |
2692 /* tell libpng to strip 16 bit depth files down to 8 bits */ | |
2693 if (info_ptr->bit_depth == 16) | |
2694 png_set_strip_16 (png_ptr); | |
2695 if (info_ptr->bit_depth < 8) | |
2696 png_set_packing (png_ptr); | |
2697 /* ##### Perhaps some way to specify the screen gamma should be in here? */ | |
2698 | |
2699 { | |
2700 int height = info_ptr->height; | |
2701 int width = info_ptr->width; | |
2702 int depth = info_ptr->bit_depth; | |
2703 int linesize = max (info_ptr->bit_depth >> 3, 1) * width; | |
2704 int bitmap_pad; | |
2705 int y; | |
2706 XColor color; | |
2707 png_byte *png_pixels; | |
2708 png_byte **row_pointers; | |
2709 png_color static_color_cube[216]; | |
2710 | |
2711 /* Wow, allocate all the memory. Truly, exciting. */ | |
2712 unwind.pixcount = 32; | |
2713 unwind.pixels = xnew_array (unsigned long, unwind.pixcount); | |
2714 png_pixels = xnew_array (png_byte, linesize * height); | |
2715 row_pointers = xnew_array (png_byte *, height); | |
2716 | |
2717 for (y = 0; y < height; y++) | |
2718 row_pointers[y] = png_pixels + (linesize * y); | |
2719 | |
2720 /* #### This is where we should handle transparency, but I am unsure of | |
2721 how exactly to get that information right now, in a safe manner. */ | |
2722 #if 0 | |
2723 { | |
2724 png_color_16 current_background; | |
2725 | |
2726 /* Some appropriate magic should go here to get the current | |
2727 buffers (device?) background color and convert it to a | |
2728 png_color_16 struct */ | |
2729 if (info_ptr->valid & PNG_INFO_bKGD) | |
2730 png_set_background (png_ptr, &(info_ptr->background), PNG_GAMMA_FILE, | |
2731 1, 1.0); | |
2732 else | |
2733 png_set_background (png_ptr, ¤t_background, PNG_GAMMA_SCREEN, | |
2734 0, 1.0); | |
2735 } | |
2736 #endif | |
2737 | |
2738 if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || | |
2739 (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) && | |
2740 (vis->class == PseudoColor)) | |
2741 { | |
2742 if (!(info_ptr->valid & PNG_INFO_PLTE)) | |
2743 { | |
2744 for (y = 0; y < 216; y++) | |
2745 { | |
2746 static_color_cube[y].red = (png_byte) ((y % 6) * 255.0 / 5); | |
2747 static_color_cube[y].green = (png_byte) (((y / 6) % 6) * 255.0 / 5); | |
2748 static_color_cube[y].blue = (png_byte) ((y / 36) * 255.0 / 5); | |
2749 } | |
2750 png_set_dither (png_ptr, static_color_cube, 216, 216, NULL, 1); | |
2751 } | |
2752 else | |
2753 { | |
2754 png_set_dither (png_ptr, info_ptr->palette, info_ptr->num_palette, | |
2755 info_ptr->num_palette, info_ptr->hist, 1); | |
2756 } | |
2757 } | |
2758 | |
2759 png_read_image (png_ptr, row_pointers); | |
2760 png_read_end (png_ptr, info_ptr); | |
2761 | |
2762 /* Ok, now we go and allocate all the colors */ | |
2763 if (info_ptr->valid & PNG_INFO_PLTE) | |
2764 { | |
2765 unwind.npixels = 0; | |
2766 for (y = 0; y < info_ptr->num_palette; y++) | |
2767 { | |
2768 int res; | |
2769 color.red = info_ptr->palette[y].red << 8; | |
2770 color.green = info_ptr->palette[y].green << 8; | |
2771 color.blue = info_ptr->palette[y].blue << 8; | |
2772 color.flags = DoRed | DoGreen | DoBlue; | |
2773 res = allocate_nearest_color (dpy, cmap, vis, &color); | |
2774 if (res > 0 && res < 3) | |
2775 { | |
2776 DO_REALLOC(unwind.pixels, unwind.pixcount, unwind.npixels+1, unsigned long); | |
2777 unwind.pixels[unwind.npixels] = color.pixel; | |
2778 unwind.npixels++; | |
2779 } | |
2780 } | |
2781 } | |
2782 else | |
2783 { | |
2784 unwind.npixels = 0; | |
2785 for (y = 0; y < 216; y++) | |
2786 { | |
2787 int res; | |
2788 color.red = static_color_cube[y].red << 8; | |
2789 color.green = static_color_cube[y].green << 8; | |
2790 color.blue = static_color_cube[y].blue << 8; | |
2791 color.flags = DoRed|DoGreen|DoBlue; | |
2792 res = allocate_nearest_color (dpy, cmap, vis, &color); | |
2793 if (res > 0 && res < 3) | |
2794 { | |
2795 unwind.pixels[unwind.npixels] = color.pixel; | |
2796 unwind.npixels++; | |
2797 } | |
2798 } | |
2799 } | |
2800 | |
2801 #ifdef PNG_SHOW_COMMENTS | |
2802 /* #### | |
2803 * I turn this off by default now, because the !%^@#!% comments | |
2804 * show up every time the image is instantiated, which can get | |
2805 * really really annoying. There should be some way to pass this | |
2806 * type of data down into the glyph code, where you can get to it | |
2807 * from lisp anyway. - WMP | |
2808 */ | |
2809 { | |
2810 int i; | |
2811 | |
2812 for (i = 0 ; i < info_ptr->num_text ; i++) | |
2813 { | |
2814 /* How paranoid do I have to be about no trailing NULLs, and | |
2815 using (int)info_ptr->text[i].text_length, and strncpy and a temp | |
2816 string somewhere? */ | |
2817 | |
2818 warn_when_safe (Qpng, Qinfo, "%s - %s", | |
2819 info_ptr->text[i].key, | |
2820 info_ptr->text[i].text); | |
2821 } | |
2822 } | |
2823 #endif | |
2824 | |
2825 /* Now create the image */ | |
2826 | |
2827 depth = DEVICE_X_DEPTH(XDEVICE(device)); | |
2828 | |
2829 /* first get bitmap_pad (from XPM) */ | |
2830 bitmap_pad = ((depth > 16) ? 32 : | |
2831 (depth > 8) ? 16 : | |
2832 8); | |
2833 | |
2834 unwind.ximage = XCreateImage (dpy, vis, | |
2835 depth, ZPixmap, 0, 0, width, height, | |
2836 bitmap_pad, 0); | |
2837 | |
2838 if (!unwind.ximage) | |
2839 signal_image_error ("Unable to create X image struct", | |
2840 instantiator); | |
2841 | |
2842 /* now that bytes_per_line must have been set properly alloc data */ | |
2843 unwind.ximage->data = (char *) xmalloc (unwind.ximage->bytes_per_line * | |
2844 height); | |
2845 | |
2846 { | |
2847 int i, j; | |
2848 for (i = 0; i < height; i++) | |
2849 for (j = 0; j < width; j++) | |
2850 XPutPixel (unwind.ximage, j, i, | |
2851 unwind.pixels[png_pixels[i * width + j]]); | |
2852 } | |
2853 | |
2854 xfree (row_pointers); | |
2855 xfree (png_pixels); | |
2856 } | |
2857 #else | |
2858 { | |
2859 int height = info_ptr->height; | |
2860 int width = info_ptr->width; | |
2861 int y; | |
2862 unsigned char **row_pointers; | |
2863 | |
2864 /* Wow, allocate all the memory. Truly, exciting. */ | |
2865 unwind.eimage = xnew_array_and_zero (unsigned char, width * height * 3); | |
2866 /* libpng expects that the image buffer passed in contains a | |
2867 picture to draw on top of if the png has any transparencies. | |
2868 This could be a good place to pass that in... */ | |
2869 | |
2870 row_pointers = xnew_array (png_byte *, height); | |
2871 | |
2872 for (y = 0; y < height; y++) | |
2873 row_pointers[y] = unwind.eimage + (width * 3 * y); | |
2874 | |
2875 /* Now that we're using EImage, ask for 8bit RGB triples for any type | |
2876 of image*/ | |
2877 /* convert palatte images to full RGB */ | |
2878 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) | |
2879 png_set_expand (png_ptr); | |
2880 /* send grayscale images to RGB too */ | |
2881 if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY || | |
2882 info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) | |
2883 png_set_gray_to_rgb (png_ptr); | |
2884 /* we can't handle alpha values */ | |
2885 if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) | |
2886 png_set_strip_alpha (png_ptr); | |
2887 /* rip out any transparancy layers/colors */ | |
2888 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) | |
2889 { | |
2890 png_set_expand (png_ptr); | |
2891 png_set_strip_alpha (png_ptr); | |
2892 } | |
2893 /* tell libpng to strip 16 bit depth files down to 8 bits */ | |
2894 if (info_ptr->bit_depth == 16) | |
2895 png_set_strip_16 (png_ptr); | |
2896 /* if the image is < 8 bits, pad it out */ | |
2897 if (info_ptr->bit_depth < 8) | |
2898 { | |
2899 if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY) | |
2900 png_set_expand (png_ptr); | |
2901 else | |
2902 png_set_packing (png_ptr); | |
2903 } | |
2904 | |
2905 #if 1 /* tests? or permanent? */ | |
2906 { | |
2907 /* if the png specifies a background chunk, go ahead and | |
2908 use it */ | |
2909 png_color_16 my_background, *image_background; | |
2910 | |
2911 /* ### how do I get the background of the current frame? */ | |
2912 my_background.red = 0x7fff; | |
2913 my_background.green = 0x7fff; | |
2914 my_background.blue = 0x7fff; | |
2915 | |
2916 if (png_get_bKGD (png_ptr, info_ptr, &image_background)) | |
2917 png_set_background (png_ptr, image_background, | |
2918 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); | |
2919 else | |
2920 png_set_background (png_ptr, &my_background, | |
2921 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); | |
2922 } | |
2923 #endif | |
2924 png_read_image (png_ptr, row_pointers); | |
2925 png_read_end (png_ptr, info_ptr); | |
2926 | |
2927 #ifdef PNG_SHOW_COMMENTS | |
2928 /* #### | |
2929 * I turn this off by default now, because the !%^@#!% comments | |
2930 * show up every time the image is instantiated, which can get | |
2931 * really really annoying. There should be some way to pass this | |
2932 * type of data down into the glyph code, where you can get to it | |
2933 * from lisp anyway. - WMP | |
2934 */ | |
2935 { | |
2936 int i; | |
2937 | |
2938 for (i = 0 ; i < info_ptr->num_text ; i++) | |
2939 { | |
2940 /* How paranoid do I have to be about no trailing NULLs, and | |
2941 using (int)info_ptr->text[i].text_length, and strncpy and a temp | |
2942 string somewhere? */ | |
2943 | |
2944 warn_when_safe (Qpng, Qinfo, "%s - %s", | |
2945 info_ptr->text[i].key, | |
2946 info_ptr->text[i].text); | |
2947 } | |
2948 } | |
2949 #endif | |
2950 | |
2951 xfree (row_pointers); | |
2952 unwind.ximage = convert_EImage_to_XImage (device, width, height, unwind.eimage, | |
2953 &unwind.pixels, &unwind.pixcount, &unwind.npixels); | |
2954 if (!unwind.ximage) | |
2955 signal_image_error ("PNG conversion failed", instantiator); | |
2956 } | |
2957 #endif | |
2958 | |
2959 init_image_instance_from_x_image (ii, unwind.ximage, dest_mask, | |
2960 cmap, unwind.pixels, unwind.npixels, | |
2961 instantiator); | |
2962 | |
2963 /* This will clean up everything else. */ | |
2964 unwind.npixels = 0; | |
2965 unwind.pixcount = 0; | |
2966 unbind_to (speccount, Qnil); | |
2967 } | |
2968 | |
2969 #endif /* HAVE_PNG */ | |
2970 | |
2971 | |
2972 #ifdef HAVE_TIFF | |
2973 #include "tiffio.h" | |
2974 | |
2975 /********************************************************************** | |
2976 * TIFF * | |
2977 **********************************************************************/ | |
2978 static void | |
2979 tiff_validate (Lisp_Object instantiator) | |
2980 { | |
2981 file_or_data_must_be_present (instantiator); | |
2982 } | |
2983 | |
2984 static Lisp_Object | |
2985 tiff_normalize (Lisp_Object inst, Lisp_Object console_type) | |
2986 { | |
2987 return simple_image_type_normalize (inst, console_type, Qtiff); | |
2988 } | |
2989 | |
2990 static int | |
2991 tiff_possible_dest_types (void) | |
2992 { | |
2993 return IMAGE_COLOR_PIXMAP_MASK; | |
2994 } | |
2995 | |
2996 struct tiff_unwind_data | |
2997 { | |
2998 Display *dpy; | |
2999 Colormap cmap; | |
3000 unsigned char *eimage; | |
3001 /* Object that holds the decoded data from a TIFF file */ | |
3002 TIFF *tiff; | |
3003 /* Pixels to keep around while the image is active */ | |
3004 unsigned long *pixels; | |
3005 int npixels,pixcount; | |
3006 /* Client-side image structure */ | |
3007 XImage *ximage; | |
3008 }; | |
3009 | |
3010 static Lisp_Object | |
3011 tiff_instantiate_unwind (Lisp_Object unwind_obj) | |
3012 { | |
3013 struct tiff_unwind_data *data = | |
3014 (struct tiff_unwind_data *) get_opaque_ptr (unwind_obj); | |
3015 | |
3016 free_opaque_ptr (unwind_obj); | |
3017 if (data->tiff) | |
3018 { | |
3019 TIFFClose(data->tiff); | |
3020 } | |
3021 if (data->eimage) | |
3022 xfree (data->eimage); | |
3023 if (data->npixels > 0) | |
3024 XFreeColors (data->dpy, data->cmap, data->pixels, data->npixels, 0L); | |
3025 if (data->pixcount) | |
3026 xfree (data->pixels); | |
3027 if (data->ximage) | |
3028 { | |
3029 if (data->ximage->data) | |
3030 { | |
3031 xfree (data->ximage->data); | |
3032 data->ximage->data = 0; | |
3033 } | |
3034 XDestroyImage (data->ximage); | |
3035 } | |
3036 | |
3037 return Qnil; | |
3038 } | |
3039 | |
3040 typedef struct tiff_memory_storage | |
3041 { | |
3042 Extbyte *bytes; /* The data */ | |
3043 Extcount len; /* How big is it? */ | |
3044 int index; /* Where are we? */ | |
3045 } tiff_memory_storage; | |
3046 | |
3047 static size_t | |
3048 tiff_memory_read(thandle_t data, tdata_t buf, tsize_t size) | |
3049 { | |
3050 tiff_memory_storage *mem = (tiff_memory_storage*)data; | |
3051 | |
3052 if (size > (mem->len - mem->index)) | |
3053 return (size_t) -1; | |
3054 memcpy(buf, mem->bytes + mem->index, size); | |
3055 mem->index = mem->index + size; | |
3056 return size; | |
3057 } | |
3058 | |
3059 static size_t tiff_memory_write(thandle_t data, tdata_t buf, tsize_t size) | |
3060 { | |
3061 abort(); | |
3062 return 0; /* Shut up warnings. */ | |
3063 } | |
3064 | |
3065 static toff_t tiff_memory_seek(thandle_t data, toff_t off, int whence) | |
3066 { | |
3067 tiff_memory_storage *mem = (tiff_memory_storage*)data; | |
3068 int newidx; | |
3069 switch(whence) { | |
3070 case SEEK_SET: | |
3071 newidx = off; | |
3072 break; | |
3073 case SEEK_END: | |
3074 newidx = mem->len + off; | |
3075 break; | |
3076 case SEEK_CUR: | |
3077 newidx = mem->index + off; | |
3078 break; | |
3079 default: | |
3080 fprintf(stderr,"Eh? invalid seek mode in tiff_memory_seek\n"); | |
3081 return -1; | |
3082 } | |
3083 | |
3084 if ((newidx > mem->len) || (newidx < 0)) | |
3085 return -1; | |
3086 | |
3087 mem->index = newidx; | |
3088 return newidx; | |
3089 } | |
3090 | |
3091 static int | |
3092 tiff_memory_close(thandle_t data) | |
3093 { | |
3094 return 0; | |
3095 } | |
3096 | |
3097 static int | |
3098 tiff_map_noop(thandle_t data, tdata_t* pbase, toff_t* psize) | |
3099 { | |
3100 return 0; | |
3101 } | |
3102 | |
3103 static void | |
3104 tiff_unmap_noop(thandle_t data, tdata_t pbase, toff_t psize) | |
3105 { | |
3106 return; | |
3107 } | |
3108 | |
3109 static toff_t | |
3110 tiff_memory_size(thandle_t data) | |
3111 { | |
3112 tiff_memory_storage *mem = (tiff_memory_storage*)data; | |
3113 return mem->len; | |
3114 } | |
3115 | |
3116 struct tiff_error_struct | |
3117 { | |
3118 #if HAVE_VSNPRINTF | |
3119 char err_str[256]; | |
3120 #else | |
3121 char err_str[1024]; /* return the error string */ | |
3122 #endif | |
3123 jmp_buf setjmp_buffer; /* for return to caller */ | |
3124 }; | |
3125 | |
3126 /* jh 98/03/12 - ###This struct for passing data to the error functions | |
3127 is an ugly hack caused by the fact that libtiff (as of v3.4) doesn't | |
3128 have any place to store error func data. This should be rectified | |
3129 before XEmacs gets threads! */ | |
3130 static struct tiff_error_struct tiff_err_data; | |
3131 | |
3132 static void | |
3133 tiff_error_func(CONST char *module, CONST char *fmt, ...) | |
3134 { | |
3135 va_list vargs; | |
3136 | |
3137 va_start (vargs, fmt); | |
3138 #if HAVE_VSNPRINTF | |
3139 vsnprintf (tiff_err_data.err_str, 255, fmt, vargs); | |
3140 #else | |
3141 /* pray this doesn't overflow... */ | |
3142 vsprintf (tiff_err_data.err_str, fmt, vargs); | |
3143 #endif | |
3144 va_end (vargs); | |
3145 /* return to setjmp point */ | |
3146 longjmp (tiff_err_data.setjmp_buffer, 1); | |
3147 } | |
3148 | |
3149 static void | |
3150 tiff_warning_func(CONST char *module, CONST char *fmt, ...) | |
3151 { | |
3152 va_list vargs; | |
3153 #if HAVE_VSNPRINTF | |
3154 char warn_str[256]; | |
3155 #else | |
3156 char warn_str[1024]; | |
3157 #endif | |
3158 | |
3159 va_start (vargs, fmt); | |
3160 #if HAVE_VSNPRINTF | |
3161 vsnprintf (warn_str, 255, fmt, vargs); | |
3162 #else | |
3163 vsprintf (warn_str, fmt, vargs); | |
3164 #endif | |
3165 va_end (vargs); | |
3166 warn_when_safe (Qtiff, Qinfo, "%s - %s", | |
3167 module, warn_str); | |
3168 } | |
3169 | |
3170 static void | |
3171 tiff_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
3172 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
3173 int dest_mask, Lisp_Object domain) | |
3174 { | |
3175 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
3176 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
3177 Colormap cmap; | |
3178 Display *dpy; | |
3179 tiff_memory_storage mem_struct; | |
3180 /* It is OK for the unwind data to be local to this function, | |
3181 because the unwind-protect is always executed when this | |
3182 stack frame is still valid. */ | |
3183 struct tiff_unwind_data unwind; | |
3184 int speccount = specpdl_depth (); | |
3185 | |
3186 if (!DEVICE_X_P (XDEVICE (device))) | |
3187 signal_simple_error ("Not an X device", device); | |
3188 | |
3189 dpy = DEVICE_X_DISPLAY (XDEVICE (device)); | |
3190 cmap = DEVICE_X_COLORMAP (XDEVICE(device)); | |
3191 | |
3192 xzero (unwind); | |
3193 unwind.dpy = dpy; | |
3194 unwind.cmap = cmap; | |
3195 record_unwind_protect (tiff_instantiate_unwind, make_opaque_ptr (&unwind)); | |
3196 | |
3197 /* set up error facilities */ | |
3198 if (setjmp (tiff_err_data.setjmp_buffer)) | |
3199 { | |
3200 /* An error was signaled. No clean up is needed, as unwind handles that | |
3201 for us. Just pass the error along. */ | |
3202 signal_image_error_2 ("TIFF decoding error", | |
3203 build_string(tiff_err_data.err_str), | |
3204 instantiator); | |
3205 } | |
3206 TIFFSetErrorHandler ((TIFFErrorHandler)tiff_error_func); | |
3207 TIFFSetWarningHandler ((TIFFErrorHandler)tiff_warning_func); | |
3208 { | |
3209 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
3210 Extbyte *bytes; | |
3211 Extcount len; | |
3212 | |
3213 uint32 width, height; | |
3214 uint32 *raster; | |
3215 unsigned char *ep; | |
3216 | |
3217 assert (!NILP (data)); | |
3218 | |
3219 /* #### This is a definite problem under Mule due to the amount of | |
3220 stack data it might allocate. Think about Lstreams... */ | |
3221 GET_STRING_BINARY_DATA_ALLOCA (data, bytes, len); | |
3222 mem_struct.bytes = bytes; | |
3223 mem_struct.len = len; | |
3224 mem_struct.index = 0; | |
3225 | |
3226 unwind.tiff = TIFFClientOpen ("memfile", "r", &mem_struct, | |
3227 (TIFFReadWriteProc)tiff_memory_read, | |
3228 (TIFFReadWriteProc)tiff_memory_write, | |
3229 tiff_memory_seek, tiff_memory_close, tiff_memory_size, | |
3230 tiff_map_noop, tiff_unmap_noop); | |
3231 if (!unwind.tiff) | |
3232 signal_image_error ("Insufficent memory to instantiate TIFF image", instantiator); | |
3233 | |
3234 TIFFGetField (unwind.tiff, TIFFTAG_IMAGEWIDTH, &width); | |
3235 TIFFGetField (unwind.tiff, TIFFTAG_IMAGELENGTH, &height); | |
3236 unwind.eimage = (unsigned char *) xmalloc (width * height * 3); | |
3237 | |
3238 /* ### This is little more than proof-of-concept/function testing. | |
3239 It needs to be reimplimented via scanline reads for both memory | |
3240 compactness. */ | |
3241 raster = (uint32*) _TIFFmalloc (width * height * sizeof (uint32)); | |
3242 if (raster != NULL) | |
3243 { | |
3244 int i,j; | |
3245 uint32 *rp; | |
3246 ep = unwind.eimage; | |
3247 rp = raster; | |
3248 if (TIFFReadRGBAImage (unwind.tiff, width, height, raster, 0)) | |
3249 { | |
3250 for (i = height - 1; i >= 0; i--) | |
3251 { | |
3252 /* This is to get around weirdness in the libtiff library where properly | |
3253 made TIFFs will come out upside down. libtiff bug or jhod-brainlock? */ | |
3254 rp = raster + (i * width); | |
3255 for (j = 0; j < width; j++) | |
3256 { | |
3257 *ep++ = (unsigned char)TIFFGetR(*rp); | |
3258 *ep++ = (unsigned char)TIFFGetG(*rp); | |
3259 *ep++ = (unsigned char)TIFFGetB(*rp); | |
3260 rp++; | |
3261 } | |
3262 } | |
3263 } | |
3264 _TIFFfree (raster); | |
3265 } else | |
3266 signal_image_error ("Unable to allocate memory for TIFFReadRGBA", instantiator); | |
3267 | |
3268 unwind.ximage = convert_EImage_to_XImage (device, width, height, unwind.eimage, | |
3269 &unwind.pixels, &unwind.pixcount, &unwind.npixels); | |
3270 if (!unwind.ximage) | |
3271 signal_image_error ("TIFF conversion failed", instantiator); | |
3272 } | |
3273 /* Now create the pixmap and set up the image instance */ | |
3274 init_image_instance_from_x_image (ii, unwind.ximage, dest_mask, | |
3275 cmap, unwind.pixels, unwind.npixels, | |
3276 instantiator); | |
3277 /* Now that we've succeeded, we don't want the pixels | |
3278 freed right now. They're kept around in the image instance | |
3279 structure until it's destroyed. */ | |
3280 unwind.npixels = 0; | |
3281 unwind.pixcount = 0; | |
3282 unbind_to (speccount, Qnil); | |
3283 } | |
3284 | |
3285 #endif /* HAVE_TIFF */ | |
3286 | |
3287 | |
3288 #ifdef HAVE_XFACE | 1468 #ifdef HAVE_XFACE |
3289 | 1469 |
3290 /********************************************************************** | 1470 /********************************************************************** |
3291 * X-Face * | 1471 * X-Face * |
3292 **********************************************************************/ | 1472 **********************************************************************/ |
4162 | 2342 |
4163 IIFORMAT_VALID_KEYWORD (font, Q_data, check_valid_string); | 2343 IIFORMAT_VALID_KEYWORD (font, Q_data, check_valid_string); |
4164 IIFORMAT_VALID_KEYWORD (font, Q_foreground, check_valid_string); | 2344 IIFORMAT_VALID_KEYWORD (font, Q_foreground, check_valid_string); |
4165 IIFORMAT_VALID_KEYWORD (font, Q_background, check_valid_string); | 2345 IIFORMAT_VALID_KEYWORD (font, Q_background, check_valid_string); |
4166 | 2346 |
4167 #ifdef HAVE_JPEG | |
4168 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (jpeg, "jpeg"); | |
4169 | |
4170 IIFORMAT_HAS_METHOD (jpeg, validate); | |
4171 IIFORMAT_HAS_METHOD (jpeg, normalize); | |
4172 IIFORMAT_HAS_METHOD (jpeg, possible_dest_types); | |
4173 IIFORMAT_HAS_METHOD (jpeg, instantiate); | |
4174 | |
4175 IIFORMAT_VALID_KEYWORD (jpeg, Q_data, check_valid_string); | |
4176 IIFORMAT_VALID_KEYWORD (jpeg, Q_file, check_valid_string); | |
4177 #endif | |
4178 | |
4179 #ifdef HAVE_GIF | |
4180 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (gif, "gif"); | |
4181 | |
4182 IIFORMAT_HAS_METHOD (gif, validate); | |
4183 IIFORMAT_HAS_METHOD (gif, normalize); | |
4184 IIFORMAT_HAS_METHOD (gif, possible_dest_types); | |
4185 IIFORMAT_HAS_METHOD (gif, instantiate); | |
4186 | |
4187 IIFORMAT_VALID_KEYWORD (gif, Q_data, check_valid_string); | |
4188 IIFORMAT_VALID_KEYWORD (gif, Q_file, check_valid_string); | |
4189 #endif | |
4190 | |
4191 #ifdef HAVE_PNG | |
4192 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (png, "png"); | |
4193 | |
4194 IIFORMAT_HAS_METHOD (png, validate); | |
4195 IIFORMAT_HAS_METHOD (png, normalize); | |
4196 IIFORMAT_HAS_METHOD (png, possible_dest_types); | |
4197 IIFORMAT_HAS_METHOD (png, instantiate); | |
4198 | |
4199 IIFORMAT_VALID_KEYWORD (png, Q_data, check_valid_string); | |
4200 IIFORMAT_VALID_KEYWORD (png, Q_file, check_valid_string); | |
4201 #endif | |
4202 | |
4203 #ifdef HAVE_TIFF | |
4204 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tiff, "tiff"); | |
4205 | |
4206 IIFORMAT_HAS_METHOD (tiff, validate); | |
4207 IIFORMAT_HAS_METHOD (tiff, normalize); | |
4208 IIFORMAT_HAS_METHOD (tiff, possible_dest_types); | |
4209 IIFORMAT_HAS_METHOD (tiff, instantiate); | |
4210 | |
4211 IIFORMAT_VALID_KEYWORD (tiff, Q_data, check_valid_string); | |
4212 IIFORMAT_VALID_KEYWORD (tiff, Q_file, check_valid_string); | |
4213 #endif | |
4214 | |
4215 #ifdef HAVE_XFACE | 2347 #ifdef HAVE_XFACE |
4216 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (xface, "xface"); | 2348 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (xface, "xface"); |
4217 | 2349 |
4218 IIFORMAT_HAS_METHOD (xface, validate); | 2350 IIFORMAT_HAS_METHOD (xface, validate); |
4219 IIFORMAT_HAS_METHOD (xface, normalize); | 2351 IIFORMAT_HAS_METHOD (xface, normalize); |
4240 } | 2372 } |
4241 | 2373 |
4242 void | 2374 void |
4243 vars_of_glyphs_x (void) | 2375 vars_of_glyphs_x (void) |
4244 { | 2376 { |
4245 #ifdef HAVE_JPEG | |
4246 Fprovide (Qjpeg); | |
4247 #endif | |
4248 | |
4249 #ifdef HAVE_GIF | |
4250 Fprovide (Qgif); | |
4251 #endif | |
4252 | |
4253 #ifdef HAVE_PNG | |
4254 Fprovide (Qpng); | |
4255 #endif | |
4256 | |
4257 #ifdef HAVE_TIFF | |
4258 Fprovide (Qtiff); | |
4259 #endif | |
4260 | |
4261 #ifdef HAVE_XFACE | 2377 #ifdef HAVE_XFACE |
4262 Fprovide (Qxface); | 2378 Fprovide (Qxface); |
4263 #endif | 2379 #endif |
4264 | 2380 |
4265 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path /* | 2381 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path /* |