1 /* jpeg.c
2  * JPEG decoding
3  * (c) 2002 Karel 'Clock' Kulhavy
4  * This file is a part of the Links program, released under GPL.
5  */
6 
7 #include "cfg.h"
8 
9 #ifdef G
10 #include "links.h"
11 
12 #ifdef HAVE_JPEG
13 #include <jpeglib.h>
14 
15 #if BITS_IN_JSAMPLE != 8
16 #error "You have a weird jpeglib compiled for 12 bits per sample that is not able to read ordinary JPEG's. \
17 See INSTALL for description how to compile Links with jpeglib statically to supply your own \"good\" version \
18 of jpeglib or reinstall your system's jpeglib to be a normal one."
19 #endif /* #if BITS_IN_JSAMPLE != 8 */
20 
21 struct jerr_struct{
22 	struct jpeg_error_mgr pub;
23 	jmp_buf setjmp_buffer;
24 };
25 
26 struct jpg_decoder{
27 	struct jpeg_decompress_struct *cinfo;
28 	struct jerr_struct *jerr;
29 	unsigned char state; /* 0: header 1: start 2: scanlines 3: end 4,5: also
30 			something */
31 	int skip_bytes;
32 	unsigned char *jdata;
33 	unsigned char *scanlines[16];
34 };
35 
36 static struct jerr_struct *global_jerr;
37 static struct jpeg_decompress_struct *global_cinfo;
38 static int mesg_unsup_emitted = 0; /* Defaults to zero at program startup and once
39 				* set is never reset back to zero */
40 
41 
42 /*#include <jerror.h>*/
43 
my_error_exit(j_common_ptr cinfo)44 METHODDEF(void) my_error_exit(j_common_ptr cinfo)
45 {
46 	/*fprintf(stderr, "jpeg error %d (%d)\n", cinfo->err->msg_code, JERR_OUT_OF_MEMORY);*/
47 	longjmp(global_jerr->setjmp_buffer,2);
48 }
49 
50 METHODDEF(void) /* Only for the sake of libjpeg */
nop(j_decompress_ptr cinfo)51 nop(j_decompress_ptr cinfo)
52 {
53 }
54 
55 METHODDEF(void)
my_output_message(j_common_ptr cinfo)56 my_output_message(j_common_ptr cinfo)
57 {
58 }
59 
my_fill_input_buffer(j_decompress_ptr cinfo)60 METHODDEF(boolean) my_fill_input_buffer(j_decompress_ptr cinfo)
61 {
62  return FALSE; /* We utilize I/O suspension (or emulsion? ;-) ) */
63 }
64 
my_skip_input_data(j_decompress_ptr cinfo,long num_bytes)65 METHODDEF(void) my_skip_input_data(j_decompress_ptr cinfo,long num_bytes)
66 {
67 	if ((unsigned long)num_bytes>cinfo->src->bytes_in_buffer)
68 	{
69 		/* We have to enter skipping state */
70 		cinfo->src->next_input_byte+=cinfo->src->bytes_in_buffer;
71 		((struct jpg_decoder *)(global_cimg->decoder))->skip_bytes
72 			=(int)(num_bytes-cinfo->src->bytes_in_buffer);
73 		cinfo->src->bytes_in_buffer=0;
74 	}
75 	else
76 	{
77 		/* We only pull out some bytes from buffer. */
78 		cinfo->src->next_input_byte+=num_bytes;
79 		cinfo->src->bytes_in_buffer-=num_bytes;
80 	}
81 }
82 
jpeg_start(struct cached_image * cimg)83 void jpeg_start(struct cached_image *cimg)
84 {
85 	struct jpg_decoder *jd;
86 
87 	global_cinfo=mem_alloc(sizeof(*global_cinfo));
88 	global_jerr=mem_alloc(sizeof(*global_jerr));
89 	global_cinfo->err = jpeg_std_error(&(global_jerr->pub));
90 	global_jerr->pub.error_exit=my_error_exit;
91 	global_jerr->pub.output_message=my_output_message;
92 	if (setjmp(global_jerr->setjmp_buffer)){
93 g19_2000:
94 		mem_free(global_cinfo);
95 		mem_free(global_jerr);
96 		img_end(cimg);
97 		return;
98 	}
99 	jpeg_create_decompress(global_cinfo);
100 	if (setjmp(global_jerr->setjmp_buffer)){
101 		jpeg_destroy_decompress(global_cinfo);
102 		goto g19_2000;
103 	}
104 	jpeg_stdio_src(global_cinfo,stdin);
105 	global_cinfo->src->init_source=&nop;
106 	global_cinfo->src->fill_input_buffer=&my_fill_input_buffer;
107 	global_cinfo->src->skip_input_data=&my_skip_input_data;
108 	global_cinfo->src->resync_to_restart=&jpeg_resync_to_restart;
109 	global_cinfo->src->term_source=nop;
110 	global_cinfo->src->bytes_in_buffer=0;
111 	global_cinfo->src->next_input_byte=NULL;
112 	cimg->decoder=mem_alloc(sizeof(struct jpg_decoder));
113 	jd=(struct jpg_decoder *)cimg->decoder;
114 	jd->cinfo=global_cinfo;
115 	jd->jerr=global_jerr;
116 	jd->state=0;
117 	jd->skip_bytes=0;
118 	jd->jdata=NULL;
119 	/* Scanlines can be left unititialized */
120 }
121 
122 /* This is here because libjpeg doesn't support transformation from CMYK
123  * to RGB so that we must do it ourselves.
124  *
125  * data must be non-NULL. */
cmyk_to_rgb(unsigned char * data,int pixels)126 static void cmyk_to_rgb(unsigned char *data, int pixels)
127 {
128 	for (;pixels;pixels--, data+=4)
129 	{
130 		/* C -> R */
131 		data[0]=((data[0])*(data[3])+127)/255;
132 
133 		/* M -> G */
134 		data[1]=((data[1])*(data[3])+127)/255;
135 
136 		/* Y -> B */
137 		data[2]=((data[2])*(data[3])+127)/255;
138 
139 		/* Put alpha=1 instead of K */
140 		data[3]=255;
141 	}
142 }
143 
144 /* data must be non-NULL */
gray_to_rgb(unsigned char * data,int pixels)145 static void gray_to_rgb(unsigned char *data, int pixels)
146 {
147 	unsigned char *dest;
148 
149 	dest=data+(pixels-1)*3;
150 	data+=pixels-1;
151 	for(;pixels;pixels--,data--,dest-=3){
152 		dest[2]=*data;
153 		dest[1]=*data;
154 		dest[0]=*data;
155 	}
156 }
157 
158 /* Fixes returned data in case they are CMYK or grayscale. */
fix_data(struct jpg_decoder * deco,int lines_read)159 static inline void fix_data( struct jpg_decoder *deco, int lines_read)
160 {
161 	/* ICC bug */
162 	icc_volatile int a;
163 
164 	switch (global_cinfo->output_components){
165 		case 1:
166 		for (a=0; a<lines_read; a++)
167 			gray_to_rgb(deco->scanlines[a], global_cinfo
168 				->output_width);
169 		break;
170 
171 		case 3:
172 		break;
173 
174 		case 4:
175 		cmyk_to_rgb(deco->scanlines[0], global_cinfo
176 			->output_width*lines_read);
177 		break;
178 
179 		default: internal_error("Invalid output_components");
180 	}
181 }
182 
jpeg_restart(struct cached_image * cimg,unsigned char * data,int length)183 void jpeg_restart(struct cached_image *cimg, unsigned char *data, int length)
184 {
185 	struct jpg_decoder *deco;
186 
187 	deco=(struct jpg_decoder *)(cimg->decoder);
188 #ifdef DEBUG
189 	if (!deco) internal_error("NULL decoder in jpeg_restart");
190 #endif /* #ifdef DEBUG */
191 	global_cinfo=((struct jpg_decoder *)(cimg->decoder))->cinfo;
192 	global_jerr=((struct jpg_decoder *)(cimg->decoder))->jerr;
193 	/* These global variables are here so that we don't have to pass lots
194 	 * of structure pointers into each function. The jpeg decoder is never
195 	 * running twice at the same time so it doesn't matter.
196 	 */
197 
198 	/* If the decoder wants us to skip bytes it's not interested in */
199 	if (deco->skip_bytes>=length){
200 		/* If the decoder wants to skip as much as or more bytes than
201 		 * the chunk that has just arrived */
202 		deco->skip_bytes-=length;
203 		return;
204 	}else{
205 		/* If the decoder wants to skip less bytes than the chunk
206 		 * that has just arrived */
207 		data+=deco->skip_bytes;
208 		length-=deco->skip_bytes;
209 		deco->skip_bytes=0;
210 	}
211 
212 	/* Add the arrived data chunk into the decoder buffer. Sometimes the
213 	 * chunks are so small the decoder can't move on on a single chunk
214 	 * so it has to accumulate more chunks together. This is why the buffer
215 	 * is there. */
216 	if ((unsigned)global_cinfo->src->bytes_in_buffer + (unsigned)length > MAXINT) overalloc();
217 	if ((unsigned)global_cinfo->src->bytes_in_buffer + (unsigned)length < (unsigned)length) overalloc();
218 	if (deco->jdata){
219 		/* If there is already some decoder buffer, we have to
220 		 * allocate more space */
221 		memmove(deco->jdata,global_cinfo->src->next_input_byte,
222 			global_cinfo->src->bytes_in_buffer);
223 		deco->jdata=mem_realloc(
224 			deco->jdata, global_cinfo->src->bytes_in_buffer+length);
225 	}else{
226 		/* If there is no decoder buffer we'll have to allocate
227 		 * space for a new buffer */
228 		deco->jdata=mem_alloc(global_cinfo->src->bytes_in_buffer+length);
229 	}
230 
231 	/* Copy the data iself into the decoder buffer */
232 	memcpy(deco->jdata+global_cinfo->src->bytes_in_buffer
233 		,data,length);
234 
235 	/* Update the next input byte pointer for the decoder to continue at
236 	 * the right position */
237 	global_cinfo->src->next_input_byte=(void *)deco->jdata;
238 
239 	/* ...:::...:..:.:::.:.::::.::.:.:.:.::..::::.::::.:...: */
240 	/* Update the length of data in the decoder buffer */
241 	global_cinfo->src->bytes_in_buffer+=length;
242 
243 	if (setjmp(global_jerr->setjmp_buffer)) goto decoder_ended;
244 	switch(deco->state){
245 		case 0:
246 		/* jpeg_read_header */
247 		if (JPEG_SUSPENDED==jpeg_read_header(global_cinfo,TRUE))
248 			break;
249 		global_cinfo->buffered_image=TRUE;
250 		deco->state=1;
251 		/*-fallthrough*/
252 
253 		case 1:
254 		/* If the scaling is sufficiently brutal we can leave out
255 		 * some DCT coefficients...: */
256 		/* jpeg_start_decompress */
257 		if (jpeg_start_decompress(global_cinfo)==FALSE)
258 			break;
259 
260 		cimg->width=global_cinfo->output_width;
261 		cimg->height=global_cinfo->output_height;
262 
263 		switch(cimg->buffer_bytes_per_pixel=
264 			global_cinfo->output_components)
265 		{
266 			case 1:
267 				/* We'll do the conversion ourselves
268 				 * because libjpeg seems to be buggy */
269 				cimg->buffer_bytes_per_pixel=3;
270 				break;
271 
272 
273 			case 3: /* RGB or YCrCb. We will ask libjpeg to
274 				 * possibly convert from YCrCb to RGB. */
275 
276 				global_cinfo->out_color_space=JCS_RGB;
277 				break;
278 
279 			case 4:
280 				/* CMYK or YCCK. We need to enable conversion
281 				 * to CMYK and then convert CMYK data to RGBA
282 				 * with dummy A ourselves.
283 				 * We will ask libjpeg to possibly convert from
284 				 * YCCK to CMYK. */
285 				global_cinfo->out_color_space=JCS_CMYK;
286 				break;
287 
288 			default:
289 			/* Let's make a decompression fatal error here */
290 
291 			if (!mesg_unsup_emitted){
292 				error(
293 			"Unsupported JPEG output components number: %d.\n",
294 			cimg->buffer_bytes_per_pixel);
295 				mesg_unsup_emitted=1;
296 			}
297 			longjmp(global_jerr->setjmp_buffer,2);
298 
299 			/* longjmp()  and  siglongjmp() make programs hard to
300 			 * understand and maintain.  If possible an alternative
301 			 * should be used. Hahaha :) ;-)
302 			 */
303 			/* Free will makes people hard to understand
304 			 * and maintain. If possible an alternative should be
305 			 * used.
306 			 */
307 			/* With our new LongJump(TM) your jumps will be longer
308 			 * than with ordinary commercially available jumps.
309 			 */
310 		}
311 		cimg->red_gamma=(float)sRGB_gamma;
312 		cimg->green_gamma=(float)sRGB_gamma;
313 		cimg->blue_gamma=(float)sRGB_gamma;
314 		/* This is defined in the JPEG standard somehow that sRGB
315 		 * color space is used. */
316 
317 		cimg->strip_optimized=0;
318 		/* Strip optimization yet waits to be written. This will
319 		 * allow huge jpegs to be processed without consuming
320 		 * Links memory and consuming Xserver memory instead ;-)
321 		 * However strip optimization is already written for PNG's.
322 		 */
323 
324 		if (header_dimensions_known(cimg)) {
325 			longjmp(global_jerr->setjmp_buffer,2);
326 		}
327 new_scan:
328 		deco->state=2;
329 		/*-fallthrough*/
330 
331 		case 2:
332 		/* jpeg_start_output */
333 		if (FALSE==jpeg_start_output(global_cinfo,global_cinfo->input_scan_number)){
334 susp0:
335 			/* Suspended */
336 			break;
337 		}
338 		deco->state=3;
339 
340 		case 3:
341 		/* jpeg_read_scanlines */
342 			/* color */
343 		while (global_cinfo->output_scanline < global_cinfo->output_height) {
344 			int a, lines;
345 
346 			for (a = 0; a < 16; a++) {
347 				deco->scanlines[a] = cimg->buffer + ((size_t)global_cinfo->output_scanline + a) * global_cinfo->output_width * cimg->buffer_bytes_per_pixel;
348 			}
349 
350 			if ((lines = jpeg_read_scanlines(global_cinfo, deco->scanlines, 1))) {
351 				/* Some lines were written into cimg buffer */
352 				cimg->rows_added = 1;
353 				fix_data(deco, lines);
354 			} else {
355 				/* No lines have been written into cimg
356 				 * buffer */
357 				/* We are suspended and we want more data */
358 				goto susp0; /* Break the outer
359 					     * switch statement */
360 			}
361 		}
362 		deco->state=4;
363 		/*-fallthrough*/
364 
365 		case 4:
366 		/* jpeg_finish_output */
367 		if (FALSE==jpeg_finish_output(global_cinfo))
368 		{
369 			/* Suspended */
370 			break;
371 		}
372 		if (!jpeg_input_complete(global_cinfo))
373 		{
374 			/* Some more scans awaited... */
375 			goto new_scan;
376 		}
377 		deco->state=5;
378 		/*-fallthrough*/
379 
380 		case 5:
381 		/* jpeg_finish_decompress */
382 		if (FALSE==jpeg_finish_decompress(global_cinfo))
383 			break;
384 decoder_ended:
385 		img_end(cimg);
386 	}
387 }
388 
jpeg_destroy_decoder(struct cached_image * cimg)389 void jpeg_destroy_decoder(struct cached_image *cimg)
390 {
391 	struct jpg_decoder *deco = (struct jpg_decoder *)cimg->decoder;
392 	jpeg_destroy_decompress(deco->cinfo);
393 	mem_free(deco->cinfo);
394 	mem_free(deco->jerr);
395 	if (deco->jdata) mem_free(deco->jdata);
396 }
397 
add_jpeg_version(unsigned char ** s,int * l)398 void add_jpeg_version(unsigned char **s, int *l)
399 {
400 #if defined(LIBJPEG_TURBO_VERSION)
401 	add_to_str(s, l, cast_uchar "JPEG-TURBO (");
402 	add_to_str(s, l, cast_uchar stringify(LIBJPEG_TURBO_VERSION));
403 	add_to_str(s, l, cast_uchar ", ABI ");
404 #else
405 	add_to_str(s, l, cast_uchar "JPEG (");
406 #endif
407 #if defined(JPEG_LIB_VERSION_MAJOR) && defined(JPEG_LIB_VERSION_MINOR)
408 	add_num_to_str(s, l, JPEG_LIB_VERSION_MAJOR);
409 	add_chr_to_str(s, l, '.');
410 	add_num_to_str(s, l, JPEG_LIB_VERSION_MINOR);
411 #else
412 	add_num_to_str(s, l, JPEG_LIB_VERSION / 10);
413 	add_chr_to_str(s, l, '.');
414 	add_num_to_str(s, l, JPEG_LIB_VERSION % 10);
415 #endif
416 	add_chr_to_str(s, l, ')');
417 }
418 
419 #endif /* #ifdef HAVE_JPEG */
420 
421 #endif /* #ifdef G */
422 
423