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