479.1.1
by Matthew Fuller
Start breaking up util.c by pulling out the JPEG-related functions |
1 |
/*
|
2 |
* JPEG image handling functions
|
|
3 |
*/
|
|
4 |
||
5 |
#include "ctwm.h" |
|
6 |
||
7 |
#include <stdio.h> |
|
8 |
#include <stdlib.h> |
|
9 |
#include <string.h> |
|
492.2.122
by Matthew Fuller
We're now aiming strongly at C99, so just use stdint.h in place of |
10 |
#include <stdint.h> |
479.1.1
by Matthew Fuller
Start breaking up util.c by pulling out the JPEG-related functions |
11 |
|
12 |
#include "screen.h" |
|
479.1.5
by Matthew Fuller
Switch to single central reportfilenotfound in the "to move to |
13 |
#include "image.h" |
479.1.1
by Matthew Fuller
Start breaking up util.c by pulling out the JPEG-related functions |
14 |
#include "image_jpeg.h" |
15 |
||
16 |
/* Bits needed for libjpeg and interaction */
|
|
17 |
#include <setjmp.h> |
|
18 |
#include <jpeglib.h> |
|
19 |
#include <jerror.h> |
|
20 |
||
21 |
#include <X11/Xlib.h> |
|
22 |
||
480.1.14
by Matthew Fuller
Rearrange and comment image_jpeg to put the public func first, and |
23 |
|
24 |
/* Various internal bits */
|
|
480.1.17
by Matthew Fuller
const-ify all these image names we pass through this process. |
25 |
static Image *LoadJpegImage(const char *name); |
26 |
static Image *LoadJpegImageCp(const char *name, ColorPair cp); |
|
480.1.14
by Matthew Fuller
Rearrange and comment image_jpeg to put the public func first, and |
27 |
static void convert_for_16(int w, int x, int y, int r, int g, int b); |
28 |
static void convert_for_32(int w, int x, int y, int r, int g, int b); |
|
29 |
static void jpeg_error_exit(j_common_ptr cinfo); |
|
479.1.1
by Matthew Fuller
Start breaking up util.c by pulling out the JPEG-related functions |
30 |
|
31 |
struct jpeg_error { |
|
32 |
struct jpeg_error_mgr pub; |
|
33 |
sigjmp_buf setjmp_buffer; |
|
34 |
};
|
|
35 |
||
36 |
typedef struct jpeg_error *jerr_ptr; |
|
37 |
||
38 |
static uint16_t *buffer_16bpp; |
|
39 |
static uint32_t *buffer_32bpp; |
|
40 |
||
480.1.14
by Matthew Fuller
Rearrange and comment image_jpeg to put the public func first, and |
41 |
|
42 |
/*
|
|
43 |
* External entry point
|
|
44 |
*/
|
|
479.1.1
by Matthew Fuller
Start breaking up util.c by pulling out the JPEG-related functions |
45 |
Image * |
480.1.17
by Matthew Fuller
const-ify all these image names we pass through this process. |
46 |
GetJpegImage(const char *name) |
479.1.1
by Matthew Fuller
Start breaking up util.c by pulling out the JPEG-related functions |
47 |
{
|
496.1.4
by Matthew Fuller
Use a dummy temp var here instead of an inline literal; astyle doesn't |
48 |
ColorPair dummy = {0}; |
49 |
||
480.1.15
by Matthew Fuller
Change GetJpegImage() to use the common func for loading animations. |
50 |
/* Non-animated */
|
479.1.1
by Matthew Fuller
Start breaking up util.c by pulling out the JPEG-related functions |
51 |
if(! strchr(name, '%')) { |
52 |
return (LoadJpegImage(name)); |
|
53 |
}
|
|
480.1.15
by Matthew Fuller
Change GetJpegImage() to use the common func for loading animations. |
54 |
|
55 |
/* Animated */
|
|
496.1.4
by Matthew Fuller
Use a dummy temp var here instead of an inline literal; astyle doesn't |
56 |
return get_image_anim_cp(name, dummy, LoadJpegImageCp); |
479.1.1
by Matthew Fuller
Start breaking up util.c by pulling out the JPEG-related functions |
57 |
}
|
58 |
||
480.1.14
by Matthew Fuller
Rearrange and comment image_jpeg to put the public func first, and |
59 |
|
60 |
/*
|
|
61 |
* Internal backend func
|
|
62 |
*/
|
|
480.1.15
by Matthew Fuller
Change GetJpegImage() to use the common func for loading animations. |
63 |
|
64 |
/* Trivial thunk for get_image_anim_cp() callback */
|
|
65 |
static Image * |
|
480.1.17
by Matthew Fuller
const-ify all these image names we pass through this process. |
66 |
LoadJpegImageCp(const char *name, ColorPair cp) |
480.1.15
by Matthew Fuller
Change GetJpegImage() to use the common func for loading animations. |
67 |
{
|
68 |
return LoadJpegImage(name); |
|
69 |
}
|
|
70 |
||
71 |
/* The actual loader */
|
|
479.1.29
by Matthew Fuller
Split the rest of the image* function definitions, and make indent. |
72 |
static Image * |
480.1.17
by Matthew Fuller
const-ify all these image names we pass through this process. |
73 |
LoadJpegImage(const char *name) |
479.1.1
by Matthew Fuller
Start breaking up util.c by pulling out the JPEG-related functions |
74 |
{
|
75 |
char *fullname; |
|
76 |
XImage *ximage; |
|
77 |
FILE *infile; |
|
78 |
Image *image; |
|
79 |
Pixmap pixret; |
|
80 |
void (*store_data)(int w, int x, int y, int r, int g, int b); |
|
81 |
struct jpeg_decompress_struct cinfo; |
|
82 |
struct jpeg_error jerr; |
|
83 |
JSAMPARRAY buffer; |
|
84 |
int width, height; |
|
85 |
int row_stride; |
|
86 |
int g, i, a; |
|
87 |
int bpix; |
|
88 |
GC gc; |
|
89 |
||
90 |
fullname = ExpandPixmapPath(name); |
|
91 |
if(! fullname) { |
|
501.1.9
by Matthew Fuller
Convert pointer values from None -> NULL in image*. |
92 |
return NULL; |
479.1.1
by Matthew Fuller
Start breaking up util.c by pulling out the JPEG-related functions |
93 |
}
|
94 |
||
480.1.19
by Matthew Fuller
Add an AllocImage() to ensure new Image's are initialized properly, |
95 |
image = AllocImage(); |
501.1.9
by Matthew Fuller
Convert pointer values from None -> NULL in image*. |
96 |
if(image == NULL) { |
479.1.1
by Matthew Fuller
Start breaking up util.c by pulling out the JPEG-related functions |
97 |
free(fullname); |
501.1.9
by Matthew Fuller
Convert pointer values from None -> NULL in image*. |
98 |
return NULL; |
479.1.1
by Matthew Fuller
Start breaking up util.c by pulling out the JPEG-related functions |
99 |
}
|
100 |
||
101 |
if((infile = fopen(fullname, "rb")) == NULL) { |
|
479.1.3
by Matthew Fuller
Stop jumping hoops on these reportfilenotfound's and just make them |
102 |
if(reportfilenotfound) { |
479.1.1
by Matthew Fuller
Start breaking up util.c by pulling out the JPEG-related functions |
103 |
fprintf(stderr, "unable to locate %s\n", fullname); |
104 |
}
|
|
105 |
fflush(stdout); |
|
106 |
free(image); |
|
107 |
free(fullname); |
|
501.1.9
by Matthew Fuller
Convert pointer values from None -> NULL in image*. |
108 |
return NULL; |
479.1.1
by Matthew Fuller
Start breaking up util.c by pulling out the JPEG-related functions |
109 |
}
|
110 |
free(fullname); |
|
111 |
cinfo.err = jpeg_std_error(&jerr.pub); |
|
112 |
jerr.pub.error_exit = jpeg_error_exit; |
|
113 |
||
114 |
if(sigsetjmp(jerr.setjmp_buffer, 1)) { |
|
115 |
jpeg_destroy_decompress(&cinfo); |
|
116 |
free(image); |
|
117 |
fclose(infile); |
|
501.1.9
by Matthew Fuller
Convert pointer values from None -> NULL in image*. |
118 |
return NULL; |
479.1.1
by Matthew Fuller
Start breaking up util.c by pulling out the JPEG-related functions |
119 |
}
|
120 |
jpeg_create_decompress(&cinfo); |
|
121 |
jpeg_stdio_src(&cinfo, infile); |
|
122 |
jpeg_read_header(&cinfo, FALSE); |
|
123 |
cinfo.do_fancy_upsampling = FALSE; |
|
124 |
cinfo.do_block_smoothing = FALSE; |
|
125 |
jpeg_start_decompress(&cinfo); |
|
126 |
width = cinfo.output_width; |
|
127 |
height = cinfo.output_height; |
|
128 |
||
129 |
if(Scr->d_depth == 16) { |
|
130 |
store_data = &convert_for_16; |
|
491.1.8
by Matthew Fuller
Stop casting return values of [mc]alloc(). void * has existed for 27 |
131 |
buffer_16bpp = malloc((width) * (height) * 2); |
479.1.1
by Matthew Fuller
Start breaking up util.c by pulling out the JPEG-related functions |
132 |
ximage = XCreateImage(dpy, CopyFromParent, Scr->d_depth, ZPixmap, 0, |
133 |
(char *) buffer_16bpp, width, height, 16, width * 2); |
|
134 |
}
|
|
135 |
else if(Scr->d_depth == 24 || Scr->d_depth == 32) { |
|
136 |
store_data = &convert_for_32; |
|
137 |
buffer_32bpp = malloc(width * height * 4); |
|
138 |
ximage = XCreateImage(dpy, CopyFromParent, Scr->d_depth, ZPixmap, 0, |
|
139 |
(char *) buffer_32bpp, width, height, 32, width * 4); |
|
140 |
}
|
|
141 |
else { |
|
142 |
fprintf(stderr, "Image %s unsupported depth : %d\n", name, Scr->d_depth); |
|
143 |
free(image); |
|
144 |
fclose(infile); |
|
501.1.9
by Matthew Fuller
Convert pointer values from None -> NULL in image*. |
145 |
return NULL; |
479.1.1
by Matthew Fuller
Start breaking up util.c by pulling out the JPEG-related functions |
146 |
}
|
501.1.9
by Matthew Fuller
Convert pointer values from None -> NULL in image*. |
147 |
if(ximage == NULL) { |
479.1.1
by Matthew Fuller
Start breaking up util.c by pulling out the JPEG-related functions |
148 |
fprintf(stderr, "cannot create image for %s\n", name); |
149 |
free(image); |
|
150 |
fclose(infile); |
|
501.1.9
by Matthew Fuller
Convert pointer values from None -> NULL in image*. |
151 |
return NULL; |
479.1.1
by Matthew Fuller
Start breaking up util.c by pulling out the JPEG-related functions |
152 |
}
|
153 |
g = 0; |
|
154 |
row_stride = cinfo.output_width * cinfo.output_components; |
|
155 |
buffer = (*cinfo.mem->alloc_sarray) |
|
156 |
((j_common_ptr) & cinfo, JPOOL_IMAGE, row_stride, 1); |
|
157 |
||
158 |
bpix = cinfo.output_components; |
|
159 |
while(cinfo.output_scanline < cinfo.output_height) { |
|
160 |
jpeg_read_scanlines(&cinfo, buffer, 1); |
|
161 |
a = 0; |
|
162 |
for(i = 0; i < bpix * cinfo.output_width; i += bpix) { |
|
163 |
(*store_data)(width, a, g, buffer[0][i], buffer[0][i + 1], buffer[0][i + 2]); |
|
164 |
a++; |
|
165 |
}
|
|
166 |
g++; |
|
167 |
}
|
|
168 |
jpeg_finish_decompress(&cinfo); |
|
169 |
jpeg_destroy_decompress(&cinfo); |
|
170 |
fclose(infile); |
|
171 |
||
172 |
gc = DefaultGC(dpy, Scr->screen); |
|
173 |
if((width > (Scr->rootw / 2)) || (height > (Scr->rooth / 2))) { |
|
174 |
int x, y; |
|
175 |
||
176 |
pixret = XCreatePixmap(dpy, Scr->Root, Scr->rootw, Scr->rooth, Scr->d_depth); |
|
177 |
x = (Scr->rootw - width) / 2; |
|
178 |
y = (Scr->rooth - height) / 2; |
|
179 |
XFillRectangle(dpy, pixret, gc, 0, 0, Scr->rootw, Scr->rooth); |
|
180 |
XPutImage(dpy, pixret, gc, ximage, 0, 0, x, y, width, height); |
|
181 |
image->width = Scr->rootw; |
|
182 |
image->height = Scr->rooth; |
|
183 |
}
|
|
184 |
else { |
|
185 |
pixret = XCreatePixmap(dpy, Scr->Root, width, height, Scr->d_depth); |
|
186 |
XPutImage(dpy, pixret, gc, ximage, 0, 0, 0, 0, width, height); |
|
187 |
image->width = width; |
|
188 |
image->height = height; |
|
189 |
}
|
|
190 |
if(ximage) { |
|
191 |
XDestroyImage(ximage); |
|
192 |
}
|
|
193 |
image->pixmap = pixret; |
|
194 |
||
195 |
return image; |
|
196 |
}
|
|
480.1.14
by Matthew Fuller
Rearrange and comment image_jpeg to put the public func first, and |
197 |
|
198 |
||
199 |
||
200 |
/*
|
|
201 |
* Utils
|
|
202 |
*/
|
|
203 |
static void |
|
204 |
convert_for_16(int w, int x, int y, int r, int g, int b) |
|
205 |
{
|
|
206 |
buffer_16bpp [y * w + x] = ((r >> 3) << 11) + ((g >> 2) << 5) + (b >> 3); |
|
207 |
}
|
|
208 |
||
209 |
static void |
|
210 |
convert_for_32(int w, int x, int y, int r, int g, int b) |
|
211 |
{
|
|
212 |
buffer_32bpp [y * w + x] = ((r << 16) + (g << 8) + b) & 0xFFFFFFFF; |
|
213 |
}
|
|
214 |
||
215 |
static void |
|
216 |
jpeg_error_exit(j_common_ptr cinfo) |
|
217 |
{
|
|
218 |
jerr_ptr errmgr = (jerr_ptr) cinfo->err; |
|
219 |
cinfo->err->output_message(cinfo); |
|
220 |
siglongjmp(errmgr->setjmp_buffer, 1); |
|
221 |
return; |
|
222 |
}
|