Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


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

1 niro 144 # 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