271l_int32 cyan, yellow, magenta, black, nwarn;
272l_int32 i, j, k, rval, gval, bval;
273l_int32 nlinesread, abort_on_warning;
274l_int32 w, h, wpl, spp, ncolors, cindex, ycck, cmyk;
276l_uint32 *line, *ppixel;
280struct jpeg_decompress_struct cinfo = { 0 };
281struct jpeg_error_mgr jerr = { 0 };
284 if (pnwarn) *pnwarn = 0;
286 return (
PIX *)ERROR_PTR(
"fp not defined", __func__, NULL);
287 if (cmapflag != 0 && cmapflag != 1)
289 if (reduction != 1 && reduction != 2 && reduction != 4 && reduction != 8)
290 return (
PIX *)ERROR_PTR(
"reduction not in {1,2,4,8}", __func__, NULL);
292 if (BITS_IN_JSAMPLE != 8)
293 return (
PIX *)ERROR_PTR(
"BITS_IN_JSAMPLE != 8", __func__, NULL);
300 cinfo.err = jpeg_std_error(&jerr);
302 cinfo.client_data = (
void *)&jmpbuf;
303 if (setjmp(jmpbuf)) {
304 jpeg_destroy_decompress(&cinfo);
306 LEPT_FREE(rowbuffer);
307 return (
PIX *)ERROR_PTR(
"internal jpeg error", __func__, NULL);
311 jpeg_create_decompress(&cinfo);
312 jpeg_stdio_src(&cinfo, fp);
313 jpeg_read_header(&cinfo, TRUE);
314 cinfo.scale_denom = reduction;
316 jpeg_calc_output_dimensions(&cinfo);
318 cinfo.out_color_space = JCS_GRAYSCALE;
320 L_INFO(
"reading luminance channel only\n", __func__);
322 spp = cinfo.out_color_components;
326 w = cinfo.output_width;
327 h = cinfo.output_height;
328 ycck = (cinfo.jpeg_color_space == JCS_YCCK && spp == 4 && cmapflag == 0);
329 cmyk = (cinfo.jpeg_color_space == JCS_CMYK && spp == 4 && cmapflag == 0);
330 if (spp != 1 && spp != 3 && !ycck && !cmyk) {
331 jpeg_destroy_decompress(&cinfo);
332 return (
PIX *)ERROR_PTR(
"spp must be 1 or 3, or YCCK or CMYK",
335 if ((spp == 3 && cmapflag == 0) || ycck || cmyk) {
336 rowbuffer = (JSAMPROW)LEPT_CALLOC(
sizeof(JSAMPLE), (
size_t)spp * w);
337 pix = pixCreate(w, h, 32);
339 rowbuffer = (JSAMPROW)LEPT_CALLOC(
sizeof(JSAMPLE), w);
340 pix = pixCreate(w, h, 8);
342 if (!rowbuffer || !pix) {
343 LEPT_FREE(rowbuffer);
346 jpeg_destroy_decompress(&cinfo);
347 return (
PIX *)ERROR_PTR(
"rowbuffer or pix not made", __func__, NULL);
349 pixSetInputFormat(pix, IFF_JFIF_JPEG);
359 jpeg_start_decompress(&cinfo);
362 cinfo.quantize_colors = FALSE;
363 jpeg_start_decompress(&cinfo);
365 cinfo.quantize_colors = TRUE;
366 cinfo.desired_number_of_colors = 256;
367 jpeg_start_decompress(&cinfo);
370 cmap = pixcmapCreate(8);
371 ncolors = cinfo.actual_number_of_colors;
372 for (cindex = 0; cindex < ncolors; cindex++) {
373 rval = cinfo.colormap[0][cindex];
374 gval = cinfo.colormap[1][cindex];
375 bval = cinfo.colormap[2][cindex];
376 pixcmapAddColor(cmap, rval, gval, bval);
378 pixSetColormap(pix, cmap);
381 wpl = pixGetWpl(pix);
382 data = pixGetData(pix);
394 for (i = 0; i < h; i++) {
395 nlinesread = jpeg_read_scanlines(&cinfo, &rowbuffer, (JDIMENSION)1);
396 nwarn = cinfo.err->num_warnings;
397 if (nlinesread == 0 || (abort_on_warning && nwarn > 0)) {
398 L_ERROR(
"read error at scanline %d; nwarn = %d\n",
401 jpeg_destroy_decompress(&cinfo);
402 LEPT_FREE(rowbuffer);
404 if (pnwarn) *pnwarn = nwarn;
405 return (
PIX *)ERROR_PTR(
"bad data", __func__, NULL);
409 if ((spp == 3 && cmapflag == 0) || ycck || cmyk) {
410 ppixel = data + i * wpl;
412 for (j = k = 0; j < w; j++) {
440 for (j = k = 0; j < w; j++) {
441 cyan = rowbuffer[k++];
442 magenta = rowbuffer[k++];
443 yellow = rowbuffer[k++];
444 black = rowbuffer[k++];
445 if (cinfo.saw_Adobe_marker) {
446 rval = (black * cyan) / 255;
447 gval = (black * magenta) / 255;
448 bval = (black * yellow) / 255;
450 rval = black * (255 - cyan) / 255;
451 gval = black * (255 - magenta) / 255;
452 bval = black * (255 - yellow) / 255;
454 rval = L_MIN(L_MAX(rval, 0), 255);
455 gval = L_MIN(L_MAX(gval, 0), 255);
456 bval = L_MIN(L_MAX(bval, 0), 255);
457 composeRGBPixel(rval, gval, bval, ppixel);
462 line = data + i * wpl;
463 for (j = 0; j < w; j++)
470 if (cinfo.density_unit == 1) {
471 pixSetXRes(pix, cinfo.X_density);
472 pixSetYRes(pix, cinfo.Y_density);
473 }
else if (cinfo.density_unit == 2) {
474 pixSetXRes(pix, (l_int32)((l_float32)cinfo.X_density * 2.54 + 0.5));
475 pixSetYRes(pix, (l_int32)((l_float32)cinfo.Y_density * 2.54 + 0.5));
478 if (cinfo.output_components != spp)
479 lept_stderr(
"output spp = %d, spp = %d\n",
480 cinfo.output_components, spp);
482 jpeg_finish_decompress(&cinfo);
483 jpeg_destroy_decompress(&cinfo);
484 LEPT_FREE(rowbuffer);
486 if (pnwarn) *pnwarn = nwarn;
488 L_WARNING(
"%d warning(s) of bad data\n", __func__, nwarn);
556struct jpeg_decompress_struct cinfo = { 0 };
557struct jpeg_error_mgr jerr = { 0 };
563 if (pycck) *pycck = 0;
564 if (pcmyk) *pcmyk = 0;
566 return ERROR_INT(
"stream not defined", __func__, 1);
567 if (!pw && !ph && !pspp && !pycck && !pcmyk)
568 return ERROR_INT(
"no results requested", __func__, 1);
573 cinfo.err = jpeg_std_error(&jerr);
574 cinfo.client_data = (
void *)&jmpbuf;
577 return ERROR_INT(
"internal jpeg error", __func__, 1);
580 jpeg_create_decompress(&cinfo);
581 jpeg_stdio_src(&cinfo, fp);
582 jpeg_read_header(&cinfo, TRUE);
583 jpeg_calc_output_dimensions(&cinfo);
584 spp = cinfo.out_color_components;
585 w = cinfo.output_width;
586 h = cinfo.output_height;
587 if (w < 1 || h < 1 || spp < 1 || spp > 4) {
588 jpeg_destroy_decompress(&cinfo);
590 return ERROR_INT(
"bad jpeg image parameters", __func__, 1);
593 if (pspp) *pspp = spp;
594 if (pw) *pw = cinfo.output_width;
595 if (ph) *ph = cinfo.output_height;
597 (cinfo.jpeg_color_space == JCS_YCCK && spp == 4);
599 (cinfo.jpeg_color_space == JCS_CMYK && spp == 4);
601 jpeg_destroy_decompress(&cinfo);
798l_int32 w, h, d, wpl, spp, colorflag, rowsamples;
799l_uint32 *ppixel, *line, *data;
802struct jpeg_compress_struct cinfo = { 0 };
803struct jpeg_error_mgr jerr = { 0 };
808 return ERROR_INT(
"stream not open", __func__, 1);
810 return ERROR_INT(
"pixs not defined", __func__, 1);
811 if (quality <= 0) quality = 75;
813 L_ERROR(
"invalid jpeg quality; setting to 75\n", __func__);
820 pixGetDimensions(pixs, &w, &h, &d);
822 if (pixGetColormap(pixs) != NULL) {
823 L_INFO(
"removing colormap; may be better to compress losslessly\n",
826 }
else if (d >= 8 && d != 16) {
827 pix = pixClone(pixs);
828 }
else if (d < 8 || d == 16) {
829 L_INFO(
"converting from %d to 8 bpp\n", __func__, d);
830 pix = pixConvertTo8(pixs, 0);
832 L_ERROR(
"unknown pix type with d = %d and no cmap\n", __func__, d);
836 return ERROR_INT(
"pix not made", __func__, 1);
837 pixSetPadBits(pix, 0);
843 cinfo.err = jpeg_std_error(&jerr);
844 cinfo.client_data = (
void *)&jmpbuf;
846 if (setjmp(jmpbuf)) {
847 LEPT_FREE(rowbuffer);
849 return ERROR_INT(
"internal jpeg error", __func__, 1);
853 jpeg_create_compress(&cinfo);
854 jpeg_stdio_dest(&cinfo, fp);
855 cinfo.image_width = w;
856 cinfo.image_height = h;
859 d = pixGetDepth(pix);
862 cinfo.input_components = 1;
863 cinfo.in_color_space = JCS_GRAYSCALE;
866 cinfo.input_components = 3;
867 cinfo.in_color_space = JCS_RGB;
870 jpeg_set_defaults(&cinfo);
874 cinfo.optimize_coding = FALSE;
877 xres = pixGetXRes(pix);
878 yres = pixGetYRes(pix);
879 if ((xres != 0) && (yres != 0)) {
880 cinfo.density_unit = 1;
881 cinfo.X_density = xres;
882 cinfo.Y_density = yres;
886 jpeg_set_quality(&cinfo, quality, TRUE);
888 jpeg_simple_progression(&cinfo);
899 cinfo.comp_info[0].h_samp_factor = 1;
900 cinfo.comp_info[0].v_samp_factor = 1;
901 cinfo.comp_info[1].h_samp_factor = 1;
902 cinfo.comp_info[1].v_samp_factor = 1;
903 cinfo.comp_info[2].h_samp_factor = 1;
904 cinfo.comp_info[2].v_samp_factor = 1;
907 jpeg_start_compress(&cinfo, TRUE);
911 if ((text = pixGetText(pix)) != NULL) {
912 if (strlen(text) > 65433) {
913 L_WARNING(
"text is %zu bytes; clipping to 65433\n",
914 __func__, strlen(text));
917 jpeg_write_marker(&cinfo, JPEG_COM, (
const JOCTET *)text, strlen(text));
921 spp = cinfo.input_components;
922 rowsamples = spp * w;
923 if ((rowbuffer = (JSAMPROW)LEPT_CALLOC(
sizeof(JSAMPLE), rowsamples))
926 return ERROR_INT(
"calloc fail for rowbuffer", __func__, 1);
929 data = pixGetData(pix);
930 wpl = pixGetWpl(pix);
931 for (i = 0; i < h; i++) {
932 line = data + i * wpl;
933 if (colorflag == 0) {
934 for (j = 0; j < w; j++)
938 jpeg_write_scanlines(&cinfo, (JSAMPROW *)&line, 1);
941 for (j = k = 0; j < w; j++) {
950 jpeg_write_scanlines(&cinfo, &rowbuffer, 1);
952 jpeg_finish_compress(&cinfo);
955 LEPT_FREE(rowbuffer);
957 jpeg_destroy_compress(&cinfo);