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