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