131 #include "config_auto.h" 135 #include "allheaders.h" 153 static l_uint8 jpeg_getc(j_decompress_ptr cinfo);
169 #ifndef NO_CONSOLE_IO 225 PROCNAME(
"pixReadJpeg");
227 if (pnwarn) *pnwarn = 0;
229 return (
PIX *)ERROR_PTR(
"filename not defined", procName, NULL);
230 if (cmapflag != 0 && cmapflag != 1)
232 if (reduction != 1 && reduction != 2 && reduction != 4 && reduction != 8)
233 return (
PIX *)ERROR_PTR(
"reduction not in {1,2,4,8}", procName, NULL);
236 return (
PIX *)ERROR_PTR(
"image file not found", procName, NULL);
239 ret = fgetJpegComment(fp, &comment);
247 return (
PIX *)ERROR_PTR(
"image not returned", procName, NULL);
276 l_int32 cyan, yellow, magenta, black, nwarn;
277 l_int32 i, j, k, rval, gval, bval;
278 l_int32 w, h, wpl, spp, ncolors, cindex, ycck, cmyk;
280 l_uint32 *line, *ppixel;
284 struct jpeg_decompress_struct cinfo;
285 struct jpeg_error_mgr jerr;
288 PROCNAME(
"pixReadStreamJpeg");
290 if (pnwarn) *pnwarn = 0;
292 return (
PIX *)ERROR_PTR(
"fp not defined", procName, NULL);
293 if (cmapflag != 0 && cmapflag != 1)
295 if (reduction != 1 && reduction != 2 && reduction != 4 && reduction != 8)
296 return (
PIX *)ERROR_PTR(
"reduction not in {1,2,4,8}", procName, NULL);
298 if (BITS_IN_JSAMPLE != 8)
299 return (
PIX *)ERROR_PTR(
"BITS_IN_JSAMPLE != 8", procName, NULL);
306 cinfo.err = jpeg_std_error(&jerr);
308 cinfo.client_data = (
void *)&jmpbuf;
309 if (setjmp(jmpbuf)) {
311 LEPT_FREE(rowbuffer);
312 return (
PIX *)ERROR_PTR(
"internal jpeg error", procName, NULL);
316 jpeg_create_decompress(&cinfo);
317 jpeg_stdio_src(&cinfo, fp);
318 jpeg_read_header(&cinfo, TRUE);
319 cinfo.scale_denom = reduction;
321 jpeg_calc_output_dimensions(&cinfo);
323 cinfo.out_color_space = JCS_GRAYSCALE;
325 L_INFO(
"reading luminance channel only\n", procName);
327 spp = cinfo.out_color_components;
331 w = cinfo.output_width;
332 h = cinfo.output_height;
333 ycck = (cinfo.jpeg_color_space == JCS_YCCK && spp == 4 && cmapflag == 0);
334 cmyk = (cinfo.jpeg_color_space == JCS_CMYK && spp == 4 && cmapflag == 0);
335 if (spp != 1 && spp != 3 && !ycck && !cmyk) {
336 return (
PIX *)ERROR_PTR(
"spp must be 1 or 3, or YCCK or CMYK",
339 if ((spp == 3 && cmapflag == 0) || ycck || cmyk) {
340 rowbuffer = (JSAMPROW)LEPT_CALLOC(
sizeof(JSAMPLE), (size_t)spp * w);
343 rowbuffer = (JSAMPROW)LEPT_CALLOC(
sizeof(JSAMPLE), w);
346 pixSetInputFormat(pix, IFF_JFIF_JPEG);
347 if (!rowbuffer || !pix) {
348 LEPT_FREE(rowbuffer);
350 return (
PIX *)ERROR_PTR(
"rowbuffer or pix not made", procName, NULL);
356 jpeg_start_decompress(&cinfo);
359 cinfo.quantize_colors = FALSE;
360 jpeg_start_decompress(&cinfo);
362 cinfo.quantize_colors = TRUE;
363 cinfo.desired_number_of_colors = 256;
364 jpeg_start_decompress(&cinfo);
368 ncolors = cinfo.actual_number_of_colors;
369 for (cindex = 0; cindex < ncolors; cindex++) {
370 rval = cinfo.colormap[0][cindex];
371 gval = cinfo.colormap[1][cindex];
372 bval = cinfo.colormap[2][cindex];
378 wpl = pixGetWpl(pix);
389 for (i = 0; i < h; i++) {
390 if (jpeg_read_scanlines(&cinfo, &rowbuffer, (JDIMENSION)1) == 0) {
391 L_ERROR(
"read error at scanline %d\n", procName, i);
393 jpeg_destroy_decompress(&cinfo);
394 LEPT_FREE(rowbuffer);
395 return (
PIX *)ERROR_PTR(
"bad data", procName, NULL);
399 if ((spp == 3 && cmapflag == 0) || ycck || cmyk) {
400 ppixel = data + i * wpl;
402 for (j = k = 0; j < w; j++) {
430 for (j = k = 0; j < w; j++) {
431 cyan = rowbuffer[k++];
432 magenta = rowbuffer[k++];
433 yellow = rowbuffer[k++];
434 black = rowbuffer[k++];
435 if (cinfo.saw_Adobe_marker) {
436 rval = (black * cyan) / 255;
437 gval = (black * magenta) / 255;
438 bval = (black * yellow) / 255;
440 rval = black * (255 - cyan) / 255;
441 gval = black * (255 - magenta) / 255;
442 bval = black * (255 - yellow) / 255;
444 rval = L_MIN(L_MAX(rval, 0), 255);
445 gval = L_MIN(L_MAX(gval, 0), 255);
446 bval = L_MIN(L_MAX(bval, 0), 255);
452 line = data + i * wpl;
453 for (j = 0; j < w; j++)
458 nwarn = cinfo.err->num_warnings;
459 if (pnwarn) *pnwarn = nwarn;
463 if (cinfo.density_unit == 1) {
464 pixSetXRes(pix, cinfo.X_density);
465 pixSetYRes(pix, cinfo.Y_density);
466 }
else if (cinfo.density_unit == 2) {
467 pixSetXRes(pix, (l_int32)((l_float32)cinfo.X_density * 2.54 + 0.5));
468 pixSetYRes(pix, (l_int32)((l_float32)cinfo.Y_density * 2.54 + 0.5));
471 if (cinfo.output_components != spp)
472 fprintf(stderr,
"output spp = %d, spp = %d\n",
473 cinfo.output_components, spp);
475 jpeg_finish_decompress(&cinfo);
476 jpeg_destroy_decompress(&cinfo);
477 LEPT_FREE(rowbuffer);
481 L_ERROR(
"fail with %d warning(s) of bad data\n", procName, nwarn);
484 L_WARNING(
"%d warning(s) of bad data\n", procName, nwarn);
517 PROCNAME(
"readHeaderJpeg");
522 if (pycck) *pycck = 0;
523 if (pcmyk) *pcmyk = 0;
525 return ERROR_INT(
"filename not defined", procName, 1);
526 if (!pw && !ph && !pspp && !pycck && !pcmyk)
527 return ERROR_INT(
"no results requested", procName, 1);
530 return ERROR_INT(
"image file not found", procName, 1);
557 struct jpeg_decompress_struct cinfo;
558 struct jpeg_error_mgr jerr;
561 PROCNAME(
"freadHeaderJpeg");
566 if (pycck) *pycck = 0;
567 if (pcmyk) *pcmyk = 0;
569 return ERROR_INT(
"stream not defined", procName, 1);
570 if (!pw && !ph && !pspp && !pycck && !pcmyk)
571 return ERROR_INT(
"no results requested", procName, 1);
576 cinfo.err = jpeg_std_error(&jerr);
577 cinfo.client_data = (
void *)&jmpbuf;
580 return ERROR_INT(
"internal jpeg error", procName, 1);
583 jpeg_create_decompress(&cinfo);
584 jpeg_stdio_src(&cinfo, fp);
585 jpeg_read_header(&cinfo, TRUE);
586 jpeg_calc_output_dimensions(&cinfo);
588 spp = cinfo.out_color_components;
589 if (pspp) *pspp = spp;
590 if (pw) *pw = cinfo.output_width;
591 if (ph) *ph = cinfo.output_height;
593 (cinfo.jpeg_color_space == JCS_YCCK && spp == 4);
595 (cinfo.jpeg_color_space == JCS_CMYK && spp == 4);
597 jpeg_destroy_decompress(&cinfo);
618 fgetJpegResolution(FILE *fp,
622 struct jpeg_decompress_struct cinfo;
623 struct jpeg_error_mgr jerr;
626 PROCNAME(
"fgetJpegResolution");
628 if (pxres) *pxres = 0;
629 if (pyres) *pyres = 0;
630 if (!pxres || !pyres)
631 return ERROR_INT(
"&xres and &yres not both defined", procName, 1);
633 return ERROR_INT(
"stream not opened", procName, 1);
638 cinfo.err = jpeg_std_error(&jerr);
639 cinfo.client_data = (
void *)&jmpbuf;
642 return ERROR_INT(
"internal jpeg error", procName, 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;
685 PROCNAME(
"fgetJpegComment");
688 return ERROR_INT(
"&comment not defined", procName, 1);
691 return ERROR_INT(
"stream not opened", procName, 1);
696 cinfo.err = jpeg_std_error(&jerr);
698 cb_data.comment = NULL;
699 cinfo.client_data = (
void *)&cb_data;
700 if (setjmp(cb_data.jmpbuf)) {
701 LEPT_FREE(cb_data.comment);
702 return ERROR_INT(
"internal jpeg error", procName, 1);
706 jpeg_create_decompress(&cinfo);
708 jpeg_stdio_src(&cinfo, fp);
709 jpeg_read_header(&cinfo, TRUE);
712 *pcomment = cb_data.comment;
713 jpeg_destroy_decompress(&cinfo);
739 PROCNAME(
"pixWriteJpeg");
742 return ERROR_INT(
"pix not defined", procName, 1);
744 return ERROR_INT(
"filename not defined", procName, 1);
747 return ERROR_INT(
"stream not opened", procName, 1);
751 return ERROR_INT(
"pix not written to stream", procName, 1);
800 l_int32 w, h, d, wpl, spp, colorflag, rowsamples;
801 l_uint32 *ppixel, *line, *data;
804 struct jpeg_compress_struct cinfo;
805 struct jpeg_error_mgr jerr;
809 PROCNAME(
"pixWriteStreamJpeg");
812 return ERROR_INT(
"stream not open", procName, 1);
814 return ERROR_INT(
"pixs not defined", procName, 1);
815 if (quality <= 0) quality = 75;
817 L_ERROR(
"invalid jpeg quality; setting to 75\n", procName);
826 if (pixGetColormap(pixs) != NULL) {
827 L_INFO(
"removing colormap; may be better to compress losslessly\n",
830 }
else if (d >= 8 && d != 16) {
832 }
else if (d < 8 || d == 16) {
833 L_INFO(
"converting from %d to 8 bpp\n", procName, d);
836 L_ERROR(
"unknown pix type with d = %d and no cmap\n", procName, d);
840 return ERROR_INT(
"pix not made", procName, 1);
847 cinfo.err = jpeg_std_error(&jerr);
848 cinfo.client_data = (
void *)&jmpbuf;
850 if (setjmp(jmpbuf)) {
851 LEPT_FREE(rowbuffer);
853 return ERROR_INT(
"internal jpeg error", procName, 1);
857 jpeg_create_compress(&cinfo);
858 jpeg_stdio_dest(&cinfo, fp);
859 cinfo.image_width = w;
860 cinfo.image_height = h;
863 d = pixGetDepth(pix);
866 cinfo.input_components = 1;
867 cinfo.in_color_space = JCS_GRAYSCALE;
870 cinfo.input_components = 3;
871 cinfo.in_color_space = JCS_RGB;
874 jpeg_set_defaults(&cinfo);
878 cinfo.optimize_coding = FALSE;
881 xres = pixGetXRes(pix);
882 yres = pixGetYRes(pix);
883 if ((xres != 0) && (yres != 0)) {
884 cinfo.density_unit = 1;
885 cinfo.X_density = xres;
886 cinfo.Y_density = yres;
890 jpeg_set_quality(&cinfo, quality, TRUE);
892 jpeg_simple_progression(&cinfo);
903 cinfo.comp_info[0].h_samp_factor = 1;
904 cinfo.comp_info[0].v_samp_factor = 1;
905 cinfo.comp_info[1].h_samp_factor = 1;
906 cinfo.comp_info[1].v_samp_factor = 1;
907 cinfo.comp_info[2].h_samp_factor = 1;
908 cinfo.comp_info[2].v_samp_factor = 1;
911 jpeg_start_compress(&cinfo, TRUE);
916 if (strlen(text) > 65433) {
917 L_WARNING(
"text is %lu bytes; clipping to 65433\n",
918 procName, (
unsigned long)strlen(text));
921 jpeg_write_marker(&cinfo, JPEG_COM, (
const JOCTET *)text, strlen(text));
925 spp = cinfo.input_components;
926 rowsamples = spp * w;
927 if ((rowbuffer = (JSAMPROW)LEPT_CALLOC(
sizeof(JSAMPLE), rowsamples))
930 return ERROR_INT(
"calloc fail for rowbuffer", procName, 1);
934 wpl = pixGetWpl(pix);
935 for (i = 0; i < h; i++) {
936 line = data + i * wpl;
937 if (colorflag == 0) {
938 for (j = 0; j < w; j++)
942 jpeg_write_scanlines(&cinfo, (JSAMPROW *)&line, 1);
945 for (j = k = 0; j < w; j++) {
954 jpeg_write_scanlines(&cinfo, &rowbuffer, 1);
956 jpeg_finish_compress(&cinfo);
959 LEPT_FREE(rowbuffer);
960 jpeg_destroy_compress(&cinfo);
1003 PROCNAME(
"pixReadMemJpeg");
1005 if (pnwarn) *pnwarn = 0;
1007 return (
PIX *)ERROR_PTR(
"data not defined", procName, NULL);
1010 return (
PIX *)ERROR_PTR(
"stream not opened", procName, NULL);
1013 ret = fgetJpegComment(fp, &comment);
1014 if (!ret && comment) {
1020 if (!pix) L_ERROR(
"pix not read\n", procName);
1049 PROCNAME(
"readHeaderMemJpeg");
1053 if (pspp) *pspp = 0;
1054 if (pycck) *pycck = 0;
1055 if (pcmyk) *pcmyk = 0;
1057 return ERROR_INT(
"data not defined", procName, 1);
1058 if (!pw && !ph && !pspp && !pycck && !pcmyk)
1059 return ERROR_INT(
"no results requested", procName, 1);
1062 return ERROR_INT(
"stream not opened", procName, 1);
1087 PROCNAME(
"readResolutionMemJpeg");
1089 if (pxres) *pxres = 0;
1090 if (pyres) *pyres = 0;
1092 return ERROR_INT(
"data not defined", procName, 1);
1093 if (!pxres && !pyres)
1094 return ERROR_INT(
"no results requested", procName, 1);
1097 return ERROR_INT(
"stream not opened", procName, 1);
1098 ret = fgetJpegResolution(fp, pxres, pyres);
1125 l_int32 progressive)
1130 PROCNAME(
"pixWriteMemJpeg");
1132 if (pdata) *pdata = NULL;
1133 if (psize) *psize = 0;
1135 return ERROR_INT(
"&data not defined", procName, 1 );
1137 return ERROR_INT(
"&size not defined", procName, 1 );
1139 return ERROR_INT(
"&pix not defined", procName, 1 );
1142 if ((fp = open_memstream((
char **)pdata, psize)) == NULL)
1143 return ERROR_INT(
"stream not opened", procName, 1);
1146 L_INFO(
"work-around: writing to a temp file\n", procName);
1149 return ERROR_INT(
"tmpfile stream not opened", procName, 1);
1151 if ((fp = tmpfile()) == NULL)
1152 return ERROR_INT(
"tmpfile stream not opened", procName, 1);
1185 PROCNAME(
"pixSetChromaSampling");
1188 return ERROR_INT(
"pix not defined", procName, 1 );
1190 pixSetSpecial(pix, 0);
1212 jmp_buf *pjmpbuf = (jmp_buf *)cinfo->client_data;
1213 (*cinfo->err->output_message) (cinfo);
1214 jpeg_destroy(cinfo);
1215 longjmp(*pjmpbuf, 1);
1233 (*cinfo->err->output_message) (cinfo);
1234 jpeg_destroy(cinfo);
1235 longjmp(pcb_data->jmpbuf, 1);
1241 jpeg_getc(j_decompress_ptr cinfo)
1243 struct jpeg_source_mgr *datasrc;
1245 datasrc = cinfo->src;
1246 if (datasrc->bytes_in_buffer == 0) {
1247 if (! (*datasrc->fill_input_buffer) (cinfo)) {
1251 datasrc->bytes_in_buffer--;
1252 return GETJOCTET(*datasrc->next_input_byte++);
1271 length = jpeg_getc(cinfo) << 8;
1272 length += jpeg_getc(cinfo);
1278 if ((comment = (l_uint8 *)LEPT_CALLOC(length + 1,
sizeof(l_uint8))) == NULL)
1280 for (i = 0; i < length; i++)
1281 comment[i] = jpeg_getc(cinfo);
1285 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()
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()
FILE * fopenWriteWinTempfile()
fopenWriteWinTempfile()
#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 * 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()