1 /*====================================================================*
2 - Copyright (C) 2001 Leptonica. All rights reserved.
3 - This software is distributed in the hope that it will be
4 - useful, but with NO WARRANTY OF ANY KIND.
5 - No author or distributor accepts responsibility to anyone for the
6 - consequences of using this software, or for whether it serves any
7 - particular purpose or works at all, unless he or she says so in
8 - writing. Everyone is granted permission to copy, modify and
9 - redistribute this source code, for commercial or non-commercial
10 - purposes, with the following restrictions: (1) the origin of this
11 - source code must not be misrepresented; (2) modified versions must
12 - be plainly marked as such; and (3) this notice may not be removed
13 - or altered from any source or modified source distribution.
14 *====================================================================*/
15
16 /*
17 * jpegio.c
18 *
19 * Read jpeg from file
20 * PIX *pixReadJpeg() [ special top level ]
21 * PIX *pixReadStreamJpeg()
22 *
23 * Write jpeg to file
24 * l_int32 pixWriteJpeg() [ special top level ]
25 * l_int32 pixWriteStreamJpeg()
26 *
27 * Setting special flag(s)
28 * void l_jpegSetNoChromaSampling()
29 *
30 * Extraction of jpeg header information
31 * l_int32 extractJpegDataFromFile()
32 * l_int32 extractJpegDataFromArray()
33 * static l_int32 locateJpegImageParameters()
34 * static l_int32 getNextJpegMarker()
35 * static l_int32 getTwoByteParameter()
36 *
37 * Read/write to memory [not on windows]
38 * PIX *pixReadMemJpeg()
39 * l_int32 pixWriteMemJpeg()
40 *
41 * Static system helpers
42 * static void jpeg_error_do_not_exit()
43 * static l_uint8 jpeg_getc()
44 * static l_int32 jpeg_comment_callback()
45 *
46 * Documentation: libjpeg.doc can be found, along with all
47 * source code, at ftp://ftp.uu.net/graphics/jpeg
48 * Download and untar the file: jpegsrc.v6b.tar.gz
49 * A good paper on jpeg can also be found there: wallace.ps.gz
50 *
51 * The functions in libjpeg make it very simple to compress
52 * and decompress images. On input (decompression from file),
53 * 3 component color images can be read into either an 8 bpp Pix
54 * with a colormap or a 32 bpp Pix with RGB components. For output
55 * (compression to file), all color Pix, whether 8 bpp with a
56 * colormap or 32 bpp, are written compressed as a set of three
57 * 8 bpp (rgb) images.
58 *
59 * The default behavior of the jpeg library is to call exit.
60 * This is often undesirable, and the caller should make the
61 * decision when to abort a process. So I inserted setjmp(s)
62 * in the reader and writer, wrote a static error handler that
63 * does not exit, and set up the cinfo structure so that the
64 * low-level jpeg library will call this error handler instead
65 * of the default function error_exit().
66 *
67 * There is a special flag for not subsampling the U,V (chroma)
68 * channels. This gives higher quality for the color, which is
69 * important for some situations. The standard subsampling is
70 * 2x2 on both channels.
71 * var_JPEG_NO_CHROMA_SAMPLING: default is 0 (false)
72 * This is set with l_jpegSetNoChromaSampling().
73 */
74
75 #include <stdio.h>
76 #include <stdlib.h>
77 #include <string.h>
78 #include "allheaders.h"
79
80 #ifdef HAVE_CONFIG_H
81 #include "config_auto.h"
82 #endif /* HAVE_CONFIG_H */
83
84 /* --------------------------------------------*/
85 #if HAVE_LIBJPEG /* defined in environ.h */
86 /* --------------------------------------------*/
87
88 #include <setjmp.h>
89 //#include "jpeglib.h"
90 #include <plugin/jpg/lib/jpeglib.h>
91
92 static void jpeg_error_do_not_exit(j_common_ptr cinfo);
93 static l_uint8 jpeg_getc(j_decompress_ptr cinfo);
94 static jmp_buf jpeg_jmpbuf;
95
96 /* Note: 'boolean' is defined in jmorecfg.h. We use it explicitly
97 * here because for windows where __MINGW32__ is defined,
98 * the prototype for jpeg_comment_callback() is given as
99 * returning a boolean. */
100 static boolean jpeg_comment_callback(j_decompress_ptr cinfo);
101
102 /* Helpers for extraction of jpeg data */
103 static l_int32 locateJpegImageParameters(l_uint8 *, l_int32, l_int32 *);
104 static l_int32 getNextJpegMarker(l_uint8 *, l_int32, l_int32 *);
105 static l_int32 getTwoByteParameter(l_uint8 *, l_int32);
106
107 /* ----------------Set default for write option ----------------- */
108 /* Do not subsample the chroma channels; default is 2x2 subsampling */
109 static l_int32 var_JPEG_NO_CHROMA_SAMPLING = 0;
110
111 #ifndef NO_CONSOLE_IO
112 #define DEBUG_INFO 0
113 #endif /* ~NO_CONSOLE_IO */
114
115
116 /*---------------------------------------------------------------------*
117 * Reading Jpeg *
118 *---------------------------------------------------------------------*/
119 /*!
120 * pixReadJpeg()
121 *
122 * Input: filename
123 * colormap flag (0 means return RGB image if color;
124 * 1 means create colormap and return 8 bpp
125 * palette image if color)
126 * reduction (scaling factor: 1, 2, 4 or 8)
127 * &pnwarn (<optional return> number of warnings about
128 * corrupted data)
129 * Return: pix, or null on error
130 *
131 * Images reduced by factors of 2, 4 or 8 can be returned
132 * significantly faster than full resolution images.
133 *
134 * The jpeg library will return warnings (or exit) if
135 * the jpeg data is bad. Use this function if you want the
136 * jpeg library to create an 8 bpp palette image, or to
137 * tell if the jpeg data has been corrupted. For corrupt jpeg
138 * data, there are two possible outcomes:
139 * (1) a damaged pix will be returned, along with a nonzero
140 * number of warnings, or
141 * (2) for sufficiently serious problems, the library will attempt
142 * to exit (caught by our error handler) and no pix will be returned.
143 */
144 PIX *
pixReadJpeg(const char * filename,l_int32 cmflag,l_int32 reduction,l_int32 * pnwarn)145 pixReadJpeg(const char *filename,
146 l_int32 cmflag,
147 l_int32 reduction,
148 l_int32 *pnwarn)
149 {
150 FILE *fp;
151 PIX *pix;
152
153 PROCNAME("pixReadJpeg");
154
155 if (!filename)
156 return (PIX *)ERROR_PTR("filename not defined", procName, NULL);
157 if (pnwarn)
158 *pnwarn = 0; /* init */
159 if (cmflag != 0 && cmflag != 1)
160 cmflag = 0; /* default */
161 if (reduction != 1 && reduction != 2 && reduction != 4 && reduction != 8)
162 return (PIX *)ERROR_PTR("reduction not in {1,2,4,8}", procName, NULL);
163
164 if ((fp = fopenReadStream(filename)) == NULL)
165 return (PIX *)ERROR_PTR("image file not found", procName, NULL);
166 pix = pixReadStreamJpeg(fp, cmflag, reduction, pnwarn, 0);
167 fclose(fp);
168
169 if (!pix)
170 return (PIX *)ERROR_PTR("image not returned", procName, NULL);
171 return pix;
172 }
173
174
175 /*!
176 * pixReadStreamJpeg()
177 *
178 * Input: stream
179 * colormap flag (0 means return RGB image if color;
180 * 1 means create colormap and return 8 bpp
181 * palette image if color)
182 * reduction (scaling factor: 1, 2, 4 or 8)
183 * &pnwarn (<optional return> number of warnings)
184 * hint: (a bitwise OR of L_HINT_* values); use 0 for no hints
185 * Return: pix, or null on error
186 *
187 * Usage: see pixReadJpeg()
188 */
189 PIX *
pixReadStreamJpeg(FILE * fp,l_int32 cmflag,l_int32 reduction,l_int32 * pnwarn,l_int32 hint)190 pixReadStreamJpeg(FILE *fp,
191 l_int32 cmflag,
192 l_int32 reduction,
193 l_int32 *pnwarn,
194 l_int32 hint)
195 {
196 l_uint8 cyan, yellow, magenta, black, white;
197 l_int32 rval, gval, bval;
198 l_int32 i, j, k;
199 l_int32 w, h, wpl, spp, ncolors, cindex, ycck, cmyk;
200 l_uint32 *data;
201 l_uint32 *line, *ppixel;
202 JSAMPROW rowbuffer;
203 PIX *pix;
204 PIXCMAP *cmap;
205 struct jpeg_decompress_struct cinfo;
206 struct jpeg_error_mgr jerr;
207 l_uint8 *comment = NULL;
208
209 PROCNAME("pixReadStreamJpeg");
210
211 if (!fp)
212 return (PIX *)ERROR_PTR("fp not defined", procName, NULL);
213 if (pnwarn)
214 *pnwarn = 0; /* init */
215 if (cmflag != 0 && cmflag != 1)
216 cmflag = 0; /* default */
217 if (reduction != 1 && reduction != 2 && reduction != 4 && reduction != 8)
218 return (PIX *)ERROR_PTR("reduction not in {1,2,4,8}", procName, NULL);
219
220 if (BITS_IN_JSAMPLE != 8) /* set in jmorecfg.h */
221 return (PIX *)ERROR_PTR("BITS_IN_JSAMPLE != 8", procName, NULL);
222
223 rewind(fp);
224
225 pix = NULL; /* init */
226 if (setjmp(jpeg_jmpbuf)) {
227 pixDestroy(&pix);
228 FREE(rowbuffer);
229 return (PIX *)ERROR_PTR("internal jpeg error", procName, NULL);
230 }
231
232 rowbuffer = NULL;
233 cinfo.err = jpeg_std_error(&jerr);
234 jerr.error_exit = jpeg_error_do_not_exit; /* catch error; do not exit! */
235
236 jpeg_create_decompress(&cinfo);
237
238 cinfo.client_data = &comment;
239 jpeg_set_marker_processor(&cinfo, JPEG_COM, jpeg_comment_callback);
240 jpeg_stdio_src(&cinfo, fp);
241 jpeg_read_header(&cinfo, TRUE);
242 cinfo.scale_denom = reduction;
243 cinfo.scale_num = 1;
244 if (hint & L_HINT_GRAY)
245 cinfo.out_color_space = JCS_GRAYSCALE;
246 jpeg_calc_output_dimensions(&cinfo);
247
248 /* Allocate the image and a row buffer */
249 spp = cinfo.out_color_components;
250 w = cinfo.output_width;
251 h = cinfo.output_height;
252 ycck = (cinfo.jpeg_color_space == JCS_YCCK && spp == 4 && cmflag == 0);
253 cmyk = (cinfo.jpeg_color_space == JCS_CMYK && spp == 4 && cmflag == 0);
254 if (spp != 1 && spp != 3 && !ycck && !cmyk) {
255 if (comment) FREE(comment);
256 return (PIX *)ERROR_PTR("spp must be 1 or 3, or YCCK or CMYK",
257 procName, NULL);
258 }
259 if ((spp == 3 && cmflag == 0) || ycck || cmyk) { /* rgb or 4 bpp color */
260 rowbuffer = (JSAMPROW)CALLOC(sizeof(JSAMPLE), spp * w);
261 pix = pixCreate(w, h, 32);
262 }
263 else { /* 8 bpp gray or colormapped */
264 rowbuffer = (JSAMPROW)CALLOC(sizeof(JSAMPLE), w);
265 pix = pixCreate(w, h, 8);
266 }
267 if (!rowbuffer || !pix) {
268 if (comment) FREE(comment);
269 if (rowbuffer) FREE(rowbuffer);
270 pixDestroy(&pix);
271 return (PIX *)ERROR_PTR("rowbuffer or pix not made", procName, NULL);
272 }
273
274 if (comment) {
275 pixSetText(pix, (char *)comment);
276 FREE(comment);
277 }
278
279 if (spp == 1) /* Grayscale or colormapped */
280 jpeg_start_decompress(&cinfo);
281 else { /* Color; spp == 3 or YCCK or CMYK */
282 if (cmflag == 0) { /* -- 24 bit color in 32 bit pix or YCCK/CMYK -- */
283 cinfo.quantize_colors = FALSE;
284 jpeg_start_decompress(&cinfo);
285 }
286 else { /* Color quantize to 8 bits */
287 cinfo.quantize_colors = TRUE;
288 cinfo.desired_number_of_colors = 256;
289 jpeg_start_decompress(&cinfo);
290
291 /* Construct a pix cmap */
292 cmap = pixcmapCreate(8);
293 ncolors = cinfo.actual_number_of_colors;
294 for (cindex = 0; cindex < ncolors; cindex++)
295 {
296 rval = cinfo.colormap[0][cindex];
297 gval = cinfo.colormap[1][cindex];
298 bval = cinfo.colormap[2][cindex];
299 pixcmapAddColor(cmap, rval, gval, bval);
300 }
301 pixSetColormap(pix, cmap);
302 }
303 }
304 wpl = pixGetWpl(pix);
305 data = pixGetData(pix);
306
307 /* Decompress */
308 if ((spp == 3 && cmflag == 0) || ycck || cmyk) { /* -- 24 bit color -- */
309 for (i = 0; i < h; i++) {
310 if (jpeg_read_scanlines(&cinfo, &rowbuffer, (JDIMENSION)1) != 1)
311 return (PIX *)ERROR_PTR("bad read scanline", procName, NULL);
312 ppixel = data + i * wpl;
313 if (spp == 3) {
314 for (j = k = 0; j < w; j++) {
315 SET_DATA_BYTE(ppixel, COLOR_RED, rowbuffer[k++]);
316 SET_DATA_BYTE(ppixel, COLOR_GREEN, rowbuffer[k++]);
317 SET_DATA_BYTE(ppixel, COLOR_BLUE, rowbuffer[k++]);
318 ppixel++;
319 }
320 } else {
321 /* This is a conversion from CMYK -> RGB that ignores
322 color profiles, and is invoked when the image header
323 claims to be in CMYK or YCCK colorspace. If in YCCK,
324 libjpeg may be doing YCCK -> CMYK under the hood.
325 To understand why the colors are inverted on read-in,
326 see the "Special color spaces" section of
327 "Using the IJG JPEG Library" by Thomas G. Lane. */
328 for (j = k = 0; j < w; j++) {
329 cyan = 255 - rowbuffer[k++];
330 magenta = 255 - rowbuffer[k++];
331 yellow = 255 - rowbuffer[k++];
332 white = rowbuffer[k++];
333 black = 255 - white;
334 rval = 255 - (cyan * white) / 255 - black;
335 gval = 255 - (magenta * white) / 255 - black;
336 bval = 255 - (yellow * white) / 255 - black;
337 rval = L_MIN(L_MAX(rval, 0), 255);
338 gval = L_MIN(L_MAX(gval, 0), 255);
339 bval = L_MIN(L_MAX(bval, 0), 255);
340 composeRGBPixel(rval, gval, bval, ppixel);
341 ppixel++;
342 }
343 }
344 }
345 }
346 else { /* 8 bpp grayscale or colormapped pix */
347 for (i = 0; i < h; i++) {
348 if (jpeg_read_scanlines(&cinfo, &rowbuffer, (JDIMENSION)1) != 1)
349 return (PIX *)ERROR_PTR("bad read scanline", procName, NULL);
350 line = data + i * wpl;
351 for (j = 0; j < w; j++)
352 SET_DATA_BYTE(line, j, rowbuffer[j]);
353 }
354 }
355
356 if (pnwarn)
357 *pnwarn = cinfo.err->num_warnings;
358
359 switch (cinfo.density_unit)
360 {
361 case 1: /* pixels per inch */
362 pixSetXRes(pix, cinfo.X_density);
363 pixSetYRes(pix, cinfo.Y_density);
364 break;
365 case 2: /* pixels per centimeter */
366 pixSetXRes(pix, (l_int32)((l_float32)cinfo.X_density * 2.54 + 0.5));
367 pixSetYRes(pix, (l_int32)((l_float32)cinfo.Y_density * 2.54 + 0.5));
368 break;
369 default: /* the pixel density may not be defined; ignore */
370 break;
371 }
372
373 jpeg_finish_decompress(&cinfo);
374 jpeg_destroy_decompress(&cinfo);
375 FREE(rowbuffer);
376
377 return pix;
378 }
379
380
381 /*---------------------------------------------------------------------*
382 * Writing Jpeg *
383 *---------------------------------------------------------------------*/
384 /*!
385 * pixWriteJpeg()
386 *
387 * Input: filename
388 * pix
389 * quality (1 - 100; 75 is default)
390 * progressive (0 for baseline sequential; 1 for progressive)
391 * Return: 0 if OK; 1 on error
392 */
393 l_int32
pixWriteJpeg(const char * filename,PIX * pix,l_int32 quality,l_int32 progressive)394 pixWriteJpeg(const char *filename,
395 PIX *pix,
396 l_int32 quality,
397 l_int32 progressive)
398 {
399 FILE *fp;
400
401 PROCNAME("pixWriteJpeg");
402
403 if (!pix)
404 return ERROR_INT("pix not defined", procName, 1);
405 if (!filename)
406 return ERROR_INT("filename not defined", procName, 1);
407
408 if ((fp = fopen(filename, "wb+")) == NULL)
409 return ERROR_INT("stream not opened", procName, 1);
410
411 if (pixWriteStreamJpeg(fp, pix, quality, progressive)) {
412 fclose(fp);
413 return ERROR_INT("pix not written to stream", procName, 1);
414 }
415
416 fclose(fp);
417 return 0;
418 }
419
420
421 /*!
422 * pixWriteStreamJpeg()
423 *
424 * Input: stream
425 * pix (8 or 32 bpp)
426 * quality (1 - 100; 75 is default value; 0 is also default)
427 * progressive (0 for baseline sequential; 1 for progressive)
428 * Return: 0 if OK, 1 on error
429 *
430 * Notes:
431 * (1) Under the covers, the library transforms rgb to a
432 * luminence-chromaticity triple, each component of which is
433 * also 8 bits, and compresses that. It uses 2 Huffman tables,
434 * a higher resolution one (with more quantization levels)
435 * for luminosity and a lower resolution one for the chromas.
436 * (2) Progressive encoding gives better compression, at the
437 * expense of slower encoding and decoding.
438 * (3) Standard chroma subsampling is 2x2 on both the U and V
439 * channels. For highest quality, use no subsampling. This
440 * option is set by l_jpegSetNoChromaSampling(1).
441 * (4) There are three possibilities:
442 * * Grayscale image, no colormap: compress as 8 bpp image.
443 * * rgb full color image: copy each line into the color
444 * line buffer, and compress as three 8 bpp images.
445 * * 8 bpp colormapped image: convert each line to three
446 * 8 bpp line images in the color line buffer, and
447 * compress as three 8 bpp images.
448 * (5) The only valid pixel depths in leptonica are 1, 2, 4, 8, 16
449 * and 32 bpp. However, it is possible, and in some cases desirable,
450 * to write out a jpeg file using an rgb pix that has 24 bpp.
451 * This can be created by appending the raster data for a 24 bpp
452 * image (with proper scanline padding) directly to a 24 bpp
453 * pix that was created without a data array. See note in
454 * pixWriteStreamPng() for an example.
455 */
456 l_int32
pixWriteStreamJpeg(FILE * fp,PIX * pix,l_int32 quality,l_int32 progressive)457 pixWriteStreamJpeg(FILE *fp,
458 PIX *pix,
459 l_int32 quality,
460 l_int32 progressive)
461 {
462 l_uint8 byteval;
463 l_int32 xres, yres;
464 l_int32 i, j, k;
465 l_int32 w, h, d, wpl, spp, colorflg, rowsamples;
466 l_int32 *rmap, *gmap, *bmap;
467 l_uint32 *ppixel, *line, *data;
468 JSAMPROW rowbuffer;
469 PIXCMAP *cmap;
470 struct jpeg_compress_struct cinfo;
471 struct jpeg_error_mgr jerr;
472 const char *text;
473
474 PROCNAME("pixWriteStreamJpeg");
475
476 if (!fp)
477 return ERROR_INT("stream not open", procName, 1);
478 if (!pix)
479 return ERROR_INT("pix not defined", procName, 1);
480 rewind(fp);
481
482 if (setjmp(jpeg_jmpbuf)) {
483 FREE(rowbuffer);
484 if (colorflg == 1) {
485 FREE(rmap);
486 FREE(gmap);
487 FREE(bmap);
488 }
489 return ERROR_INT("internal jpeg error", procName, 1);
490 }
491
492 rowbuffer = NULL;
493 rmap = NULL;
494 gmap = NULL;
495 bmap = NULL;
496 pixGetDimensions(pix, &w, &h, &d);
497 if (d != 8 && d != 24 && d != 32)
498 return ERROR_INT("bpp must be 8, 24 or 32", procName, 1);
499
500 if (quality <= 0)
501 quality = 75; /* default */
502
503 if (d == 32 || d == 24)
504 colorflg = 2; /* rgb; no colormap */
505 else if ((cmap = pixGetColormap(pix)) == NULL)
506 colorflg = 0; /* 8 bpp grayscale; no colormap */
507 else {
508 colorflg = 1; /* 8 bpp; colormap */
509 pixcmapToArrays(cmap, &rmap, &gmap, &bmap);
510 }
511
512 cinfo.err = jpeg_std_error(&jerr);
513 jerr.error_exit = jpeg_error_do_not_exit; /* catch error; do not exit! */
514
515 jpeg_create_compress(&cinfo);
516 jpeg_stdio_dest(&cinfo, fp);
517
518 cinfo.image_width = w;
519 cinfo.image_height = h;
520
521 if (colorflg == 0) {
522 cinfo.input_components = 1;
523 cinfo.in_color_space = JCS_GRAYSCALE;
524 }
525 else { /* colorflg == 1 or 2 */
526 cinfo.input_components = 3;
527 cinfo.in_color_space = JCS_RGB;
528 }
529
530 jpeg_set_defaults(&cinfo);
531
532 /* Setting optimize_coding to TRUE seems to improve compression
533 * by approx 2-4 percent, and increases comp time by approx 20%. */
534 cinfo.optimize_coding = FALSE;
535
536 xres = pixGetXRes(pix);
537 yres = pixGetYRes(pix);
538 if ((xres != 0) && (yres != 0)) {
539 cinfo.density_unit = 1; /* designates pixels per inch */
540 cinfo.X_density = xres;
541 cinfo.Y_density = yres;
542 }
543
544 /* Set the quality and progressive parameters */
545 jpeg_set_quality(&cinfo, quality, TRUE);
546 if (progressive) {
547 jpeg_simple_progression(&cinfo);
548 }
549
550 /* Set the chroma subsampling parameters. This is done in
551 * YUV color space. The Y (intensity) channel is never subsampled.
552 * The standard subsampling is 2x2 on both the U and V channels.
553 * Notation on this is confusing. For a nice illustrations, see
554 * http://en.wikipedia.org/wiki/Chroma_subsampling
555 * The standard subsampling is written as 4:2:0.
556 * We allow high quality where there is no subsampling on the
557 * chroma channels: denoted as 4:4:4. */
558 if (var_JPEG_NO_CHROMA_SAMPLING == 1) {
559 cinfo.comp_info[0].h_samp_factor = 1;
560 cinfo.comp_info[0].v_samp_factor = 1;
561 cinfo.comp_info[1].h_samp_factor = 1;
562 cinfo.comp_info[1].v_samp_factor = 1;
563 cinfo.comp_info[2].h_samp_factor = 1;
564 cinfo.comp_info[2].v_samp_factor = 1;
565 }
566
567 jpeg_start_compress(&cinfo, TRUE);
568
569 if ((text = pixGetText(pix))) {
570 jpeg_write_marker(&cinfo, JPEG_COM, (const JOCTET *)text, strlen(text));
571 }
572
573 /* Allocate row buffer */
574 spp = cinfo.input_components;
575 rowsamples = spp * w;
576 if ((rowbuffer = (JSAMPROW)CALLOC(sizeof(JSAMPLE), rowsamples)) == NULL)
577 return ERROR_INT("calloc fail for rowbuffer", procName, 1);
578
579 data = pixGetData(pix);
580 wpl = pixGetWpl(pix);
581 for (i = 0; i < h; i++) {
582 line = data + i * wpl;
583 if (colorflg == 0) { /* 8 bpp gray */
584 for (j = 0; j < w; j++)
585 rowbuffer[j] = GET_DATA_BYTE(line, j);
586 }
587 else if (colorflg == 1) { /* 8 bpp colormapped */
588 for (j = 0; j < w; j++) {
589 byteval = GET_DATA_BYTE(line, j);
590 rowbuffer[3 * j + COLOR_RED] = rmap[byteval];
591 rowbuffer[3 * j + COLOR_GREEN] = gmap[byteval];
592 rowbuffer[3 * j + COLOR_BLUE] = bmap[byteval];
593 }
594 }
595 else { /* colorflg == 2 */
596 if (d == 24) { /* See note 4 above; special case of 24 bpp rgb */
597 jpeg_write_scanlines(&cinfo, (JSAMPROW *)&line, 1);
598 }
599 else { /* standard 32 bpp rgb */
600 ppixel = line;
601 for (j = k = 0; j < w; j++) {
602 rowbuffer[k++] = GET_DATA_BYTE(ppixel, COLOR_RED);
603 rowbuffer[k++] = GET_DATA_BYTE(ppixel, COLOR_GREEN);
604 rowbuffer[k++] = GET_DATA_BYTE(ppixel, COLOR_BLUE);
605 ppixel++;
606 }
607 }
608 }
609 if (d != 24)
610 jpeg_write_scanlines(&cinfo, &rowbuffer, 1);
611 }
612
613 jpeg_finish_compress(&cinfo);
614
615 FREE(rowbuffer);
616 if (colorflg == 1) {
617 FREE(rmap);
618 FREE(gmap);
619 FREE(bmap);
620 }
621
622 jpeg_destroy_compress(&cinfo);
623 return 0;
624 }
625
626
627 /*---------------------------------------------------------------------*
628 * Setting special write flag *
629 *---------------------------------------------------------------------*/
630 /*!
631 * l_jpegSetNoChromaSampling()
632 *
633 * Input: flag (0 for standard 2x2 chroma subsampling)
634 * 1 for no chroma subsampling (high quality))
635 * Return: void
636 */
637 void
l_jpegSetNoChromaSampling(l_int32 flag)638 l_jpegSetNoChromaSampling(l_int32 flag)
639 {
640 var_JPEG_NO_CHROMA_SAMPLING = flag;
641 }
642
643
644 /*---------------------------------------------------------------------*
645 * Extraction of jpeg header information *
646 *---------------------------------------------------------------------*/
647 /*!
648 * extractJpegDataFromFile()
649 *
650 * Input: filein
651 * &data (<return> binary data consisting of the entire jpeg file)
652 * &nbytes (<return> size of binary data)
653 * &w (<optional return> image width)
654 * &h (<optional return> image height)
655 * &bps (<optional return> bits/sample; should be 8)
656 * &spp (<optional return> samples/pixel; should be 1 or 3)
657 * Return: 0 if OK, 1 on error
658 */
659 l_int32
extractJpegDataFromFile(const char * filein,l_uint8 ** pdata,l_int32 * pnbytes,l_int32 * pw,l_int32 * ph,l_int32 * pbps,l_int32 * pspp)660 extractJpegDataFromFile(const char *filein,
661 l_uint8 **pdata,
662 l_int32 *pnbytes,
663 l_int32 *pw,
664 l_int32 *ph,
665 l_int32 *pbps,
666 l_int32 *pspp)
667 {
668 l_uint8 *data;
669 l_int32 format, nbytes;
670 FILE *fpin;
671
672 PROCNAME("extractJpegDataFromFile");
673
674 if (!filein)
675 return ERROR_INT("filein not defined", procName, 1);
676 if (!pdata)
677 return ERROR_INT("&data not defined", procName, 1);
678 if (!pnbytes)
679 return ERROR_INT("&nbytes not defined", procName, 1);
680 if (!pw && !ph && !pbps && !pspp)
681 return ERROR_INT("no output data requested", procName, 1);
682 *pdata = NULL;
683 *pnbytes = 0;
684
685 if ((fpin = fopen(filein, "rb")) == NULL)
686 return ERROR_INT("filein not defined", procName, 1);
687 findFileFormat(fpin, &format);
688 fclose(fpin);
689 if (format != IFF_JFIF_JPEG)
690 return ERROR_INT("filein not jfif jpeg", procName, 1);
691
692 if ((data = arrayRead(filein, &nbytes)) == NULL)
693 return ERROR_INT("inarray not made", procName, 1);
694 *pnbytes = nbytes;
695 *pdata = data;
696
697 /* On error, free the data */
698 if (extractJpegDataFromArray(data, nbytes, pw, ph, pbps, pspp)) {
699 FREE(data);
700 *pdata = NULL;
701 *pnbytes = 0;
702 }
703
704 return 0;
705 }
706
707
708 /*!
709 * extractJpegDataFromArray()
710 *
711 * Input: data (binary data consisting of the entire jpeg file)
712 * nbytes (size of binary data)
713 * &w (<optional return> image width)
714 * &h (<optional return> image height)
715 * &bps (<optional return> bits/sample; should be 8)
716 * &spp (<optional return> samples/pixel; should be 1, 3 or 4)
717 * Return: 0 if OK, 1 on error
718 */
719 l_int32
extractJpegDataFromArray(const void * data,l_int32 nbytes,l_int32 * pw,l_int32 * ph,l_int32 * pbps,l_int32 * pspp)720 extractJpegDataFromArray(const void *data,
721 l_int32 nbytes,
722 l_int32 *pw,
723 l_int32 *ph,
724 l_int32 *pbps,
725 l_int32 *pspp)
726 {
727 l_uint8 *data8;
728 l_int32 imeta, msize, bps, w, h, spp;
729
730 PROCNAME("extractJpegDataFromArray");
731
732 if (!data)
733 return ERROR_INT("data not defined", procName, 1);
734 if (!pw && !ph && !pbps && !pspp)
735 return ERROR_INT("no output data requested", procName, 1);
736 data8 = (l_uint8 *)data;
737
738 /* Find where the image metadata begins in header:
739 * 0xc0 is start of metadata for baseline DCT;
740 * 0xc1 is start of metadata for extended sequential DCT;
741 * ... */
742 imeta = 0;
743 if (locateJpegImageParameters(data8, nbytes, &imeta))
744 return ERROR_INT("metadata not found", procName, 1);
745
746 /* Save the metadata */
747 msize = getTwoByteParameter(data8, imeta); /* metadata size */
748 bps = data8[imeta + 2];
749 h = getTwoByteParameter(data8, imeta + 3);
750 w = getTwoByteParameter(data8, imeta + 5);
751 spp = data8[imeta + 7];
752 if (pbps) *pbps = bps;
753 if (ph) *ph = h;
754 if (pw) *pw = w;
755 if (pspp) *pspp = spp;
756
757 #if DEBUG_INFO
758 fprintf(stderr, "w = %d, h = %d, bps = %d, spp = %d\n", w, h, bps, spp);
759 fprintf(stderr, "imeta = %d, msize = %d\n", imeta, msize);
760 #endif /* DEBUG_INFO */
761
762 /* Is the data obviously bad? */
763 if (h <= 0 || w <= 0 || bps != 8 || (spp != 1 && spp !=3 && spp != 4)) {
764 fprintf(stderr, "h = %d, w = %d, bps = %d, spp = %d\n", h, w, bps, spp);
765 return ERROR_INT("image parameters not valid", procName, 1);
766 }
767
768 return 0;
769 }
770
771
772 /*
773 * locateJpegImageParameters()
774 *
775 * Input: inarray (binary jpeg)
776 * size (of the data array)
777 * &index (<return> location of image metadata)
778 * Return: 0 if OK, 1 on error. Caller must check this!
779 *
780 * Notes:
781 * (1) The parameters listed here appear to be the only jpeg flags
782 * we need to worry about. It would have been nice to have
783 * avoided the switch with all these parameters, but
784 * unfortunately the parser for the jpeg header is set
785 * to accept any old flag that's not on the approved list!
786 * So we have to look for a flag that's not on the list
787 * (and is not 0), and then interpret the size of the
788 * data chunk and skip it. Sometimes such a chunk contains
789 * a thumbnail version of the image, so if we don't skip it,
790 * we will find a pair of bytes such as 0xffc0, followed
791 * by small w and h dimensions.
792 */
793 static l_int32
locateJpegImageParameters(l_uint8 * inarray,l_int32 size,l_int32 * pindex)794 locateJpegImageParameters(l_uint8 *inarray,
795 l_int32 size,
796 l_int32 *pindex)
797 {
798 l_uint8 val;
799 l_int32 index, skiplength;
800
801 PROCNAME("locateJpegImageParameters");
802
803 if (!inarray)
804 return ERROR_INT("inarray not defined", procName, 1);
805 if (!pindex)
806 return ERROR_INT("&index not defined", procName, 1);
807
808 index = *pindex;
809 while (1) {
810 if (getNextJpegMarker(inarray, size, &index))
811 break;
812 if ((val = inarray[index]) == 0) /* ignore if "escaped" */
813 continue;
814 /* fprintf(stderr, " marker %x at %o, %d\n", val, index, index); */
815 switch(val)
816 {
817 case 0xc0: /* M_SOF0 */
818 case 0xc1: /* M_SOF1 */
819 case 0xc2: /* M_SOF2 */
820 case 0xc3: /* M_SOF3 */
821 case 0xc5: /* M_SOF5 */
822 case 0xc6: /* M_SOF6 */
823 case 0xc7: /* M_SOF7 */
824 case 0xc9: /* M_SOF9 */
825 case 0xca: /* M_SOF10 */
826 case 0xcd: /* M_SOF13 */
827 case 0xce: /* M_SOF14 */
828 case 0xcf: /* M_SOF15 */
829 *pindex = index + 1; /* found it */
830 return 0;
831
832 case 0x01: /* M_TEM */
833 case 0xd0: /* M_RST0 */
834 case 0xd1: /* M_RST1 */
835 case 0xd2: /* M_RST2 */
836 case 0xd3: /* M_RST3 */
837 case 0xd4: /* M_RST4 */
838 case 0xd5: /* M_RST5 */
839 case 0xd6: /* M_RST6 */
840 case 0xd7: /* M_RST7 */
841 case 0xd8: /* M_SOI */
842 case 0xd9: /* M_EOI */
843 case 0xe0: /* M_APP0 */
844 case 0xee: /* M_APP14 */
845 break;
846
847 default:
848 skiplength = getTwoByteParameter(inarray, index + 1);
849 index += skiplength;
850 break;
851 }
852 }
853
854 return 1; /* not found */
855 }
856
857
858 /*
859 * getNextJpegMarker()
860 *
861 * Input: array (jpeg data)
862 * size (from current point to the end)
863 * &index (<return> the last position searched. If it
864 * is not at the end of the array, we return
865 * the first byte that is not 0xff, after
866 * having encountered at least one 0xff.)
867 * Return: 0 if a marker is found, 1 if the end of the array is reached
868 *
869 * Notes:
870 * (1) In jpeg, 0xff is used to mark the end of a data segment.
871 * There may be more than one 0xff in succession. But not every
872 * 0xff marks the end of a segment. It is possible, though
873 * rare, that 0xff can occur within some data. In that case,
874 * the marker is "escaped", by following it with 0x00.
875 * (2) This function parses a jpeg data stream. It doesn't
876 * _really_ get the next marker, because it doesn't check if
877 * the 0xff is escaped. But the caller checks for this escape
878 * condition, and ignores the marker if escaped.
879 */
880 static l_int32
getNextJpegMarker(l_uint8 * array,l_int32 size,l_int32 * pindex)881 getNextJpegMarker(l_uint8 *array,
882 l_int32 size,
883 l_int32 *pindex)
884 {
885 l_uint8 val;
886 l_int32 index;
887
888 PROCNAME("getNextJpegMarker");
889
890 if (!array)
891 return ERROR_INT("array not defined", procName, 1);
892 if (!pindex)
893 return ERROR_INT("&index not defined", procName, 1);
894
895 index = *pindex;
896
897 while (index < size) { /* skip to 0xff */
898 val = array[index++];
899 if (val == 0xff)
900 break;
901 }
902
903 while (index < size) { /* skip repeated 0xff */
904 val = array[index++];
905 if (val != 0xff)
906 break;
907 }
908
909 *pindex = index - 1;
910 if (index >= size)
911 return 1;
912 else
913 return 0;
914 }
915
916
917 static l_int32
getTwoByteParameter(l_uint8 * array,l_int32 index)918 getTwoByteParameter(l_uint8 *array,
919 l_int32 index)
920 {
921 return (l_int32)((array[index]) << 8) + (l_int32)(array[index + 1]);
922 }
923
924
925
926 /*---------------------------------------------------------------------*
927 * Read/write to memory *
928 *---------------------------------------------------------------------*/
929 #if HAVE_FMEMOPEN
930
931 extern FILE *open_memstream(char **data, size_t *size);
932 extern FILE *fmemopen(void *data, size_t size, const char *mode);
933
934 /*!
935 * pixReadMemJpeg()
936 *
937 * Input: cdata (const; jpeg-encoded)
938 * size (of data)
939 * colormap flag (0 means return RGB image if color;
940 * 1 means create colormap and return 8 bpp
941 * palette image if color)
942 * reduction (scaling factor: 1, 2, 4 or 8)
943 * &pnwarn (<optional return> number of warnings)
944 * hint (bitwise OR of L_HINT_* values; use 0 for no hint)
945 * Return: pix, or null on error
946 *
947 * Notes:
948 * (1) The @size byte of @data must be a null character.
949 * (2) See pixReadJpeg() for usage.
950 */
951 PIX *
pixReadMemJpeg(const l_uint8 * cdata,size_t size,l_int32 cmflag,l_int32 reduction,l_int32 * pnwarn,l_int32 hint)952 pixReadMemJpeg(const l_uint8 *cdata,
953 size_t size,
954 l_int32 cmflag,
955 l_int32 reduction,
956 l_int32 *pnwarn,
957 l_int32 hint)
958 {
959 l_uint8 *data;
960 FILE *fp;
961 PIX *pix;
962
963 PROCNAME("pixReadMemJpeg");
964
965 if (!cdata)
966 return (PIX *)ERROR_PTR("cdata not defined", procName, NULL);
967
968 data = (l_uint8 *)cdata; /* we're really not going to change this */
969 if ((fp = fmemopen(data, size, "r")) == NULL)
970 return (PIX *)ERROR_PTR("stream not opened", procName, NULL);
971 pix = pixReadStreamJpeg(fp, cmflag, reduction, pnwarn, hint);
972 fclose(fp);
973 return pix;
974 }
975
976
977 /*!
978 * pixWriteMemJpeg()
979 *
980 * Input: &data (<return> data of tiff compressed image)
981 * &size (<return> size of returned data)
982 * pix
983 * quality (1 - 100; 75 is default value; 0 is also default)
984 * progressive (0 for baseline sequential; 1 for progressive)
985 * Return: 0 if OK, 1 on error
986 *
987 * Notes:
988 * (1) See pixWriteStreamJpeg() for usage. This version writes to
989 * memory instead of to a file stream.
990 */
991 l_int32
pixWriteMemJpeg(l_uint8 ** pdata,size_t * psize,PIX * pix,l_int32 quality,l_int32 progressive)992 pixWriteMemJpeg(l_uint8 **pdata,
993 size_t *psize,
994 PIX *pix,
995 l_int32 quality,
996 l_int32 progressive)
997 {
998 l_int32 ret;
999 FILE *fp;
1000
1001 PROCNAME("pixWriteMemJpeg");
1002
1003 if (!pdata)
1004 return ERROR_INT("&data not defined", procName, 1 );
1005 if (!psize)
1006 return ERROR_INT("&size not defined", procName, 1 );
1007 if (!pix)
1008 return ERROR_INT("&pix not defined", procName, 1 );
1009
1010 if ((fp = open_memstream((char **)pdata, psize)) == NULL)
1011 return ERROR_INT("stream not opened", procName, 1);
1012 ret = pixWriteStreamJpeg(fp, pix, quality, progressive);
1013 fclose(fp);
1014 return ret;
1015 }
1016
1017 #else
1018
1019 PIX *
pixReadMemJpeg(const l_uint8 * cdata,size_t size,l_int32 cmflag,l_int32 reduction,l_int32 * pnwarn,l_int32 hint)1020 pixReadMemJpeg(const l_uint8 *cdata,
1021 size_t size,
1022 l_int32 cmflag,
1023 l_int32 reduction,
1024 l_int32 *pnwarn,
1025 l_int32 hint)
1026 {
1027 return (PIX *)ERROR_PTR(
1028 "jpeg read from memory not implemented on this platform",
1029 "pixReadMemJpeg", NULL);
1030 }
1031
1032
1033 l_int32
pixWriteMemJpeg(l_uint8 ** pdata,size_t * psize,PIX * pix,l_int32 quality,l_int32 progressive)1034 pixWriteMemJpeg(l_uint8 **pdata,
1035 size_t *psize,
1036 PIX *pix,
1037 l_int32 quality,
1038 l_int32 progressive)
1039 {
1040 return ERROR_INT(
1041 "jpeg write to memory not implemented on this platform",
1042 "pixWriteMemJpeg", 1);
1043 }
1044
1045 #endif /* HAVE_FMEMOPEN */
1046
1047
1048 /*---------------------------------------------------------------------*
1049 * Static helpers *
1050 *---------------------------------------------------------------------*/
1051 /* The default jpeg error_exit() kills the process.
1052 * We don't want leptonica to allow this to happen.
1053 * If you want this default behavior, remove the
1054 * calls to this in the functions above. */
1055 static void
jpeg_error_do_not_exit(j_common_ptr cinfo)1056 jpeg_error_do_not_exit(j_common_ptr cinfo)
1057 {
1058 (*cinfo->err->output_message) (cinfo);
1059 jpeg_destroy(cinfo);
1060 longjmp(jpeg_jmpbuf, 0);
1061 return;
1062 }
1063
1064 /* This function was borrowed from libjpeg. */
1065 static l_uint8
jpeg_getc(j_decompress_ptr cinfo)1066 jpeg_getc(j_decompress_ptr cinfo)
1067 {
1068 struct jpeg_source_mgr *datasrc;
1069
1070 datasrc = cinfo->src;
1071 if (datasrc->bytes_in_buffer == 0) {
1072 if (! (*datasrc->fill_input_buffer) (cinfo)) {
1073 return 0;
1074 }
1075 }
1076 datasrc->bytes_in_buffer--;
1077 return GETJOCTET(*datasrc->next_input_byte++);
1078 }
1079
1080
1081 /* This function is required for reading jpeg comments, and
1082 * was contributed by Antony Dovgal. Why 'boolean'? See
1083 * note above the declaration. */
1084 static boolean
jpeg_comment_callback(j_decompress_ptr cinfo)1085 jpeg_comment_callback(j_decompress_ptr cinfo)
1086 {
1087 l_int32 length, i;
1088 l_uint32 c;
1089 l_uint8 **comment;
1090
1091 comment = (l_uint8 **)cinfo->client_data;
1092 length = jpeg_getc(cinfo) << 8;
1093 length += jpeg_getc(cinfo);
1094 length -= 2;
1095
1096 if (length <= 0)
1097 return 1;
1098
1099 *comment = (l_uint8 *)MALLOC(length + 1);
1100 if (!(*comment))
1101 return 0;
1102
1103 for (i = 0; i < length; i++) {
1104 c = jpeg_getc(cinfo);
1105 (*comment)[i] = c;
1106 }
1107 (*comment)[length] = 0;
1108
1109 return 1;
1110 }
1111
1112 /* --------------------------------------------*/
1113 #endif /* HAVE_LIBJPEG */
1114 /* --------------------------------------------*/
1115
1116