OLD | NEW |
1 /* | 1 /* |
2 * djpeg.c | 2 * djpeg.c |
3 * | 3 * |
4 * This file was part of the Independent JPEG Group's software: | 4 * This file was part of the Independent JPEG Group's software: |
5 * Copyright (C) 1991-1997, Thomas G. Lane. | 5 * Copyright (C) 1991-1997, Thomas G. Lane. |
| 6 * Modified 2013 by Guido Vollbeding. |
6 * libjpeg-turbo Modifications: | 7 * libjpeg-turbo Modifications: |
7 * Copyright (C) 2010-2011, 2013-2015, D. R. Commander. | 8 * Copyright (C) 2010-2011, 2013-2016, D. R. Commander. |
8 * Copyright (C) 2015, Google, Inc. | 9 * Copyright (C) 2015, Google, Inc. |
9 * For conditions of distribution and use, see the accompanying README file. | 10 * For conditions of distribution and use, see the accompanying README.ijg |
| 11 * file. |
10 * | 12 * |
11 * This file contains a command-line user interface for the JPEG decompressor. | 13 * This file contains a command-line user interface for the JPEG decompressor. |
12 * It should work on any system with Unix- or MS-DOS-style command lines. | 14 * It should work on any system with Unix- or MS-DOS-style command lines. |
13 * | 15 * |
14 * Two different command line styles are permitted, depending on the | 16 * Two different command line styles are permitted, depending on the |
15 * compile-time switch TWO_FILE_COMMANDLINE: | 17 * compile-time switch TWO_FILE_COMMANDLINE: |
16 *» djpeg [options] inputfile outputfile | 18 * djpeg [options] inputfile outputfile |
17 *» djpeg [options] [inputfile] | 19 * djpeg [options] [inputfile] |
18 * In the second style, output is always to standard output, which you'd | 20 * In the second style, output is always to standard output, which you'd |
19 * normally redirect to a file or pipe to some other program. Input is | 21 * normally redirect to a file or pipe to some other program. Input is |
20 * either from a named file or from standard input (typically redirected). | 22 * either from a named file or from standard input (typically redirected). |
21 * The second style is convenient on Unix but is unhelpful on systems that | 23 * The second style is convenient on Unix but is unhelpful on systems that |
22 * don't support pipes. Also, you MUST use the first style if your system | 24 * don't support pipes. Also, you MUST use the first style if your system |
23 * doesn't do binary I/O to stdin/stdout. | 25 * doesn't do binary I/O to stdin/stdout. |
24 * To simplify script writing, the "-outfile" switch is provided. The syntax | 26 * To simplify script writing, the "-outfile" switch is provided. The syntax |
25 *» djpeg [options] -outfile outputfile inputfile | 27 * djpeg [options] -outfile outputfile inputfile |
26 * works regardless of which command line style is used. | 28 * works regardless of which command line style is used. |
27 */ | 29 */ |
28 | 30 |
29 #include "cdjpeg.h"» » /* Common decls for cjpeg/djpeg applications */ | 31 #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ |
30 #include "jversion.h"» » /* for version message */ | 32 #include "jversion.h" /* for version message */ |
31 #include "config.h" | 33 #include "jconfigint.h" |
| 34 #include "wrppm.h" |
32 | 35 |
33 #include <ctype.h>» » /* to declare isprint() */ | 36 #include <ctype.h> /* to declare isprint() */ |
34 | 37 |
35 #ifdef USE_CCOMMAND» » /* command-line reader for Macintosh */ | 38 #ifdef USE_CCOMMAND /* command-line reader for Macintosh */ |
36 #ifdef __MWERKS__ | 39 #ifdef __MWERKS__ |
37 #include <SIOUX.h> /* Metrowerks needs this */ | 40 #include <SIOUX.h> /* Metrowerks needs this */ |
38 #include <console.h>» » /* ... and this */ | 41 #include <console.h> /* ... and this */ |
39 #endif | 42 #endif |
40 #ifdef THINK_C | 43 #ifdef THINK_C |
41 #include <console.h>» » /* Think declares it here */ | 44 #include <console.h> /* Think declares it here */ |
42 #endif | 45 #endif |
43 #endif | 46 #endif |
44 | 47 |
45 | 48 |
46 /* Create the add-on message string table. */ | 49 /* Create the add-on message string table. */ |
47 | 50 |
48 #define JMESSAGE(code,string)» string , | 51 #define JMESSAGE(code,string) string , |
49 | 52 |
50 static const char * const cdjpeg_message_table[] = { | 53 static const char * const cdjpeg_message_table[] = { |
51 #include "cderror.h" | 54 #include "cderror.h" |
52 NULL | 55 NULL |
53 }; | 56 }; |
54 | 57 |
55 | 58 |
56 /* | 59 /* |
57 * This list defines the known output image formats | 60 * This list defines the known output image formats |
58 * (not all of which need be supported by a given version). | 61 * (not all of which need be supported by a given version). |
59 * You can change the default output format by defining DEFAULT_FMT; | 62 * You can change the default output format by defining DEFAULT_FMT; |
60 * indeed, you had better do so if you undefine PPM_SUPPORTED. | 63 * indeed, you had better do so if you undefine PPM_SUPPORTED. |
61 */ | 64 */ |
62 | 65 |
63 typedef enum { | 66 typedef enum { |
64 » FMT_BMP,» » /* BMP format (Windows flavor) */ | 67 FMT_BMP, /* BMP format (Windows flavor) */ |
65 » FMT_GIF,» » /* GIF format */ | 68 FMT_GIF, /* GIF format */ |
66 » FMT_OS2,» » /* BMP format (OS/2 flavor) */ | 69 FMT_OS2, /* BMP format (OS/2 flavor) */ |
67 » FMT_PPM,» » /* PPM/PGM (PBMPLUS formats) */ | 70 FMT_PPM, /* PPM/PGM (PBMPLUS formats) */ |
68 » FMT_RLE,» » /* RLE format */ | 71 FMT_RLE, /* RLE format */ |
69 » FMT_TARGA,» » /* Targa format */ | 72 FMT_TARGA, /* Targa format */ |
70 » FMT_TIFF» » /* TIFF format */ | 73 FMT_TIFF /* TIFF format */ |
71 } IMAGE_FORMATS; | 74 } IMAGE_FORMATS; |
72 | 75 |
73 #ifndef DEFAULT_FMT» » /* so can override from CFLAGS in Makefile */ | 76 #ifndef DEFAULT_FMT /* so can override from CFLAGS in Makefile */ |
74 #define DEFAULT_FMT» FMT_PPM | 77 #define DEFAULT_FMT FMT_PPM |
75 #endif | 78 #endif |
76 | 79 |
77 static IMAGE_FORMATS requested_fmt; | 80 static IMAGE_FORMATS requested_fmt; |
78 | 81 |
79 | 82 |
80 /* | 83 /* |
81 * Argument-parsing code. | 84 * Argument-parsing code. |
82 * The switch parser is designed to be useful with DOS-style command line | 85 * The switch parser is designed to be useful with DOS-style command line |
83 * syntax, ie, intermixed switches and file names, where only the switches | 86 * syntax, ie, intermixed switches and file names, where only the switches |
84 * to the left of a given file name affect processing of that file. | 87 * to the left of a given file name affect processing of that file. |
85 * The main program in this file doesn't actually use this capability... | 88 * The main program in this file doesn't actually use this capability... |
86 */ | 89 */ |
87 | 90 |
88 | 91 |
89 static const char * progname;» /* program name for error messages */ | 92 static const char *progname; /* program name for error messages */ |
90 static char * outfilename;» /* for -outfile switch */ | 93 static char *outfilename; /* for -outfile switch */ |
91 boolean memsrc; /* for -memsrc switch */ | 94 boolean memsrc; /* for -memsrc switch */ |
92 boolean strip, skip; | 95 boolean skip, crop; |
93 JDIMENSION startY, endY; | 96 JDIMENSION skip_start, skip_end; |
| 97 JDIMENSION crop_x, crop_y, crop_width, crop_height; |
94 #define INPUT_BUF_SIZE 4096 | 98 #define INPUT_BUF_SIZE 4096 |
95 | 99 |
96 | 100 |
97 LOCAL(void) | 101 LOCAL(void) |
98 usage (void) | 102 usage (void) |
99 /* complain about bad command line */ | 103 /* complain about bad command line */ |
100 { | 104 { |
101 fprintf(stderr, "usage: %s [switches] ", progname); | 105 fprintf(stderr, "usage: %s [switches] ", progname); |
102 #ifdef TWO_FILE_COMMANDLINE | 106 #ifdef TWO_FILE_COMMANDLINE |
103 fprintf(stderr, "inputfile outputfile\n"); | 107 fprintf(stderr, "inputfile outputfile\n"); |
104 #else | 108 #else |
105 fprintf(stderr, "[inputfile]\n"); | 109 fprintf(stderr, "[inputfile]\n"); |
106 #endif | 110 #endif |
107 | 111 |
108 fprintf(stderr, "Switches (names may be abbreviated):\n"); | 112 fprintf(stderr, "Switches (names may be abbreviated):\n"); |
109 fprintf(stderr, " -colors N Reduce image to no more than N colors\n"); | 113 fprintf(stderr, " -colors N Reduce image to no more than N colors\n"); |
110 fprintf(stderr, " -fast Fast, low-quality processing\n"); | 114 fprintf(stderr, " -fast Fast, low-quality processing\n"); |
111 fprintf(stderr, " -grayscale Force grayscale output\n"); | 115 fprintf(stderr, " -grayscale Force grayscale output\n"); |
112 fprintf(stderr, " -rgb Force RGB output\n"); | 116 fprintf(stderr, " -rgb Force RGB output\n"); |
113 fprintf(stderr, " -rgb565 Force RGB565 output\n"); | 117 fprintf(stderr, " -rgb565 Force RGB565 output\n"); |
114 #ifdef IDCT_SCALING_SUPPORTED | 118 #ifdef IDCT_SCALING_SUPPORTED |
115 fprintf(stderr, " -scale M/N Scale output image by fraction M/N, eg, 1/8\
n"); | 119 fprintf(stderr, " -scale M/N Scale output image by fraction M/N, eg, 1/8\
n"); |
116 #endif | 120 #endif |
117 #ifdef BMP_SUPPORTED | 121 #ifdef BMP_SUPPORTED |
118 fprintf(stderr, " -bmp Select BMP output format (Windows style)%s\n
", | 122 fprintf(stderr, " -bmp Select BMP output format (Windows style)%s\n
", |
119 » (DEFAULT_FMT == FMT_BMP ? " (default)" : "")); | 123 (DEFAULT_FMT == FMT_BMP ? " (default)" : "")); |
120 #endif | 124 #endif |
121 #ifdef GIF_SUPPORTED | 125 #ifdef GIF_SUPPORTED |
122 fprintf(stderr, " -gif Select GIF output format%s\n", | 126 fprintf(stderr, " -gif Select GIF output format%s\n", |
123 » (DEFAULT_FMT == FMT_GIF ? " (default)" : "")); | 127 (DEFAULT_FMT == FMT_GIF ? " (default)" : "")); |
124 #endif | 128 #endif |
125 #ifdef BMP_SUPPORTED | 129 #ifdef BMP_SUPPORTED |
126 fprintf(stderr, " -os2 Select BMP output format (OS/2 style)%s\n", | 130 fprintf(stderr, " -os2 Select BMP output format (OS/2 style)%s\n", |
127 » (DEFAULT_FMT == FMT_OS2 ? " (default)" : "")); | 131 (DEFAULT_FMT == FMT_OS2 ? " (default)" : "")); |
128 #endif | 132 #endif |
129 #ifdef PPM_SUPPORTED | 133 #ifdef PPM_SUPPORTED |
130 fprintf(stderr, " -pnm Select PBMPLUS (PPM/PGM) output format%s\n", | 134 fprintf(stderr, " -pnm Select PBMPLUS (PPM/PGM) output format%s\n", |
131 » (DEFAULT_FMT == FMT_PPM ? " (default)" : "")); | 135 (DEFAULT_FMT == FMT_PPM ? " (default)" : "")); |
132 #endif | 136 #endif |
133 #ifdef RLE_SUPPORTED | 137 #ifdef RLE_SUPPORTED |
134 fprintf(stderr, " -rle Select Utah RLE output format%s\n", | 138 fprintf(stderr, " -rle Select Utah RLE output format%s\n", |
135 » (DEFAULT_FMT == FMT_RLE ? " (default)" : "")); | 139 (DEFAULT_FMT == FMT_RLE ? " (default)" : "")); |
136 #endif | 140 #endif |
137 #ifdef TARGA_SUPPORTED | 141 #ifdef TARGA_SUPPORTED |
138 fprintf(stderr, " -targa Select Targa output format%s\n", | 142 fprintf(stderr, " -targa Select Targa output format%s\n", |
139 » (DEFAULT_FMT == FMT_TARGA ? " (default)" : "")); | 143 (DEFAULT_FMT == FMT_TARGA ? " (default)" : "")); |
140 #endif | 144 #endif |
141 fprintf(stderr, "Switches for advanced users:\n"); | 145 fprintf(stderr, "Switches for advanced users:\n"); |
142 #ifdef DCT_ISLOW_SUPPORTED | 146 #ifdef DCT_ISLOW_SUPPORTED |
143 fprintf(stderr, " -dct int Use integer DCT method%s\n", | 147 fprintf(stderr, " -dct int Use integer DCT method%s\n", |
144 » (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : "")); | 148 (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : "")); |
145 #endif | 149 #endif |
146 #ifdef DCT_IFAST_SUPPORTED | 150 #ifdef DCT_IFAST_SUPPORTED |
147 fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n", | 151 fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n", |
148 » (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : "")); | 152 (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : "")); |
149 #endif | 153 #endif |
150 #ifdef DCT_FLOAT_SUPPORTED | 154 #ifdef DCT_FLOAT_SUPPORTED |
151 fprintf(stderr, " -dct float Use floating-point DCT method%s\n", | 155 fprintf(stderr, " -dct float Use floating-point DCT method%s\n", |
152 » (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : "")); | 156 (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : "")); |
153 #endif | 157 #endif |
154 fprintf(stderr, " -dither fs Use F-S dithering (default)\n"); | 158 fprintf(stderr, " -dither fs Use F-S dithering (default)\n"); |
155 fprintf(stderr, " -dither none Don't use dithering in quantization\n"); | 159 fprintf(stderr, " -dither none Don't use dithering in quantization\n"); |
156 fprintf(stderr, " -dither ordered Use ordered dither (medium speed, quality)
\n"); | 160 fprintf(stderr, " -dither ordered Use ordered dither (medium speed, quality)
\n"); |
157 #ifdef QUANT_2PASS_SUPPORTED | 161 #ifdef QUANT_2PASS_SUPPORTED |
158 fprintf(stderr, " -map FILE Map to colors used in named image file\n"); | 162 fprintf(stderr, " -map FILE Map to colors used in named image file\n"); |
159 #endif | 163 #endif |
160 fprintf(stderr, " -nosmooth Don't use high-quality upsampling\n"); | 164 fprintf(stderr, " -nosmooth Don't use high-quality upsampling\n"); |
161 #ifdef QUANT_1PASS_SUPPORTED | 165 #ifdef QUANT_1PASS_SUPPORTED |
162 fprintf(stderr, " -onepass Use 1-pass quantization (fast, low quality)\
n"); | 166 fprintf(stderr, " -onepass Use 1-pass quantization (fast, low quality)\
n"); |
163 #endif | 167 #endif |
164 fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n"); | 168 fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n"); |
165 fprintf(stderr, " -outfile name Specify name for output file\n"); | 169 fprintf(stderr, " -outfile name Specify name for output file\n"); |
166 #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) | 170 #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) |
167 fprintf(stderr, " -memsrc Load input file into memory before decompres
sing\n"); | 171 fprintf(stderr, " -memsrc Load input file into memory before decompres
sing\n"); |
168 #endif | 172 #endif |
169 | 173 |
170 fprintf(stderr, " -skip Y0,Y1 Decode all rows except those between Y0 and
Y1 (inclusive)\n"); | 174 fprintf(stderr, " -skip Y0,Y1 Decompress all rows except those between Y0
and Y1 (inclusive)\n"); |
171 fprintf(stderr, " -strip Y0,Y1 Decode only rows between Y0 and Y1 (inclusiv
e)\n"); | 175 fprintf(stderr, " -crop WxH+X+Y Decompress only a rectangular subregion of t
he image\n"); |
172 fprintf(stderr, " -verbose or -debug Emit debug output\n"); | 176 fprintf(stderr, " -verbose or -debug Emit debug output\n"); |
| 177 fprintf(stderr, " -version Print version information and exit\n"); |
173 exit(EXIT_FAILURE); | 178 exit(EXIT_FAILURE); |
174 } | 179 } |
175 | 180 |
176 | 181 |
177 LOCAL(int) | 182 LOCAL(int) |
178 parse_switches (j_decompress_ptr cinfo, int argc, char **argv, | 183 parse_switches (j_decompress_ptr cinfo, int argc, char **argv, |
179 » » int last_file_arg_seen, boolean for_real) | 184 int last_file_arg_seen, boolean for_real) |
180 /* Parse optional switches. | 185 /* Parse optional switches. |
181 * Returns argv[] index of first file-name argument (== argc if none). | 186 * Returns argv[] index of first file-name argument (== argc if none). |
182 * Any file names with indexes <= last_file_arg_seen are ignored; | 187 * Any file names with indexes <= last_file_arg_seen are ignored; |
183 * they have presumably been processed in a previous iteration. | 188 * they have presumably been processed in a previous iteration. |
184 * (Pass 0 for last_file_arg_seen on the first or only iteration.) | 189 * (Pass 0 for last_file_arg_seen on the first or only iteration.) |
185 * for_real is FALSE on the first (dummy) pass; we may skip any expensive | 190 * for_real is FALSE on the first (dummy) pass; we may skip any expensive |
186 * processing. | 191 * processing. |
187 */ | 192 */ |
188 { | 193 { |
189 int argn; | 194 int argn; |
190 char * arg; | 195 char *arg; |
191 | 196 |
192 /* Set up default JPEG parameters. */ | 197 /* Set up default JPEG parameters. */ |
193 requested_fmt = DEFAULT_FMT;» /* set default output file format */ | 198 requested_fmt = DEFAULT_FMT; /* set default output file format */ |
194 outfilename = NULL; | 199 outfilename = NULL; |
195 memsrc = FALSE; | 200 memsrc = FALSE; |
196 strip = FALSE; | |
197 skip = FALSE; | 201 skip = FALSE; |
| 202 crop = FALSE; |
198 cinfo->err->trace_level = 0; | 203 cinfo->err->trace_level = 0; |
199 | 204 |
200 /* Scan command line options, adjust parameters */ | 205 /* Scan command line options, adjust parameters */ |
201 | 206 |
202 for (argn = 1; argn < argc; argn++) { | 207 for (argn = 1; argn < argc; argn++) { |
203 arg = argv[argn]; | 208 arg = argv[argn]; |
204 if (*arg != '-') { | 209 if (*arg != '-') { |
205 /* Not a switch, must be a file name argument */ | 210 /* Not a switch, must be a file name argument */ |
206 if (argn <= last_file_arg_seen) { | 211 if (argn <= last_file_arg_seen) { |
207 » outfilename = NULL;» /* -outfile applies to just one input file */ | 212 outfilename = NULL; /* -outfile applies to just one input file */ |
208 » continue;» » /* ignore this name if previously processed */ | 213 continue; /* ignore this name if previously processed */ |
209 } | 214 } |
210 break;» » » /* else done parsing switches */ | 215 break; /* else done parsing switches */ |
211 } | 216 } |
212 arg++;» » » /* advance past switch marker character */ | 217 arg++; /* advance past switch marker character */ |
213 | 218 |
214 if (keymatch(arg, "bmp", 1)) { | 219 if (keymatch(arg, "bmp", 1)) { |
215 /* BMP output format. */ | 220 /* BMP output format. */ |
216 requested_fmt = FMT_BMP; | 221 requested_fmt = FMT_BMP; |
217 | 222 |
218 } else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) || | 223 } else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) || |
219 » keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) { | 224 keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) { |
220 /* Do color quantization. */ | 225 /* Do color quantization. */ |
221 int val; | 226 int val; |
222 | 227 |
223 if (++argn >= argc)» /* advance to next argument */ | 228 if (++argn >= argc) /* advance to next argument */ |
224 » usage(); | 229 usage(); |
225 if (sscanf(argv[argn], "%d", &val) != 1) | 230 if (sscanf(argv[argn], "%d", &val) != 1) |
226 » usage(); | 231 usage(); |
227 cinfo->desired_number_of_colors = val; | 232 cinfo->desired_number_of_colors = val; |
228 cinfo->quantize_colors = TRUE; | 233 cinfo->quantize_colors = TRUE; |
229 | 234 |
230 } else if (keymatch(arg, "dct", 2)) { | 235 } else if (keymatch(arg, "dct", 2)) { |
231 /* Select IDCT algorithm. */ | 236 /* Select IDCT algorithm. */ |
232 if (++argn >= argc)» /* advance to next argument */ | 237 if (++argn >= argc) /* advance to next argument */ |
233 » usage(); | 238 usage(); |
234 if (keymatch(argv[argn], "int", 1)) { | 239 if (keymatch(argv[argn], "int", 1)) { |
235 » cinfo->dct_method = JDCT_ISLOW; | 240 cinfo->dct_method = JDCT_ISLOW; |
236 } else if (keymatch(argv[argn], "fast", 2)) { | 241 } else if (keymatch(argv[argn], "fast", 2)) { |
237 » cinfo->dct_method = JDCT_IFAST; | 242 cinfo->dct_method = JDCT_IFAST; |
238 } else if (keymatch(argv[argn], "float", 2)) { | 243 } else if (keymatch(argv[argn], "float", 2)) { |
239 » cinfo->dct_method = JDCT_FLOAT; | 244 cinfo->dct_method = JDCT_FLOAT; |
240 } else | 245 } else |
241 » usage(); | 246 usage(); |
242 | 247 |
243 } else if (keymatch(arg, "dither", 2)) { | 248 } else if (keymatch(arg, "dither", 2)) { |
244 /* Select dithering algorithm. */ | 249 /* Select dithering algorithm. */ |
245 if (++argn >= argc)» /* advance to next argument */ | 250 if (++argn >= argc) /* advance to next argument */ |
246 » usage(); | 251 usage(); |
247 if (keymatch(argv[argn], "fs", 2)) { | 252 if (keymatch(argv[argn], "fs", 2)) { |
248 » cinfo->dither_mode = JDITHER_FS; | 253 cinfo->dither_mode = JDITHER_FS; |
249 } else if (keymatch(argv[argn], "none", 2)) { | 254 } else if (keymatch(argv[argn], "none", 2)) { |
250 » cinfo->dither_mode = JDITHER_NONE; | 255 cinfo->dither_mode = JDITHER_NONE; |
251 } else if (keymatch(argv[argn], "ordered", 2)) { | 256 } else if (keymatch(argv[argn], "ordered", 2)) { |
252 » cinfo->dither_mode = JDITHER_ORDERED; | 257 cinfo->dither_mode = JDITHER_ORDERED; |
253 } else | 258 } else |
254 » usage(); | 259 usage(); |
255 | 260 |
256 } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) { | 261 } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) { |
257 /* Enable debug printouts. */ | 262 /* Enable debug printouts. */ |
258 /* On first -d, print version identification */ | 263 /* On first -d, print version identification */ |
259 static boolean printed_version = FALSE; | 264 static boolean printed_version = FALSE; |
260 | 265 |
261 if (! printed_version) { | 266 if (! printed_version) { |
262 » fprintf(stderr, "%s version %s (build %s)\n", | 267 fprintf(stderr, "%s version %s (build %s)\n", |
263 » » PACKAGE_NAME, VERSION, BUILD); | 268 PACKAGE_NAME, VERSION, BUILD); |
264 » fprintf(stderr, "%s\n\n", JCOPYRIGHT); | 269 fprintf(stderr, "%s\n\n", JCOPYRIGHT); |
265 » fprintf(stderr, "Emulating The Independent JPEG Group's software, versio
n %s\n\n", | 270 fprintf(stderr, "Emulating The Independent JPEG Group's software, versio
n %s\n\n", |
266 » » JVERSION); | 271 JVERSION); |
267 » printed_version = TRUE; | 272 printed_version = TRUE; |
268 } | 273 } |
269 cinfo->err->trace_level++; | 274 cinfo->err->trace_level++; |
270 | 275 |
| 276 } else if (keymatch(arg, "version", 4)) { |
| 277 fprintf(stderr, "%s version %s (build %s)\n", |
| 278 PACKAGE_NAME, VERSION, BUILD); |
| 279 exit(EXIT_SUCCESS); |
| 280 |
271 } else if (keymatch(arg, "fast", 1)) { | 281 } else if (keymatch(arg, "fast", 1)) { |
272 /* Select recommended processing options for quick-and-dirty output. */ | 282 /* Select recommended processing options for quick-and-dirty output. */ |
273 cinfo->two_pass_quantize = FALSE; | 283 cinfo->two_pass_quantize = FALSE; |
274 cinfo->dither_mode = JDITHER_ORDERED; | 284 cinfo->dither_mode = JDITHER_ORDERED; |
275 if (! cinfo->quantize_colors) /* don't override an earlier -colors */ | 285 if (! cinfo->quantize_colors) /* don't override an earlier -colors */ |
276 » cinfo->desired_number_of_colors = 216; | 286 cinfo->desired_number_of_colors = 216; |
277 cinfo->dct_method = JDCT_FASTEST; | 287 cinfo->dct_method = JDCT_FASTEST; |
278 cinfo->do_fancy_upsampling = FALSE; | 288 cinfo->do_fancy_upsampling = FALSE; |
279 | 289 |
280 } else if (keymatch(arg, "gif", 1)) { | 290 } else if (keymatch(arg, "gif", 1)) { |
281 /* GIF output format. */ | 291 /* GIF output format. */ |
282 requested_fmt = FMT_GIF; | 292 requested_fmt = FMT_GIF; |
283 | 293 |
284 } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) { | 294 } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) { |
285 /* Force monochrome output. */ | 295 /* Force monochrome output. */ |
286 cinfo->out_color_space = JCS_GRAYSCALE; | 296 cinfo->out_color_space = JCS_GRAYSCALE; |
287 | 297 |
288 } else if (keymatch(arg, "rgb", 2)) { | 298 } else if (keymatch(arg, "rgb", 2)) { |
289 /* Force RGB output. */ | 299 /* Force RGB output. */ |
290 cinfo->out_color_space = JCS_RGB; | 300 cinfo->out_color_space = JCS_RGB; |
291 | 301 |
292 } else if (keymatch(arg, "rgb565", 2)) { | 302 } else if (keymatch(arg, "rgb565", 2)) { |
293 /* Force RGB565 output. */ | 303 /* Force RGB565 output. */ |
294 cinfo->out_color_space = JCS_RGB565; | 304 cinfo->out_color_space = JCS_RGB565; |
295 | 305 |
296 } else if (keymatch(arg, "map", 3)) { | 306 } else if (keymatch(arg, "map", 3)) { |
297 /* Quantize to a color map taken from an input file. */ | 307 /* Quantize to a color map taken from an input file. */ |
298 if (++argn >= argc)» /* advance to next argument */ | 308 if (++argn >= argc) /* advance to next argument */ |
299 » usage(); | 309 usage(); |
300 if (for_real) {» » /* too expensive to do twice! */ | 310 if (for_real) { /* too expensive to do twice! */ |
301 #ifdef QUANT_2PASS_SUPPORTED» /* otherwise can't quantize to supplied map */ | 311 #ifdef QUANT_2PASS_SUPPORTED /* otherwise can't quantize to supplied map */ |
302 » FILE * mapfile; | 312 FILE *mapfile; |
303 | 313 |
304 » if ((mapfile = fopen(argv[argn], READ_BINARY)) == NULL) { | 314 if ((mapfile = fopen(argv[argn], READ_BINARY)) == NULL) { |
305 » fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]); | 315 fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]); |
306 » exit(EXIT_FAILURE); | 316 exit(EXIT_FAILURE); |
307 » } | 317 } |
308 » read_color_map(cinfo, mapfile); | 318 read_color_map(cinfo, mapfile); |
309 » fclose(mapfile); | 319 fclose(mapfile); |
310 » cinfo->quantize_colors = TRUE; | 320 cinfo->quantize_colors = TRUE; |
311 #else | 321 #else |
312 » ERREXIT(cinfo, JERR_NOT_COMPILED); | 322 ERREXIT(cinfo, JERR_NOT_COMPILED); |
313 #endif | 323 #endif |
314 } | 324 } |
315 | 325 |
316 } else if (keymatch(arg, "maxmemory", 3)) { | 326 } else if (keymatch(arg, "maxmemory", 3)) { |
317 /* Maximum memory in Kb (or Mb with 'm'). */ | 327 /* Maximum memory in Kb (or Mb with 'm'). */ |
318 long lval; | 328 long lval; |
319 char ch = 'x'; | 329 char ch = 'x'; |
320 | 330 |
321 if (++argn >= argc)» /* advance to next argument */ | 331 if (++argn >= argc) /* advance to next argument */ |
322 » usage(); | 332 usage(); |
323 if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) | 333 if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) |
324 » usage(); | 334 usage(); |
325 if (ch == 'm' || ch == 'M') | 335 if (ch == 'm' || ch == 'M') |
326 » lval *= 1000L; | 336 lval *= 1000L; |
327 cinfo->mem->max_memory_to_use = lval * 1000L; | 337 cinfo->mem->max_memory_to_use = lval * 1000L; |
328 | 338 |
329 } else if (keymatch(arg, "nosmooth", 3)) { | 339 } else if (keymatch(arg, "nosmooth", 3)) { |
330 /* Suppress fancy upsampling */ | 340 /* Suppress fancy upsampling */ |
331 cinfo->do_fancy_upsampling = FALSE; | 341 cinfo->do_fancy_upsampling = FALSE; |
332 | 342 |
333 } else if (keymatch(arg, "onepass", 3)) { | 343 } else if (keymatch(arg, "onepass", 3)) { |
334 /* Use fast one-pass quantization. */ | 344 /* Use fast one-pass quantization. */ |
335 cinfo->two_pass_quantize = FALSE; | 345 cinfo->two_pass_quantize = FALSE; |
336 | 346 |
337 } else if (keymatch(arg, "os2", 3)) { | 347 } else if (keymatch(arg, "os2", 3)) { |
338 /* BMP output format (OS/2 flavor). */ | 348 /* BMP output format (OS/2 flavor). */ |
339 requested_fmt = FMT_OS2; | 349 requested_fmt = FMT_OS2; |
340 | 350 |
341 } else if (keymatch(arg, "outfile", 4)) { | 351 } else if (keymatch(arg, "outfile", 4)) { |
342 /* Set output file name. */ | 352 /* Set output file name. */ |
343 if (++argn >= argc)» /* advance to next argument */ | 353 if (++argn >= argc) /* advance to next argument */ |
344 » usage(); | 354 usage(); |
345 outfilename = argv[argn];»/* save it away for later use */ | 355 outfilename = argv[argn]; /* save it away for later use */ |
346 | 356 |
347 } else if (keymatch(arg, "memsrc", 2)) { | 357 } else if (keymatch(arg, "memsrc", 2)) { |
348 /* Use in-memory source manager */ | 358 /* Use in-memory source manager */ |
349 #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) | 359 #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) |
350 memsrc = TRUE; | 360 memsrc = TRUE; |
351 #else | 361 #else |
352 fprintf(stderr, "%s: sorry, in-memory source manager was not compiled in\n
", | 362 fprintf(stderr, "%s: sorry, in-memory source manager was not compiled in\n
", |
353 progname); | 363 progname); |
354 exit(EXIT_FAILURE); | 364 exit(EXIT_FAILURE); |
355 #endif | 365 #endif |
356 | 366 |
357 } else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) { | 367 } else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) { |
358 /* PPM/PGM output format. */ | 368 /* PPM/PGM output format. */ |
359 requested_fmt = FMT_PPM; | 369 requested_fmt = FMT_PPM; |
360 | 370 |
361 } else if (keymatch(arg, "rle", 1)) { | 371 } else if (keymatch(arg, "rle", 1)) { |
362 /* RLE output format. */ | 372 /* RLE output format. */ |
363 requested_fmt = FMT_RLE; | 373 requested_fmt = FMT_RLE; |
364 | 374 |
365 } else if (keymatch(arg, "scale", 2)) { | 375 } else if (keymatch(arg, "scale", 2)) { |
366 /* Scale the output image by a fraction M/N. */ | 376 /* Scale the output image by a fraction M/N. */ |
367 if (++argn >= argc)» /* advance to next argument */ | 377 if (++argn >= argc) /* advance to next argument */ |
368 » usage(); | |
369 if (sscanf(argv[argn], "%d/%d", | |
370 » » &cinfo->scale_num, &cinfo->scale_denom) != 2) | |
371 » usage(); | |
372 | |
373 } else if (keymatch(arg, "strip", 2)) { | |
374 if (++argn >= argc) | |
375 usage(); | 378 usage(); |
376 if (sscanf(argv[argn], "%d,%d", &startY, &endY) != 2 || startY > endY) | 379 if (sscanf(argv[argn], "%u/%u", |
| 380 &cinfo->scale_num, &cinfo->scale_denom) != 2) |
377 usage(); | 381 usage(); |
378 strip = TRUE; | |
379 | 382 |
380 } else if (keymatch(arg, "skip", 2)) { | 383 } else if (keymatch(arg, "skip", 2)) { |
381 if (++argn >= argc) | 384 if (++argn >= argc) |
382 usage(); | 385 usage(); |
383 if (sscanf(argv[argn], "%d,%d", &startY, &endY) != 2 || startY > endY) | 386 if (sscanf(argv[argn], "%u,%u", &skip_start, &skip_end) != 2 || |
| 387 skip_start > skip_end) |
384 usage(); | 388 usage(); |
385 skip = TRUE; | 389 skip = TRUE; |
386 | 390 |
| 391 } else if (keymatch(arg, "crop", 2)) { |
| 392 char c; |
| 393 if (++argn >= argc) |
| 394 usage(); |
| 395 if (sscanf(argv[argn], "%u%c%u+%u+%u", &crop_width, &c, &crop_height, |
| 396 &crop_x, &crop_y) != 5 || |
| 397 (c != 'X' && c != 'x') || crop_width < 1 || crop_height < 1) |
| 398 usage(); |
| 399 crop = TRUE; |
| 400 |
387 } else if (keymatch(arg, "targa", 1)) { | 401 } else if (keymatch(arg, "targa", 1)) { |
388 /* Targa output format. */ | 402 /* Targa output format. */ |
389 requested_fmt = FMT_TARGA; | 403 requested_fmt = FMT_TARGA; |
390 | 404 |
391 } else { | 405 } else { |
392 usage();» » » /* bogus switch */ | 406 usage(); /* bogus switch */ |
393 } | 407 } |
394 } | 408 } |
395 | 409 |
396 return argn;» » » /* return index of next arg (file name) */ | 410 return argn; /* return index of next arg (file name) */ |
397 } | 411 } |
398 | 412 |
399 | 413 |
400 /* | 414 /* |
401 * Marker processor for COM and interesting APPn markers. | 415 * Marker processor for COM and interesting APPn markers. |
402 * This replaces the library's built-in processor, which just skips the marker. | 416 * This replaces the library's built-in processor, which just skips the marker. |
403 * We want to print out the marker as text, to the extent possible. | 417 * We want to print out the marker as text, to the extent possible. |
404 * Note this code relies on a non-suspending data source. | 418 * Note this code relies on a non-suspending data source. |
405 */ | 419 */ |
406 | 420 |
407 LOCAL(unsigned int) | 421 LOCAL(unsigned int) |
408 jpeg_getc (j_decompress_ptr cinfo) | 422 jpeg_getc (j_decompress_ptr cinfo) |
409 /* Read next byte */ | 423 /* Read next byte */ |
410 { | 424 { |
411 struct jpeg_source_mgr * datasrc = cinfo->src; | 425 struct jpeg_source_mgr *datasrc = cinfo->src; |
412 | 426 |
413 if (datasrc->bytes_in_buffer == 0) { | 427 if (datasrc->bytes_in_buffer == 0) { |
414 if (! (*datasrc->fill_input_buffer) (cinfo)) | 428 if (! (*datasrc->fill_input_buffer) (cinfo)) |
415 ERREXIT(cinfo, JERR_CANT_SUSPEND); | 429 ERREXIT(cinfo, JERR_CANT_SUSPEND); |
416 } | 430 } |
417 datasrc->bytes_in_buffer--; | 431 datasrc->bytes_in_buffer--; |
418 return GETJOCTET(*datasrc->next_input_byte++); | 432 return GETJOCTET(*datasrc->next_input_byte++); |
419 } | 433 } |
420 | 434 |
421 | 435 |
422 METHODDEF(boolean) | 436 METHODDEF(boolean) |
423 print_text_marker (j_decompress_ptr cinfo) | 437 print_text_marker (j_decompress_ptr cinfo) |
424 { | 438 { |
425 boolean traceit = (cinfo->err->trace_level >= 1); | 439 boolean traceit = (cinfo->err->trace_level >= 1); |
426 INT32 length; | 440 long length; |
427 unsigned int ch; | 441 unsigned int ch; |
428 unsigned int lastch = 0; | 442 unsigned int lastch = 0; |
429 | 443 |
430 length = jpeg_getc(cinfo) << 8; | 444 length = jpeg_getc(cinfo) << 8; |
431 length += jpeg_getc(cinfo); | 445 length += jpeg_getc(cinfo); |
432 length -= 2;» » » /* discount the length word itself */ | 446 length -= 2; /* discount the length word itself */ |
433 | 447 |
434 if (traceit) { | 448 if (traceit) { |
435 if (cinfo->unread_marker == JPEG_COM) | 449 if (cinfo->unread_marker == JPEG_COM) |
436 fprintf(stderr, "Comment, length %ld:\n", (long) length); | 450 fprintf(stderr, "Comment, length %ld:\n", (long) length); |
437 else» » » /* assume it is an APPn otherwise */ | 451 else /* assume it is an APPn otherwise */ |
438 fprintf(stderr, "APP%d, length %ld:\n", | 452 fprintf(stderr, "APP%d, length %ld:\n", |
439 » cinfo->unread_marker - JPEG_APP0, (long) length); | 453 cinfo->unread_marker - JPEG_APP0, (long) length); |
440 } | 454 } |
441 | 455 |
442 while (--length >= 0) { | 456 while (--length >= 0) { |
443 ch = jpeg_getc(cinfo); | 457 ch = jpeg_getc(cinfo); |
444 if (traceit) { | 458 if (traceit) { |
445 /* Emit the character in a readable form. | 459 /* Emit the character in a readable form. |
446 * Nonprintables are converted to \nnn form, | 460 * Nonprintables are converted to \nnn form, |
447 * while \ is converted to \\. | 461 * while \ is converted to \\. |
448 * Newlines in CR, CR/LF, or LF form will be printed as one newline. | 462 * Newlines in CR, CR/LF, or LF form will be printed as one newline. |
449 */ | 463 */ |
450 if (ch == '\r') { | 464 if (ch == '\r') { |
451 » fprintf(stderr, "\n"); | 465 fprintf(stderr, "\n"); |
452 } else if (ch == '\n') { | 466 } else if (ch == '\n') { |
453 » if (lastch != '\r') | 467 if (lastch != '\r') |
454 » fprintf(stderr, "\n"); | 468 fprintf(stderr, "\n"); |
455 } else if (ch == '\\') { | 469 } else if (ch == '\\') { |
456 » fprintf(stderr, "\\\\"); | 470 fprintf(stderr, "\\\\"); |
457 } else if (isprint(ch)) { | 471 } else if (isprint(ch)) { |
458 » putc(ch, stderr); | 472 putc(ch, stderr); |
459 } else { | 473 } else { |
460 » fprintf(stderr, "\\%03o", ch); | 474 fprintf(stderr, "\\%03o", ch); |
461 } | 475 } |
462 lastch = ch; | 476 lastch = ch; |
463 } | 477 } |
464 } | 478 } |
465 | 479 |
466 if (traceit) | 480 if (traceit) |
467 fprintf(stderr, "\n"); | 481 fprintf(stderr, "\n"); |
468 | 482 |
469 return TRUE; | 483 return TRUE; |
470 } | 484 } |
471 | 485 |
472 | 486 |
473 /* | 487 /* |
474 * The main program. | 488 * The main program. |
475 */ | 489 */ |
476 | 490 |
477 int | 491 int |
478 main (int argc, char **argv) | 492 main (int argc, char **argv) |
479 { | 493 { |
480 struct jpeg_decompress_struct cinfo; | 494 struct jpeg_decompress_struct cinfo; |
481 struct jpeg_error_mgr jerr; | 495 struct jpeg_error_mgr jerr; |
482 #ifdef PROGRESS_REPORT | 496 #ifdef PROGRESS_REPORT |
483 struct cdjpeg_progress_mgr progress; | 497 struct cdjpeg_progress_mgr progress; |
484 #endif | 498 #endif |
485 int file_index; | 499 int file_index; |
486 djpeg_dest_ptr dest_mgr = NULL; | 500 djpeg_dest_ptr dest_mgr = NULL; |
487 FILE * input_file; | 501 FILE *input_file; |
488 FILE * output_file; | 502 FILE *output_file; |
489 unsigned char *inbuffer = NULL; | 503 unsigned char *inbuffer = NULL; |
490 unsigned long insize = 0; | 504 unsigned long insize = 0; |
491 JDIMENSION num_scanlines; | 505 JDIMENSION num_scanlines; |
492 | 506 |
493 /* On Mac, fetch a command line. */ | 507 /* On Mac, fetch a command line. */ |
494 #ifdef USE_CCOMMAND | 508 #ifdef USE_CCOMMAND |
495 argc = ccommand(&argv); | 509 argc = ccommand(&argv); |
496 #endif | 510 #endif |
497 | 511 |
498 progname = argv[0]; | 512 progname = argv[0]; |
499 if (progname == NULL || progname[0] == 0) | 513 if (progname == NULL || progname[0] == 0) |
500 progname = "djpeg";»» /* in case C library doesn't provide it */ | 514 progname = "djpeg"; /* in case C library doesn't provide it */ |
501 | 515 |
502 /* Initialize the JPEG decompression object with default error handling. */ | 516 /* Initialize the JPEG decompression object with default error handling. */ |
503 cinfo.err = jpeg_std_error(&jerr); | 517 cinfo.err = jpeg_std_error(&jerr); |
504 jpeg_create_decompress(&cinfo); | 518 jpeg_create_decompress(&cinfo); |
505 /* Add some application-specific error messages (from cderror.h) */ | 519 /* Add some application-specific error messages (from cderror.h) */ |
506 jerr.addon_message_table = cdjpeg_message_table; | 520 jerr.addon_message_table = cdjpeg_message_table; |
507 jerr.first_addon_message = JMSG_FIRSTADDONCODE; | 521 jerr.first_addon_message = JMSG_FIRSTADDONCODE; |
508 jerr.last_addon_message = JMSG_LASTADDONCODE; | 522 jerr.last_addon_message = JMSG_LASTADDONCODE; |
509 | 523 |
510 /* Insert custom marker processor for COM and APP12. | 524 /* Insert custom marker processor for COM and APP12. |
511 * APP12 is used by some digital camera makers for textual info, | 525 * APP12 is used by some digital camera makers for textual info, |
512 * so we provide the ability to display it as text. | 526 * so we provide the ability to display it as text. |
513 * If you like, additional APPn marker types can be selected for display, | 527 * If you like, additional APPn marker types can be selected for display, |
514 * but don't try to override APP0 or APP14 this way (see libjpeg.txt). | 528 * but don't try to override APP0 or APP14 this way (see libjpeg.txt). |
515 */ | 529 */ |
516 jpeg_set_marker_processor(&cinfo, JPEG_COM, print_text_marker); | 530 jpeg_set_marker_processor(&cinfo, JPEG_COM, print_text_marker); |
517 jpeg_set_marker_processor(&cinfo, JPEG_APP0+12, print_text_marker); | 531 jpeg_set_marker_processor(&cinfo, JPEG_APP0+12, print_text_marker); |
518 | 532 |
519 /* Now safe to enable signal catcher. */ | |
520 #ifdef NEED_SIGNAL_CATCHER | |
521 enable_signal_catcher((j_common_ptr) &cinfo); | |
522 #endif | |
523 | |
524 /* Scan command line to find file names. */ | 533 /* Scan command line to find file names. */ |
525 /* It is convenient to use just one switch-parsing routine, but the switch | 534 /* It is convenient to use just one switch-parsing routine, but the switch |
526 * values read here are ignored; we will rescan the switches after opening | 535 * values read here are ignored; we will rescan the switches after opening |
527 * the input file. | 536 * the input file. |
528 * (Exception: tracing level set here controls verbosity for COM markers | 537 * (Exception: tracing level set here controls verbosity for COM markers |
529 * found during jpeg_read_header...) | 538 * found during jpeg_read_header...) |
530 */ | 539 */ |
531 | 540 |
532 file_index = parse_switches(&cinfo, argc, argv, 0, FALSE); | 541 file_index = parse_switches(&cinfo, argc, argv, 0, FALSE); |
533 | 542 |
534 #ifdef TWO_FILE_COMMANDLINE | 543 #ifdef TWO_FILE_COMMANDLINE |
535 /* Must have either -outfile switch or explicit output file name */ | 544 /* Must have either -outfile switch or explicit output file name */ |
536 if (outfilename == NULL) { | 545 if (outfilename == NULL) { |
537 if (file_index != argc-2) { | 546 if (file_index != argc-2) { |
538 fprintf(stderr, "%s: must name one input and one output file\n", | 547 fprintf(stderr, "%s: must name one input and one output file\n", |
539 » progname); | 548 progname); |
540 usage(); | 549 usage(); |
541 } | 550 } |
542 outfilename = argv[file_index+1]; | 551 outfilename = argv[file_index+1]; |
543 } else { | 552 } else { |
544 if (file_index != argc-1) { | 553 if (file_index != argc-1) { |
545 fprintf(stderr, "%s: must name one input and one output file\n", | 554 fprintf(stderr, "%s: must name one input and one output file\n", |
546 » progname); | 555 progname); |
547 usage(); | 556 usage(); |
548 } | 557 } |
549 } | 558 } |
550 #else | 559 #else |
551 /* Unix style: expect zero or one file name */ | 560 /* Unix style: expect zero or one file name */ |
552 if (file_index < argc-1) { | 561 if (file_index < argc-1) { |
553 fprintf(stderr, "%s: only one input file\n", progname); | 562 fprintf(stderr, "%s: only one input file\n", progname); |
554 usage(); | 563 usage(); |
555 } | 564 } |
556 #endif /* TWO_FILE_COMMANDLINE */ | 565 #endif /* TWO_FILE_COMMANDLINE */ |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
647 #endif | 656 #endif |
648 default: | 657 default: |
649 ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT); | 658 ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT); |
650 break; | 659 break; |
651 } | 660 } |
652 dest_mgr->output_file = output_file; | 661 dest_mgr->output_file = output_file; |
653 | 662 |
654 /* Start decompressor */ | 663 /* Start decompressor */ |
655 (void) jpeg_start_decompress(&cinfo); | 664 (void) jpeg_start_decompress(&cinfo); |
656 | 665 |
657 /* Strip decode */ | 666 /* Skip rows */ |
658 if (strip || skip) { | 667 if (skip) { |
659 JDIMENSION tmp; | 668 JDIMENSION tmp; |
660 | 669 |
661 /* Check for valid endY. We cannot check this value until after | 670 /* Check for valid skip_end. We cannot check this value until after |
662 * jpeg_start_decompress() is called. Note that we have already verified | 671 * jpeg_start_decompress() is called. Note that we have already verified |
663 * that startY <= endY. | 672 * that skip_start <= skip_end. |
664 */ | 673 */ |
665 if (endY > cinfo.output_height - 1) { | 674 if (skip_end > cinfo.output_height - 1) { |
666 fprintf(stderr, "%s: strip %d-%d exceeds image height %d\n", progname, | 675 fprintf(stderr, "%s: skip region exceeds image height %d\n", progname, |
667 startY, endY, cinfo.output_height); | 676 cinfo.output_height); |
668 exit(EXIT_FAILURE); | 677 exit(EXIT_FAILURE); |
669 } | 678 } |
670 | 679 |
671 /* Write output file header. This is a hack to ensure that the destination | 680 /* Write output file header. This is a hack to ensure that the destination |
672 * manager creates an image of the proper size for the partial decode. | 681 * manager creates an output image of the proper size. |
673 */ | 682 */ |
674 tmp = cinfo.output_height; | 683 tmp = cinfo.output_height; |
675 cinfo.output_height = endY - startY + 1; | 684 cinfo.output_height -= (skip_end - skip_start + 1); |
676 if (skip) | |
677 cinfo.output_height = tmp - cinfo.output_height; | |
678 (*dest_mgr->start_output) (&cinfo, dest_mgr); | 685 (*dest_mgr->start_output) (&cinfo, dest_mgr); |
679 cinfo.output_height = tmp; | 686 cinfo.output_height = tmp; |
680 | 687 |
681 /* Process data */ | 688 /* Process data */ |
682 if (skip) { | 689 while (cinfo.output_scanline < skip_start) { |
683 while (cinfo.output_scanline < startY) { | 690 num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer, |
684 num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer, | 691 dest_mgr->buffer_height); |
685 dest_mgr->buffer_height); | 692 (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); |
686 (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); | 693 } |
687 } | 694 jpeg_skip_scanlines(&cinfo, skip_end - skip_start + 1); |
688 jpeg_skip_scanlines(&cinfo, endY - startY + 1); | 695 while (cinfo.output_scanline < cinfo.output_height) { |
689 while (cinfo.output_scanline < cinfo.output_height) { | 696 num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer, |
690 num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer, | 697 dest_mgr->buffer_height); |
691 dest_mgr->buffer_height); | 698 (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); |
692 (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); | |
693 } | |
694 } else { | |
695 jpeg_skip_scanlines(&cinfo, startY); | |
696 while (cinfo.output_scanline <= endY) { | |
697 num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer, | |
698 dest_mgr->buffer_height); | |
699 (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); | |
700 } | |
701 jpeg_skip_scanlines(&cinfo, cinfo.output_height - endY + 1); | |
702 } | 699 } |
703 | 700 |
704 /* Normal full image decode */ | 701 /* Decompress a subregion */ |
| 702 } else if (crop) { |
| 703 JDIMENSION tmp; |
| 704 |
| 705 /* Check for valid crop dimensions. We cannot check these values until |
| 706 * after jpeg_start_decompress() is called. |
| 707 */ |
| 708 if (crop_x + crop_width > cinfo.output_width || |
| 709 crop_y + crop_height > cinfo.output_height) { |
| 710 fprintf(stderr, "%s: crop dimensions exceed image dimensions %d x %d\n", |
| 711 progname, cinfo.output_width, cinfo.output_height); |
| 712 exit(EXIT_FAILURE); |
| 713 } |
| 714 |
| 715 jpeg_crop_scanline(&cinfo, &crop_x, &crop_width); |
| 716 ((ppm_dest_ptr) dest_mgr)->buffer_width = cinfo.output_width * |
| 717 cinfo.out_color_components * |
| 718 sizeof(JSAMPLE); |
| 719 |
| 720 /* Write output file header. This is a hack to ensure that the destination |
| 721 * manager creates an output image of the proper size. |
| 722 */ |
| 723 tmp = cinfo.output_height; |
| 724 cinfo.output_height = crop_height; |
| 725 (*dest_mgr->start_output) (&cinfo, dest_mgr); |
| 726 cinfo.output_height = tmp; |
| 727 |
| 728 /* Process data */ |
| 729 jpeg_skip_scanlines(&cinfo, crop_y); |
| 730 while (cinfo.output_scanline < crop_y + crop_height) { |
| 731 num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer, |
| 732 dest_mgr->buffer_height); |
| 733 (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); |
| 734 } |
| 735 jpeg_skip_scanlines(&cinfo, cinfo.output_height - crop_y - crop_height); |
| 736 |
| 737 /* Normal full-image decompress */ |
705 } else { | 738 } else { |
706 /* Write output file header */ | 739 /* Write output file header */ |
707 (*dest_mgr->start_output) (&cinfo, dest_mgr); | 740 (*dest_mgr->start_output) (&cinfo, dest_mgr); |
708 | 741 |
709 /* Process data */ | 742 /* Process data */ |
710 while (cinfo.output_scanline < cinfo.output_height) { | 743 while (cinfo.output_scanline < cinfo.output_height) { |
711 num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer, | 744 num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer, |
712 dest_mgr->buffer_height); | 745 dest_mgr->buffer_height); |
713 (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); | 746 (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); |
714 } | 747 } |
(...skipping 22 matching lines...) Expand all Loading... |
737 | 770 |
738 #ifdef PROGRESS_REPORT | 771 #ifdef PROGRESS_REPORT |
739 end_progress_monitor((j_common_ptr) &cinfo); | 772 end_progress_monitor((j_common_ptr) &cinfo); |
740 #endif | 773 #endif |
741 | 774 |
742 if (memsrc && inbuffer != NULL) | 775 if (memsrc && inbuffer != NULL) |
743 free(inbuffer); | 776 free(inbuffer); |
744 | 777 |
745 /* All done. */ | 778 /* All done. */ |
746 exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS); | 779 exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS); |
747 return 0;» » » /* suppress no-return-value warnings */ | 780 return 0; /* suppress no-return-value warnings */ |
748 } | 781 } |
OLD | NEW |