1 #include "JpegI.h"
2 #include <jerror.h>
3 #include <stdlib.h>
4 #include <X11/Intrinsic.h>
5
6 void
_XmJpegErrorExit(j_common_ptr cinfo)7 _XmJpegErrorExit(j_common_ptr cinfo)
8 {
9 int rc;
10 XmJpegErrorMgr err = (XmJpegErrorMgr) cinfo->err;
11
12 switch (cinfo->err->msg_code) {
13 case JERR_NO_SOI:
14 rc = 1;
15 break;
16 case JERR_OUT_OF_MEMORY:
17 rc = 4;
18 break;
19 default:
20 rc = 2;
21 break;
22 }
23 longjmp(err->setjmp_buffer, rc);
24 }
25
26 int
load_jpeg(FILE * infile,unsigned long * pWidth,unsigned long * pHeight,CTable ** image_data)27 load_jpeg(FILE * infile, unsigned long *pWidth, unsigned long *pHeight,
28 CTable ** image_data)
29 {
30 CTable *buf;
31 struct jpeg_decompress_struct cinfo;
32 XmJpegErrorMgrRec jerr;
33 JSAMPROW row_pointer[1];
34 int x, y;
35 int rc;
36
37 *image_data = NULL;
38 cinfo.err = jpeg_std_error((struct jpeg_error_mgr *) &jerr);
39 jerr.pub.error_exit = _XmJpegErrorExit;
40 if ((rc = setjmp(jerr.setjmp_buffer))) {
41 jpeg_destroy_decompress(&cinfo);
42 return rc;
43 }
44 jpeg_create_decompress(&cinfo);
45 jpeg_stdio_src(&cinfo, infile);
46 jpeg_read_header(&cinfo, TRUE);
47 jpeg_calc_output_dimensions(&cinfo);
48 jpeg_start_decompress(&cinfo);
49 *pWidth = cinfo.output_width;
50 *pHeight = cinfo.output_height;
51 *image_data =
52 malloc(cinfo.output_width * cinfo.output_height * sizeof(CTable));
53 for (buf = *image_data;
54 cinfo.output_scanline < cinfo.output_height;
55 buf += cinfo.output_width)
56 jpeg_read_scanlines(&cinfo, (JSAMPARRAY) (&buf), 1);
57 if (cinfo.out_color_space == JCS_GRAYSCALE) {
58 for (y = 0, buf = *image_data; y < cinfo.output_height;
59 y++, buf += cinfo.output_width)
60 for (x = cinfo.output_width - 1; x >= 0; x--)
61 buf[x].red = buf[x].green = buf[x].blue =
62 ((JSAMPLE *) buf)[x];
63 }
64 jpeg_finish_decompress(&cinfo);
65 jpeg_destroy_decompress(&cinfo);
66 return 0;
67 }
68
69 Pixel
get_cval(unsigned char c,unsigned long mask)70 get_cval(unsigned char c, unsigned long mask)
71 {
72 Pixel value = c, x;
73 int i;
74 for (i = 0, x = 1; i < 32; i++, x <<= 1)
75 if (mask & x)
76 break;
77 for (; i < 32; i++, x <<= 1)
78 if (!(mask & x))
79 break;
80 if (i < 8)
81 value >>= 8 - i;
82 else if (i > 8)
83 value <<= i - 8;
84 return (value & mask);
85 }
86
87 void
store_pixel(Screen * screen,CTable * p,int x,char * cdata)88 store_pixel(Screen * screen, CTable * p, int x, char *cdata)
89 {
90 Pixel px = get_cval(p->red, screen->root_visual->red_mask)
91 | get_cval(p->green, screen->root_visual->green_mask)
92 | get_cval(p->blue, screen->root_visual->blue_mask);
93 if (screen->root_depth <= 16) {
94 if (ImageByteOrder(screen->display) == MSBFirst) {
95 cdata[x * 2] = (px >> 8);
96 cdata[x * 2 + 1] = (px & 0xff);
97 } else {
98 cdata[x * 2] = (px & 0xff);
99 cdata[x * 2 + 1] = (px >> 8);
100 }
101 } else {
102 if (ImageByteOrder(screen->display) == MSBFirst) {
103 cdata[x * 4] = (px >> 24);
104 cdata[x * 4 + 1] = (px >> 16);
105 cdata[x * 4 + 2] = (px >> 8);
106 cdata[x * 4 + 3] = (px & 0xff);
107 } else {
108 cdata[x * 4 + 3] = (px >> 24);
109 cdata[x * 4 + 2] = (px >> 16);
110 cdata[x * 4 + 1] = (px >> 8);
111 cdata[x * 4] = (px & 0xff);
112 }
113 }
114 }
115
116 int
_XmJpegGetImage(Screen * screen,FILE * infile,XImage ** ximage)117 _XmJpegGetImage(Screen * screen, FILE * infile, XImage ** ximage)
118 {
119 unsigned long image_width, image_height;
120 unsigned char *xdata;
121 int pad;
122 CTable *image_data;
123 int rc;
124
125 if ((rc = load_jpeg(infile, &image_width, &image_height, &image_data)))
126 return rc;
127 if (screen->root_depth == 24 || screen->root_depth == 32) {
128 xdata = (unsigned char *) malloc(4 * image_width * image_height);
129 pad = 32;
130 } else if (screen->root_depth == 16) {
131 xdata = (unsigned char *) malloc(2 * image_width * image_height);
132 pad = 16;
133 } else { /* depth == 8 */
134 xdata = (unsigned char *) malloc(image_width * image_height);
135 pad = 8;
136 }
137
138 if (!xdata)
139 return 4;
140
141 *ximage =
142 XCreateImage(screen->display, screen->root_visual,
143 screen->root_depth, ZPixmap, 0, (char *) xdata,
144 image_width, image_height, pad, 0);
145 if (!*ximage) {
146 free(xdata);
147 return 4;
148 }
149
150 {
151 int xx, yy;
152 CTable *p;
153 for (yy = 0; yy < (*ximage)->height; yy++) {
154 p = image_data + yy * (*ximage)->width;
155 for (xx = 0; xx < (*ximage)->width; xx++, p++)
156 store_pixel(screen, p, xx + yy * (*ximage)->width,
157 (*ximage)->data);
158 }
159 }
160
161 if (image_data) {
162 free(image_data);
163 image_data = NULL;
164 }
165 return 0;
166 }
167