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