130 #include "config_auto.h" 134 #include "allheaders.h" 152 static l_uint8 jpeg_getc(j_decompress_ptr cinfo);
168 #ifndef NO_CONSOLE_IO 224 PROCNAME(
"pixReadJpeg");
226 if (pnwarn) *pnwarn = 0;
228 return (
PIX *)ERROR_PTR(
"filename not defined", procName, NULL);
229 if (cmapflag != 0 && cmapflag != 1)
231 if (reduction != 1 && reduction != 2 && reduction != 4 && reduction != 8)
232 return (
PIX *)ERROR_PTR(
"reduction not in {1,2,4,8}", procName, NULL);
235 return (
PIX *)ERROR_PTR(
"image file not found", procName, NULL);
238 ret = fgetJpegComment(fp, &comment);
246 return (
PIX *)ERROR_PTR(
"image not returned", procName, NULL);
275 l_int32 cyan, yellow, magenta, black, nwarn;
276 l_int32 i, j, k, rval, gval, bval;
277 l_int32 w, h, wpl, spp, ncolors, cindex, ycck, cmyk;
279 l_uint32 *line, *ppixel;
283 struct jpeg_decompress_struct cinfo;
284 struct jpeg_error_mgr jerr;
287 PROCNAME(
"pixReadStreamJpeg");
289 if (pnwarn) *pnwarn = 0;
291 return (
PIX *)ERROR_PTR(
"fp not defined", procName, NULL);
292 if (cmapflag != 0 && cmapflag != 1)
294 if (reduction != 1 && reduction != 2 && reduction != 4 && reduction != 8)
295 return (
PIX *)ERROR_PTR(
"reduction not in {1,2,4,8}", procName, NULL);
297 if (BITS_IN_JSAMPLE != 8)
298 return (
PIX *)ERROR_PTR(
"BITS_IN_JSAMPLE != 8", procName, NULL);
305 cinfo.err = jpeg_std_error(&jerr);
307 cinfo.client_data = (
void *)&jmpbuf;
308 if (setjmp(jmpbuf)) {
310 LEPT_FREE(rowbuffer);
311 return (
PIX *)ERROR_PTR(
"internal jpeg error", procName, NULL);
315 jpeg_create_decompress(&cinfo);
316 jpeg_stdio_src(&cinfo, fp);
317 jpeg_read_header(&cinfo, TRUE);
318 cinfo.scale_denom = reduction;
320 jpeg_calc_output_dimensions(&cinfo);
322 cinfo.out_color_space = JCS_GRAYSCALE;
324 L_INFO(
"reading luminance channel only\n", procName);
326 spp = cinfo.out_color_components;
330 w = cinfo.output_width;
331 h = cinfo.output_height;
332 ycck = (cinfo.jpeg_color_space == JCS_YCCK && spp == 4 && cmapflag == 0);
333 cmyk = (cinfo.jpeg_color_space == JCS_CMYK && spp == 4 && cmapflag == 0);
334 if (spp != 1 && spp != 3 && !ycck && !cmyk) {
335 return (
PIX *)ERROR_PTR(
"spp must be 1 or 3, or YCCK or CMYK",
338 if ((spp == 3 && cmapflag == 0) || ycck || cmyk) {
339 rowbuffer = (JSAMPROW)LEPT_CALLOC(
sizeof(JSAMPLE), spp * w);
342 rowbuffer = (JSAMPROW)LEPT_CALLOC(
sizeof(JSAMPLE), w);
345 pixSetInputFormat(pix, IFF_JFIF_JPEG);
346 if (!rowbuffer || !pix) {
347 LEPT_FREE(rowbuffer);
349 return (
PIX *)ERROR_PTR(
"rowbuffer or pix not made", procName, NULL);
355 jpeg_start_decompress(&cinfo);
358 cinfo.quantize_colors = FALSE;
359 jpeg_start_decompress(&cinfo);
361 cinfo.quantize_colors = TRUE;
362 cinfo.desired_number_of_colors = 256;
363 jpeg_start_decompress(&cinfo);
367 ncolors = cinfo.actual_number_of_colors;
368 for (cindex = 0; cindex < ncolors; cindex++) {
369 rval = cinfo.colormap[0][cindex];
370 gval = cinfo.colormap[1][cindex];
371 bval = cinfo.colormap[2][cindex];
377 wpl = pixGetWpl(pix);
388 for (i = 0; i < h; i++) {
389 if (jpeg_read_scanlines(&cinfo, &rowbuffer, (JDIMENSION)1) == 0) {
390 L_ERROR(
"read error at scanline %d\n", procName, i);
392 jpeg_destroy_decompress(&cinfo);
393 LEPT_FREE(rowbuffer);
394 return (
PIX *)ERROR_PTR(
"bad data", procName, NULL);
398 if ((spp == 3 && cmapflag == 0) || ycck || cmyk) {
399 ppixel = data + i * wpl;
401 for (j = k = 0; j < w; j++) {
429 for (j = k = 0; j < w; j++) {
430 cyan = rowbuffer[k++];
431 magenta = rowbuffer[k++];
432 yellow = rowbuffer[k++];
433 black = rowbuffer[k++];
434 if (cinfo.saw_Adobe_marker) {
435 rval = (black * cyan) / 255;
436 gval = (black * magenta) / 255;
437 bval = (black * yellow) / 255;
439 rval = black * (255 - cyan) / 255;
440 gval = black * (255 - magenta) / 255;
441 bval = black * (255 - yellow) / 255;
443 rval = L_MIN(L_MAX(rval, 0), 255);
444 gval = L_MIN(L_MAX(gval, 0), 255);
445 bval = L_MIN(L_MAX(bval, 0), 255);
451 line = data + i * wpl;
452 for (j = 0; j < w; j++)
457 nwarn = cinfo.err->num_warnings;
458 if (pnwarn) *pnwarn = nwarn;
462 if (cinfo.density_unit == 1) {
463 pixSetXRes(pix, cinfo.X_density);
464 pixSetYRes(pix, cinfo.Y_density);
465 }
else if (cinfo.density_unit == 2) {
466 pixSetXRes(pix, (l_int32)((l_float32)cinfo.X_density * 2.54 + 0.5));
467 pixSetYRes(pix, (l_int32)((l_float32)cinfo.Y_density * 2.54 + 0.5));
470 if (cinfo.output_components != spp)
471 fprintf(stderr,
"output spp = %d, spp = %d\n",
472 cinfo.output_components, spp);
474 jpeg_finish_decompress(&cinfo);
475 jpeg_destroy_decompress(&cinfo);
476 LEPT_FREE(rowbuffer);
480 L_ERROR(
"fail with %d warning(s) of bad data\n", procName, nwarn);
483 L_WARNING(
"%d warning(s) of bad data\n", procName, nwarn);
516 PROCNAME(
"readHeaderJpeg");
521 if (pycck) *pycck = 0;
522 if (pcmyk) *pcmyk = 0;
524 return ERROR_INT(
"filename not defined", procName, 1);
525 if (!pw && !ph && !pspp && !pycck && !pcmyk)
526 return ERROR_INT(
"no results requested", procName, 1);
529 return ERROR_INT(
"image file not found", procName, 1);
556 struct jpeg_decompress_struct cinfo;
557 struct jpeg_error_mgr jerr;
560 PROCNAME(
"freadHeaderJpeg");
565 if (pycck) *pycck = 0;
566 if (pcmyk) *pcmyk = 0;
568 return ERROR_INT(
"stream not defined", procName, 1);
569 if (!pw && !ph && !pspp && !pycck && !pcmyk)
570 return ERROR_INT(
"no results requested", procName, 1);
575 cinfo.err = jpeg_std_error(&jerr);
576 cinfo.client_data = (
void *)&jmpbuf;
579 return ERROR_INT(
"internal jpeg error", procName, 1);
582 jpeg_create_decompress(&cinfo);
583 jpeg_stdio_src(&cinfo, fp);
584 jpeg_read_header(&cinfo, TRUE);
585 jpeg_calc_output_dimensions(&cinfo);
587 spp = cinfo.out_color_components;
588 if (pspp) *pspp = spp;
589 if (pw) *pw = cinfo.output_width;
590 if (ph) *ph = cinfo.output_height;
592 (cinfo.jpeg_color_space == JCS_YCCK && spp == 4);
594 (cinfo.jpeg_color_space == JCS_CMYK && spp == 4);
596 jpeg_destroy_decompress(&cinfo);
615 fgetJpegResolution(FILE *fp,
619 struct jpeg_decompress_struct cinfo;
620 struct jpeg_error_mgr jerr;
623 PROCNAME(
"fgetJpegResolution");
625 if (pxres) *pxres = 0;
626 if (pyres) *pyres = 0;
627 if (!pxres || !pyres)
628 return ERROR_INT(
"&xres and &yres not both defined", procName, 1);
630 return ERROR_INT(
"stream not opened", procName, 1);
635 cinfo.err = jpeg_std_error(&jerr);
636 cinfo.client_data = (
void *)&jmpbuf;
639 return ERROR_INT(
"internal jpeg error", procName, 1);
642 jpeg_create_decompress(&cinfo);
643 jpeg_stdio_src(&cinfo, fp);
644 jpeg_read_header(&cinfo, TRUE);
648 if (cinfo.density_unit == 1) {
649 *pxres = cinfo.X_density;
650 *pyres = cinfo.Y_density;
651 }
else if (cinfo.density_unit == 2) {
652 *pxres = (l_int32)((l_float32)cinfo.X_density * 2.54 + 0.5);
653 *pyres = (l_int32)((l_float32)cinfo.Y_density * 2.54 + 0.5);
656 jpeg_destroy_decompress(&cinfo);
673 fgetJpegComment(FILE *fp,
676 struct jpeg_decompress_struct cinfo;
677 struct jpeg_error_mgr jerr;
680 PROCNAME(
"fgetJpegComment");
683 return ERROR_INT(
"&comment not defined", procName, 1);
686 return ERROR_INT(
"stream not opened", procName, 1);
691 cinfo.err = jpeg_std_error(&jerr);
693 cb_data.comment = NULL;
694 cinfo.client_data = (
void *)&cb_data;
695 if (setjmp(cb_data.jmpbuf)) {
696 LEPT_FREE(cb_data.comment);
697 return ERROR_INT(
"internal jpeg error", procName, 1);
701 jpeg_create_decompress(&cinfo);
703 jpeg_stdio_src(&cinfo, fp);
704 jpeg_read_header(&cinfo, TRUE);
707 *pcomment = cb_data.comment;
708 jpeg_destroy_decompress(&cinfo);
734 PROCNAME(
"pixWriteJpeg");
737 return ERROR_INT(
"pix not defined", procName, 1);
739 return ERROR_INT(
"filename not defined", procName, 1);
742 return ERROR_INT(
"stream not opened", procName, 1);
746 return ERROR_INT(
"pix not written to stream", procName, 1);
795 l_int32 w, h, d, wpl, spp, colorflag, rowsamples;
796 l_uint32 *ppixel, *line, *data;
799 struct jpeg_compress_struct cinfo;
800 struct jpeg_error_mgr jerr;
804 PROCNAME(
"pixWriteStreamJpeg");
807 return ERROR_INT(
"stream not open", procName, 1);
809 return ERROR_INT(
"pixs not defined", procName, 1);
818 if (pixGetColormap(pixs) != NULL) {
819 L_INFO(
"removing colormap; may be better to compress losslessly\n",
822 }
else if (d >= 8 && d != 16) {
824 }
else if (d < 8 || d == 16) {
825 L_INFO(
"converting from %d to 8 bpp\n", procName, d);
828 L_ERROR(
"unknown pix type with d = %d and no cmap\n", procName, d);
832 return ERROR_INT(
"pix not made", procName, 1);
839 cinfo.err = jpeg_std_error(&jerr);
840 cinfo.client_data = (
void *)&jmpbuf;
842 if (setjmp(jmpbuf)) {
843 LEPT_FREE(rowbuffer);
845 return ERROR_INT(
"internal jpeg error", procName, 1);
849 jpeg_create_compress(&cinfo);
850 jpeg_stdio_dest(&cinfo, fp);
851 cinfo.image_width = w;
852 cinfo.image_height = h;
855 d = pixGetDepth(pix);
858 cinfo.input_components = 1;
859 cinfo.in_color_space = JCS_GRAYSCALE;
862 cinfo.input_components = 3;
863 cinfo.in_color_space = JCS_RGB;
866 jpeg_set_defaults(&cinfo);
870 cinfo.optimize_coding = FALSE;
873 xres = pixGetXRes(pix);
874 yres = pixGetYRes(pix);
875 if ((xres != 0) && (yres != 0)) {
876 cinfo.density_unit = 1;
877 cinfo.X_density = xres;
878 cinfo.Y_density = yres;
882 jpeg_set_quality(&cinfo, quality, TRUE);
884 jpeg_simple_progression(&cinfo);
895 cinfo.comp_info[0].h_samp_factor = 1;
896 cinfo.comp_info[0].v_samp_factor = 1;
897 cinfo.comp_info[1].h_samp_factor = 1;
898 cinfo.comp_info[1].v_samp_factor = 1;
899 cinfo.comp_info[2].h_samp_factor = 1;
900 cinfo.comp_info[2].v_samp_factor = 1;
903 jpeg_start_compress(&cinfo, TRUE);
908 if (strlen(text) > 65433) {
909 L_WARNING(
"text is %lu bytes; clipping to 65433\n",
910 procName, (
unsigned long)strlen(text));
913 jpeg_write_marker(&cinfo, JPEG_COM, (
const JOCTET *)text, strlen(text));
917 spp = cinfo.input_components;
918 rowsamples = spp * w;
919 if ((rowbuffer = (JSAMPROW)LEPT_CALLOC(
sizeof(JSAMPLE), rowsamples))
922 return ERROR_INT(
"calloc fail for rowbuffer", procName, 1);
926 wpl = pixGetWpl(pix);
927 for (i = 0; i < h; i++) {
928 line = data + i * wpl;
929 if (colorflag == 0) {
930 for (j = 0; j < w; j++)
934 jpeg_write_scanlines(&cinfo, (JSAMPROW *)&line, 1);
937 for (j = k = 0; j < w; j++) {
946 jpeg_write_scanlines(&cinfo, &rowbuffer, 1);
948 jpeg_finish_compress(&cinfo);
951 LEPT_FREE(rowbuffer);
952 jpeg_destroy_compress(&cinfo);
995 PROCNAME(
"pixReadMemJpeg");
997 if (pnwarn) *pnwarn = 0;
999 return (
PIX *)ERROR_PTR(
"data not defined", procName, NULL);
1002 return (
PIX *)ERROR_PTR(
"stream not opened", procName, NULL);
1005 ret = fgetJpegComment(fp, &comment);
1006 if (!ret && comment) {
1012 if (!pix) L_ERROR(
"pix not read\n", procName);
1041 PROCNAME(
"readHeaderMemJpeg");
1045 if (pspp) *pspp = 0;
1046 if (pycck) *pycck = 0;
1047 if (pcmyk) *pcmyk = 0;
1049 return ERROR_INT(
"data not defined", procName, 1);
1050 if (!pw && !ph && !pspp && !pycck && !pcmyk)
1051 return ERROR_INT(
"no results requested", procName, 1);
1054 return ERROR_INT(
"stream not opened", procName, 1);
1082 l_int32 progressive)
1087 PROCNAME(
"pixWriteMemJpeg");
1089 if (pdata) *pdata = NULL;
1090 if (psize) *psize = 0;
1092 return ERROR_INT(
"&data not defined", procName, 1 );
1094 return ERROR_INT(
"&size not defined", procName, 1 );
1096 return ERROR_INT(
"&pix not defined", procName, 1 );
1099 if ((fp = open_memstream((
char **)pdata, psize)) == NULL)
1100 return ERROR_INT(
"stream not opened", procName, 1);
1103 L_INFO(
"work-around: writing to a temp file\n", procName);
1106 return ERROR_INT(
"tmpfile stream not opened", procName, 1);
1108 if ((fp = tmpfile()) == NULL)
1109 return ERROR_INT(
"tmpfile stream not opened", procName, 1);
1142 PROCNAME(
"pixSetChromaSampling");
1145 return ERROR_INT(
"pix not defined", procName, 1 );
1147 pixSetSpecial(pix, 0);
1169 jmp_buf *pjmpbuf = (jmp_buf *)cinfo->client_data;
1170 (*cinfo->err->output_message) (cinfo);
1171 jpeg_destroy(cinfo);
1172 longjmp(*pjmpbuf, 1);
1190 (*cinfo->err->output_message) (cinfo);
1191 jpeg_destroy(cinfo);
1192 longjmp(pcb_data->jmpbuf, 1);
1198 jpeg_getc(j_decompress_ptr cinfo)
1200 struct jpeg_source_mgr *datasrc;
1202 datasrc = cinfo->src;
1203 if (datasrc->bytes_in_buffer == 0) {
1204 if (! (*datasrc->fill_input_buffer) (cinfo)) {
1208 datasrc->bytes_in_buffer--;
1209 return GETJOCTET(*datasrc->next_input_byte++);
1228 length = jpeg_getc(cinfo) << 8;
1229 length += jpeg_getc(cinfo);
1235 if ((comment = (l_uint8 *)LEPT_CALLOC(length + 1,
sizeof(l_uint8))) == NULL)
1237 for (i = 0; i < length; i++)
1238 comment[i] = jpeg_getc(cinfo);
1242 pcb_data->comment = comment;
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_int32 pixWriteMemJpeg(l_uint8 **pdata, size_t *psize, PIX *pix, l_int32 quality, l_int32 progressive)
pixWriteMemJpeg()
l_int32 pixSetChromaSampling(PIX *pix, l_int32 sampling)
pixSetChromaSampling()
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()
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_int32 pixcmapAddColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapAddColor()
l_int32 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()
l_int32 pixSetPadBits(PIX *pix, l_int32 val)
pixSetPadBits()
l_int32 pixWriteJpeg(const char *filename, PIX *pix, l_int32 quality, l_int32 progressive)
pixWriteJpeg()
l_int32 readHeaderJpeg(const char *filename, l_int32 *pw, l_int32 *ph, l_int32 *pspp, l_int32 *pycck, l_int32 *pcmyk)
readHeaderJpeg()
#define SET_DATA_BYTE(pdata, n, val)
l_int32 pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
FILE * fopenWriteWinTempfile()
fopenWriteWinTempfile()
#define GET_DATA_BYTE(pdata, n)
PIX * pixClone(PIX *pixs)
pixClone()
void pixDestroy(PIX **ppix)
pixDestroy()
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()
l_int32 freadHeaderJpeg(FILE *fp, l_int32 *pw, l_int32 *ph, l_int32 *pspp, l_int32 *pycck, l_int32 *pcmyk)
freadHeaderJpeg()
char * pixGetText(PIX *pix)
pixGetText()
static boolean jpeg_comment_callback(j_decompress_ptr cinfo)
jpeg_comment_callback()
l_int32 composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
l_int32 pixGetDimensions(PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
l_int32 pixSetText(PIX *pix, const char *textstring)
pixSetText()
l_int32 readHeaderMemJpeg(const l_uint8 *data, size_t size, l_int32 *pw, l_int32 *ph, l_int32 *pspp, l_int32 *pycck, l_int32 *pcmyk)
readHeaderMemJpeg()