125 #include <config_auto.h> 129 #include "allheaders.h" 147 static l_uint8 jpeg_getc(j_decompress_ptr cinfo);
163 #ifndef NO_CONSOLE_IO 219 PROCNAME(
"pixReadJpeg");
221 if (pnwarn) *pnwarn = 0;
223 return (
PIX *)ERROR_PTR(
"filename not defined", procName, NULL);
224 if (cmapflag != 0 && cmapflag != 1)
226 if (reduction != 1 && reduction != 2 && reduction != 4 && reduction != 8)
227 return (
PIX *)ERROR_PTR(
"reduction not in {1,2,4,8}", procName, NULL);
230 return (
PIX *)ERROR_PTR(
"image file not found", procName, NULL);
233 ret = fgetJpegComment(fp, &comment);
241 return (
PIX *)ERROR_PTR(
"image not returned", procName, NULL);
270 l_int32 cyan, yellow, magenta, black, nwarn;
271 l_int32 i, j, k, rval, gval, bval;
272 l_int32 nlinesread, abort_on_warning;
273 l_int32 w, h, wpl, spp, ncolors, cindex, ycck, cmyk;
275 l_uint32 *line, *ppixel;
279 struct jpeg_decompress_struct cinfo;
280 struct jpeg_error_mgr jerr;
283 PROCNAME(
"pixReadStreamJpeg");
285 if (pnwarn) *pnwarn = 0;
287 return (
PIX *)ERROR_PTR(
"fp not defined", procName, NULL);
288 if (cmapflag != 0 && cmapflag != 1)
290 if (reduction != 1 && reduction != 2 && reduction != 4 && reduction != 8)
291 return (
PIX *)ERROR_PTR(
"reduction not in {1,2,4,8}", procName, NULL);
293 if (BITS_IN_JSAMPLE != 8)
294 return (
PIX *)ERROR_PTR(
"BITS_IN_JSAMPLE != 8", procName, NULL);
301 cinfo.err = jpeg_std_error(&jerr);
303 cinfo.client_data = (
void *)&jmpbuf;
304 if (setjmp(jmpbuf)) {
305 jpeg_destroy_decompress(&cinfo);
307 LEPT_FREE(rowbuffer);
308 return (
PIX *)ERROR_PTR(
"internal jpeg error", procName, NULL);
312 jpeg_create_decompress(&cinfo);
313 jpeg_stdio_src(&cinfo, fp);
314 jpeg_read_header(&cinfo, TRUE);
315 cinfo.scale_denom = reduction;
317 jpeg_calc_output_dimensions(&cinfo);
319 cinfo.out_color_space = JCS_GRAYSCALE;
321 L_INFO(
"reading luminance channel only\n", procName);
323 spp = cinfo.out_color_components;
327 w = cinfo.output_width;
328 h = cinfo.output_height;
329 ycck = (cinfo.jpeg_color_space == JCS_YCCK && spp == 4 && cmapflag == 0);
330 cmyk = (cinfo.jpeg_color_space == JCS_CMYK && spp == 4 && cmapflag == 0);
331 if (spp != 1 && spp != 3 && !ycck && !cmyk) {
332 jpeg_destroy_decompress(&cinfo);
333 return (
PIX *)ERROR_PTR(
"spp must be 1 or 3, or YCCK or CMYK",
336 if ((spp == 3 && cmapflag == 0) || ycck || cmyk) {
337 rowbuffer = (JSAMPROW)LEPT_CALLOC(
sizeof(JSAMPLE), (size_t)spp * w);
340 rowbuffer = (JSAMPROW)LEPT_CALLOC(
sizeof(JSAMPLE), w);
343 pixSetInputFormat(pix, IFF_JFIF_JPEG);
344 if (!rowbuffer || !pix) {
345 LEPT_FREE(rowbuffer);
348 jpeg_destroy_decompress(&cinfo);
349 return (
PIX *)ERROR_PTR(
"rowbuffer or pix not made", procName, NULL);
360 jpeg_start_decompress(&cinfo);
363 cinfo.quantize_colors = FALSE;
364 jpeg_start_decompress(&cinfo);
366 cinfo.quantize_colors = TRUE;
367 cinfo.desired_number_of_colors = 256;
368 jpeg_start_decompress(&cinfo);
372 ncolors = cinfo.actual_number_of_colors;
373 for (cindex = 0; cindex < ncolors; cindex++) {
374 rval = cinfo.colormap[0][cindex];
375 gval = cinfo.colormap[1][cindex];
376 bval = cinfo.colormap[2][cindex];
382 wpl = pixGetWpl(pix);
395 for (i = 0; i < h; i++) {
396 nlinesread = jpeg_read_scanlines(&cinfo, &rowbuffer, (JDIMENSION)1);
397 nwarn = cinfo.err->num_warnings;
398 if (nlinesread == 0 || (abort_on_warning && nwarn > 0)) {
399 L_ERROR(
"read error at scanline %d; nwarn = %d\n",
402 jpeg_destroy_decompress(&cinfo);
403 LEPT_FREE(rowbuffer);
405 if (pnwarn) *pnwarn = nwarn;
406 return (
PIX *)ERROR_PTR(
"bad data", procName, NULL);
410 if ((spp == 3 && cmapflag == 0) || ycck || cmyk) {
411 ppixel = data + i * wpl;
413 for (j = k = 0; j < w; j++) {
441 for (j = k = 0; j < w; j++) {
442 cyan = rowbuffer[k++];
443 magenta = rowbuffer[k++];
444 yellow = rowbuffer[k++];
445 black = rowbuffer[k++];
446 if (cinfo.saw_Adobe_marker) {
447 rval = (black * cyan) / 255;
448 gval = (black * magenta) / 255;
449 bval = (black * yellow) / 255;
451 rval = black * (255 - cyan) / 255;
452 gval = black * (255 - magenta) / 255;
453 bval = black * (255 - yellow) / 255;
455 rval = L_MIN(L_MAX(rval, 0), 255);
456 gval = L_MIN(L_MAX(gval, 0), 255);
457 bval = L_MIN(L_MAX(bval, 0), 255);
463 line = data + i * wpl;
464 for (j = 0; j < w; j++)
471 if (cinfo.density_unit == 1) {
472 pixSetXRes(pix, cinfo.X_density);
473 pixSetYRes(pix, cinfo.Y_density);
474 }
else if (cinfo.density_unit == 2) {
475 pixSetXRes(pix, (l_int32)((l_float32)cinfo.X_density * 2.54 + 0.5));
476 pixSetYRes(pix, (l_int32)((l_float32)cinfo.Y_density * 2.54 + 0.5));
479 if (cinfo.output_components != spp)
481 cinfo.output_components, spp);
483 jpeg_finish_decompress(&cinfo);
484 jpeg_destroy_decompress(&cinfo);
485 LEPT_FREE(rowbuffer);
487 if (pnwarn) *pnwarn = nwarn;
489 L_WARNING(
"%d warning(s) of bad data\n", procName, nwarn);
519 PROCNAME(
"readHeaderJpeg");
524 if (pycck) *pycck = 0;
525 if (pcmyk) *pcmyk = 0;
527 return ERROR_INT(
"filename not defined", procName, 1);
528 if (!pw && !ph && !pspp && !pycck && !pcmyk)
529 return ERROR_INT(
"no results requested", procName, 1);
532 return ERROR_INT(
"image file not found", procName, 1);
559 struct jpeg_decompress_struct cinfo;
560 struct jpeg_error_mgr jerr;
563 PROCNAME(
"freadHeaderJpeg");
568 if (pycck) *pycck = 0;
569 if (pcmyk) *pcmyk = 0;
571 return ERROR_INT(
"stream not defined", procName, 1);
572 if (!pw && !ph && !pspp && !pycck && !pcmyk)
573 return ERROR_INT(
"no results requested", procName, 1);
578 cinfo.err = jpeg_std_error(&jerr);
579 cinfo.client_data = (
void *)&jmpbuf;
582 return ERROR_INT(
"internal jpeg error", procName, 1);
585 jpeg_create_decompress(&cinfo);
586 jpeg_stdio_src(&cinfo, fp);
587 jpeg_read_header(&cinfo, TRUE);
588 jpeg_calc_output_dimensions(&cinfo);
589 spp = cinfo.out_color_components;
590 w = cinfo.output_width;
591 h = cinfo.output_height;
592 if (w < 1 || h < 1 || spp < 1 || spp > 4) {
593 jpeg_destroy_decompress(&cinfo);
595 return ERROR_INT(
"bad jpeg image parameters", procName, 1);
598 if (pspp) *pspp = spp;
599 if (pw) *pw = cinfo.output_width;
600 if (ph) *ph = cinfo.output_height;
602 (cinfo.jpeg_color_space == JCS_YCCK && spp == 4);
604 (cinfo.jpeg_color_space == JCS_CMYK && spp == 4);
606 jpeg_destroy_decompress(&cinfo);
627 fgetJpegResolution(FILE *fp,
631 struct jpeg_decompress_struct cinfo;
632 struct jpeg_error_mgr jerr;
635 PROCNAME(
"fgetJpegResolution");
637 if (pxres) *pxres = 0;
638 if (pyres) *pyres = 0;
639 if (!pxres || !pyres)
640 return ERROR_INT(
"&xres and &yres not both defined", procName, 1);
642 return ERROR_INT(
"stream not opened", procName, 1);
647 cinfo.err = jpeg_std_error(&jerr);
648 cinfo.client_data = (
void *)&jmpbuf;
651 return ERROR_INT(
"internal jpeg error", procName, 1);
654 jpeg_create_decompress(&cinfo);
655 jpeg_stdio_src(&cinfo, fp);
656 jpeg_read_header(&cinfo, TRUE);
660 if (cinfo.density_unit == 1) {
661 *pxres = cinfo.X_density;
662 *pyres = cinfo.Y_density;
663 }
else if (cinfo.density_unit == 2) {
664 *pxres = (l_int32)((l_float32)cinfo.X_density * 2.54 + 0.5);
665 *pyres = (l_int32)((l_float32)cinfo.Y_density * 2.54 + 0.5);
668 jpeg_destroy_decompress(&cinfo);
687 fgetJpegComment(FILE *fp,
690 struct jpeg_decompress_struct cinfo;
691 struct jpeg_error_mgr jerr;
694 PROCNAME(
"fgetJpegComment");
697 return ERROR_INT(
"&comment not defined", procName, 1);
700 return ERROR_INT(
"stream not opened", procName, 1);
705 cinfo.err = jpeg_std_error(&jerr);
707 cb_data.comment = NULL;
708 cinfo.client_data = (
void *)&cb_data;
709 if (setjmp(cb_data.jmpbuf)) {
710 LEPT_FREE(cb_data.comment);
711 return ERROR_INT(
"internal jpeg error", procName, 1);
715 jpeg_create_decompress(&cinfo);
717 jpeg_stdio_src(&cinfo, fp);
718 jpeg_read_header(&cinfo, TRUE);
721 *pcomment = cb_data.comment;
722 jpeg_destroy_decompress(&cinfo);
748 PROCNAME(
"pixWriteJpeg");
751 return ERROR_INT(
"pix not defined", procName, 1);
753 return ERROR_INT(
"filename not defined", procName, 1);
756 return ERROR_INT(
"stream not opened", procName, 1);
760 return ERROR_INT(
"pix not written to stream", procName, 1);
809 l_int32 w, h, d, wpl, spp, colorflag, rowsamples;
810 l_uint32 *ppixel, *line, *data;
813 struct jpeg_compress_struct cinfo;
814 struct jpeg_error_mgr jerr;
818 PROCNAME(
"pixWriteStreamJpeg");
821 return ERROR_INT(
"stream not open", procName, 1);
823 return ERROR_INT(
"pixs not defined", procName, 1);
824 if (quality <= 0) quality = 75;
826 L_ERROR(
"invalid jpeg quality; setting to 75\n", procName);
835 if (pixGetColormap(pixs) != NULL) {
836 L_INFO(
"removing colormap; may be better to compress losslessly\n",
839 }
else if (d >= 8 && d != 16) {
841 }
else if (d < 8 || d == 16) {
842 L_INFO(
"converting from %d to 8 bpp\n", procName, d);
845 L_ERROR(
"unknown pix type with d = %d and no cmap\n", procName, d);
849 return ERROR_INT(
"pix not made", procName, 1);
856 cinfo.err = jpeg_std_error(&jerr);
857 cinfo.client_data = (
void *)&jmpbuf;
859 if (setjmp(jmpbuf)) {
860 LEPT_FREE(rowbuffer);
862 return ERROR_INT(
"internal jpeg error", procName, 1);
866 jpeg_create_compress(&cinfo);
867 jpeg_stdio_dest(&cinfo, fp);
868 cinfo.image_width = w;
869 cinfo.image_height = h;
872 d = pixGetDepth(pix);
875 cinfo.input_components = 1;
876 cinfo.in_color_space = JCS_GRAYSCALE;
879 cinfo.input_components = 3;
880 cinfo.in_color_space = JCS_RGB;
883 jpeg_set_defaults(&cinfo);
887 cinfo.optimize_coding = FALSE;
890 xres = pixGetXRes(pix);
891 yres = pixGetYRes(pix);
892 if ((xres != 0) && (yres != 0)) {
893 cinfo.density_unit = 1;
894 cinfo.X_density = xres;
895 cinfo.Y_density = yres;
899 jpeg_set_quality(&cinfo, quality, TRUE);
901 jpeg_simple_progression(&cinfo);
912 cinfo.comp_info[0].h_samp_factor = 1;
913 cinfo.comp_info[0].v_samp_factor = 1;
914 cinfo.comp_info[1].h_samp_factor = 1;
915 cinfo.comp_info[1].v_samp_factor = 1;
916 cinfo.comp_info[2].h_samp_factor = 1;
917 cinfo.comp_info[2].v_samp_factor = 1;
920 jpeg_start_compress(&cinfo, TRUE);
925 if (strlen(text) > 65433) {
926 L_WARNING(
"text is %zu bytes; clipping to 65433\n",
927 procName, strlen(text));
930 jpeg_write_marker(&cinfo, JPEG_COM, (
const JOCTET *)text, strlen(text));
934 spp = cinfo.input_components;
935 rowsamples = spp * w;
936 if ((rowbuffer = (JSAMPROW)LEPT_CALLOC(
sizeof(JSAMPLE), rowsamples))
939 return ERROR_INT(
"calloc fail for rowbuffer", procName, 1);
943 wpl = pixGetWpl(pix);
944 for (i = 0; i < h; i++) {
945 line = data + i * wpl;
946 if (colorflag == 0) {
947 for (j = 0; j < w; j++)
951 jpeg_write_scanlines(&cinfo, (JSAMPROW *)&line, 1);
954 for (j = k = 0; j < w; j++) {
963 jpeg_write_scanlines(&cinfo, &rowbuffer, 1);
965 jpeg_finish_compress(&cinfo);
968 LEPT_FREE(rowbuffer);
970 jpeg_destroy_compress(&cinfo);
1013 PROCNAME(
"pixReadMemJpeg");
1015 if (pnwarn) *pnwarn = 0;
1017 return (
PIX *)ERROR_PTR(
"data not defined", procName, NULL);
1020 return (
PIX *)ERROR_PTR(
"stream not opened", procName, NULL);
1023 ret = fgetJpegComment(fp, &comment);
1024 if (!ret && comment) {
1030 if (!pix) L_ERROR(
"pix not read\n", procName);
1059 PROCNAME(
"readHeaderMemJpeg");
1063 if (pspp) *pspp = 0;
1064 if (pycck) *pycck = 0;
1065 if (pcmyk) *pcmyk = 0;
1067 return ERROR_INT(
"data not defined", procName, 1);
1068 if (!pw && !ph && !pspp && !pycck && !pcmyk)
1069 return ERROR_INT(
"no results requested", procName, 1);
1072 return ERROR_INT(
"stream not opened", procName, 1);
1097 PROCNAME(
"readResolutionMemJpeg");
1099 if (pxres) *pxres = 0;
1100 if (pyres) *pyres = 0;
1102 return ERROR_INT(
"data not defined", procName, 1);
1103 if (!pxres && !pyres)
1104 return ERROR_INT(
"no results requested", procName, 1);
1107 return ERROR_INT(
"stream not opened", procName, 1);
1108 ret = fgetJpegResolution(fp, pxres, pyres);
1135 l_int32 progressive)
1140 PROCNAME(
"pixWriteMemJpeg");
1142 if (pdata) *pdata = NULL;
1143 if (psize) *psize = 0;
1145 return ERROR_INT(
"&data not defined", procName, 1 );
1147 return ERROR_INT(
"&size not defined", procName, 1 );
1149 return ERROR_INT(
"&pix not defined", procName, 1 );
1152 if ((fp = open_memstream((
char **)pdata, psize)) == NULL)
1153 return ERROR_INT(
"stream not opened", procName, 1);
1157 *psize = *psize - 1;
1159 L_INFO(
"work-around: writing to a temp file\n", procName);
1162 return ERROR_INT(
"tmpfile stream not opened", procName, 1);
1164 if ((fp = tmpfile()) == NULL)
1165 return ERROR_INT(
"tmpfile stream not opened", procName, 1);
1198 PROCNAME(
"pixSetChromaSampling");
1201 return ERROR_INT(
"pix not defined", procName, 1 );
1203 pixSetSpecial(pix, 0);
1225 jmp_buf *pjmpbuf = (jmp_buf *)cinfo->client_data;
1226 (*cinfo->err->output_message) (cinfo);
1227 jpeg_destroy(cinfo);
1228 longjmp(*pjmpbuf, 1);
1245 (*cinfo->err->output_message) (cinfo);
1246 jpeg_destroy(cinfo);
1247 longjmp(pcb_data->jmpbuf, 1);
1252 jpeg_getc(j_decompress_ptr cinfo)
1254 struct jpeg_source_mgr *datasrc;
1256 datasrc = cinfo->src;
1257 if (datasrc->bytes_in_buffer == 0) {
1258 if (! (*datasrc->fill_input_buffer) (cinfo)) {
1262 datasrc->bytes_in_buffer--;
1263 return GETJOCTET(*datasrc->next_input_byte++);
1282 length = jpeg_getc(cinfo) << 8;
1283 length += jpeg_getc(cinfo);
1289 if ((comment = (l_uint8 *)LEPT_CALLOC(length + 1,
sizeof(l_uint8))) == NULL)
1291 for (i = 0; i < length; i++)
1292 comment[i] = jpeg_getc(cinfo);
1296 if (pcb_data->comment) {
1297 LEPT_FREE(pcb_data->comment);
1298 pcb_data->comment = NULL;
1300 pcb_data->comment = comment;
l_ok readResolutionMemJpeg(const l_uint8 *data, size_t size, l_int32 *pxres, l_int32 *pyres)
readResolutionMemJpeg()
static void jpeg_error_catch_all_1(j_common_ptr cinfo)
jpeg_error_catch_all_1()
static void jpeg_error_catch_all_2(j_common_ptr cinfo)
jpeg_error_catch_all_2()
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
l_ok pixWriteMemJpeg(l_uint8 **pdata, size_t *psize, PIX *pix, l_int32 quality, l_int32 progressive)
pixWriteMemJpeg()
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
void lept_stderr(const char *fmt,...)
lept_stderr()
PIX * pixReadJpeg(const char *filename, l_int32 cmapflag, l_int32 reduction, l_int32 *pnwarn, l_int32 hint)
pixReadJpeg()
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
FILE * fopenReadFromMemory(const l_uint8 *data, size_t size)
fopenReadFromMemory()
l_uint32 * pixGetData(PIX *pix)
pixGetData()
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
l_ok pixSetText(PIX *pix, const char *textstring)
pixSetText()
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
PIX * pixReadMemJpeg(const l_uint8 *data, size_t size, l_int32 cmflag, l_int32 reduction, l_int32 *pnwarn, l_int32 hint)
pixReadMemJpeg()
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 pixWriteStreamJpeg(FILE *fp, PIX *pixs, l_int32 quality, l_int32 progressive)
pixWriteStreamJpeg()
PIX * pixReadStreamJpeg(FILE *fp, l_int32 cmapflag, l_int32 reduction, l_int32 *pnwarn, l_int32 hint)
pixReadStreamJpeg()
#define SET_DATA_BYTE(pdata, n, val)
l_ok pixSetPadBits(PIX *pix, l_int32 val)
pixSetPadBits()
#define GET_DATA_BYTE(pdata, n)
l_ok pixWriteJpeg(const char *filename, PIX *pix, l_int32 quality, l_int32 progressive)
pixWriteJpeg()
PIX * pixClone(PIX *pixs)
pixClone()
void pixDestroy(PIX **ppix)
pixDestroy()
l_ok freadHeaderJpeg(FILE *fp, l_int32 *pw, l_int32 *ph, l_int32 *pspp, l_int32 *pycck, l_int32 *pcmyk)
freadHeaderJpeg()
l_ok pixSetChromaSampling(PIX *pix, l_int32 sampling)
pixSetChromaSampling()
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
FILE * fopenWriteWinTempfile(void)
fopenWriteWinTempfile()
FILE * fopenReadStream(const char *filename)
fopenReadStream()
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
char * pixGetText(PIX *pix)
pixGetText()
static boolean jpeg_comment_callback(j_decompress_ptr cinfo)
jpeg_comment_callback()
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
l_ok pixcmapAddColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapAddColor()
l_ok readHeaderJpeg(const char *filename, l_int32 *pw, l_int32 *ph, l_int32 *pspp, l_int32 *pycck, l_int32 *pcmyk)
readHeaderJpeg()