125 #include <config_auto.h>
129 #include "allheaders.h"
148 static l_uint8 jpeg_getc(j_decompress_ptr cinfo);
164 #ifndef NO_CONSOLE_IO
220 if (pnwarn) *pnwarn = 0;
222 return (
PIX *)ERROR_PTR(
"filename not defined", __func__, NULL);
223 if (cmapflag != 0 && cmapflag != 1)
225 if (reduction != 1 && reduction != 2 && reduction != 4 && reduction != 8)
226 return (
PIX *)ERROR_PTR(
"reduction not in {1,2,4,8}", __func__, NULL);
229 return (
PIX *)ERROR_PTR(
"image file not found", __func__, NULL);
232 ret = fgetJpegComment(fp, &comment);
240 return (
PIX *)ERROR_PTR(
"image not returned", __func__, NULL);
269 l_int32 cyan, yellow, magenta, black, nwarn;
270 l_int32 i, j, k, rval, gval, bval;
271 l_int32 nlinesread, abort_on_warning;
272 l_int32 w, h, wpl, spp, ncolors, cindex, ycck, cmyk;
274 l_uint32 *line, *ppixel;
278 struct jpeg_decompress_struct cinfo;
279 struct jpeg_error_mgr jerr;
282 if (pnwarn) *pnwarn = 0;
284 return (
PIX *)ERROR_PTR(
"fp not defined", __func__, NULL);
285 if (cmapflag != 0 && cmapflag != 1)
287 if (reduction != 1 && reduction != 2 && reduction != 4 && reduction != 8)
288 return (
PIX *)ERROR_PTR(
"reduction not in {1,2,4,8}", __func__, NULL);
290 if (BITS_IN_JSAMPLE != 8)
291 return (
PIX *)ERROR_PTR(
"BITS_IN_JSAMPLE != 8", __func__, NULL);
298 cinfo.err = jpeg_std_error(&jerr);
300 cinfo.client_data = (
void *)&jmpbuf;
301 if (setjmp(jmpbuf)) {
302 jpeg_destroy_decompress(&cinfo);
304 LEPT_FREE(rowbuffer);
305 return (
PIX *)ERROR_PTR(
"internal jpeg error", __func__, NULL);
309 jpeg_create_decompress(&cinfo);
310 jpeg_stdio_src(&cinfo, fp);
311 jpeg_read_header(&cinfo, TRUE);
312 cinfo.scale_denom = reduction;
314 jpeg_calc_output_dimensions(&cinfo);
316 cinfo.out_color_space = JCS_GRAYSCALE;
318 L_INFO(
"reading luminance channel only\n", __func__);
320 spp = cinfo.out_color_components;
324 w = cinfo.output_width;
325 h = cinfo.output_height;
326 ycck = (cinfo.jpeg_color_space == JCS_YCCK && spp == 4 && cmapflag == 0);
327 cmyk = (cinfo.jpeg_color_space == JCS_CMYK && spp == 4 && cmapflag == 0);
328 if (spp != 1 && spp != 3 && !ycck && !cmyk) {
329 jpeg_destroy_decompress(&cinfo);
330 return (
PIX *)ERROR_PTR(
"spp must be 1 or 3, or YCCK or CMYK",
333 if ((spp == 3 && cmapflag == 0) || ycck || cmyk) {
334 rowbuffer = (JSAMPROW)LEPT_CALLOC(
sizeof(JSAMPLE), (size_t)spp * w);
337 rowbuffer = (JSAMPROW)LEPT_CALLOC(
sizeof(JSAMPLE), w);
340 pixSetInputFormat(pix, IFF_JFIF_JPEG);
341 if (!rowbuffer || !pix) {
342 LEPT_FREE(rowbuffer);
345 jpeg_destroy_decompress(&cinfo);
346 return (
PIX *)ERROR_PTR(
"rowbuffer or pix not made", __func__, NULL);
357 jpeg_start_decompress(&cinfo);
360 cinfo.quantize_colors = FALSE;
361 jpeg_start_decompress(&cinfo);
363 cinfo.quantize_colors = TRUE;
364 cinfo.desired_number_of_colors = 256;
365 jpeg_start_decompress(&cinfo);
369 ncolors = cinfo.actual_number_of_colors;
370 for (cindex = 0; cindex < ncolors; cindex++) {
371 rval = cinfo.colormap[0][cindex];
372 gval = cinfo.colormap[1][cindex];
373 bval = cinfo.colormap[2][cindex];
379 wpl = pixGetWpl(pix);
392 for (i = 0; i < h; i++) {
393 nlinesread = jpeg_read_scanlines(&cinfo, &rowbuffer, (JDIMENSION)1);
394 nwarn = cinfo.err->num_warnings;
395 if (nlinesread == 0 || (abort_on_warning && nwarn > 0)) {
396 L_ERROR(
"read error at scanline %d; nwarn = %d\n",
399 jpeg_destroy_decompress(&cinfo);
400 LEPT_FREE(rowbuffer);
402 if (pnwarn) *pnwarn = nwarn;
403 return (
PIX *)ERROR_PTR(
"bad data", __func__, NULL);
407 if ((spp == 3 && cmapflag == 0) || ycck || cmyk) {
408 ppixel = data + i * wpl;
410 for (j = k = 0; j < w; j++) {
438 for (j = k = 0; j < w; j++) {
439 cyan = rowbuffer[k++];
440 magenta = rowbuffer[k++];
441 yellow = rowbuffer[k++];
442 black = rowbuffer[k++];
443 if (cinfo.saw_Adobe_marker) {
444 rval = (black * cyan) / 255;
445 gval = (black * magenta) / 255;
446 bval = (black * yellow) / 255;
448 rval = black * (255 - cyan) / 255;
449 gval = black * (255 - magenta) / 255;
450 bval = black * (255 - yellow) / 255;
452 rval = L_MIN(L_MAX(rval, 0), 255);
453 gval = L_MIN(L_MAX(gval, 0), 255);
454 bval = L_MIN(L_MAX(bval, 0), 255);
460 line = data + i * wpl;
461 for (j = 0; j < w; j++)
468 if (cinfo.density_unit == 1) {
469 pixSetXRes(pix, cinfo.X_density);
470 pixSetYRes(pix, cinfo.Y_density);
471 }
else if (cinfo.density_unit == 2) {
472 pixSetXRes(pix, (l_int32)((l_float32)cinfo.X_density * 2.54 + 0.5));
473 pixSetYRes(pix, (l_int32)((l_float32)cinfo.Y_density * 2.54 + 0.5));
476 if (cinfo.output_components != spp)
478 cinfo.output_components, spp);
480 jpeg_finish_decompress(&cinfo);
481 jpeg_destroy_decompress(&cinfo);
482 LEPT_FREE(rowbuffer);
484 if (pnwarn) *pnwarn = nwarn;
486 L_WARNING(
"%d warning(s) of bad data\n", __func__, nwarn);
519 if (pycck) *pycck = 0;
520 if (pcmyk) *pcmyk = 0;
522 return ERROR_INT(
"filename not defined", __func__, 1);
523 if (!pw && !ph && !pspp && !pycck && !pcmyk)
524 return ERROR_INT(
"no results requested", __func__, 1);
527 return ERROR_INT(
"image file not found", __func__, 1);
554 struct jpeg_decompress_struct cinfo;
555 struct jpeg_error_mgr jerr;
561 if (pycck) *pycck = 0;
562 if (pcmyk) *pcmyk = 0;
564 return ERROR_INT(
"stream not defined", __func__, 1);
565 if (!pw && !ph && !pspp && !pycck && !pcmyk)
566 return ERROR_INT(
"no results requested", __func__, 1);
571 cinfo.err = jpeg_std_error(&jerr);
572 cinfo.client_data = (
void *)&jmpbuf;
575 return ERROR_INT(
"internal jpeg error", __func__, 1);
578 jpeg_create_decompress(&cinfo);
579 jpeg_stdio_src(&cinfo, fp);
580 jpeg_read_header(&cinfo, TRUE);
581 jpeg_calc_output_dimensions(&cinfo);
582 spp = cinfo.out_color_components;
583 w = cinfo.output_width;
584 h = cinfo.output_height;
585 if (w < 1 || h < 1 || spp < 1 || spp > 4) {
586 jpeg_destroy_decompress(&cinfo);
588 return ERROR_INT(
"bad jpeg image parameters", __func__, 1);
591 if (pspp) *pspp = spp;
592 if (pw) *pw = cinfo.output_width;
593 if (ph) *ph = cinfo.output_height;
595 (cinfo.jpeg_color_space == JCS_YCCK && spp == 4);
597 (cinfo.jpeg_color_space == JCS_CMYK && spp == 4);
599 jpeg_destroy_decompress(&cinfo);
620 fgetJpegResolution(FILE *fp,
624 struct jpeg_decompress_struct cinfo;
625 struct jpeg_error_mgr jerr;
628 if (pxres) *pxres = 0;
629 if (pyres) *pyres = 0;
630 if (!pxres || !pyres)
631 return ERROR_INT(
"&xres and &yres not both defined", __func__, 1);
633 return ERROR_INT(
"stream not opened", __func__, 1);
638 cinfo.err = jpeg_std_error(&jerr);
639 cinfo.client_data = (
void *)&jmpbuf;
642 return ERROR_INT(
"internal jpeg error", __func__, 1);
645 jpeg_create_decompress(&cinfo);
646 jpeg_stdio_src(&cinfo, fp);
647 jpeg_read_header(&cinfo, TRUE);
651 if (cinfo.density_unit == 1) {
652 *pxres = cinfo.X_density;
653 *pyres = cinfo.Y_density;
654 }
else if (cinfo.density_unit == 2) {
655 *pxres = (l_int32)((l_float32)cinfo.X_density * 2.54 + 0.5);
656 *pyres = (l_int32)((l_float32)cinfo.Y_density * 2.54 + 0.5);
659 jpeg_destroy_decompress(&cinfo);
678 fgetJpegComment(FILE *fp,
681 struct jpeg_decompress_struct cinfo;
682 struct jpeg_error_mgr jerr;
686 return ERROR_INT(
"&comment not defined", __func__, 1);
689 return ERROR_INT(
"stream not opened", __func__, 1);
694 cinfo.err = jpeg_std_error(&jerr);
696 cb_data.comment = NULL;
697 cinfo.client_data = (
void *)&cb_data;
698 if (setjmp(cb_data.jmpbuf)) {
699 LEPT_FREE(cb_data.comment);
700 return ERROR_INT(
"internal jpeg error", __func__, 1);
704 jpeg_create_decompress(&cinfo);
706 jpeg_stdio_src(&cinfo, fp);
707 jpeg_read_header(&cinfo, TRUE);
710 *pcomment = cb_data.comment;
711 jpeg_destroy_decompress(&cinfo);
738 return ERROR_INT(
"pix not defined", __func__, 1);
740 return ERROR_INT(
"filename not defined", __func__, 1);
743 return ERROR_INT(
"stream not opened", __func__, 1);
747 return ERROR_INT(
"pix not written to stream", __func__, 1);
796 l_int32 w, h, d, wpl, spp, colorflag, rowsamples;
797 l_uint32 *ppixel, *line, *data;
800 struct jpeg_compress_struct cinfo;
801 struct jpeg_error_mgr jerr;
806 return ERROR_INT(
"stream not open", __func__, 1);
808 return ERROR_INT(
"pixs not defined", __func__, 1);
809 if (quality <= 0) quality = 75;
811 L_ERROR(
"invalid jpeg quality; setting to 75\n", __func__);
820 if (pixGetColormap(pixs) != NULL) {
821 L_INFO(
"removing colormap; may be better to compress losslessly\n",
824 }
else if (d >= 8 && d != 16) {
826 }
else if (d < 8 || d == 16) {
827 L_INFO(
"converting from %d to 8 bpp\n", __func__, d);
830 L_ERROR(
"unknown pix type with d = %d and no cmap\n", __func__, d);
834 return ERROR_INT(
"pix not made", __func__, 1);
841 cinfo.err = jpeg_std_error(&jerr);
842 cinfo.client_data = (
void *)&jmpbuf;
844 if (setjmp(jmpbuf)) {
845 LEPT_FREE(rowbuffer);
847 return ERROR_INT(
"internal jpeg error", __func__, 1);
851 jpeg_create_compress(&cinfo);
852 jpeg_stdio_dest(&cinfo, fp);
853 cinfo.image_width = w;
854 cinfo.image_height = h;
857 d = pixGetDepth(pix);
860 cinfo.input_components = 1;
861 cinfo.in_color_space = JCS_GRAYSCALE;
864 cinfo.input_components = 3;
865 cinfo.in_color_space = JCS_RGB;
868 jpeg_set_defaults(&cinfo);
872 cinfo.optimize_coding = FALSE;
875 xres = pixGetXRes(pix);
876 yres = pixGetYRes(pix);
877 if ((xres != 0) && (yres != 0)) {
878 cinfo.density_unit = 1;
879 cinfo.X_density = xres;
880 cinfo.Y_density = yres;
884 jpeg_set_quality(&cinfo, quality, TRUE);
886 jpeg_simple_progression(&cinfo);
897 cinfo.comp_info[0].h_samp_factor = 1;
898 cinfo.comp_info[0].v_samp_factor = 1;
899 cinfo.comp_info[1].h_samp_factor = 1;
900 cinfo.comp_info[1].v_samp_factor = 1;
901 cinfo.comp_info[2].h_samp_factor = 1;
902 cinfo.comp_info[2].v_samp_factor = 1;
905 jpeg_start_compress(&cinfo, TRUE);
910 if (strlen(text) > 65433) {
911 L_WARNING(
"text is %zu bytes; clipping to 65433\n",
912 __func__, strlen(text));
915 jpeg_write_marker(&cinfo, JPEG_COM, (
const JOCTET *)text, strlen(text));
919 spp = cinfo.input_components;
920 rowsamples = spp * w;
921 if ((rowbuffer = (JSAMPROW)LEPT_CALLOC(
sizeof(JSAMPLE), rowsamples))
924 return ERROR_INT(
"calloc fail for rowbuffer", __func__, 1);
928 wpl = pixGetWpl(pix);
929 for (i = 0; i < h; i++) {
930 line = data + i * wpl;
931 if (colorflag == 0) {
932 for (j = 0; j < w; j++)
936 jpeg_write_scanlines(&cinfo, (JSAMPROW *)&line, 1);
939 for (j = k = 0; j < w; j++) {
948 jpeg_write_scanlines(&cinfo, &rowbuffer, 1);
950 jpeg_finish_compress(&cinfo);
953 LEPT_FREE(rowbuffer);
955 jpeg_destroy_compress(&cinfo);
998 if (pnwarn) *pnwarn = 0;
1000 return (
PIX *)ERROR_PTR(
"data not defined", __func__, NULL);
1003 return (
PIX *)ERROR_PTR(
"stream not opened", __func__, NULL);
1006 ret = fgetJpegComment(fp, &comment);
1007 if (!ret && comment) {
1013 if (!pix) L_ERROR(
"pix not read\n", __func__);
1044 if (pspp) *pspp = 0;
1045 if (pycck) *pycck = 0;
1046 if (pcmyk) *pcmyk = 0;
1048 return ERROR_INT(
"data not defined", __func__, 1);
1049 if (!pw && !ph && !pspp && !pycck && !pcmyk)
1050 return ERROR_INT(
"no results requested", __func__, 1);
1053 return ERROR_INT(
"stream not opened", __func__, 1);
1078 if (pxres) *pxres = 0;
1079 if (pyres) *pyres = 0;
1081 return ERROR_INT(
"data not defined", __func__, 1);
1082 if (!pxres && !pyres)
1083 return ERROR_INT(
"no results requested", __func__, 1);
1086 return ERROR_INT(
"stream not opened", __func__, 1);
1087 ret = fgetJpegResolution(fp, pxres, pyres);
1114 l_int32 progressive)
1119 if (pdata) *pdata = NULL;
1120 if (psize) *psize = 0;
1122 return ERROR_INT(
"&data not defined", __func__, 1 );
1124 return ERROR_INT(
"&size not defined", __func__, 1 );
1126 return ERROR_INT(
"&pix not defined", __func__, 1 );
1129 if ((fp = open_memstream((
char **)pdata, psize)) == NULL)
1130 return ERROR_INT(
"stream not opened", __func__, 1);
1134 *psize = *psize - 1;
1136 L_INFO(
"work-around: writing to a temp file\n", __func__);
1139 return ERROR_INT(
"tmpfile stream not opened", __func__, 1);
1141 if ((fp = tmpfile()) == NULL)
1142 return ERROR_INT(
"tmpfile stream not opened", __func__, 1);
1176 return ERROR_INT(
"pix not defined", __func__, 1 );
1178 pixSetSpecial(pix, 0);
1200 jmp_buf *pjmpbuf = (jmp_buf *)cinfo->client_data;
1201 (*cinfo->err->output_message) (cinfo);
1202 jpeg_destroy(cinfo);
1203 longjmp(*pjmpbuf, 1);
1220 (*cinfo->err->output_message) (cinfo);
1221 jpeg_destroy(cinfo);
1222 longjmp(pcb_data->jmpbuf, 1);
1227 jpeg_getc(j_decompress_ptr cinfo)
1229 struct jpeg_source_mgr *datasrc;
1231 datasrc = cinfo->src;
1232 if (datasrc->bytes_in_buffer == 0) {
1233 if (! (*datasrc->fill_input_buffer) (cinfo)) {
1237 datasrc->bytes_in_buffer--;
1238 return GETJOCTET(*datasrc->next_input_byte++);
1257 length = jpeg_getc(cinfo) << 8;
1258 length += jpeg_getc(cinfo);
1264 if ((comment = (l_uint8 *)LEPT_CALLOC(length + 1,
sizeof(l_uint8))) == NULL)
1266 for (i = 0; i < length; i++)
1267 comment[i] = jpeg_getc(cinfo);
1271 if (pcb_data->comment) {
1272 LEPT_FREE(pcb_data->comment);
1273 pcb_data->comment = NULL;
1275 pcb_data->comment = comment;
#define GET_DATA_BYTE(pdata, n)
#define SET_DATA_BYTE(pdata, n, val)
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
l_ok pixcmapAddColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapAddColor()
@ L_JPEG_CONTINUE_WITH_BAD_DATA
static void jpeg_error_catch_all_1(j_common_ptr cinfo)
jpeg_error_catch_all_1()
l_ok pixWriteMemJpeg(l_uint8 **pdata, size_t *psize, PIX *pix, l_int32 quality, l_int32 progressive)
pixWriteMemJpeg()
PIX * pixReadJpeg(const char *filename, l_int32 cmapflag, l_int32 reduction, l_int32 *pnwarn, l_int32 hint)
pixReadJpeg()
PIX * pixReadStreamJpeg(FILE *fp, l_int32 cmapflag, l_int32 reduction, l_int32 *pnwarn, l_int32 hint)
pixReadStreamJpeg()
PIX * pixReadMemJpeg(const l_uint8 *data, size_t size, l_int32 cmflag, l_int32 reduction, l_int32 *pnwarn, l_int32 hint)
pixReadMemJpeg()
static void jpeg_error_catch_all_2(j_common_ptr cinfo)
jpeg_error_catch_all_2()
l_ok readHeaderMemJpeg(const l_uint8 *data, size_t size, l_int32 *pw, l_int32 *ph, l_int32 *pspp, l_int32 *pycck, l_int32 *pcmyk)
readHeaderMemJpeg()
l_ok readResolutionMemJpeg(const l_uint8 *data, size_t size, l_int32 *pxres, l_int32 *pyres)
readResolutionMemJpeg()
l_ok freadHeaderJpeg(FILE *fp, l_int32 *pw, l_int32 *ph, l_int32 *pspp, l_int32 *pycck, l_int32 *pcmyk)
freadHeaderJpeg()
l_ok pixWriteStreamJpeg(FILE *fp, PIX *pixs, l_int32 quality, l_int32 progressive)
pixWriteStreamJpeg()
l_ok readHeaderJpeg(const char *filename, l_int32 *pw, l_int32 *ph, l_int32 *pspp, l_int32 *pycck, l_int32 *pcmyk)
readHeaderJpeg()
l_ok pixWriteJpeg(const char *filename, PIX *pix, l_int32 quality, l_int32 progressive)
pixWriteJpeg()
static boolean jpeg_comment_callback(j_decompress_ptr cinfo)
jpeg_comment_callback()
l_ok pixSetChromaSampling(PIX *pix, l_int32 sampling)
pixSetChromaSampling()
l_uint32 * pixGetData(PIX *pix)
pixGetData()
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
void pixDestroy(PIX **ppix)
pixDestroy()
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
char * pixGetText(PIX *pix)
pixGetText()
l_ok pixSetText(PIX *pix, const char *textstring)
pixSetText()
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
PIX * pixClone(PIX *pixs)
pixClone()
l_ok pixSetPadBits(PIX *pix, l_int32 val)
pixSetPadBits()
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
@ REMOVE_CMAP_BASED_ON_SRC
@ L_NO_CHROMA_SAMPLING_JPEG
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
void lept_stderr(const char *fmt,...)
lept_stderr()
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
FILE * fopenReadFromMemory(const l_uint8 *data, size_t size)
fopenReadFromMemory()
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
FILE * fopenWriteWinTempfile(void)
fopenWriteWinTempfile()
FILE * fopenReadStream(const char *filename)
fopenReadStream()