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
90LOCAL(void)
91do_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
128LOCAL(void)
129do_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
195LOCAL(void)
196do_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
257LOCAL(void)
258do_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
337LOCAL(void)
338do_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
385LOCAL(void)
386do_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
466LOCAL(void)
467do_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
537LOCAL(void)
538do_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
645LOCAL(void)
646do_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
765LOCAL(boolean)
766jt_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
795GLOBAL(boolean)
796jtransform_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
849LOCAL(void)
850trim_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
860LOCAL(void)
861trim_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
889GLOBAL(boolean)
890jtransform_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
1131LOCAL(void)
1132transpose_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
1180LOCAL(void)
1181adjust_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
1343GLOBAL(jvirt_barray_ptr *)
1344jtransform_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
1450GLOBAL(void)
1451jtransform_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
1523GLOBAL(boolean)
1524jtransform_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
1562GLOBAL(void)
1563jcopy_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
1587GLOBAL(void)
1588jcopy_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