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