diff options
Diffstat (limited to 'djpeg.c')
-rw-r--r-- | djpeg.c | 126 |
1 files changed, 86 insertions, 40 deletions
@@ -3,9 +3,9 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. - * Modified 2013 by Guido Vollbeding. + * Modified 2013-2019 by Guido Vollbeding. * libjpeg-turbo Modifications: - * Copyright (C) 2010-2011, 2013-2017, D. R. Commander. + * Copyright (C) 2010-2011, 2013-2017, 2019-2020, D. R. Commander. * Copyright (C) 2015, Google, Inc. * For conditions of distribution and use, see the accompanying README.ijg * file. @@ -68,10 +68,10 @@ static const char * const cdjpeg_message_table[] = { typedef enum { FMT_BMP, /* BMP format (Windows flavor) */ - FMT_GIF, /* GIF format */ + FMT_GIF, /* GIF format (LZW-compressed) */ + FMT_GIF0, /* GIF format (uncompressed) */ FMT_OS2, /* BMP format (OS/2 flavor) */ FMT_PPM, /* PPM/PGM (PBMPLUS formats) */ - FMT_RLE, /* RLE format */ FMT_TARGA, /* Targa format */ FMT_TIFF /* TIFF format */ } IMAGE_FORMATS; @@ -94,11 +94,14 @@ static IMAGE_FORMATS requested_fmt; static const char *progname; /* program name for error messages */ static char *icc_filename; /* for -icc switch */ +static JDIMENSION max_scans; /* for -maxscans switch */ static char *outfilename; /* for -outfile switch */ -boolean memsrc; /* for -memsrc switch */ +static boolean memsrc; /* for -memsrc switch */ +static boolean report; /* for -report switch */ boolean skip, crop; JDIMENSION skip_start, skip_end; JDIMENSION crop_x, crop_y, crop_width, crop_height; +static boolean strict; /* for -strict switch */ #define INPUT_BUF_SIZE 4096 @@ -127,8 +130,10 @@ usage(void) (DEFAULT_FMT == FMT_BMP ? " (default)" : "")); #endif #ifdef GIF_SUPPORTED - fprintf(stderr, " -gif Select GIF output format%s\n", + fprintf(stderr, " -gif Select GIF output format (LZW-compressed)%s\n", (DEFAULT_FMT == FMT_GIF ? " (default)" : "")); + fprintf(stderr, " -gif0 Select GIF output format (uncompressed)%s\n", + (DEFAULT_FMT == FMT_GIF0 ? " (default)" : "")); #endif #ifdef BMP_SUPPORTED fprintf(stderr, " -os2 Select BMP output format (OS/2 style)%s\n", @@ -138,25 +143,21 @@ usage(void) fprintf(stderr, " -pnm Select PBMPLUS (PPM/PGM) output format%s\n", (DEFAULT_FMT == FMT_PPM ? " (default)" : "")); #endif -#ifdef RLE_SUPPORTED - fprintf(stderr, " -rle Select Utah RLE output format%s\n", - (DEFAULT_FMT == FMT_RLE ? " (default)" : "")); -#endif #ifdef TARGA_SUPPORTED fprintf(stderr, " -targa Select Targa output format%s\n", (DEFAULT_FMT == FMT_TARGA ? " (default)" : "")); #endif fprintf(stderr, "Switches for advanced users:\n"); #ifdef DCT_ISLOW_SUPPORTED - fprintf(stderr, " -dct int Use integer DCT method%s\n", + fprintf(stderr, " -dct int Use accurate integer DCT method%s\n", (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : "")); #endif #ifdef DCT_IFAST_SUPPORTED - fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n", + fprintf(stderr, " -dct fast Use less accurate integer DCT method [legacy feature]%s\n", (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : "")); #endif #ifdef DCT_FLOAT_SUPPORTED - fprintf(stderr, " -dct float Use floating-point DCT method%s\n", + fprintf(stderr, " -dct float Use floating-point DCT method [legacy feature]%s\n", (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : "")); #endif fprintf(stderr, " -dither fs Use F-S dithering (default)\n"); @@ -171,14 +172,16 @@ usage(void) fprintf(stderr, " -onepass Use 1-pass quantization (fast, low quality)\n"); #endif fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n"); + fprintf(stderr, " -maxscans N Maximum number of scans to allow in input file\n"); fprintf(stderr, " -outfile name Specify name for output file\n"); #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) fprintf(stderr, " -memsrc Load input file into memory before decompressing\n"); #endif - + fprintf(stderr, " -report Report decompression progress\n"); fprintf(stderr, " -skip Y0,Y1 Decompress all rows except those between Y0 and Y1 (inclusive)\n"); fprintf(stderr, " -crop WxH+X+Y Decompress only a rectangular subregion of the image\n"); fprintf(stderr, " [requires PBMPLUS (PPM/PGM), GIF, or Targa output format]\n"); + fprintf(stderr, " -strict Treat all warnings as fatal\n"); fprintf(stderr, " -verbose or -debug Emit debug output\n"); fprintf(stderr, " -version Print version information and exit\n"); exit(EXIT_FAILURE); @@ -203,10 +206,13 @@ parse_switches(j_decompress_ptr cinfo, int argc, char **argv, /* Set up default JPEG parameters. */ requested_fmt = DEFAULT_FMT; /* set default output file format */ icc_filename = NULL; + max_scans = 0; outfilename = NULL; memsrc = FALSE; + report = FALSE; skip = FALSE; crop = FALSE; + strict = FALSE; cinfo->err->trace_level = 0; /* Scan command line options, adjust parameters */ @@ -224,7 +230,7 @@ parse_switches(j_decompress_ptr cinfo, int argc, char **argv, arg++; /* advance past switch marker character */ if (keymatch(arg, "bmp", 1)) { - /* BMP output format. */ + /* BMP output format (Windows flavor). */ requested_fmt = FMT_BMP; } else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) || @@ -295,9 +301,13 @@ parse_switches(j_decompress_ptr cinfo, int argc, char **argv, cinfo->do_fancy_upsampling = FALSE; } else if (keymatch(arg, "gif", 1)) { - /* GIF output format. */ + /* GIF output format (LZW-compressed). */ requested_fmt = FMT_GIF; + } else if (keymatch(arg, "gif0", 4)) { + /* GIF output format (uncompressed). */ + requested_fmt = FMT_GIF0; + } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale", 2)) { /* Force monochrome output. */ @@ -351,6 +361,12 @@ parse_switches(j_decompress_ptr cinfo, int argc, char **argv, lval *= 1000L; cinfo->mem->max_memory_to_use = lval * 1000L; + } else if (keymatch(arg, "maxscans", 4)) { + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%u", &max_scans) != 1) + usage(); + } else if (keymatch(arg, "nosmooth", 3)) { /* Suppress fancy upsampling */ cinfo->do_fancy_upsampling = FALSE; @@ -383,9 +399,8 @@ parse_switches(j_decompress_ptr cinfo, int argc, char **argv, /* PPM/PGM output format. */ requested_fmt = FMT_PPM; - } else if (keymatch(arg, "rle", 1)) { - /* RLE output format. */ - requested_fmt = FMT_RLE; + } else if (keymatch(arg, "report", 2)) { + report = TRUE; } else if (keymatch(arg, "scale", 2)) { /* Scale the output image by a fraction M/N. */ @@ -413,6 +428,9 @@ parse_switches(j_decompress_ptr cinfo, int argc, char **argv, usage(); crop = TRUE; + } else if (keymatch(arg, "strict", 2)) { + strict = TRUE; + } else if (keymatch(arg, "targa", 1)) { /* Targa output format. */ requested_fmt = FMT_TARGA; @@ -444,7 +462,7 @@ jpeg_getc(j_decompress_ptr cinfo) ERREXIT(cinfo, JERR_CANT_SUSPEND); } datasrc->bytes_in_buffer--; - return GETJOCTET(*datasrc->next_input_byte++); + return *datasrc->next_input_byte++; } @@ -499,6 +517,19 @@ print_text_marker(j_decompress_ptr cinfo) } +METHODDEF(void) +my_emit_message(j_common_ptr cinfo, int msg_level) +{ + if (msg_level < 0) { + /* Treat warning as fatal */ + cinfo->err->error_exit(cinfo); + } else { + if (cinfo->err->trace_level >= msg_level) + cinfo->err->output_message(cinfo); + } +} + + /* * The main program. */ @@ -512,9 +543,7 @@ main(int argc, char **argv) { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; -#ifdef PROGRESS_REPORT struct cdjpeg_progress_mgr progress; -#endif int file_index; djpeg_dest_ptr dest_mgr = NULL; FILE *input_file; @@ -561,6 +590,9 @@ main(int argc, char **argv) file_index = parse_switches(&cinfo, argc, argv, 0, FALSE); + if (strict) + jerr.emit_message = my_emit_message; + #ifdef TWO_FILE_COMMANDLINE /* Must have either -outfile switch or explicit output file name */ if (outfilename == NULL) { @@ -607,9 +639,11 @@ main(int argc, char **argv) output_file = write_stdout(); } -#ifdef PROGRESS_REPORT - start_progress_monitor((j_common_ptr)&cinfo, &progress); -#endif + if (report || max_scans != 0) { + start_progress_monitor((j_common_ptr)&cinfo, &progress); + progress.report = report; + progress.max_scans = max_scans; + } /* Specify data source for decompression */ #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) @@ -657,7 +691,10 @@ main(int argc, char **argv) #endif #ifdef GIF_SUPPORTED case FMT_GIF: - dest_mgr = jinit_write_gif(&cinfo); + dest_mgr = jinit_write_gif(&cinfo, TRUE); + break; + case FMT_GIF0: + dest_mgr = jinit_write_gif(&cinfo, FALSE); break; #endif #ifdef PPM_SUPPORTED @@ -665,11 +702,6 @@ main(int argc, char **argv) dest_mgr = jinit_write_ppm(&cinfo); break; #endif -#ifdef RLE_SUPPORTED - case FMT_RLE: - dest_mgr = jinit_write_rle(&cinfo); - break; -#endif #ifdef TARGA_SUPPORTED case FMT_TARGA: dest_mgr = jinit_write_targa(&cinfo); @@ -712,7 +744,12 @@ main(int argc, char **argv) dest_mgr->buffer_height); (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); } - jpeg_skip_scanlines(&cinfo, skip_end - skip_start + 1); + if ((tmp = jpeg_skip_scanlines(&cinfo, skip_end - skip_start + 1)) != + skip_end - skip_start + 1) { + fprintf(stderr, "%s: jpeg_skip_scanlines() returned %d rather than %d\n", + progname, tmp, skip_end - skip_start + 1); + return EXIT_FAILURE; + } while (cinfo.output_scanline < cinfo.output_height) { num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer, dest_mgr->buffer_height); @@ -748,13 +785,24 @@ main(int argc, char **argv) cinfo.output_height = tmp; /* Process data */ - jpeg_skip_scanlines(&cinfo, crop_y); + if ((tmp = jpeg_skip_scanlines(&cinfo, crop_y)) != crop_y) { + fprintf(stderr, "%s: jpeg_skip_scanlines() returned %d rather than %d\n", + progname, tmp, crop_y); + return EXIT_FAILURE; + } while (cinfo.output_scanline < crop_y + crop_height) { num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer, dest_mgr->buffer_height); (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); } - jpeg_skip_scanlines(&cinfo, cinfo.output_height - crop_y - crop_height); + if ((tmp = + jpeg_skip_scanlines(&cinfo, + cinfo.output_height - crop_y - crop_height)) != + cinfo.output_height - crop_y - crop_height) { + fprintf(stderr, "%s: jpeg_skip_scanlines() returned %d rather than %d\n", + progname, tmp, cinfo.output_height - crop_y - crop_height); + return EXIT_FAILURE; + } /* Normal full-image decompress */ } else { @@ -769,12 +817,11 @@ main(int argc, char **argv) } } -#ifdef PROGRESS_REPORT /* Hack: count final pass as done in case finish_output does an extra pass. * The library won't have updated completed_passes. */ - progress.pub.completed_passes = progress.pub.total_passes; -#endif + if (report || max_scans != 0) + progress.pub.completed_passes = progress.pub.total_passes; if (icc_filename != NULL) { FILE *icc_file; @@ -813,9 +860,8 @@ main(int argc, char **argv) if (output_file != stdout) fclose(output_file); -#ifdef PROGRESS_REPORT - end_progress_monitor((j_common_ptr)&cinfo); -#endif + if (report || max_scans != 0) + end_progress_monitor((j_common_ptr)&cinfo); if (memsrc) free(inbuffer); |