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