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