Magellan Linux

Contents of /trunk/libjpeg/patches/libjpeg-6b-crop.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 144 - (show annotations) (download)
Tue May 8 20:06:05 2007 UTC (17 years ago) by niro
File size: 72760 byte(s)
-import

1 # DP: Lossless-crop patch from <http://sylvana.net/jpegcrop/croppatch.tar.gz>
2 # DP: by <guido@jpegclub.org>.
3
4 diff -urNad /home/bill/debian/libjpeg/libjpeg6b-6b/jerror.h libjpeg6b-6b/jerror.h
5 --- /home/bill/debian/libjpeg/libjpeg6b-6b/jerror.h 2003-09-22 18:15:48.000000000 +0200
6 +++ libjpeg6b-6b/jerror.h 2003-09-22 18:16:12.000000000 +0200
7 @@ -45,6 +45,7 @@
8 JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix")
9 JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode")
10 JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS")
11 +JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request")
12 JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range")
13 JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported")
14 JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition")
15 diff -urNad /home/bill/debian/libjpeg/libjpeg6b-6b/jpegtran.c libjpeg6b-6b/jpegtran.c
16 --- /home/bill/debian/libjpeg/libjpeg6b-6b/jpegtran.c 2003-09-22 18:15:48.000000000 +0200
17 +++ libjpeg6b-6b/jpegtran.c 2003-09-22 18:16:22.000000000 +0200
18 @@ -1,7 +1,7 @@
19 /*
20 * jpegtran.c
21 *
22 - * Copyright (C) 1995-1997, Thomas G. Lane.
23 + * Copyright (C) 1995-2001, Thomas G. Lane.
24 * This file is part of the Independent JPEG Group's software.
25 * For conditions of distribution and use, see the accompanying README file.
26 *
27 @@ -64,8 +64,10 @@
28 #endif
29 #if TRANSFORMS_SUPPORTED
30 fprintf(stderr, "Switches for modifying the image:\n");
31 + fprintf(stderr, " -crop WxH+X+Y Crop to a rectangular subarea\n");
32 fprintf(stderr, " -grayscale Reduce to grayscale (omit color data)\n");
33 fprintf(stderr, " -flip [horizontal|vertical] Mirror image (left-right or top-bottom)\n");
34 + fprintf(stderr, " -perfect Fail if there is non-transformable edge blocks\n");
35 fprintf(stderr, " -rotate [90|180|270] Rotate image (degrees clockwise)\n");
36 fprintf(stderr, " -transpose Transpose image\n");
37 fprintf(stderr, " -transverse Transverse transpose image\n");
38 @@ -133,7 +135,9 @@
39 copyoption = JCOPYOPT_DEFAULT;
40 transformoption.transform = JXFORM_NONE;
41 transformoption.trim = FALSE;
42 + transformoption.perfect = FALSE;
43 transformoption.force_grayscale = FALSE;
44 + transformoption.crop = FALSE;
45 cinfo->err->trace_level = 0;
46
47 /* Scan command line options, adjust parameters */
48 @@ -160,7 +164,7 @@
49 exit(EXIT_FAILURE);
50 #endif
51
52 - } else if (keymatch(arg, "copy", 1)) {
53 + } else if (keymatch(arg, "copy", 2)) {
54 /* Select which extra markers to copy. */
55 if (++argn >= argc) /* advance to next argument */
56 usage();
57 @@ -173,6 +177,20 @@
58 } else
59 usage();
60
61 + } else if (keymatch(arg, "crop", 2)) {
62 + /* Perform lossless cropping. */
63 +#if TRANSFORMS_SUPPORTED
64 + if (++argn >= argc) /* advance to next argument */
65 + usage();
66 + if (! jtransform_parse_crop_spec(&transformoption, argv[argn])) {
67 + fprintf(stderr, "%s: bogus -crop argument '%s'\n",
68 + progname, argv[argn]);
69 + exit(EXIT_FAILURE);
70 + }
71 +#else
72 + select_transform(JXFORM_NONE); /* force an error */
73 +#endif
74 +
75 } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
76 /* Enable debug printouts. */
77 /* On first -d, print version identification */
78 @@ -233,7 +251,12 @@
79 usage();
80 outfilename = argv[argn]; /* save it away for later use */
81
82 - } else if (keymatch(arg, "progressive", 1)) {
83 + } else if (keymatch(arg, "perfect", 2)) {
84 + /* Fail if there is any partial edge MCUs that the transform can't
85 + * handle. */
86 + transformoption.perfect = TRUE;
87 +
88 + } else if (keymatch(arg, "progressive", 2)) {
89 /* Select simple progressive mode. */
90 #ifdef C_PROGRESSIVE_SUPPORTED
91 simple_progressive = TRUE;
92 @@ -342,8 +365,10 @@
93 jvirt_barray_ptr * src_coef_arrays;
94 jvirt_barray_ptr * dst_coef_arrays;
95 int file_index;
96 - FILE * input_file;
97 - FILE * output_file;
98 + /* We assume all-in-memory processing and can therefore use only a
99 + * single file pointer for sequential input and output operation.
100 + */
101 + FILE * fp;
102
103 /* On Mac, fetch a command line. */
104 #ifdef USE_CCOMMAND
105 @@ -406,24 +431,13 @@
106
107 /* Open the input file. */
108 if (file_index < argc) {
109 - if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
110 - fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
111 + if ((fp = fopen(argv[file_index], READ_BINARY)) == NULL) {
112 + fprintf(stderr, "%s: can't open %s for reading\n", progname, argv[file_index]);
113 exit(EXIT_FAILURE);
114 }
115 } else {
116 /* default input file is stdin */
117 - input_file = read_stdin();
118 - }
119 -
120 - /* Open the output file. */
121 - if (outfilename != NULL) {
122 - if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
123 - fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
124 - exit(EXIT_FAILURE);
125 - }
126 - } else {
127 - /* default output file is stdout */
128 - output_file = write_stdout();
129 + fp = read_stdin();
130 }
131
132 #ifdef PROGRESS_REPORT
133 @@ -431,7 +445,7 @@
134 #endif
135
136 /* Specify data source for decompression */
137 - jpeg_stdio_src(&srcinfo, input_file);
138 + jpeg_stdio_src(&srcinfo, fp);
139
140 /* Enable saving of extra markers that we want to copy */
141 jcopy_markers_setup(&srcinfo, copyoption);
142 @@ -443,6 +457,15 @@
143 * jpeg_read_coefficients so that memory allocation will be done right.
144 */
145 #if TRANSFORMS_SUPPORTED
146 + /* Fails right away if -perfect is given and transformation is not perfect.
147 + */
148 + if (transformoption.perfect &&
149 + !jtransform_perfect_transform(srcinfo.image_width, srcinfo.image_height,
150 + srcinfo.max_h_samp_factor * DCTSIZE, srcinfo.max_v_samp_factor * DCTSIZE,
151 + transformoption.transform)) {
152 + fprintf(stderr, "%s: transformation is not perfect\n", progname);
153 + exit(EXIT_FAILURE);
154 + }
155 jtransform_request_workspace(&srcinfo, &transformoption);
156 #endif
157
158 @@ -463,11 +486,32 @@
159 dst_coef_arrays = src_coef_arrays;
160 #endif
161
162 + /* Close input file, if we opened it.
163 + * Note: we assume that jpeg_read_coefficients consumed all input
164 + * until JPEG_REACHED_EOI, and that jpeg_finish_decompress will
165 + * only consume more while (! cinfo->inputctl->eoi_reached).
166 + * We cannot call jpeg_finish_decompress here since we still need the
167 + * virtual arrays allocated from the source object for processing.
168 + */
169 + if (fp != stdin)
170 + fclose(fp);
171 +
172 + /* Open the output file. */
173 + if (outfilename != NULL) {
174 + if ((fp = fopen(outfilename, WRITE_BINARY)) == NULL) {
175 + fprintf(stderr, "%s: can't open %s for writing\n", progname, outfilename);
176 + exit(EXIT_FAILURE);
177 + }
178 + } else {
179 + /* default output file is stdout */
180 + fp = write_stdout();
181 + }
182 +
183 /* Adjust default compression parameters by re-parsing the options */
184 file_index = parse_switches(&dstinfo, argc, argv, 0, TRUE);
185
186 /* Specify data destination for compression */
187 - jpeg_stdio_dest(&dstinfo, output_file);
188 + jpeg_stdio_dest(&dstinfo, fp);
189
190 /* Start compressor (note no image data is actually written here) */
191 jpeg_write_coefficients(&dstinfo, dst_coef_arrays);
192 @@ -488,11 +532,9 @@
193 (void) jpeg_finish_decompress(&srcinfo);
194 jpeg_destroy_decompress(&srcinfo);
195
196 - /* Close files, if we opened them */
197 - if (input_file != stdin)
198 - fclose(input_file);
199 - if (output_file != stdout)
200 - fclose(output_file);
201 + /* Close output file, if we opened it */
202 + if (fp != stdout)
203 + fclose(fp);
204
205 #ifdef PROGRESS_REPORT
206 end_progress_monitor((j_common_ptr) &dstinfo);
207 diff -urNad /home/bill/debian/libjpeg/libjpeg6b-6b/transupp.c libjpeg6b-6b/transupp.c
208 --- /home/bill/debian/libjpeg/libjpeg6b-6b/transupp.c 2003-09-22 18:15:49.000000000 +0200
209 +++ libjpeg6b-6b/transupp.c 2003-09-22 18:16:28.000000000 +0200
210 @@ -1,7 +1,7 @@
211 /*
212 * transupp.c
213 *
214 - * Copyright (C) 1997, Thomas G. Lane.
215 + * Copyright (C) 1997-2001, Thomas G. Lane.
216 * This file is part of the Independent JPEG Group's software.
217 * For conditions of distribution and use, see the accompanying README file.
218 *
219 @@ -20,6 +20,7 @@
220 #include "jinclude.h"
221 #include "jpeglib.h"
222 #include "transupp.h" /* My own external interface */
223 +#include <ctype.h> /* to declare isdigit() */
224
225
226 #if TRANSFORMS_SUPPORTED
227 @@ -28,7 +29,8 @@
228 * Lossless image transformation routines. These routines work on DCT
229 * coefficient arrays and thus do not require any lossy decompression
230 * or recompression of the image.
231 - * Thanks to Guido Vollbeding for the initial design and code of this feature.
232 + * Thanks to Guido Vollbeding for the initial design and code of this feature,
233 + * and to Ben Jackson for introducing the cropping feature.
234 *
235 * Horizontal flipping is done in-place, using a single top-to-bottom
236 * pass through the virtual source array. It will thus be much the
237 @@ -42,6 +44,13 @@
238 * arrays for most of the transforms. That could result in much thrashing
239 * if the image is larger than main memory.
240 *
241 + * If cropping or trimming is involved, the destination arrays may be smaller
242 + * than the source arrays. Note it is not possible to do horizontal flip
243 + * in-place when a nonzero Y crop offset is specified, since we'd have to move
244 + * data from one block row to another but the virtual array manager doesn't
245 + * guarantee we can touch more than one row at a time. So in that case,
246 + * we have to use a separate destination array.
247 + *
248 * Some notes about the operating environment of the individual transform
249 * routines:
250 * 1. Both the source and destination virtual arrays are allocated from the
251 @@ -54,20 +63,65 @@
252 * and we may as well take that as the effective iMCU size.
253 * 4. When "trim" is in effect, the destination's dimensions will be the
254 * trimmed values but the source's will be untrimmed.
255 - * 5. All the routines assume that the source and destination buffers are
256 + * 5. When "crop" is in effect, the destination's dimensions will be the
257 + * cropped values but the source's will be uncropped. Each transform
258 + * routine is responsible for picking up source data starting at the
259 + * correct X and Y offset for the crop region. (The X and Y offsets
260 + * passed to the transform routines are measured in iMCU blocks of the
261 + * destination.)
262 + * 6. All the routines assume that the source and destination buffers are
263 * padded out to a full iMCU boundary. This is true, although for the
264 * source buffer it is an undocumented property of jdcoefct.c.
265 - * Notes 2,3,4 boil down to this: generally we should use the destination's
266 - * dimensions and ignore the source's.
267 */
268
269
270 LOCAL(void)
271 -do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
272 - jvirt_barray_ptr *src_coef_arrays)
273 -/* Horizontal flip; done in-place, so no separate dest array is required */
274 +do_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
275 + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
276 + jvirt_barray_ptr *src_coef_arrays,
277 + jvirt_barray_ptr *dst_coef_arrays)
278 +/* Crop. This is only used when no rotate/flip is requested with the crop. */
279 {
280 - JDIMENSION MCU_cols, comp_width, blk_x, blk_y;
281 + JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks;
282 + int ci, offset_y;
283 + JBLOCKARRAY src_buffer, dst_buffer;
284 + jpeg_component_info *compptr;
285 +
286 + /* We simply have to copy the right amount of data (the destination's
287 + * image size) starting at the given X and Y offsets in the source.
288 + */
289 + for (ci = 0; ci < dstinfo->num_components; ci++) {
290 + compptr = dstinfo->comp_info + ci;
291 + x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
292 + y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
293 + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
294 + dst_blk_y += compptr->v_samp_factor) {
295 + dst_buffer = (*srcinfo->mem->access_virt_barray)
296 + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
297 + (JDIMENSION) compptr->v_samp_factor, TRUE);
298 + src_buffer = (*srcinfo->mem->access_virt_barray)
299 + ((j_common_ptr) srcinfo, src_coef_arrays[ci],
300 + dst_blk_y + y_crop_blocks,
301 + (JDIMENSION) compptr->v_samp_factor, FALSE);
302 + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
303 + jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
304 + dst_buffer[offset_y],
305 + compptr->width_in_blocks);
306 + }
307 + }
308 + }
309 +}
310 +
311 +
312 +LOCAL(void)
313 +do_flip_h_no_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
314 + JDIMENSION x_crop_offset,
315 + jvirt_barray_ptr *src_coef_arrays)
316 +/* Horizontal flip; done in-place, so no separate dest array is required.
317 + * NB: this only works when y_crop_offset is zero.
318 + */
319 +{
320 + JDIMENSION MCU_cols, comp_width, blk_x, blk_y, x_crop_blocks;
321 int ci, k, offset_y;
322 JBLOCKARRAY buffer;
323 JCOEFPTR ptr1, ptr2;
324 @@ -79,17 +133,19 @@
325 * mirroring by changing the signs of odd-numbered columns.
326 * Partial iMCUs at the right edge are left untouched.
327 */
328 - MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
329 + MCU_cols = srcinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
330
331 for (ci = 0; ci < dstinfo->num_components; ci++) {
332 compptr = dstinfo->comp_info + ci;
333 comp_width = MCU_cols * compptr->h_samp_factor;
334 + x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
335 for (blk_y = 0; blk_y < compptr->height_in_blocks;
336 blk_y += compptr->v_samp_factor) {
337 buffer = (*srcinfo->mem->access_virt_barray)
338 ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y,
339 (JDIMENSION) compptr->v_samp_factor, TRUE);
340 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
341 + /* Do the mirroring */
342 for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) {
343 ptr1 = buffer[offset_y][blk_x];
344 ptr2 = buffer[offset_y][comp_width - blk_x - 1];
345 @@ -105,6 +161,79 @@
346 *ptr2++ = -temp1;
347 }
348 }
349 + if (x_crop_blocks > 0) {
350 + /* Now left-justify the portion of the data to be kept.
351 + * We can't use a single jcopy_block_row() call because that routine
352 + * depends on memcpy(), whose behavior is unspecified for overlapping
353 + * source and destination areas. Sigh.
354 + */
355 + for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
356 + jcopy_block_row(buffer[offset_y] + blk_x + x_crop_blocks,
357 + buffer[offset_y] + blk_x,
358 + (JDIMENSION) 1);
359 + }
360 + }
361 + }
362 + }
363 + }
364 +}
365 +
366 +
367 +LOCAL(void)
368 +do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
369 + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
370 + jvirt_barray_ptr *src_coef_arrays,
371 + jvirt_barray_ptr *dst_coef_arrays)
372 +/* Horizontal flip in general cropping case */
373 +{
374 + JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
375 + JDIMENSION x_crop_blocks, y_crop_blocks;
376 + int ci, k, offset_y;
377 + JBLOCKARRAY src_buffer, dst_buffer;
378 + JBLOCKROW src_row_ptr, dst_row_ptr;
379 + JCOEFPTR src_ptr, dst_ptr;
380 + jpeg_component_info *compptr;
381 +
382 + /* Here we must output into a separate array because we can't touch
383 + * different rows of a single virtual array simultaneously. Otherwise,
384 + * this is essentially the same as the routine above.
385 + */
386 + MCU_cols = srcinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
387 +
388 + for (ci = 0; ci < dstinfo->num_components; ci++) {
389 + compptr = dstinfo->comp_info + ci;
390 + comp_width = MCU_cols * compptr->h_samp_factor;
391 + x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
392 + y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
393 + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
394 + dst_blk_y += compptr->v_samp_factor) {
395 + dst_buffer = (*srcinfo->mem->access_virt_barray)
396 + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
397 + (JDIMENSION) compptr->v_samp_factor, TRUE);
398 + src_buffer = (*srcinfo->mem->access_virt_barray)
399 + ((j_common_ptr) srcinfo, src_coef_arrays[ci],
400 + dst_blk_y + y_crop_blocks,
401 + (JDIMENSION) compptr->v_samp_factor, FALSE);
402 + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
403 + dst_row_ptr = dst_buffer[offset_y];
404 + src_row_ptr = src_buffer[offset_y];
405 + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
406 + if (x_crop_blocks + dst_blk_x < comp_width) {
407 + /* Do the mirrorable blocks */
408 + dst_ptr = dst_row_ptr[dst_blk_x];
409 + src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
410 + /* this unrolled loop doesn't need to know which row it's on... */
411 + for (k = 0; k < DCTSIZE2; k += 2) {
412 + *dst_ptr++ = *src_ptr++; /* copy even column */
413 + *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */
414 + }
415 + } else {
416 + /* Copy last partial block(s) verbatim */
417 + jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
418 + dst_row_ptr + dst_blk_x,
419 + (JDIMENSION) 1);
420 + }
421 + }
422 }
423 }
424 }
425 @@ -113,11 +242,13 @@
426
427 LOCAL(void)
428 do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
429 + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
430 jvirt_barray_ptr *src_coef_arrays,
431 jvirt_barray_ptr *dst_coef_arrays)
432 /* Vertical flip */
433 {
434 JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
435 + JDIMENSION x_crop_blocks, y_crop_blocks;
436 int ci, i, j, offset_y;
437 JBLOCKARRAY src_buffer, dst_buffer;
438 JBLOCKROW src_row_ptr, dst_row_ptr;
439 @@ -131,33 +262,38 @@
440 * of odd-numbered rows.
441 * Partial iMCUs at the bottom edge are copied verbatim.
442 */
443 - MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
444 + MCU_rows = srcinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
445
446 for (ci = 0; ci < dstinfo->num_components; ci++) {
447 compptr = dstinfo->comp_info + ci;
448 comp_height = MCU_rows * compptr->v_samp_factor;
449 + x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
450 + y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
451 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
452 dst_blk_y += compptr->v_samp_factor) {
453 dst_buffer = (*srcinfo->mem->access_virt_barray)
454 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
455 (JDIMENSION) compptr->v_samp_factor, TRUE);
456 - if (dst_blk_y < comp_height) {
457 + if (y_crop_blocks + dst_blk_y < comp_height) {
458 /* Row is within the mirrorable area. */
459 src_buffer = (*srcinfo->mem->access_virt_barray)
460 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
461 - comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor,
462 + comp_height - y_crop_blocks - dst_blk_y -
463 + (JDIMENSION) compptr->v_samp_factor,
464 (JDIMENSION) compptr->v_samp_factor, FALSE);
465 } else {
466 /* Bottom-edge blocks will be copied verbatim. */
467 src_buffer = (*srcinfo->mem->access_virt_barray)
468 - ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y,
469 + ((j_common_ptr) srcinfo, src_coef_arrays[ci],
470 + dst_blk_y + y_crop_blocks,
471 (JDIMENSION) compptr->v_samp_factor, FALSE);
472 }
473 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
474 - if (dst_blk_y < comp_height) {
475 + if (y_crop_blocks + dst_blk_y < comp_height) {
476 /* Row is within the mirrorable area. */
477 dst_row_ptr = dst_buffer[offset_y];
478 src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
479 + src_row_ptr += x_crop_blocks;
480 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
481 dst_blk_x++) {
482 dst_ptr = dst_row_ptr[dst_blk_x];
483 @@ -173,7 +309,8 @@
484 }
485 } else {
486 /* Just copy row verbatim. */
487 - jcopy_block_row(src_buffer[offset_y], dst_buffer[offset_y],
488 + jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
489 + dst_buffer[offset_y],
490 compptr->width_in_blocks);
491 }
492 }
493 @@ -184,11 +321,12 @@
494
495 LOCAL(void)
496 do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
497 + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
498 jvirt_barray_ptr *src_coef_arrays,
499 jvirt_barray_ptr *dst_coef_arrays)
500 /* Transpose source into destination */
501 {
502 - JDIMENSION dst_blk_x, dst_blk_y;
503 + JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks;
504 int ci, i, j, offset_x, offset_y;
505 JBLOCKARRAY src_buffer, dst_buffer;
506 JCOEFPTR src_ptr, dst_ptr;
507 @@ -201,6 +339,8 @@
508 */
509 for (ci = 0; ci < dstinfo->num_components; ci++) {
510 compptr = dstinfo->comp_info + ci;
511 + x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
512 + y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
513 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
514 dst_blk_y += compptr->v_samp_factor) {
515 dst_buffer = (*srcinfo->mem->access_virt_barray)
516 @@ -210,11 +350,12 @@
517 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
518 dst_blk_x += compptr->h_samp_factor) {
519 src_buffer = (*srcinfo->mem->access_virt_barray)
520 - ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
521 + ((j_common_ptr) srcinfo, src_coef_arrays[ci],
522 + dst_blk_x + x_crop_blocks,
523 (JDIMENSION) compptr->h_samp_factor, FALSE);
524 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
525 - src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
526 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
527 + src_ptr = src_buffer[offset_x][dst_blk_y + offset_y + y_crop_blocks];
528 for (i = 0; i < DCTSIZE; i++)
529 for (j = 0; j < DCTSIZE; j++)
530 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
531 @@ -228,6 +369,7 @@
532
533 LOCAL(void)
534 do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
535 + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
536 jvirt_barray_ptr *src_coef_arrays,
537 jvirt_barray_ptr *dst_coef_arrays)
538 /* 90 degree rotation is equivalent to
539 @@ -237,6 +379,7 @@
540 */
541 {
542 JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
543 + JDIMENSION x_crop_blocks, y_crop_blocks;
544 int ci, i, j, offset_x, offset_y;
545 JBLOCKARRAY src_buffer, dst_buffer;
546 JCOEFPTR src_ptr, dst_ptr;
547 @@ -246,11 +389,13 @@
548 * at the (output) right edge properly. They just get transposed and
549 * not mirrored.
550 */
551 - MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
552 + MCU_cols = srcinfo->image_height / (dstinfo->max_h_samp_factor * DCTSIZE);
553
554 for (ci = 0; ci < dstinfo->num_components; ci++) {
555 compptr = dstinfo->comp_info + ci;
556 comp_width = MCU_cols * compptr->h_samp_factor;
557 + x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
558 + y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
559 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
560 dst_blk_y += compptr->v_samp_factor) {
561 dst_buffer = (*srcinfo->mem->access_virt_barray)
562 @@ -259,15 +404,26 @@
563 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
564 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
565 dst_blk_x += compptr->h_samp_factor) {
566 - src_buffer = (*srcinfo->mem->access_virt_barray)
567 - ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
568 - (JDIMENSION) compptr->h_samp_factor, FALSE);
569 + if (x_crop_blocks + dst_blk_x < comp_width) {
570 + /* Block is within the mirrorable area. */
571 + src_buffer = (*srcinfo->mem->access_virt_barray)
572 + ((j_common_ptr) srcinfo, src_coef_arrays[ci],
573 + comp_width - x_crop_blocks - dst_blk_x -
574 + (JDIMENSION) compptr->h_samp_factor,
575 + (JDIMENSION) compptr->h_samp_factor, FALSE);
576 + } else {
577 + /* Edge blocks are transposed but not mirrored. */
578 + src_buffer = (*srcinfo->mem->access_virt_barray)
579 + ((j_common_ptr) srcinfo, src_coef_arrays[ci],
580 + dst_blk_x + x_crop_blocks,
581 + (JDIMENSION) compptr->h_samp_factor, FALSE);
582 + }
583 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
584 - src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
585 - if (dst_blk_x < comp_width) {
586 + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
587 + if (x_crop_blocks + dst_blk_x < comp_width) {
588 /* Block is within the mirrorable area. */
589 - dst_ptr = dst_buffer[offset_y]
590 - [comp_width - dst_blk_x - offset_x - 1];
591 + src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
592 + [dst_blk_y + offset_y + y_crop_blocks];
593 for (i = 0; i < DCTSIZE; i++) {
594 for (j = 0; j < DCTSIZE; j++)
595 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
596 @@ -277,7 +433,8 @@
597 }
598 } else {
599 /* Edge blocks are transposed but not mirrored. */
600 - dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
601 + src_ptr = src_buffer[offset_x]
602 + [dst_blk_y + offset_y + y_crop_blocks];
603 for (i = 0; i < DCTSIZE; i++)
604 for (j = 0; j < DCTSIZE; j++)
605 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
606 @@ -292,6 +449,7 @@
607
608 LOCAL(void)
609 do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
610 + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
611 jvirt_barray_ptr *src_coef_arrays,
612 jvirt_barray_ptr *dst_coef_arrays)
613 /* 270 degree rotation is equivalent to
614 @@ -301,6 +459,7 @@
615 */
616 {
617 JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
618 + JDIMENSION x_crop_blocks, y_crop_blocks;
619 int ci, i, j, offset_x, offset_y;
620 JBLOCKARRAY src_buffer, dst_buffer;
621 JCOEFPTR src_ptr, dst_ptr;
622 @@ -310,11 +469,13 @@
623 * at the (output) bottom edge properly. They just get transposed and
624 * not mirrored.
625 */
626 - MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
627 + MCU_rows = srcinfo->image_width / (dstinfo->max_v_samp_factor * DCTSIZE);
628
629 for (ci = 0; ci < dstinfo->num_components; ci++) {
630 compptr = dstinfo->comp_info + ci;
631 comp_height = MCU_rows * compptr->v_samp_factor;
632 + x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
633 + y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
634 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
635 dst_blk_y += compptr->v_samp_factor) {
636 dst_buffer = (*srcinfo->mem->access_virt_barray)
637 @@ -324,14 +485,15 @@
638 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
639 dst_blk_x += compptr->h_samp_factor) {
640 src_buffer = (*srcinfo->mem->access_virt_barray)
641 - ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
642 + ((j_common_ptr) srcinfo, src_coef_arrays[ci],
643 + dst_blk_x + x_crop_blocks,
644 (JDIMENSION) compptr->h_samp_factor, FALSE);
645 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
646 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
647 - if (dst_blk_y < comp_height) {
648 + if (y_crop_blocks + dst_blk_y < comp_height) {
649 /* Block is within the mirrorable area. */
650 src_ptr = src_buffer[offset_x]
651 - [comp_height - dst_blk_y - offset_y - 1];
652 + [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
653 for (i = 0; i < DCTSIZE; i++) {
654 for (j = 0; j < DCTSIZE; j++) {
655 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
656 @@ -341,7 +503,8 @@
657 }
658 } else {
659 /* Edge blocks are transposed but not mirrored. */
660 - src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
661 + src_ptr = src_buffer[offset_x]
662 + [dst_blk_y + offset_y + y_crop_blocks];
663 for (i = 0; i < DCTSIZE; i++)
664 for (j = 0; j < DCTSIZE; j++)
665 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
666 @@ -356,6 +519,7 @@
667
668 LOCAL(void)
669 do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
670 + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
671 jvirt_barray_ptr *src_coef_arrays,
672 jvirt_barray_ptr *dst_coef_arrays)
673 /* 180 degree rotation is equivalent to
674 @@ -365,89 +529,93 @@
675 */
676 {
677 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
678 + JDIMENSION x_crop_blocks, y_crop_blocks;
679 int ci, i, j, offset_y;
680 JBLOCKARRAY src_buffer, dst_buffer;
681 JBLOCKROW src_row_ptr, dst_row_ptr;
682 JCOEFPTR src_ptr, dst_ptr;
683 jpeg_component_info *compptr;
684
685 - MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
686 - MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
687 + MCU_cols = srcinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
688 + MCU_rows = srcinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
689
690 for (ci = 0; ci < dstinfo->num_components; ci++) {
691 compptr = dstinfo->comp_info + ci;
692 comp_width = MCU_cols * compptr->h_samp_factor;
693 comp_height = MCU_rows * compptr->v_samp_factor;
694 + x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
695 + y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
696 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
697 dst_blk_y += compptr->v_samp_factor) {
698 dst_buffer = (*srcinfo->mem->access_virt_barray)
699 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
700 (JDIMENSION) compptr->v_samp_factor, TRUE);
701 - if (dst_blk_y < comp_height) {
702 + if (y_crop_blocks + dst_blk_y < comp_height) {
703 /* Row is within the vertically mirrorable area. */
704 src_buffer = (*srcinfo->mem->access_virt_barray)
705 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
706 - comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor,
707 + comp_height - y_crop_blocks - dst_blk_y -
708 + (JDIMENSION) compptr->v_samp_factor,
709 (JDIMENSION) compptr->v_samp_factor, FALSE);
710 } else {
711 /* Bottom-edge rows are only mirrored horizontally. */
712 src_buffer = (*srcinfo->mem->access_virt_barray)
713 - ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y,
714 + ((j_common_ptr) srcinfo, src_coef_arrays[ci],
715 + dst_blk_y + y_crop_blocks,
716 (JDIMENSION) compptr->v_samp_factor, FALSE);
717 }
718 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
719 - if (dst_blk_y < comp_height) {
720 + dst_row_ptr = dst_buffer[offset_y];
721 + if (y_crop_blocks + dst_blk_y < comp_height) {
722 /* Row is within the mirrorable area. */
723 - dst_row_ptr = dst_buffer[offset_y];
724 src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
725 - /* Process the blocks that can be mirrored both ways. */
726 - for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) {
727 + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
728 dst_ptr = dst_row_ptr[dst_blk_x];
729 - src_ptr = src_row_ptr[comp_width - dst_blk_x - 1];
730 - for (i = 0; i < DCTSIZE; i += 2) {
731 - /* For even row, negate every odd column. */
732 - for (j = 0; j < DCTSIZE; j += 2) {
733 - *dst_ptr++ = *src_ptr++;
734 - *dst_ptr++ = - *src_ptr++;
735 + if (x_crop_blocks + dst_blk_x < comp_width) {
736 + /* Process the blocks that can be mirrored both ways. */
737 + src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
738 + for (i = 0; i < DCTSIZE; i += 2) {
739 + /* For even row, negate every odd column. */
740 + for (j = 0; j < DCTSIZE; j += 2) {
741 + *dst_ptr++ = *src_ptr++;
742 + *dst_ptr++ = - *src_ptr++;
743 + }
744 + /* For odd row, negate every even column. */
745 + for (j = 0; j < DCTSIZE; j += 2) {
746 + *dst_ptr++ = - *src_ptr++;
747 + *dst_ptr++ = *src_ptr++;
748 + }
749 }
750 - /* For odd row, negate every even column. */
751 - for (j = 0; j < DCTSIZE; j += 2) {
752 - *dst_ptr++ = - *src_ptr++;
753 - *dst_ptr++ = *src_ptr++;
754 + } else {
755 + /* Any remaining right-edge blocks are only mirrored vertically. */
756 + src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x];
757 + for (i = 0; i < DCTSIZE; i += 2) {
758 + for (j = 0; j < DCTSIZE; j++)
759 + *dst_ptr++ = *src_ptr++;
760 + for (j = 0; j < DCTSIZE; j++)
761 + *dst_ptr++ = - *src_ptr++;
762 }
763 }
764 }
765 - /* Any remaining right-edge blocks are only mirrored vertically. */
766 - for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
767 - dst_ptr = dst_row_ptr[dst_blk_x];
768 - src_ptr = src_row_ptr[dst_blk_x];
769 - for (i = 0; i < DCTSIZE; i += 2) {
770 - for (j = 0; j < DCTSIZE; j++)
771 - *dst_ptr++ = *src_ptr++;
772 - for (j = 0; j < DCTSIZE; j++)
773 - *dst_ptr++ = - *src_ptr++;
774 - }
775 - }
776 } else {
777 /* Remaining rows are just mirrored horizontally. */
778 - dst_row_ptr = dst_buffer[offset_y];
779 src_row_ptr = src_buffer[offset_y];
780 - /* Process the blocks that can be mirrored. */
781 - for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) {
782 - dst_ptr = dst_row_ptr[dst_blk_x];
783 - src_ptr = src_row_ptr[comp_width - dst_blk_x - 1];
784 - for (i = 0; i < DCTSIZE2; i += 2) {
785 - *dst_ptr++ = *src_ptr++;
786 - *dst_ptr++ = - *src_ptr++;
787 + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
788 + if (x_crop_blocks + dst_blk_x < comp_width) {
789 + /* Process the blocks that can be mirrored. */
790 + dst_ptr = dst_row_ptr[dst_blk_x];
791 + src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
792 + for (i = 0; i < DCTSIZE2; i += 2) {
793 + *dst_ptr++ = *src_ptr++;
794 + *dst_ptr++ = - *src_ptr++;
795 + }
796 + } else {
797 + /* Any remaining right-edge blocks are only copied. */
798 + jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
799 + dst_row_ptr + dst_blk_x,
800 + (JDIMENSION) 1);
801 }
802 }
803 - /* Any remaining right-edge blocks are only copied. */
804 - for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
805 - dst_ptr = dst_row_ptr[dst_blk_x];
806 - src_ptr = src_row_ptr[dst_blk_x];
807 - for (i = 0; i < DCTSIZE2; i++)
808 - *dst_ptr++ = *src_ptr++;
809 - }
810 }
811 }
812 }
813 @@ -457,6 +625,7 @@
814
815 LOCAL(void)
816 do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
817 + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
818 jvirt_barray_ptr *src_coef_arrays,
819 jvirt_barray_ptr *dst_coef_arrays)
820 /* Transverse transpose is equivalent to
821 @@ -470,18 +639,21 @@
822 */
823 {
824 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
825 + JDIMENSION x_crop_blocks, y_crop_blocks;
826 int ci, i, j, offset_x, offset_y;
827 JBLOCKARRAY src_buffer, dst_buffer;
828 JCOEFPTR src_ptr, dst_ptr;
829 jpeg_component_info *compptr;
830
831 - MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
832 - MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
833 + MCU_cols = srcinfo->image_height / (dstinfo->max_h_samp_factor * DCTSIZE);
834 + MCU_rows = srcinfo->image_width / (dstinfo->max_v_samp_factor * DCTSIZE);
835
836 for (ci = 0; ci < dstinfo->num_components; ci++) {
837 compptr = dstinfo->comp_info + ci;
838 comp_width = MCU_cols * compptr->h_samp_factor;
839 comp_height = MCU_rows * compptr->v_samp_factor;
840 + x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
841 + y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
842 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
843 dst_blk_y += compptr->v_samp_factor) {
844 dst_buffer = (*srcinfo->mem->access_virt_barray)
845 @@ -490,17 +662,26 @@
846 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
847 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
848 dst_blk_x += compptr->h_samp_factor) {
849 - src_buffer = (*srcinfo->mem->access_virt_barray)
850 - ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
851 - (JDIMENSION) compptr->h_samp_factor, FALSE);
852 + if (x_crop_blocks + dst_blk_x < comp_width) {
853 + /* Block is within the mirrorable area. */
854 + src_buffer = (*srcinfo->mem->access_virt_barray)
855 + ((j_common_ptr) srcinfo, src_coef_arrays[ci],
856 + comp_width - x_crop_blocks - dst_blk_x -
857 + (JDIMENSION) compptr->h_samp_factor,
858 + (JDIMENSION) compptr->h_samp_factor, FALSE);
859 + } else {
860 + src_buffer = (*srcinfo->mem->access_virt_barray)
861 + ((j_common_ptr) srcinfo, src_coef_arrays[ci],
862 + dst_blk_x + x_crop_blocks,
863 + (JDIMENSION) compptr->h_samp_factor, FALSE);
864 + }
865 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
866 - if (dst_blk_y < comp_height) {
867 - src_ptr = src_buffer[offset_x]
868 - [comp_height - dst_blk_y - offset_y - 1];
869 - if (dst_blk_x < comp_width) {
870 + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
871 + if (y_crop_blocks + dst_blk_y < comp_height) {
872 + if (x_crop_blocks + dst_blk_x < comp_width) {
873 /* Block is within the mirrorable area. */
874 - dst_ptr = dst_buffer[offset_y]
875 - [comp_width - dst_blk_x - offset_x - 1];
876 + src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
877 + [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
878 for (i = 0; i < DCTSIZE; i++) {
879 for (j = 0; j < DCTSIZE; j++) {
880 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
881 @@ -516,7 +697,8 @@
882 }
883 } else {
884 /* Right-edge blocks are mirrored in y only */
885 - dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
886 + src_ptr = src_buffer[offset_x]
887 + [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
888 for (i = 0; i < DCTSIZE; i++) {
889 for (j = 0; j < DCTSIZE; j++) {
890 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
891 @@ -526,11 +708,10 @@
892 }
893 }
894 } else {
895 - src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
896 - if (dst_blk_x < comp_width) {
897 + if (x_crop_blocks + dst_blk_x < comp_width) {
898 /* Bottom-edge blocks are mirrored in x only */
899 - dst_ptr = dst_buffer[offset_y]
900 - [comp_width - dst_blk_x - offset_x - 1];
901 + src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
902 + [dst_blk_y + offset_y + y_crop_blocks];
903 for (i = 0; i < DCTSIZE; i++) {
904 for (j = 0; j < DCTSIZE; j++)
905 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
906 @@ -540,7 +721,8 @@
907 }
908 } else {
909 /* At lower right corner, just transpose, no mirroring */
910 - dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
911 + src_ptr = src_buffer[offset_x]
912 + [dst_blk_y + offset_y + y_crop_blocks];
913 for (i = 0; i < DCTSIZE; i++)
914 for (j = 0; j < DCTSIZE; j++)
915 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
916 @@ -554,8 +736,116 @@
917 }
918
919
920 +/* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec.
921 + * Returns TRUE if valid integer found, FALSE if not.
922 + * *strptr is advanced over the digit string, and *result is set to its value.
923 + */
924 +
925 +LOCAL(boolean)
926 +jt_read_integer (const char ** strptr, JDIMENSION * result)
927 +{
928 + const char * ptr = *strptr;
929 + JDIMENSION val = 0;
930 +
931 + for (; isdigit(*ptr); ptr++) {
932 + val = val * 10 + (JDIMENSION) (*ptr - '0');
933 + }
934 + *result = val;
935 + if (ptr == *strptr)
936 + return FALSE; /* oops, no digits */
937 + *strptr = ptr;
938 + return TRUE;
939 +}
940 +
941 +
942 +/* Parse a crop specification (written in X11 geometry style).
943 + * The routine returns TRUE if the spec string is valid, FALSE if not.
944 + *
945 + * The crop spec string should have the format
946 + * <width>x<height>{+-}<xoffset>{+-}<yoffset>
947 + * where width, height, xoffset, and yoffset are unsigned integers.
948 + * Each of the elements can be omitted to indicate a default value.
949 + * (A weakness of this style is that it is not possible to omit xoffset
950 + * while specifying yoffset, since they look alike.)
951 + *
952 + * This code is loosely based on XParseGeometry from the X11 distribution.
953 + */
954 +
955 +GLOBAL(boolean)
956 +jtransform_parse_crop_spec (jpeg_transform_info *info, const char *spec)
957 +{
958 + info->crop = FALSE;
959 + info->crop_width_set = JCROP_UNSET;
960 + info->crop_height_set = JCROP_UNSET;
961 + info->crop_xoffset_set = JCROP_UNSET;
962 + info->crop_yoffset_set = JCROP_UNSET;
963 +
964 + if (isdigit(*spec)) {
965 + /* fetch width */
966 + if (! jt_read_integer(&spec, &info->crop_width))
967 + return FALSE;
968 + info->crop_width_set = JCROP_POS;
969 + }
970 + if (*spec == 'x' || *spec == 'X') {
971 + /* fetch height */
972 + spec++;
973 + if (! jt_read_integer(&spec, &info->crop_height))
974 + return FALSE;
975 + info->crop_height_set = JCROP_POS;
976 + }
977 + if (*spec == '+' || *spec == '-') {
978 + /* fetch xoffset */
979 + info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
980 + spec++;
981 + if (! jt_read_integer(&spec, &info->crop_xoffset))
982 + return FALSE;
983 + }
984 + if (*spec == '+' || *spec == '-') {
985 + /* fetch yoffset */
986 + info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
987 + spec++;
988 + if (! jt_read_integer(&spec, &info->crop_yoffset))
989 + return FALSE;
990 + }
991 + /* We had better have gotten to the end of the string. */
992 + if (*spec != '\0')
993 + return FALSE;
994 + info->crop = TRUE;
995 + return TRUE;
996 +}
997 +
998 +
999 +/* Trim off any partial iMCUs on the indicated destination edge */
1000 +
1001 +LOCAL(void)
1002 +trim_right_edge (jpeg_transform_info *info, JDIMENSION full_width)
1003 +{
1004 + JDIMENSION MCU_cols;
1005 +
1006 + MCU_cols = info->output_width / (info->max_h_samp_factor * DCTSIZE);
1007 + if (MCU_cols > 0 && info->x_crop_offset + MCU_cols ==
1008 + full_width / (info->max_h_samp_factor * DCTSIZE))
1009 + info->output_width = MCU_cols * (info->max_h_samp_factor * DCTSIZE);
1010 +}
1011 +
1012 +LOCAL(void)
1013 +trim_bottom_edge (jpeg_transform_info *info, JDIMENSION full_height)
1014 +{
1015 + JDIMENSION MCU_rows;
1016 +
1017 + MCU_rows = info->output_height / (info->max_v_samp_factor * DCTSIZE);
1018 + if (MCU_rows > 0 && info->y_crop_offset + MCU_rows ==
1019 + full_height / (info->max_v_samp_factor * DCTSIZE))
1020 + info->output_height = MCU_rows * (info->max_v_samp_factor * DCTSIZE);
1021 +}
1022 +
1023 +
1024 /* Request any required workspace.
1025 *
1026 + * This routine figures out the size that the output image will be
1027 + * (which implies that all the transform parameters must be set before
1028 + * it is called).
1029 + *
1030 * We allocate the workspace virtual arrays from the source decompression
1031 * object, so that all the arrays (both the original data and the workspace)
1032 * will be taken into account while making memory management decisions.
1033 @@ -569,9 +859,13 @@
1034 jpeg_transform_info *info)
1035 {
1036 jvirt_barray_ptr *coef_arrays = NULL;
1037 + boolean need_workspace, transpose_it;
1038 jpeg_component_info *compptr;
1039 - int ci;
1040 + JDIMENSION xoffset, yoffset, width_in_iMCUs, height_in_iMCUs;
1041 + JDIMENSION width_in_blocks, height_in_blocks;
1042 + int ci, h_samp_factor, v_samp_factor;
1043
1044 + /* Determine number of components in output image */
1045 if (info->force_grayscale &&
1046 srcinfo->jpeg_color_space == JCS_YCbCr &&
1047 srcinfo->num_components == 3) {
1048 @@ -581,55 +875,181 @@
1049 /* Process all the components */
1050 info->num_components = srcinfo->num_components;
1051 }
1052 + /* If there is only one output component, force the iMCU size to be 1;
1053 + * else use the source iMCU size. (This allows us to do the right thing
1054 + * when reducing color to grayscale, and also provides a handy way of
1055 + * cleaning up "funny" grayscale images whose sampling factors are not 1x1.)
1056 + */
1057
1058 switch (info->transform) {
1059 + case JXFORM_TRANSPOSE:
1060 + case JXFORM_TRANSVERSE:
1061 + case JXFORM_ROT_90:
1062 + case JXFORM_ROT_270:
1063 + info->output_width = srcinfo->image_height;
1064 + info->output_height = srcinfo->image_width;
1065 + if (info->num_components == 1) {
1066 + info->max_h_samp_factor = 1;
1067 + info->max_v_samp_factor = 1;
1068 + } else {
1069 + info->max_h_samp_factor = srcinfo->max_v_samp_factor;
1070 + info->max_v_samp_factor = srcinfo->max_h_samp_factor;
1071 + }
1072 + break;
1073 + default:
1074 + info->output_width = srcinfo->image_width;
1075 + info->output_height = srcinfo->image_height;
1076 + if (info->num_components == 1) {
1077 + info->max_h_samp_factor = 1;
1078 + info->max_v_samp_factor = 1;
1079 + } else {
1080 + info->max_h_samp_factor = srcinfo->max_h_samp_factor;
1081 + info->max_v_samp_factor = srcinfo->max_v_samp_factor;
1082 + }
1083 + break;
1084 + }
1085 +
1086 + /* If cropping has been requested, compute the crop area's position and
1087 + * dimensions, ensuring that its upper left corner falls at an iMCU boundary.
1088 + */
1089 + if (info->crop) {
1090 + /* Insert default values for unset crop parameters */
1091 + if (info->crop_xoffset_set == JCROP_UNSET)
1092 + info->crop_xoffset = 0; /* default to +0 */
1093 + if (info->crop_yoffset_set == JCROP_UNSET)
1094 + info->crop_yoffset = 0; /* default to +0 */
1095 + if (info->crop_xoffset >= info->output_width ||
1096 + info->crop_yoffset >= info->output_height)
1097 + ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1098 + if (info->crop_width_set == JCROP_UNSET)
1099 + info->crop_width = info->output_width - info->crop_xoffset;
1100 + if (info->crop_height_set == JCROP_UNSET)
1101 + info->crop_height = info->output_height - info->crop_yoffset;
1102 + /* Ensure parameters are valid */
1103 + if (info->crop_width <= 0 || info->crop_width > info->output_width ||
1104 + info->crop_height <= 0 || info->crop_height > info->output_height ||
1105 + info->crop_xoffset > info->output_width - info->crop_width ||
1106 + info->crop_yoffset > info->output_height - info->crop_height)
1107 + ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1108 + /* Convert negative crop offsets into regular offsets */
1109 + if (info->crop_xoffset_set == JCROP_NEG)
1110 + xoffset = info->output_width - info->crop_width - info->crop_xoffset;
1111 + else
1112 + xoffset = info->crop_xoffset;
1113 + if (info->crop_yoffset_set == JCROP_NEG)
1114 + yoffset = info->output_height - info->crop_height - info->crop_yoffset;
1115 + else
1116 + yoffset = info->crop_yoffset;
1117 + /* Now adjust so that upper left corner falls at an iMCU boundary */
1118 + info->output_width =
1119 + info->crop_width + (xoffset % (info->max_h_samp_factor * DCTSIZE));
1120 + info->output_height =
1121 + info->crop_height + (yoffset % (info->max_v_samp_factor * DCTSIZE));
1122 + /* Save x/y offsets measured in iMCUs */
1123 + info->x_crop_offset = xoffset / (info->max_h_samp_factor * DCTSIZE);
1124 + info->y_crop_offset = yoffset / (info->max_v_samp_factor * DCTSIZE);
1125 + } else {
1126 + info->x_crop_offset = 0;
1127 + info->y_crop_offset = 0;
1128 + }
1129 +
1130 + /* Figure out whether we need workspace arrays,
1131 + * and if so whether they are transposed relative to the source.
1132 + */
1133 + need_workspace = FALSE;
1134 + transpose_it = FALSE;
1135 + switch (info->transform) {
1136 case JXFORM_NONE:
1137 + if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
1138 + need_workspace = TRUE;
1139 + /* No workspace needed if neither cropping nor transforming */
1140 + break;
1141 case JXFORM_FLIP_H:
1142 - /* Don't need a workspace array */
1143 + if (info->trim)
1144 + trim_right_edge(info, srcinfo->image_width);
1145 + if (info->y_crop_offset != 0)
1146 + need_workspace = TRUE;
1147 + /* do_flip_h_no_crop doesn't need a workspace array */
1148 break;
1149 case JXFORM_FLIP_V:
1150 - case JXFORM_ROT_180:
1151 - /* Need workspace arrays having same dimensions as source image.
1152 - * Note that we allocate arrays padded out to the next iMCU boundary,
1153 - * so that transform routines need not worry about missing edge blocks.
1154 - */
1155 - coef_arrays = (jvirt_barray_ptr *)
1156 - (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
1157 - SIZEOF(jvirt_barray_ptr) * info->num_components);
1158 - for (ci = 0; ci < info->num_components; ci++) {
1159 - compptr = srcinfo->comp_info + ci;
1160 - coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
1161 - ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
1162 - (JDIMENSION) jround_up((long) compptr->width_in_blocks,
1163 - (long) compptr->h_samp_factor),
1164 - (JDIMENSION) jround_up((long) compptr->height_in_blocks,
1165 - (long) compptr->v_samp_factor),
1166 - (JDIMENSION) compptr->v_samp_factor);
1167 - }
1168 + if (info->trim)
1169 + trim_bottom_edge(info, srcinfo->image_height);
1170 + /* Need workspace arrays having same dimensions as source image. */
1171 + need_workspace = TRUE;
1172 break;
1173 case JXFORM_TRANSPOSE:
1174 + /* transpose does NOT have to trim anything */
1175 + /* Need workspace arrays having transposed dimensions. */
1176 + need_workspace = TRUE;
1177 + transpose_it = TRUE;
1178 + break;
1179 case JXFORM_TRANSVERSE:
1180 + if (info->trim) {
1181 + trim_right_edge(info, srcinfo->image_height);
1182 + trim_bottom_edge(info, srcinfo->image_width);
1183 + }
1184 + /* Need workspace arrays having transposed dimensions. */
1185 + need_workspace = TRUE;
1186 + transpose_it = TRUE;
1187 + break;
1188 case JXFORM_ROT_90:
1189 + if (info->trim)
1190 + trim_right_edge(info, srcinfo->image_height);
1191 + /* Need workspace arrays having transposed dimensions. */
1192 + need_workspace = TRUE;
1193 + transpose_it = TRUE;
1194 + break;
1195 + case JXFORM_ROT_180:
1196 + if (info->trim) {
1197 + trim_right_edge(info, srcinfo->image_width);
1198 + trim_bottom_edge(info, srcinfo->image_height);
1199 + }
1200 + /* Need workspace arrays having same dimensions as source image. */
1201 + need_workspace = TRUE;
1202 + break;
1203 case JXFORM_ROT_270:
1204 - /* Need workspace arrays having transposed dimensions.
1205 - * Note that we allocate arrays padded out to the next iMCU boundary,
1206 - * so that transform routines need not worry about missing edge blocks.
1207 - */
1208 + if (info->trim)
1209 + trim_bottom_edge(info, srcinfo->image_width);
1210 + /* Need workspace arrays having transposed dimensions. */
1211 + need_workspace = TRUE;
1212 + transpose_it = TRUE;
1213 + break;
1214 + }
1215 +
1216 + /* Allocate workspace if needed.
1217 + * Note that we allocate arrays padded out to the next iMCU boundary,
1218 + * so that transform routines need not worry about missing edge blocks.
1219 + */
1220 + if (need_workspace) {
1221 coef_arrays = (jvirt_barray_ptr *)
1222 (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
1223 - SIZEOF(jvirt_barray_ptr) * info->num_components);
1224 + SIZEOF(jvirt_barray_ptr) * info->num_components);
1225 + width_in_iMCUs = (JDIMENSION)
1226 + jdiv_round_up((long) info->output_width,
1227 + (long) (info->max_h_samp_factor * DCTSIZE));
1228 + height_in_iMCUs = (JDIMENSION)
1229 + jdiv_round_up((long) info->output_height,
1230 + (long) (info->max_v_samp_factor * DCTSIZE));
1231 for (ci = 0; ci < info->num_components; ci++) {
1232 compptr = srcinfo->comp_info + ci;
1233 + if (info->num_components == 1) {
1234 + /* we're going to force samp factors to 1x1 in this case */
1235 + h_samp_factor = v_samp_factor = 1;
1236 + } else if (transpose_it) {
1237 + h_samp_factor = compptr->v_samp_factor;
1238 + v_samp_factor = compptr->h_samp_factor;
1239 + } else {
1240 + h_samp_factor = compptr->h_samp_factor;
1241 + v_samp_factor = compptr->v_samp_factor;
1242 + }
1243 + width_in_blocks = width_in_iMCUs * h_samp_factor;
1244 + height_in_blocks = height_in_iMCUs * v_samp_factor;
1245 coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
1246 ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
1247 - (JDIMENSION) jround_up((long) compptr->height_in_blocks,
1248 - (long) compptr->v_samp_factor),
1249 - (JDIMENSION) jround_up((long) compptr->width_in_blocks,
1250 - (long) compptr->h_samp_factor),
1251 - (JDIMENSION) compptr->h_samp_factor);
1252 + width_in_blocks, height_in_blocks, (JDIMENSION) v_samp_factor);
1253 }
1254 - break;
1255 }
1256 +
1257 info->workspace_coef_arrays = coef_arrays;
1258 }
1259
1260 @@ -642,14 +1062,8 @@
1261 int tblno, i, j, ci, itemp;
1262 jpeg_component_info *compptr;
1263 JQUANT_TBL *qtblptr;
1264 - JDIMENSION dtemp;
1265 UINT16 qtemp;
1266
1267 - /* Transpose basic image dimensions */
1268 - dtemp = dstinfo->image_width;
1269 - dstinfo->image_width = dstinfo->image_height;
1270 - dstinfo->image_height = dtemp;
1271 -
1272 /* Transpose sampling factors */
1273 for (ci = 0; ci < dstinfo->num_components; ci++) {
1274 compptr = dstinfo->comp_info + ci;
1275 @@ -674,46 +1088,159 @@
1276 }
1277
1278
1279 -/* Trim off any partial iMCUs on the indicated destination edge */
1280 +/* Adjust Exif image parameters.
1281 + *
1282 + * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible.
1283 + */
1284
1285 LOCAL(void)
1286 -trim_right_edge (j_compress_ptr dstinfo)
1287 +adjust_exif_parameters (JOCTET FAR * data, unsigned int length,
1288 + JDIMENSION new_width, JDIMENSION new_height)
1289 {
1290 - int ci, max_h_samp_factor;
1291 - JDIMENSION MCU_cols;
1292 + boolean is_motorola; /* Flag for byte order */
1293 + unsigned int number_of_tags, tagnum;
1294 + unsigned int firstoffset, offset;
1295 + JDIMENSION new_value;
1296
1297 - /* We have to compute max_h_samp_factor ourselves,
1298 - * because it hasn't been set yet in the destination
1299 - * (and we don't want to use the source's value).
1300 - */
1301 - max_h_samp_factor = 1;
1302 - for (ci = 0; ci < dstinfo->num_components; ci++) {
1303 - int h_samp_factor = dstinfo->comp_info[ci].h_samp_factor;
1304 - max_h_samp_factor = MAX(max_h_samp_factor, h_samp_factor);
1305 + if (length < 12) return; /* Length of an IFD entry */
1306 +
1307 + /* Discover byte order */
1308 + if (GETJOCTET(data[0]) == 0x49 && GETJOCTET(data[1]) == 0x49)
1309 + is_motorola = FALSE;
1310 + else if (GETJOCTET(data[0]) == 0x4D && GETJOCTET(data[1]) == 0x4D)
1311 + is_motorola = TRUE;
1312 + else
1313 + return;
1314 +
1315 + /* Check Tag Mark */
1316 + if (is_motorola) {
1317 + if (GETJOCTET(data[2]) != 0) return;
1318 + if (GETJOCTET(data[3]) != 0x2A) return;
1319 + } else {
1320 + if (GETJOCTET(data[3]) != 0) return;
1321 + if (GETJOCTET(data[2]) != 0x2A) return;
1322 }
1323 - MCU_cols = dstinfo->image_width / (max_h_samp_factor * DCTSIZE);
1324 - if (MCU_cols > 0) /* can't trim to 0 pixels */
1325 - dstinfo->image_width = MCU_cols * (max_h_samp_factor * DCTSIZE);
1326 -}
1327
1328 -LOCAL(void)
1329 -trim_bottom_edge (j_compress_ptr dstinfo)
1330 -{
1331 - int ci, max_v_samp_factor;
1332 - JDIMENSION MCU_rows;
1333 + /* Get first IFD offset (offset to IFD0) */
1334 + if (is_motorola) {
1335 + if (GETJOCTET(data[4]) != 0) return;
1336 + if (GETJOCTET(data[5]) != 0) return;
1337 + firstoffset = GETJOCTET(data[6]);
1338 + firstoffset <<= 8;
1339 + firstoffset += GETJOCTET(data[7]);
1340 + } else {
1341 + if (GETJOCTET(data[7]) != 0) return;
1342 + if (GETJOCTET(data[6]) != 0) return;
1343 + firstoffset = GETJOCTET(data[5]);
1344 + firstoffset <<= 8;
1345 + firstoffset += GETJOCTET(data[4]);
1346 + }
1347 + if (firstoffset > length - 2) return; /* check end of data segment */
1348
1349 - /* We have to compute max_v_samp_factor ourselves,
1350 - * because it hasn't been set yet in the destination
1351 - * (and we don't want to use the source's value).
1352 - */
1353 - max_v_samp_factor = 1;
1354 - for (ci = 0; ci < dstinfo->num_components; ci++) {
1355 - int v_samp_factor = dstinfo->comp_info[ci].v_samp_factor;
1356 - max_v_samp_factor = MAX(max_v_samp_factor, v_samp_factor);
1357 + /* Get the number of directory entries contained in this IFD */
1358 + if (is_motorola) {
1359 + number_of_tags = GETJOCTET(data[firstoffset]);
1360 + number_of_tags <<= 8;
1361 + number_of_tags += GETJOCTET(data[firstoffset+1]);
1362 + } else {
1363 + number_of_tags = GETJOCTET(data[firstoffset+1]);
1364 + number_of_tags <<= 8;
1365 + number_of_tags += GETJOCTET(data[firstoffset]);
1366 }
1367 - MCU_rows = dstinfo->image_height / (max_v_samp_factor * DCTSIZE);
1368 - if (MCU_rows > 0) /* can't trim to 0 pixels */
1369 - dstinfo->image_height = MCU_rows * (max_v_samp_factor * DCTSIZE);
1370 + if (number_of_tags == 0) return;
1371 + firstoffset += 2;
1372 +
1373 + /* Search for ExifSubIFD offset Tag in IFD0 */
1374 + for (;;) {
1375 + if (firstoffset > length - 12) return; /* check end of data segment */
1376 + /* Get Tag number */
1377 + if (is_motorola) {
1378 + tagnum = GETJOCTET(data[firstoffset]);
1379 + tagnum <<= 8;
1380 + tagnum += GETJOCTET(data[firstoffset+1]);
1381 + } else {
1382 + tagnum = GETJOCTET(data[firstoffset+1]);
1383 + tagnum <<= 8;
1384 + tagnum += GETJOCTET(data[firstoffset]);
1385 + }
1386 + if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */
1387 + if (--number_of_tags == 0) return;
1388 + firstoffset += 12;
1389 + }
1390 +
1391 + /* Get the ExifSubIFD offset */
1392 + if (is_motorola) {
1393 + if (GETJOCTET(data[firstoffset+8]) != 0) return;
1394 + if (GETJOCTET(data[firstoffset+9]) != 0) return;
1395 + offset = GETJOCTET(data[firstoffset+10]);
1396 + offset <<= 8;
1397 + offset += GETJOCTET(data[firstoffset+11]);
1398 + } else {
1399 + if (GETJOCTET(data[firstoffset+11]) != 0) return;
1400 + if (GETJOCTET(data[firstoffset+10]) != 0) return;
1401 + offset = GETJOCTET(data[firstoffset+9]);
1402 + offset <<= 8;
1403 + offset += GETJOCTET(data[firstoffset+8]);
1404 + }
1405 + if (offset > length - 2) return; /* check end of data segment */
1406 +
1407 + /* Get the number of directory entries contained in this SubIFD */
1408 + if (is_motorola) {
1409 + number_of_tags = GETJOCTET(data[offset]);
1410 + number_of_tags <<= 8;
1411 + number_of_tags += GETJOCTET(data[offset+1]);
1412 + } else {
1413 + number_of_tags = GETJOCTET(data[offset+1]);
1414 + number_of_tags <<= 8;
1415 + number_of_tags += GETJOCTET(data[offset]);
1416 + }
1417 + if (number_of_tags < 2) return;
1418 + offset += 2;
1419 +
1420 + /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */
1421 + do {
1422 + if (offset > length - 12) return; /* check end of data segment */
1423 + /* Get Tag number */
1424 + if (is_motorola) {
1425 + tagnum = GETJOCTET(data[offset]);
1426 + tagnum <<= 8;
1427 + tagnum += GETJOCTET(data[offset+1]);
1428 + } else {
1429 + tagnum = GETJOCTET(data[offset+1]);
1430 + tagnum <<= 8;
1431 + tagnum += GETJOCTET(data[offset]);
1432 + }
1433 + if (tagnum == 0xA002 || tagnum == 0xA003) {
1434 + if (tagnum == 0xA002)
1435 + new_value = new_width; /* ExifImageWidth Tag */
1436 + else
1437 + new_value = new_height; /* ExifImageHeight Tag */
1438 + if (is_motorola) {
1439 + data[offset+2] = 0; /* Format = unsigned long (4 octets) */
1440 + data[offset+3] = 4;
1441 + data[offset+4] = 0; /* Number Of Components = 1 */
1442 + data[offset+5] = 0;
1443 + data[offset+6] = 0;
1444 + data[offset+7] = 1;
1445 + data[offset+8] = 0;
1446 + data[offset+9] = 0;
1447 + data[offset+10] = (JOCTET)((new_value >> 8) & 0xFF);
1448 + data[offset+11] = (JOCTET)(new_value & 0xFF);
1449 + } else {
1450 + data[offset+2] = 4; /* Format = unsigned long (4 octets) */
1451 + data[offset+3] = 0;
1452 + data[offset+4] = 1; /* Number Of Components = 1 */
1453 + data[offset+5] = 0;
1454 + data[offset+6] = 0;
1455 + data[offset+7] = 0;
1456 + data[offset+8] = (JOCTET)(new_value & 0xFF);
1457 + data[offset+9] = (JOCTET)((new_value >> 8) & 0xFF);
1458 + data[offset+10] = 0;
1459 + data[offset+11] = 0;
1460 + }
1461 + }
1462 + offset += 12;
1463 + } while (--number_of_tags);
1464 }
1465
1466
1467 @@ -736,18 +1263,22 @@
1468 {
1469 /* If force-to-grayscale is requested, adjust destination parameters */
1470 if (info->force_grayscale) {
1471 - /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
1472 - * properly. Among other things, the target h_samp_factor & v_samp_factor
1473 - * will get set to 1, which typically won't match the source.
1474 - * In fact we do this even if the source is already grayscale; that
1475 - * provides an easy way of coercing a grayscale JPEG with funny sampling
1476 - * factors to the customary 1,1. (Some decoders fail on other factors.)
1477 + /* First, ensure we have YCbCr or grayscale data, and that the source's
1478 + * Y channel is full resolution. (No reasonable person would make Y
1479 + * be less than full resolution, so actually coping with that case
1480 + * isn't worth extra code space. But we check it to avoid crashing.)
1481 */
1482 - if ((dstinfo->jpeg_color_space == JCS_YCbCr &&
1483 - dstinfo->num_components == 3) ||
1484 - (dstinfo->jpeg_color_space == JCS_GRAYSCALE &&
1485 - dstinfo->num_components == 1)) {
1486 - /* We have to preserve the source's quantization table number. */
1487 + if (((dstinfo->jpeg_color_space == JCS_YCbCr &&
1488 + dstinfo->num_components == 3) ||
1489 + (dstinfo->jpeg_color_space == JCS_GRAYSCALE &&
1490 + dstinfo->num_components == 1)) &&
1491 + srcinfo->comp_info[0].h_samp_factor == srcinfo->max_h_samp_factor &&
1492 + srcinfo->comp_info[0].v_samp_factor == srcinfo->max_v_samp_factor) {
1493 + /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
1494 + * properly. Among other things, it sets the target h_samp_factor &
1495 + * v_samp_factor to 1, which typically won't match the source.
1496 + * We have to preserve the source's quantization table number, however.
1497 + */
1498 int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no;
1499 jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE);
1500 dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no;
1501 @@ -755,50 +1286,52 @@
1502 /* Sorry, can't do it */
1503 ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL);
1504 }
1505 + } else if (info->num_components == 1) {
1506 + /* For a single-component source, we force the destination sampling factors
1507 + * to 1x1, with or without force_grayscale. This is useful because some
1508 + * decoders choke on grayscale images with other sampling factors.
1509 + */
1510 + dstinfo->comp_info[0].h_samp_factor = 1;
1511 + dstinfo->comp_info[0].v_samp_factor = 1;
1512 }
1513
1514 - /* Correct the destination's image dimensions etc if necessary */
1515 + /* Correct the destination's image dimensions as necessary
1516 + * for crop and rotate/flip operations.
1517 + */
1518 + dstinfo->image_width = info->output_width;
1519 + dstinfo->image_height = info->output_height;
1520 +
1521 + /* Transpose destination image parameters */
1522 switch (info->transform) {
1523 - case JXFORM_NONE:
1524 - /* Nothing to do */
1525 - break;
1526 - case JXFORM_FLIP_H:
1527 - if (info->trim)
1528 - trim_right_edge(dstinfo);
1529 - break;
1530 - case JXFORM_FLIP_V:
1531 - if (info->trim)
1532 - trim_bottom_edge(dstinfo);
1533 - break;
1534 case JXFORM_TRANSPOSE:
1535 - transpose_critical_parameters(dstinfo);
1536 - /* transpose does NOT have to trim anything */
1537 - break;
1538 case JXFORM_TRANSVERSE:
1539 - transpose_critical_parameters(dstinfo);
1540 - if (info->trim) {
1541 - trim_right_edge(dstinfo);
1542 - trim_bottom_edge(dstinfo);
1543 - }
1544 - break;
1545 case JXFORM_ROT_90:
1546 - transpose_critical_parameters(dstinfo);
1547 - if (info->trim)
1548 - trim_right_edge(dstinfo);
1549 - break;
1550 - case JXFORM_ROT_180:
1551 - if (info->trim) {
1552 - trim_right_edge(dstinfo);
1553 - trim_bottom_edge(dstinfo);
1554 - }
1555 - break;
1556 case JXFORM_ROT_270:
1557 transpose_critical_parameters(dstinfo);
1558 - if (info->trim)
1559 - trim_bottom_edge(dstinfo);
1560 break;
1561 }
1562
1563 + /* Adjust Exif properties */
1564 + if (srcinfo->marker_list != NULL &&
1565 + srcinfo->marker_list->marker == JPEG_APP0+1 &&
1566 + srcinfo->marker_list->data_length >= 6 &&
1567 + GETJOCTET(srcinfo->marker_list->data[0]) == 0x45 &&
1568 + GETJOCTET(srcinfo->marker_list->data[1]) == 0x78 &&
1569 + GETJOCTET(srcinfo->marker_list->data[2]) == 0x69 &&
1570 + GETJOCTET(srcinfo->marker_list->data[3]) == 0x66 &&
1571 + GETJOCTET(srcinfo->marker_list->data[4]) == 0 &&
1572 + GETJOCTET(srcinfo->marker_list->data[5]) == 0) {
1573 + /* Suppress output of JFIF marker */
1574 + dstinfo->write_JFIF_header = FALSE;
1575 + /* Adjust Exif image parameters */
1576 + if (dstinfo->image_width != srcinfo->image_width ||
1577 + dstinfo->image_height != srcinfo->image_height)
1578 + /* Align data segment to start of TIFF structure for parsing */
1579 + adjust_exif_parameters(srcinfo->marker_list->data + 6,
1580 + srcinfo->marker_list->data_length - 6,
1581 + dstinfo->image_width, dstinfo->image_height);
1582 + }
1583 +
1584 /* Return the appropriate output data set */
1585 if (info->workspace_coef_arrays != NULL)
1586 return info->workspace_coef_arrays;
1587 @@ -816,38 +1349,106 @@
1588 */
1589
1590 GLOBAL(void)
1591 -jtransform_execute_transformation (j_decompress_ptr srcinfo,
1592 - j_compress_ptr dstinfo,
1593 - jvirt_barray_ptr *src_coef_arrays,
1594 - jpeg_transform_info *info)
1595 +jtransform_execute_transform (j_decompress_ptr srcinfo,
1596 + j_compress_ptr dstinfo,
1597 + jvirt_barray_ptr *src_coef_arrays,
1598 + jpeg_transform_info *info)
1599 {
1600 jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays;
1601
1602 + /* Note: conditions tested here should match those in switch statement
1603 + * in jtransform_request_workspace()
1604 + */
1605 switch (info->transform) {
1606 case JXFORM_NONE:
1607 + if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
1608 + do_crop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
1609 + src_coef_arrays, dst_coef_arrays);
1610 break;
1611 case JXFORM_FLIP_H:
1612 - do_flip_h(srcinfo, dstinfo, src_coef_arrays);
1613 + if (info->y_crop_offset != 0)
1614 + do_flip_h(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
1615 + src_coef_arrays, dst_coef_arrays);
1616 + else
1617 + do_flip_h_no_crop(srcinfo, dstinfo, info->x_crop_offset,
1618 + src_coef_arrays);
1619 break;
1620 case JXFORM_FLIP_V:
1621 - do_flip_v(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
1622 + do_flip_v(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
1623 + src_coef_arrays, dst_coef_arrays);
1624 break;
1625 case JXFORM_TRANSPOSE:
1626 - do_transpose(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
1627 + do_transpose(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
1628 + src_coef_arrays, dst_coef_arrays);
1629 break;
1630 case JXFORM_TRANSVERSE:
1631 - do_transverse(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
1632 + do_transverse(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
1633 + src_coef_arrays, dst_coef_arrays);
1634 break;
1635 case JXFORM_ROT_90:
1636 - do_rot_90(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
1637 + do_rot_90(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
1638 + src_coef_arrays, dst_coef_arrays);
1639 break;
1640 case JXFORM_ROT_180:
1641 - do_rot_180(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
1642 + do_rot_180(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
1643 + src_coef_arrays, dst_coef_arrays);
1644 break;
1645 case JXFORM_ROT_270:
1646 - do_rot_270(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
1647 + do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
1648 + src_coef_arrays, dst_coef_arrays);
1649 + break;
1650 + }
1651 +}
1652 +
1653 +/* jtransform_perfect_transform
1654 + *
1655 + * Determine whether lossless transformation is perfectly
1656 + * possible for a specified image and transformation.
1657 + *
1658 + * Inputs:
1659 + * image_width, image_height: source image dimensions.
1660 + * MCU_width, MCU_height: pixel dimensions of MCU.
1661 + * transform: transformation identifier.
1662 + * Parameter sources from initialized jpeg_struct
1663 + * (after reading source header):
1664 + * image_width = cinfo.image_width
1665 + * image_height = cinfo.image_height
1666 + * MCU_width = cinfo.max_h_samp_factor * DCTSIZE
1667 + * MCU_height = cinfo.max_v_samp_factor * DCTSIZE
1668 + * Result:
1669 + * TRUE = perfect transformation possible
1670 + * FALSE = perfect transformation not possible
1671 + * (may use custom action then)
1672 + */
1673 +
1674 +GLOBAL(boolean)
1675 +jtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height,
1676 + int MCU_width, int MCU_height,
1677 + JXFORM_CODE transform)
1678 +{
1679 + boolean result = TRUE; /* initialize TRUE */
1680 +
1681 + switch (transform) {
1682 + case JXFORM_FLIP_H:
1683 + case JXFORM_ROT_270:
1684 + if (image_width % (JDIMENSION) MCU_width)
1685 + result = FALSE;
1686 + break;
1687 + case JXFORM_FLIP_V:
1688 + case JXFORM_ROT_90:
1689 + if (image_height % (JDIMENSION) MCU_height)
1690 + result = FALSE;
1691 + break;
1692 + case JXFORM_TRANSVERSE:
1693 + case JXFORM_ROT_180:
1694 + if (image_width % (JDIMENSION) MCU_width)
1695 + result = FALSE;
1696 + if (image_height % (JDIMENSION) MCU_height)
1697 + result = FALSE;
1698 break;
1699 }
1700 +
1701 + return result;
1702 }
1703
1704 #endif /* TRANSFORMS_SUPPORTED */
1705 diff -urNad /home/bill/debian/libjpeg/libjpeg6b-6b/transupp.h libjpeg6b-6b/transupp.h
1706 --- /home/bill/debian/libjpeg/libjpeg6b-6b/transupp.h 2003-09-22 18:15:49.000000000 +0200
1707 +++ libjpeg6b-6b/transupp.h 2003-09-22 18:16:16.000000000 +0200
1708 @@ -1,7 +1,7 @@
1709 /*
1710 * transupp.h
1711 *
1712 - * Copyright (C) 1997, Thomas G. Lane.
1713 + * Copyright (C) 1997-2001, Thomas G. Lane.
1714 * This file is part of the Independent JPEG Group's software.
1715 * For conditions of distribution and use, see the accompanying README file.
1716 *
1717 @@ -22,32 +22,6 @@
1718 #define TRANSFORMS_SUPPORTED 1 /* 0 disables transform code */
1719 #endif
1720
1721 -/* Short forms of external names for systems with brain-damaged linkers. */
1722 -
1723 -#ifdef NEED_SHORT_EXTERNAL_NAMES
1724 -#define jtransform_request_workspace jTrRequest
1725 -#define jtransform_adjust_parameters jTrAdjust
1726 -#define jtransform_execute_transformation jTrExec
1727 -#define jcopy_markers_setup jCMrkSetup
1728 -#define jcopy_markers_execute jCMrkExec
1729 -#endif /* NEED_SHORT_EXTERNAL_NAMES */
1730 -
1731 -
1732 -/*
1733 - * Codes for supported types of image transformations.
1734 - */
1735 -
1736 -typedef enum {
1737 - JXFORM_NONE, /* no transformation */
1738 - JXFORM_FLIP_H, /* horizontal flip */
1739 - JXFORM_FLIP_V, /* vertical flip */
1740 - JXFORM_TRANSPOSE, /* transpose across UL-to-LR axis */
1741 - JXFORM_TRANSVERSE, /* transpose across UR-to-LL axis */
1742 - JXFORM_ROT_90, /* 90-degree clockwise rotation */
1743 - JXFORM_ROT_180, /* 180-degree rotation */
1744 - JXFORM_ROT_270 /* 270-degree clockwise (or 90 ccw) */
1745 -} JXFORM_CODE;
1746 -
1747 /*
1748 * Although rotating and flipping data expressed as DCT coefficients is not
1749 * hard, there is an asymmetry in the JPEG format specification for images
1750 @@ -75,6 +49,19 @@
1751 * (For example, -rot 270 -trim trims only the bottom edge, but -rot 90 -trim
1752 * followed by -rot 180 -trim trims both edges.)
1753 *
1754 + * We also offer a lossless-crop option, which discards data outside a given
1755 + * image region but losslessly preserves what is inside. Like the rotate and
1756 + * flip transforms, lossless crop is restricted by the JPEG format: the upper
1757 + * left corner of the selected region must fall on an iMCU boundary. If this
1758 + * does not hold for the given crop parameters, we silently move the upper left
1759 + * corner up and/or left to make it so, simultaneously increasing the region
1760 + * dimensions to keep the lower right crop corner unchanged. (Thus, the
1761 + * output image covers at least the requested region, but may cover more.)
1762 + *
1763 + * If both crop and a rotate/flip transform are requested, the crop is applied
1764 + * last --- that is, the crop region is specified in terms of the destination
1765 + * image.
1766 + *
1767 * We also offer a "force to grayscale" option, which simply discards the
1768 * chrominance channels of a YCbCr image. This is lossless in the sense that
1769 * the luminance channel is preserved exactly. It's not the same kind of
1770 @@ -83,20 +70,89 @@
1771 * be aware of the option to know how many components to work on.
1772 */
1773
1774 +
1775 +/* Short forms of external names for systems with brain-damaged linkers. */
1776 +
1777 +#ifdef NEED_SHORT_EXTERNAL_NAMES
1778 +#define jtransform_parse_crop_spec jTrParCrop
1779 +#define jtransform_request_workspace jTrRequest
1780 +#define jtransform_adjust_parameters jTrAdjust
1781 +#define jtransform_execute_transform jTrExec
1782 +#define jtransform_perfect_transform jTrPerfect
1783 +#define jcopy_markers_setup jCMrkSetup
1784 +#define jcopy_markers_execute jCMrkExec
1785 +#endif /* NEED_SHORT_EXTERNAL_NAMES */
1786 +
1787 +
1788 +/*
1789 + * Codes for supported types of image transformations.
1790 + */
1791 +
1792 +typedef enum {
1793 + JXFORM_NONE, /* no transformation */
1794 + JXFORM_FLIP_H, /* horizontal flip */
1795 + JXFORM_FLIP_V, /* vertical flip */
1796 + JXFORM_TRANSPOSE, /* transpose across UL-to-LR axis */
1797 + JXFORM_TRANSVERSE, /* transpose across UR-to-LL axis */
1798 + JXFORM_ROT_90, /* 90-degree clockwise rotation */
1799 + JXFORM_ROT_180, /* 180-degree rotation */
1800 + JXFORM_ROT_270 /* 270-degree clockwise (or 90 ccw) */
1801 +} JXFORM_CODE;
1802 +
1803 +/*
1804 + * Codes for crop parameters, which can individually be unspecified,
1805 + * positive, or negative. (Negative width or height makes no sense, though.)
1806 + */
1807 +
1808 +typedef enum {
1809 + JCROP_UNSET,
1810 + JCROP_POS,
1811 + JCROP_NEG
1812 +} JCROP_CODE;
1813 +
1814 +/*
1815 + * Transform parameters struct.
1816 + * NB: application must not change any elements of this struct after
1817 + * calling jtransform_request_workspace.
1818 + */
1819 +
1820 typedef struct {
1821 /* Options: set by caller */
1822 JXFORM_CODE transform; /* image transform operator */
1823 + boolean perfect; /* if TRUE, fail if partial MCUs are requested */
1824 boolean trim; /* if TRUE, trim partial MCUs as needed */
1825 boolean force_grayscale; /* if TRUE, convert color image to grayscale */
1826 + boolean crop; /* if TRUE, crop source image */
1827 +
1828 + /* Crop parameters: application need not set these unless crop is TRUE.
1829 + * These can be filled in by jtransform_parse_crop_spec().
1830 + */
1831 + JDIMENSION crop_width; /* Width of selected region */
1832 + JCROP_CODE crop_width_set;
1833 + JDIMENSION crop_height; /* Height of selected region */
1834 + JCROP_CODE crop_height_set;
1835 + JDIMENSION crop_xoffset; /* X offset of selected region */
1836 + JCROP_CODE crop_xoffset_set; /* (negative measures from right edge) */
1837 + JDIMENSION crop_yoffset; /* Y offset of selected region */
1838 + JCROP_CODE crop_yoffset_set; /* (negative measures from bottom edge) */
1839
1840 /* Internal workspace: caller should not touch these */
1841 int num_components; /* # of components in workspace */
1842 jvirt_barray_ptr * workspace_coef_arrays; /* workspace for transformations */
1843 + JDIMENSION output_width; /* cropped destination dimensions */
1844 + JDIMENSION output_height;
1845 + JDIMENSION x_crop_offset; /* destination crop offsets measured in iMCUs */
1846 + JDIMENSION y_crop_offset;
1847 + int max_h_samp_factor; /* destination iMCU size */
1848 + int max_v_samp_factor;
1849 } jpeg_transform_info;
1850
1851
1852 #if TRANSFORMS_SUPPORTED
1853
1854 +/* Parse a crop specification (written in X11 geometry style) */
1855 +EXTERN(boolean) jtransform_parse_crop_spec
1856 + JPP((jpeg_transform_info *info, const char *spec));
1857 /* Request any required workspace */
1858 EXTERN(void) jtransform_request_workspace
1859 JPP((j_decompress_ptr srcinfo, jpeg_transform_info *info));
1860 @@ -106,10 +162,24 @@
1861 jvirt_barray_ptr *src_coef_arrays,
1862 jpeg_transform_info *info));
1863 /* Execute the actual transformation, if any */
1864 -EXTERN(void) jtransform_execute_transformation
1865 +EXTERN(void) jtransform_execute_transform
1866 JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
1867 jvirt_barray_ptr *src_coef_arrays,
1868 jpeg_transform_info *info));
1869 +/* Determine whether lossless transformation is perfectly
1870 + * possible for a specified image and transformation.
1871 + */
1872 +EXTERN(boolean) jtransform_perfect_transform
1873 + JPP((JDIMENSION image_width, JDIMENSION image_height,
1874 + int MCU_width, int MCU_height,
1875 + JXFORM_CODE transform));
1876 +
1877 +/* jtransform_execute_transform used to be called
1878 + * jtransform_execute_transformation, but some compilers complain about
1879 + * routine names that long. This macro is here to avoid breaking any
1880 + * old source code that uses the original name...
1881 + */
1882 +#define jtransform_execute_transformation jtransform_execute_transform
1883
1884 #endif /* TRANSFORMS_SUPPORTED */
1885