15ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/*
25ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * transupp.c
35ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *
4cf763c0cd8116ac225bd2d36a71da33a3c7fcc46DRC * This file was part of the Independent JPEG Group's software:
55829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding * Copyright (C) 1997-2011, Thomas G. Lane, Guido Vollbeding.
6a6ef282a49f2d7d1b4d19cc89f63e81fd66b35b7DRC * libjpeg-turbo Modifications:
7c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC * Copyright (C) 2010, D. R. Commander.
86eb7d3798b5a79347c62825fc4c16f7ce673bdd0Alex Naidis * For conditions of distribution and use, see the accompanying README.ijg
96eb7d3798b5a79347c62825fc4c16f7ce673bdd0Alex Naidis * file.
105ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *
115ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * This file contains image transformation routines and other utility code
125ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * used by the jpegtran sample application.  These are NOT part of the core
135ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * JPEG library.  But we keep these routines separate from jpegtran.c to
145ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * ease the task of maintaining jpegtran-like programs that have other user
155ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * interfaces.
165ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */
175ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
185ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* Although this file really shouldn't have access to the library internals,
195ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * it's helpful to let it call jround_up() and jcopy_block_row().
205ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */
215ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane#define JPEG_INTERNALS
225ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
235ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane#include "jinclude.h"
245ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane#include "jpeglib.h"
25e5eaf37440b8e337ab150c017df7c03faf846c51DRC#include "transupp.h"           /* My own external interface */
26c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#include "jpegcomp.h"
27e5eaf37440b8e337ab150c017df7c03faf846c51DRC#include <ctype.h>              /* to declare isdigit() */
285ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
295ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
30c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#if JPEG_LIB_VERSION >= 70
31c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#define dstinfo_min_DCT_h_scaled_size dstinfo->min_DCT_h_scaled_size
32c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#define dstinfo_min_DCT_v_scaled_size dstinfo->min_DCT_v_scaled_size
33c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#else
34c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#define dstinfo_min_DCT_h_scaled_size DCTSIZE
35c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#define dstinfo_min_DCT_v_scaled_size DCTSIZE
36c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#endif
375ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
385ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
395ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane#if TRANSFORMS_SUPPORTED
405ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
415ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/*
425ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * Lossless image transformation routines.  These routines work on DCT
435ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * coefficient arrays and thus do not require any lossy decompression
445ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * or recompression of the image.
455996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * Thanks to Guido Vollbeding for the initial design and code of this feature,
465996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * and to Ben Jackson for introducing the cropping feature.
475ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *
485ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * Horizontal flipping is done in-place, using a single top-to-bottom
495ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * pass through the virtual source array.  It will thus be much the
505ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * fastest option for images larger than main memory.
515ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *
525ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * The other routines require a set of destination virtual arrays, so they
535ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * need twice as much memory as jpegtran normally does.  The destination
545ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * arrays are always written in normal scan order (top to bottom) because
555ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * the virtual array manager expects this.  The source arrays will be scanned
565ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * in the corresponding order, which means multiple passes through the source
575ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * arrays for most of the transforms.  That could result in much thrashing
585ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * if the image is larger than main memory.
595ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *
605996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * If cropping or trimming is involved, the destination arrays may be smaller
615996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * than the source arrays.  Note it is not possible to do horizontal flip
625996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * in-place when a nonzero Y crop offset is specified, since we'd have to move
635996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * data from one block row to another but the virtual array manager doesn't
645996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * guarantee we can touch more than one row at a time.  So in that case,
655996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * we have to use a separate destination array.
665996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding *
675ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * Some notes about the operating environment of the individual transform
685ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * routines:
695ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 1. Both the source and destination virtual arrays are allocated from the
705ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *    source JPEG object, and therefore should be manipulated by calling the
715ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *    source's memory manager.
725ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 2. The destination's component count should be used.  It may be smaller
735ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *    than the source's when forcing to grayscale.
745ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 3. Likewise the destination's sampling factors should be used.  When
755ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *    forcing to grayscale the destination's sampling factors will be all 1,
765ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *    and we may as well take that as the effective iMCU size.
775ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 4. When "trim" is in effect, the destination's dimensions will be the
785ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *    trimmed values but the source's will be untrimmed.
795996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * 5. When "crop" is in effect, the destination's dimensions will be the
805996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding *    cropped values but the source's will be uncropped.  Each transform
815996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding *    routine is responsible for picking up source data starting at the
825996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding *    correct X and Y offset for the crop region.  (The X and Y offsets
835996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding *    passed to the transform routines are measured in iMCU blocks of the
845996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding *    destination.)
855996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * 6. All the routines assume that the source and destination buffers are
865ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *    padded out to a full iMCU boundary.  This is true, although for the
875ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *    source buffer it is an undocumented property of jdcoefct.c.
885ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */
895ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
905ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
915ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneLOCAL(void)
925996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbedingdo_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
93e5eaf37440b8e337ab150c017df7c03faf846c51DRC         JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
94e5eaf37440b8e337ab150c017df7c03faf846c51DRC         jvirt_barray_ptr *src_coef_arrays,
95e5eaf37440b8e337ab150c017df7c03faf846c51DRC         jvirt_barray_ptr *dst_coef_arrays)
965996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding/* Crop.  This is only used when no rotate/flip is requested with the crop. */
975ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{
985996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks;
995996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  int ci, offset_y;
1005996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  JBLOCKARRAY src_buffer, dst_buffer;
1015996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  jpeg_component_info *compptr;
1025996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
1035996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  /* We simply have to copy the right amount of data (the destination's
1045996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding   * image size) starting at the given X and Y offsets in the source.
1055996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding   */
1065996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  for (ci = 0; ci < dstinfo->num_components; ci++) {
1075996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    compptr = dstinfo->comp_info + ci;
1085996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
1095996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
1105996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
111e5eaf37440b8e337ab150c017df7c03faf846c51DRC         dst_blk_y += compptr->v_samp_factor) {
1125996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      dst_buffer = (*srcinfo->mem->access_virt_barray)
113e5eaf37440b8e337ab150c017df7c03faf846c51DRC        ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
114e5eaf37440b8e337ab150c017df7c03faf846c51DRC         (JDIMENSION) compptr->v_samp_factor, TRUE);
1155996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      src_buffer = (*srcinfo->mem->access_virt_barray)
116e5eaf37440b8e337ab150c017df7c03faf846c51DRC        ((j_common_ptr) srcinfo, src_coef_arrays[ci],
117e5eaf37440b8e337ab150c017df7c03faf846c51DRC         dst_blk_y + y_crop_blocks,
118e5eaf37440b8e337ab150c017df7c03faf846c51DRC         (JDIMENSION) compptr->v_samp_factor, FALSE);
1195996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
120e5eaf37440b8e337ab150c017df7c03faf846c51DRC        jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
121e5eaf37440b8e337ab150c017df7c03faf846c51DRC                        dst_buffer[offset_y],
122e5eaf37440b8e337ab150c017df7c03faf846c51DRC                        compptr->width_in_blocks);
1235996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      }
1245996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    }
1255996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  }
1265996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding}
1275996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
1285996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
1295996a25e2f50d20d6a8f09830724035b49c3927bGuido VollbedingLOCAL(void)
1305996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbedingdo_flip_h_no_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
131e5eaf37440b8e337ab150c017df7c03faf846c51DRC                   JDIMENSION x_crop_offset,
132e5eaf37440b8e337ab150c017df7c03faf846c51DRC                   jvirt_barray_ptr *src_coef_arrays)
1335996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding/* Horizontal flip; done in-place, so no separate dest array is required.
1345996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * NB: this only works when y_crop_offset is zero.
1355996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding */
1365996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding{
1375996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  JDIMENSION MCU_cols, comp_width, blk_x, blk_y, x_crop_blocks;
1385ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  int ci, k, offset_y;
1395ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  JBLOCKARRAY buffer;
1405ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  JCOEFPTR ptr1, ptr2;
1415ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  JCOEF temp1, temp2;
1425ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  jpeg_component_info *compptr;
1435ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
1445ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  /* Horizontal mirroring of DCT blocks is accomplished by swapping
1455ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   * pairs of blocks in-place.  Within a DCT block, we perform horizontal
1465ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   * mirroring by changing the signs of odd-numbered columns.
1475ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   * Partial iMCUs at the right edge are left untouched.
1485ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   */
149989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  MCU_cols = srcinfo->output_width /
150c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC    (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
1515ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
1525ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  for (ci = 0; ci < dstinfo->num_components; ci++) {
1535ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    compptr = dstinfo->comp_info + ci;
1545ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    comp_width = MCU_cols * compptr->h_samp_factor;
1555996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
1565ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    for (blk_y = 0; blk_y < compptr->height_in_blocks;
157e5eaf37440b8e337ab150c017df7c03faf846c51DRC         blk_y += compptr->v_samp_factor) {
1585ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      buffer = (*srcinfo->mem->access_virt_barray)
159e5eaf37440b8e337ab150c017df7c03faf846c51DRC        ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y,
160e5eaf37440b8e337ab150c017df7c03faf846c51DRC         (JDIMENSION) compptr->v_samp_factor, TRUE);
1615ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
162e5eaf37440b8e337ab150c017df7c03faf846c51DRC        /* Do the mirroring */
163e5eaf37440b8e337ab150c017df7c03faf846c51DRC        for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) {
164e5eaf37440b8e337ab150c017df7c03faf846c51DRC          ptr1 = buffer[offset_y][blk_x];
165e5eaf37440b8e337ab150c017df7c03faf846c51DRC          ptr2 = buffer[offset_y][comp_width - blk_x - 1];
166e5eaf37440b8e337ab150c017df7c03faf846c51DRC          /* this unrolled loop doesn't need to know which row it's on... */
167e5eaf37440b8e337ab150c017df7c03faf846c51DRC          for (k = 0; k < DCTSIZE2; k += 2) {
168e5eaf37440b8e337ab150c017df7c03faf846c51DRC            temp1 = *ptr1;      /* swap even column */
169e5eaf37440b8e337ab150c017df7c03faf846c51DRC            temp2 = *ptr2;
170e5eaf37440b8e337ab150c017df7c03faf846c51DRC            *ptr1++ = temp2;
171e5eaf37440b8e337ab150c017df7c03faf846c51DRC            *ptr2++ = temp1;
172e5eaf37440b8e337ab150c017df7c03faf846c51DRC            temp1 = *ptr1;      /* swap odd column with sign change */
173e5eaf37440b8e337ab150c017df7c03faf846c51DRC            temp2 = *ptr2;
174e5eaf37440b8e337ab150c017df7c03faf846c51DRC            *ptr1++ = -temp2;
175e5eaf37440b8e337ab150c017df7c03faf846c51DRC            *ptr2++ = -temp1;
176e5eaf37440b8e337ab150c017df7c03faf846c51DRC          }
177e5eaf37440b8e337ab150c017df7c03faf846c51DRC        }
178e5eaf37440b8e337ab150c017df7c03faf846c51DRC        if (x_crop_blocks > 0) {
179e5eaf37440b8e337ab150c017df7c03faf846c51DRC          /* Now left-justify the portion of the data to be kept.
180e5eaf37440b8e337ab150c017df7c03faf846c51DRC           * We can't use a single jcopy_block_row() call because that routine
181e5eaf37440b8e337ab150c017df7c03faf846c51DRC           * depends on memcpy(), whose behavior is unspecified for overlapping
182e5eaf37440b8e337ab150c017df7c03faf846c51DRC           * source and destination areas.  Sigh.
183e5eaf37440b8e337ab150c017df7c03faf846c51DRC           */
184e5eaf37440b8e337ab150c017df7c03faf846c51DRC          for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
185e5eaf37440b8e337ab150c017df7c03faf846c51DRC            jcopy_block_row(buffer[offset_y] + blk_x + x_crop_blocks,
186e5eaf37440b8e337ab150c017df7c03faf846c51DRC                            buffer[offset_y] + blk_x,
187e5eaf37440b8e337ab150c017df7c03faf846c51DRC                            (JDIMENSION) 1);
188e5eaf37440b8e337ab150c017df7c03faf846c51DRC          }
189e5eaf37440b8e337ab150c017df7c03faf846c51DRC        }
1905996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      }
1915996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    }
1925996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  }
1935996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding}
1945996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
1955996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
1965996a25e2f50d20d6a8f09830724035b49c3927bGuido VollbedingLOCAL(void)
1975996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbedingdo_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
198e5eaf37440b8e337ab150c017df7c03faf846c51DRC           JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
199e5eaf37440b8e337ab150c017df7c03faf846c51DRC           jvirt_barray_ptr *src_coef_arrays,
200e5eaf37440b8e337ab150c017df7c03faf846c51DRC           jvirt_barray_ptr *dst_coef_arrays)
2015996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding/* Horizontal flip in general cropping case */
2025996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding{
2035996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
2045996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  JDIMENSION x_crop_blocks, y_crop_blocks;
2055996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  int ci, k, offset_y;
2065996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  JBLOCKARRAY src_buffer, dst_buffer;
2075996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  JBLOCKROW src_row_ptr, dst_row_ptr;
2085996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  JCOEFPTR src_ptr, dst_ptr;
2095996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  jpeg_component_info *compptr;
2105996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
2115996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  /* Here we must output into a separate array because we can't touch
2125996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding   * different rows of a single virtual array simultaneously.  Otherwise,
2135996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding   * this is essentially the same as the routine above.
2145996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding   */
215989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  MCU_cols = srcinfo->output_width /
216c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC    (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
2175996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
2185996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  for (ci = 0; ci < dstinfo->num_components; ci++) {
2195996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    compptr = dstinfo->comp_info + ci;
2205996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    comp_width = MCU_cols * compptr->h_samp_factor;
2215996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
2225996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
2235996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
224e5eaf37440b8e337ab150c017df7c03faf846c51DRC         dst_blk_y += compptr->v_samp_factor) {
2255996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      dst_buffer = (*srcinfo->mem->access_virt_barray)
226e5eaf37440b8e337ab150c017df7c03faf846c51DRC        ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
227e5eaf37440b8e337ab150c017df7c03faf846c51DRC         (JDIMENSION) compptr->v_samp_factor, TRUE);
2285996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      src_buffer = (*srcinfo->mem->access_virt_barray)
229e5eaf37440b8e337ab150c017df7c03faf846c51DRC        ((j_common_ptr) srcinfo, src_coef_arrays[ci],
230e5eaf37440b8e337ab150c017df7c03faf846c51DRC         dst_blk_y + y_crop_blocks,
231e5eaf37440b8e337ab150c017df7c03faf846c51DRC         (JDIMENSION) compptr->v_samp_factor, FALSE);
2325996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
233e5eaf37440b8e337ab150c017df7c03faf846c51DRC        dst_row_ptr = dst_buffer[offset_y];
234e5eaf37440b8e337ab150c017df7c03faf846c51DRC        src_row_ptr = src_buffer[offset_y];
235e5eaf37440b8e337ab150c017df7c03faf846c51DRC        for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
236e5eaf37440b8e337ab150c017df7c03faf846c51DRC          if (x_crop_blocks + dst_blk_x < comp_width) {
237e5eaf37440b8e337ab150c017df7c03faf846c51DRC            /* Do the mirrorable blocks */
238e5eaf37440b8e337ab150c017df7c03faf846c51DRC            dst_ptr = dst_row_ptr[dst_blk_x];
239e5eaf37440b8e337ab150c017df7c03faf846c51DRC            src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
240e5eaf37440b8e337ab150c017df7c03faf846c51DRC            /* this unrolled loop doesn't need to know which row it's on... */
241e5eaf37440b8e337ab150c017df7c03faf846c51DRC            for (k = 0; k < DCTSIZE2; k += 2) {
242e5eaf37440b8e337ab150c017df7c03faf846c51DRC              *dst_ptr++ = *src_ptr++;   /* copy even column */
243e5eaf37440b8e337ab150c017df7c03faf846c51DRC              *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */
244e5eaf37440b8e337ab150c017df7c03faf846c51DRC            }
245e5eaf37440b8e337ab150c017df7c03faf846c51DRC          } else {
246e5eaf37440b8e337ab150c017df7c03faf846c51DRC            /* Copy last partial block(s) verbatim */
247e5eaf37440b8e337ab150c017df7c03faf846c51DRC            jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
248e5eaf37440b8e337ab150c017df7c03faf846c51DRC                            dst_row_ptr + dst_blk_x,
249e5eaf37440b8e337ab150c017df7c03faf846c51DRC                            (JDIMENSION) 1);
250e5eaf37440b8e337ab150c017df7c03faf846c51DRC          }
251e5eaf37440b8e337ab150c017df7c03faf846c51DRC        }
2525ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      }
2535ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    }
2545ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  }
2555ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane}
2565ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
2575ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
2585ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneLOCAL(void)
2595ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lanedo_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
260e5eaf37440b8e337ab150c017df7c03faf846c51DRC           JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
261e5eaf37440b8e337ab150c017df7c03faf846c51DRC           jvirt_barray_ptr *src_coef_arrays,
262e5eaf37440b8e337ab150c017df7c03faf846c51DRC           jvirt_barray_ptr *dst_coef_arrays)
2635ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* Vertical flip */
2645ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{
2655ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
2665996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  JDIMENSION x_crop_blocks, y_crop_blocks;
2675ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  int ci, i, j, offset_y;
2685ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  JBLOCKARRAY src_buffer, dst_buffer;
2695ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  JBLOCKROW src_row_ptr, dst_row_ptr;
2705ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  JCOEFPTR src_ptr, dst_ptr;
2715ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  jpeg_component_info *compptr;
2725ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
2735ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  /* We output into a separate array because we can't touch different
2745ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   * rows of the source virtual array simultaneously.  Otherwise, this
2755ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   * is a pretty straightforward analog of horizontal flip.
2765ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   * Within a DCT block, vertical mirroring is done by changing the signs
2775ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   * of odd-numbered rows.
2785ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   * Partial iMCUs at the bottom edge are copied verbatim.
2795ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   */
280989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  MCU_rows = srcinfo->output_height /
281c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC    (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
2825ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
2835ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  for (ci = 0; ci < dstinfo->num_components; ci++) {
2845ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    compptr = dstinfo->comp_info + ci;
2855ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    comp_height = MCU_rows * compptr->v_samp_factor;
2865996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
2875996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
2885ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
289e5eaf37440b8e337ab150c017df7c03faf846c51DRC         dst_blk_y += compptr->v_samp_factor) {
2905ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      dst_buffer = (*srcinfo->mem->access_virt_barray)
291e5eaf37440b8e337ab150c017df7c03faf846c51DRC        ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
292e5eaf37440b8e337ab150c017df7c03faf846c51DRC         (JDIMENSION) compptr->v_samp_factor, TRUE);
2935996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      if (y_crop_blocks + dst_blk_y < comp_height) {
294e5eaf37440b8e337ab150c017df7c03faf846c51DRC        /* Row is within the mirrorable area. */
295e5eaf37440b8e337ab150c017df7c03faf846c51DRC        src_buffer = (*srcinfo->mem->access_virt_barray)
296e5eaf37440b8e337ab150c017df7c03faf846c51DRC          ((j_common_ptr) srcinfo, src_coef_arrays[ci],
297e5eaf37440b8e337ab150c017df7c03faf846c51DRC           comp_height - y_crop_blocks - dst_blk_y -
298e5eaf37440b8e337ab150c017df7c03faf846c51DRC           (JDIMENSION) compptr->v_samp_factor,
299e5eaf37440b8e337ab150c017df7c03faf846c51DRC           (JDIMENSION) compptr->v_samp_factor, FALSE);
3005ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      } else {
301e5eaf37440b8e337ab150c017df7c03faf846c51DRC        /* Bottom-edge blocks will be copied verbatim. */
302e5eaf37440b8e337ab150c017df7c03faf846c51DRC        src_buffer = (*srcinfo->mem->access_virt_barray)
303e5eaf37440b8e337ab150c017df7c03faf846c51DRC          ((j_common_ptr) srcinfo, src_coef_arrays[ci],
304e5eaf37440b8e337ab150c017df7c03faf846c51DRC           dst_blk_y + y_crop_blocks,
305e5eaf37440b8e337ab150c017df7c03faf846c51DRC           (JDIMENSION) compptr->v_samp_factor, FALSE);
3065ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      }
3075ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
308e5eaf37440b8e337ab150c017df7c03faf846c51DRC        if (y_crop_blocks + dst_blk_y < comp_height) {
309e5eaf37440b8e337ab150c017df7c03faf846c51DRC          /* Row is within the mirrorable area. */
310e5eaf37440b8e337ab150c017df7c03faf846c51DRC          dst_row_ptr = dst_buffer[offset_y];
311e5eaf37440b8e337ab150c017df7c03faf846c51DRC          src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
312e5eaf37440b8e337ab150c017df7c03faf846c51DRC          src_row_ptr += x_crop_blocks;
313e5eaf37440b8e337ab150c017df7c03faf846c51DRC          for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
314e5eaf37440b8e337ab150c017df7c03faf846c51DRC               dst_blk_x++) {
315e5eaf37440b8e337ab150c017df7c03faf846c51DRC            dst_ptr = dst_row_ptr[dst_blk_x];
316e5eaf37440b8e337ab150c017df7c03faf846c51DRC            src_ptr = src_row_ptr[dst_blk_x];
317e5eaf37440b8e337ab150c017df7c03faf846c51DRC            for (i = 0; i < DCTSIZE; i += 2) {
318e5eaf37440b8e337ab150c017df7c03faf846c51DRC              /* copy even row */
319e5eaf37440b8e337ab150c017df7c03faf846c51DRC              for (j = 0; j < DCTSIZE; j++)
320e5eaf37440b8e337ab150c017df7c03faf846c51DRC                *dst_ptr++ = *src_ptr++;
321e5eaf37440b8e337ab150c017df7c03faf846c51DRC              /* copy odd row with sign change */
322e5eaf37440b8e337ab150c017df7c03faf846c51DRC              for (j = 0; j < DCTSIZE; j++)
323e5eaf37440b8e337ab150c017df7c03faf846c51DRC                *dst_ptr++ = - *src_ptr++;
324e5eaf37440b8e337ab150c017df7c03faf846c51DRC            }
325e5eaf37440b8e337ab150c017df7c03faf846c51DRC          }
326e5eaf37440b8e337ab150c017df7c03faf846c51DRC        } else {
327e5eaf37440b8e337ab150c017df7c03faf846c51DRC          /* Just copy row verbatim. */
328e5eaf37440b8e337ab150c017df7c03faf846c51DRC          jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
329e5eaf37440b8e337ab150c017df7c03faf846c51DRC                          dst_buffer[offset_y],
330e5eaf37440b8e337ab150c017df7c03faf846c51DRC                          compptr->width_in_blocks);
331e5eaf37440b8e337ab150c017df7c03faf846c51DRC        }
3325ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      }
3335ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    }
3345ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  }
3355ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane}
3365ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
3375ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
3385ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneLOCAL(void)
3395ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lanedo_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
340e5eaf37440b8e337ab150c017df7c03faf846c51DRC              JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
341e5eaf37440b8e337ab150c017df7c03faf846c51DRC              jvirt_barray_ptr *src_coef_arrays,
342e5eaf37440b8e337ab150c017df7c03faf846c51DRC              jvirt_barray_ptr *dst_coef_arrays)
3435ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* Transpose source into destination */
3445ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{
3455996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks;
3465ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  int ci, i, j, offset_x, offset_y;
3475ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  JBLOCKARRAY src_buffer, dst_buffer;
3485ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  JCOEFPTR src_ptr, dst_ptr;
3495ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  jpeg_component_info *compptr;
3505ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
3515ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  /* Transposing pixels within a block just requires transposing the
3525ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   * DCT coefficients.
3535ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   * Partial iMCUs at the edges require no special treatment; we simply
3545ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   * process all the available DCT blocks for every component.
3555ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   */
3565ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  for (ci = 0; ci < dstinfo->num_components; ci++) {
3575ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    compptr = dstinfo->comp_info + ci;
3585996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
3595996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
3605ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
361e5eaf37440b8e337ab150c017df7c03faf846c51DRC         dst_blk_y += compptr->v_samp_factor) {
3625ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      dst_buffer = (*srcinfo->mem->access_virt_barray)
363e5eaf37440b8e337ab150c017df7c03faf846c51DRC        ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
364e5eaf37440b8e337ab150c017df7c03faf846c51DRC         (JDIMENSION) compptr->v_samp_factor, TRUE);
3655ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
366e5eaf37440b8e337ab150c017df7c03faf846c51DRC        for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
367e5eaf37440b8e337ab150c017df7c03faf846c51DRC             dst_blk_x += compptr->h_samp_factor) {
368e5eaf37440b8e337ab150c017df7c03faf846c51DRC          src_buffer = (*srcinfo->mem->access_virt_barray)
369e5eaf37440b8e337ab150c017df7c03faf846c51DRC            ((j_common_ptr) srcinfo, src_coef_arrays[ci],
370e5eaf37440b8e337ab150c017df7c03faf846c51DRC             dst_blk_x + x_crop_blocks,
371e5eaf37440b8e337ab150c017df7c03faf846c51DRC             (JDIMENSION) compptr->h_samp_factor, FALSE);
372e5eaf37440b8e337ab150c017df7c03faf846c51DRC          for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
373e5eaf37440b8e337ab150c017df7c03faf846c51DRC            dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
374e5eaf37440b8e337ab150c017df7c03faf846c51DRC            src_ptr = src_buffer[offset_x][dst_blk_y + offset_y + y_crop_blocks];
375e5eaf37440b8e337ab150c017df7c03faf846c51DRC            for (i = 0; i < DCTSIZE; i++)
376e5eaf37440b8e337ab150c017df7c03faf846c51DRC              for (j = 0; j < DCTSIZE; j++)
377e5eaf37440b8e337ab150c017df7c03faf846c51DRC                dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
378e5eaf37440b8e337ab150c017df7c03faf846c51DRC          }
379e5eaf37440b8e337ab150c017df7c03faf846c51DRC        }
3805ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      }
3815ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    }
3825ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  }
3835ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane}
3845ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
3855ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
3865ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneLOCAL(void)
3875ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lanedo_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
388e5eaf37440b8e337ab150c017df7c03faf846c51DRC           JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
389e5eaf37440b8e337ab150c017df7c03faf846c51DRC           jvirt_barray_ptr *src_coef_arrays,
390e5eaf37440b8e337ab150c017df7c03faf846c51DRC           jvirt_barray_ptr *dst_coef_arrays)
3915ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* 90 degree rotation is equivalent to
3925ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *   1. Transposing the image;
3935ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *   2. Horizontal mirroring.
3945ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * These two steps are merged into a single processing routine.
3955ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */
3965ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{
3975ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
3985996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  JDIMENSION x_crop_blocks, y_crop_blocks;
3995ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  int ci, i, j, offset_x, offset_y;
4005ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  JBLOCKARRAY src_buffer, dst_buffer;
4015ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  JCOEFPTR src_ptr, dst_ptr;
4025ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  jpeg_component_info *compptr;
4035ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
4045ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  /* Because of the horizontal mirror step, we can't process partial iMCUs
4055ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   * at the (output) right edge properly.  They just get transposed and
4065ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   * not mirrored.
4075ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   */
408989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  MCU_cols = srcinfo->output_height /
409c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC    (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
4105ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
4115ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  for (ci = 0; ci < dstinfo->num_components; ci++) {
4125ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    compptr = dstinfo->comp_info + ci;
4135ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    comp_width = MCU_cols * compptr->h_samp_factor;
4145996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
4155996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
4165ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
417e5eaf37440b8e337ab150c017df7c03faf846c51DRC         dst_blk_y += compptr->v_samp_factor) {
4185ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      dst_buffer = (*srcinfo->mem->access_virt_barray)
419e5eaf37440b8e337ab150c017df7c03faf846c51DRC        ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
420e5eaf37440b8e337ab150c017df7c03faf846c51DRC         (JDIMENSION) compptr->v_samp_factor, TRUE);
4215ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
422e5eaf37440b8e337ab150c017df7c03faf846c51DRC        for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
423e5eaf37440b8e337ab150c017df7c03faf846c51DRC             dst_blk_x += compptr->h_samp_factor) {
424e5eaf37440b8e337ab150c017df7c03faf846c51DRC          if (x_crop_blocks + dst_blk_x < comp_width) {
425e5eaf37440b8e337ab150c017df7c03faf846c51DRC            /* Block is within the mirrorable area. */
426e5eaf37440b8e337ab150c017df7c03faf846c51DRC            src_buffer = (*srcinfo->mem->access_virt_barray)
427e5eaf37440b8e337ab150c017df7c03faf846c51DRC              ((j_common_ptr) srcinfo, src_coef_arrays[ci],
428e5eaf37440b8e337ab150c017df7c03faf846c51DRC               comp_width - x_crop_blocks - dst_blk_x -
429e5eaf37440b8e337ab150c017df7c03faf846c51DRC               (JDIMENSION) compptr->h_samp_factor,
430e5eaf37440b8e337ab150c017df7c03faf846c51DRC               (JDIMENSION) compptr->h_samp_factor, FALSE);
431e5eaf37440b8e337ab150c017df7c03faf846c51DRC          } else {
432e5eaf37440b8e337ab150c017df7c03faf846c51DRC            /* Edge blocks are transposed but not mirrored. */
433e5eaf37440b8e337ab150c017df7c03faf846c51DRC            src_buffer = (*srcinfo->mem->access_virt_barray)
434e5eaf37440b8e337ab150c017df7c03faf846c51DRC              ((j_common_ptr) srcinfo, src_coef_arrays[ci],
435e5eaf37440b8e337ab150c017df7c03faf846c51DRC               dst_blk_x + x_crop_blocks,
436e5eaf37440b8e337ab150c017df7c03faf846c51DRC               (JDIMENSION) compptr->h_samp_factor, FALSE);
437e5eaf37440b8e337ab150c017df7c03faf846c51DRC          }
438e5eaf37440b8e337ab150c017df7c03faf846c51DRC          for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
439e5eaf37440b8e337ab150c017df7c03faf846c51DRC            dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
440e5eaf37440b8e337ab150c017df7c03faf846c51DRC            if (x_crop_blocks + dst_blk_x < comp_width) {
441e5eaf37440b8e337ab150c017df7c03faf846c51DRC              /* Block is within the mirrorable area. */
442e5eaf37440b8e337ab150c017df7c03faf846c51DRC              src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
443e5eaf37440b8e337ab150c017df7c03faf846c51DRC                [dst_blk_y + offset_y + y_crop_blocks];
444e5eaf37440b8e337ab150c017df7c03faf846c51DRC              for (i = 0; i < DCTSIZE; i++) {
445e5eaf37440b8e337ab150c017df7c03faf846c51DRC                for (j = 0; j < DCTSIZE; j++)
446e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
447e5eaf37440b8e337ab150c017df7c03faf846c51DRC                i++;
448e5eaf37440b8e337ab150c017df7c03faf846c51DRC                for (j = 0; j < DCTSIZE; j++)
449e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
450e5eaf37440b8e337ab150c017df7c03faf846c51DRC              }
451e5eaf37440b8e337ab150c017df7c03faf846c51DRC            } else {
452e5eaf37440b8e337ab150c017df7c03faf846c51DRC              /* Edge blocks are transposed but not mirrored. */
453e5eaf37440b8e337ab150c017df7c03faf846c51DRC              src_ptr = src_buffer[offset_x]
454e5eaf37440b8e337ab150c017df7c03faf846c51DRC                [dst_blk_y + offset_y + y_crop_blocks];
455e5eaf37440b8e337ab150c017df7c03faf846c51DRC              for (i = 0; i < DCTSIZE; i++)
456e5eaf37440b8e337ab150c017df7c03faf846c51DRC                for (j = 0; j < DCTSIZE; j++)
457e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
458e5eaf37440b8e337ab150c017df7c03faf846c51DRC            }
459e5eaf37440b8e337ab150c017df7c03faf846c51DRC          }
460e5eaf37440b8e337ab150c017df7c03faf846c51DRC        }
4615ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      }
4625ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    }
4635ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  }
4645ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane}
4655ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
4665ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
4675ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneLOCAL(void)
4685ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lanedo_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
469e5eaf37440b8e337ab150c017df7c03faf846c51DRC            JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
470e5eaf37440b8e337ab150c017df7c03faf846c51DRC            jvirt_barray_ptr *src_coef_arrays,
471e5eaf37440b8e337ab150c017df7c03faf846c51DRC            jvirt_barray_ptr *dst_coef_arrays)
4725ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* 270 degree rotation is equivalent to
4735ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *   1. Horizontal mirroring;
4745ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *   2. Transposing the image.
4755ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * These two steps are merged into a single processing routine.
4765ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */
4775ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{
4785ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
4795996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  JDIMENSION x_crop_blocks, y_crop_blocks;
4805ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  int ci, i, j, offset_x, offset_y;
4815ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  JBLOCKARRAY src_buffer, dst_buffer;
4825ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  JCOEFPTR src_ptr, dst_ptr;
4835ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  jpeg_component_info *compptr;
4845ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
4855ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  /* Because of the horizontal mirror step, we can't process partial iMCUs
4865ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   * at the (output) bottom edge properly.  They just get transposed and
4875ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   * not mirrored.
4885ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   */
489989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  MCU_rows = srcinfo->output_width /
490c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC    (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
4915ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
4925ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  for (ci = 0; ci < dstinfo->num_components; ci++) {
4935ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    compptr = dstinfo->comp_info + ci;
4945ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    comp_height = MCU_rows * compptr->v_samp_factor;
4955996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
4965996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
4975ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
498e5eaf37440b8e337ab150c017df7c03faf846c51DRC         dst_blk_y += compptr->v_samp_factor) {
4995ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      dst_buffer = (*srcinfo->mem->access_virt_barray)
500e5eaf37440b8e337ab150c017df7c03faf846c51DRC        ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
501e5eaf37440b8e337ab150c017df7c03faf846c51DRC         (JDIMENSION) compptr->v_samp_factor, TRUE);
5025ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
503e5eaf37440b8e337ab150c017df7c03faf846c51DRC        for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
504e5eaf37440b8e337ab150c017df7c03faf846c51DRC             dst_blk_x += compptr->h_samp_factor) {
505e5eaf37440b8e337ab150c017df7c03faf846c51DRC          src_buffer = (*srcinfo->mem->access_virt_barray)
506e5eaf37440b8e337ab150c017df7c03faf846c51DRC            ((j_common_ptr) srcinfo, src_coef_arrays[ci],
507e5eaf37440b8e337ab150c017df7c03faf846c51DRC             dst_blk_x + x_crop_blocks,
508e5eaf37440b8e337ab150c017df7c03faf846c51DRC             (JDIMENSION) compptr->h_samp_factor, FALSE);
509e5eaf37440b8e337ab150c017df7c03faf846c51DRC          for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
510e5eaf37440b8e337ab150c017df7c03faf846c51DRC            dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
511e5eaf37440b8e337ab150c017df7c03faf846c51DRC            if (y_crop_blocks + dst_blk_y < comp_height) {
512e5eaf37440b8e337ab150c017df7c03faf846c51DRC              /* Block is within the mirrorable area. */
513e5eaf37440b8e337ab150c017df7c03faf846c51DRC              src_ptr = src_buffer[offset_x]
514e5eaf37440b8e337ab150c017df7c03faf846c51DRC                [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
515e5eaf37440b8e337ab150c017df7c03faf846c51DRC              for (i = 0; i < DCTSIZE; i++) {
516e5eaf37440b8e337ab150c017df7c03faf846c51DRC                for (j = 0; j < DCTSIZE; j++) {
517e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
518e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  j++;
519e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
520e5eaf37440b8e337ab150c017df7c03faf846c51DRC                }
521e5eaf37440b8e337ab150c017df7c03faf846c51DRC              }
522e5eaf37440b8e337ab150c017df7c03faf846c51DRC            } else {
523e5eaf37440b8e337ab150c017df7c03faf846c51DRC              /* Edge blocks are transposed but not mirrored. */
524e5eaf37440b8e337ab150c017df7c03faf846c51DRC              src_ptr = src_buffer[offset_x]
525e5eaf37440b8e337ab150c017df7c03faf846c51DRC                [dst_blk_y + offset_y + y_crop_blocks];
526e5eaf37440b8e337ab150c017df7c03faf846c51DRC              for (i = 0; i < DCTSIZE; i++)
527e5eaf37440b8e337ab150c017df7c03faf846c51DRC                for (j = 0; j < DCTSIZE; j++)
528e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
529e5eaf37440b8e337ab150c017df7c03faf846c51DRC            }
530e5eaf37440b8e337ab150c017df7c03faf846c51DRC          }
531e5eaf37440b8e337ab150c017df7c03faf846c51DRC        }
5325ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      }
5335ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    }
5345ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  }
5355ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane}
5365ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
5375ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
5385ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneLOCAL(void)
5395ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lanedo_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
540e5eaf37440b8e337ab150c017df7c03faf846c51DRC            JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
541e5eaf37440b8e337ab150c017df7c03faf846c51DRC            jvirt_barray_ptr *src_coef_arrays,
542e5eaf37440b8e337ab150c017df7c03faf846c51DRC            jvirt_barray_ptr *dst_coef_arrays)
5435ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* 180 degree rotation is equivalent to
5445ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *   1. Vertical mirroring;
5455ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *   2. Horizontal mirroring.
5465ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * These two steps are merged into a single processing routine.
5475ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */
5485ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{
5495ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
5505996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  JDIMENSION x_crop_blocks, y_crop_blocks;
5515ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  int ci, i, j, offset_y;
5525ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  JBLOCKARRAY src_buffer, dst_buffer;
5535ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  JBLOCKROW src_row_ptr, dst_row_ptr;
5545ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  JCOEFPTR src_ptr, dst_ptr;
5555ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  jpeg_component_info *compptr;
5565ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
557989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  MCU_cols = srcinfo->output_width /
558c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC    (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
559989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  MCU_rows = srcinfo->output_height /
560c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC    (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
5615ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
5625ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  for (ci = 0; ci < dstinfo->num_components; ci++) {
5635ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    compptr = dstinfo->comp_info + ci;
5645ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    comp_width = MCU_cols * compptr->h_samp_factor;
5655ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    comp_height = MCU_rows * compptr->v_samp_factor;
5665996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
5675996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
5685ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
569e5eaf37440b8e337ab150c017df7c03faf846c51DRC         dst_blk_y += compptr->v_samp_factor) {
5705ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      dst_buffer = (*srcinfo->mem->access_virt_barray)
571e5eaf37440b8e337ab150c017df7c03faf846c51DRC        ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
572e5eaf37440b8e337ab150c017df7c03faf846c51DRC         (JDIMENSION) compptr->v_samp_factor, TRUE);
5735996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      if (y_crop_blocks + dst_blk_y < comp_height) {
574e5eaf37440b8e337ab150c017df7c03faf846c51DRC        /* Row is within the vertically mirrorable area. */
575e5eaf37440b8e337ab150c017df7c03faf846c51DRC        src_buffer = (*srcinfo->mem->access_virt_barray)
576e5eaf37440b8e337ab150c017df7c03faf846c51DRC          ((j_common_ptr) srcinfo, src_coef_arrays[ci],
577e5eaf37440b8e337ab150c017df7c03faf846c51DRC           comp_height - y_crop_blocks - dst_blk_y -
578e5eaf37440b8e337ab150c017df7c03faf846c51DRC           (JDIMENSION) compptr->v_samp_factor,
579e5eaf37440b8e337ab150c017df7c03faf846c51DRC           (JDIMENSION) compptr->v_samp_factor, FALSE);
5805ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      } else {
581e5eaf37440b8e337ab150c017df7c03faf846c51DRC        /* Bottom-edge rows are only mirrored horizontally. */
582e5eaf37440b8e337ab150c017df7c03faf846c51DRC        src_buffer = (*srcinfo->mem->access_virt_barray)
583e5eaf37440b8e337ab150c017df7c03faf846c51DRC          ((j_common_ptr) srcinfo, src_coef_arrays[ci],
584e5eaf37440b8e337ab150c017df7c03faf846c51DRC           dst_blk_y + y_crop_blocks,
585e5eaf37440b8e337ab150c017df7c03faf846c51DRC           (JDIMENSION) compptr->v_samp_factor, FALSE);
5865ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      }
5875ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
588e5eaf37440b8e337ab150c017df7c03faf846c51DRC        dst_row_ptr = dst_buffer[offset_y];
589e5eaf37440b8e337ab150c017df7c03faf846c51DRC        if (y_crop_blocks + dst_blk_y < comp_height) {
590e5eaf37440b8e337ab150c017df7c03faf846c51DRC          /* Row is within the mirrorable area. */
591e5eaf37440b8e337ab150c017df7c03faf846c51DRC          src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
592e5eaf37440b8e337ab150c017df7c03faf846c51DRC          for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
593e5eaf37440b8e337ab150c017df7c03faf846c51DRC            dst_ptr = dst_row_ptr[dst_blk_x];
594e5eaf37440b8e337ab150c017df7c03faf846c51DRC            if (x_crop_blocks + dst_blk_x < comp_width) {
595e5eaf37440b8e337ab150c017df7c03faf846c51DRC              /* Process the blocks that can be mirrored both ways. */
596e5eaf37440b8e337ab150c017df7c03faf846c51DRC              src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
597e5eaf37440b8e337ab150c017df7c03faf846c51DRC              for (i = 0; i < DCTSIZE; i += 2) {
598e5eaf37440b8e337ab150c017df7c03faf846c51DRC                /* For even row, negate every odd column. */
599e5eaf37440b8e337ab150c017df7c03faf846c51DRC                for (j = 0; j < DCTSIZE; j += 2) {
600e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  *dst_ptr++ = *src_ptr++;
601e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  *dst_ptr++ = - *src_ptr++;
602e5eaf37440b8e337ab150c017df7c03faf846c51DRC                }
603e5eaf37440b8e337ab150c017df7c03faf846c51DRC                /* For odd row, negate every even column. */
604e5eaf37440b8e337ab150c017df7c03faf846c51DRC                for (j = 0; j < DCTSIZE; j += 2) {
605e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  *dst_ptr++ = - *src_ptr++;
606e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  *dst_ptr++ = *src_ptr++;
607e5eaf37440b8e337ab150c017df7c03faf846c51DRC                }
608e5eaf37440b8e337ab150c017df7c03faf846c51DRC              }
609e5eaf37440b8e337ab150c017df7c03faf846c51DRC            } else {
610e5eaf37440b8e337ab150c017df7c03faf846c51DRC              /* Any remaining right-edge blocks are only mirrored vertically. */
611e5eaf37440b8e337ab150c017df7c03faf846c51DRC              src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x];
612e5eaf37440b8e337ab150c017df7c03faf846c51DRC              for (i = 0; i < DCTSIZE; i += 2) {
613e5eaf37440b8e337ab150c017df7c03faf846c51DRC                for (j = 0; j < DCTSIZE; j++)
614e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  *dst_ptr++ = *src_ptr++;
615e5eaf37440b8e337ab150c017df7c03faf846c51DRC                for (j = 0; j < DCTSIZE; j++)
616e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  *dst_ptr++ = - *src_ptr++;
617e5eaf37440b8e337ab150c017df7c03faf846c51DRC              }
618e5eaf37440b8e337ab150c017df7c03faf846c51DRC            }
619e5eaf37440b8e337ab150c017df7c03faf846c51DRC          }
620e5eaf37440b8e337ab150c017df7c03faf846c51DRC        } else {
621e5eaf37440b8e337ab150c017df7c03faf846c51DRC          /* Remaining rows are just mirrored horizontally. */
622e5eaf37440b8e337ab150c017df7c03faf846c51DRC          src_row_ptr = src_buffer[offset_y];
623e5eaf37440b8e337ab150c017df7c03faf846c51DRC          for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
624e5eaf37440b8e337ab150c017df7c03faf846c51DRC            if (x_crop_blocks + dst_blk_x < comp_width) {
625e5eaf37440b8e337ab150c017df7c03faf846c51DRC              /* Process the blocks that can be mirrored. */
626e5eaf37440b8e337ab150c017df7c03faf846c51DRC              dst_ptr = dst_row_ptr[dst_blk_x];
627e5eaf37440b8e337ab150c017df7c03faf846c51DRC              src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
628e5eaf37440b8e337ab150c017df7c03faf846c51DRC              for (i = 0; i < DCTSIZE2; i += 2) {
629e5eaf37440b8e337ab150c017df7c03faf846c51DRC                *dst_ptr++ = *src_ptr++;
630e5eaf37440b8e337ab150c017df7c03faf846c51DRC                *dst_ptr++ = - *src_ptr++;
631e5eaf37440b8e337ab150c017df7c03faf846c51DRC              }
632e5eaf37440b8e337ab150c017df7c03faf846c51DRC            } else {
633e5eaf37440b8e337ab150c017df7c03faf846c51DRC              /* Any remaining right-edge blocks are only copied. */
634e5eaf37440b8e337ab150c017df7c03faf846c51DRC              jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
635e5eaf37440b8e337ab150c017df7c03faf846c51DRC                              dst_row_ptr + dst_blk_x,
636e5eaf37440b8e337ab150c017df7c03faf846c51DRC                              (JDIMENSION) 1);
637e5eaf37440b8e337ab150c017df7c03faf846c51DRC            }
638e5eaf37440b8e337ab150c017df7c03faf846c51DRC          }
639e5eaf37440b8e337ab150c017df7c03faf846c51DRC        }
6405ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      }
6415ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    }
6425ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  }
6435ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane}
6445ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
6455ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
6465ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneLOCAL(void)
6475ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lanedo_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
648e5eaf37440b8e337ab150c017df7c03faf846c51DRC               JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
649e5eaf37440b8e337ab150c017df7c03faf846c51DRC               jvirt_barray_ptr *src_coef_arrays,
650e5eaf37440b8e337ab150c017df7c03faf846c51DRC               jvirt_barray_ptr *dst_coef_arrays)
6515ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* Transverse transpose is equivalent to
6525ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *   1. 180 degree rotation;
6535ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *   2. Transposition;
6545ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * or
6555ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *   1. Horizontal mirroring;
6565ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *   2. Transposition;
6575ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *   3. Horizontal mirroring.
6585ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * These steps are merged into a single processing routine.
6595ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */
6605ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{
6615ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
6625996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  JDIMENSION x_crop_blocks, y_crop_blocks;
6635ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  int ci, i, j, offset_x, offset_y;
6645ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  JBLOCKARRAY src_buffer, dst_buffer;
6655ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  JCOEFPTR src_ptr, dst_ptr;
6665ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  jpeg_component_info *compptr;
6675ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
668989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  MCU_cols = srcinfo->output_height /
669c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC    (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
670989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  MCU_rows = srcinfo->output_width /
671c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC    (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
6725ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
6735ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  for (ci = 0; ci < dstinfo->num_components; ci++) {
6745ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    compptr = dstinfo->comp_info + ci;
6755ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    comp_width = MCU_cols * compptr->h_samp_factor;
6765ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    comp_height = MCU_rows * compptr->v_samp_factor;
6775996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
6785996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
6795ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
680e5eaf37440b8e337ab150c017df7c03faf846c51DRC         dst_blk_y += compptr->v_samp_factor) {
6815ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      dst_buffer = (*srcinfo->mem->access_virt_barray)
682e5eaf37440b8e337ab150c017df7c03faf846c51DRC        ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
683e5eaf37440b8e337ab150c017df7c03faf846c51DRC         (JDIMENSION) compptr->v_samp_factor, TRUE);
6845ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
685e5eaf37440b8e337ab150c017df7c03faf846c51DRC        for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
686e5eaf37440b8e337ab150c017df7c03faf846c51DRC             dst_blk_x += compptr->h_samp_factor) {
687e5eaf37440b8e337ab150c017df7c03faf846c51DRC          if (x_crop_blocks + dst_blk_x < comp_width) {
688e5eaf37440b8e337ab150c017df7c03faf846c51DRC            /* Block is within the mirrorable area. */
689e5eaf37440b8e337ab150c017df7c03faf846c51DRC            src_buffer = (*srcinfo->mem->access_virt_barray)
690e5eaf37440b8e337ab150c017df7c03faf846c51DRC              ((j_common_ptr) srcinfo, src_coef_arrays[ci],
691e5eaf37440b8e337ab150c017df7c03faf846c51DRC               comp_width - x_crop_blocks - dst_blk_x -
692e5eaf37440b8e337ab150c017df7c03faf846c51DRC               (JDIMENSION) compptr->h_samp_factor,
693e5eaf37440b8e337ab150c017df7c03faf846c51DRC               (JDIMENSION) compptr->h_samp_factor, FALSE);
694e5eaf37440b8e337ab150c017df7c03faf846c51DRC          } else {
695e5eaf37440b8e337ab150c017df7c03faf846c51DRC            src_buffer = (*srcinfo->mem->access_virt_barray)
696e5eaf37440b8e337ab150c017df7c03faf846c51DRC              ((j_common_ptr) srcinfo, src_coef_arrays[ci],
697e5eaf37440b8e337ab150c017df7c03faf846c51DRC               dst_blk_x + x_crop_blocks,
698e5eaf37440b8e337ab150c017df7c03faf846c51DRC               (JDIMENSION) compptr->h_samp_factor, FALSE);
699e5eaf37440b8e337ab150c017df7c03faf846c51DRC          }
700e5eaf37440b8e337ab150c017df7c03faf846c51DRC          for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
701e5eaf37440b8e337ab150c017df7c03faf846c51DRC            dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
702e5eaf37440b8e337ab150c017df7c03faf846c51DRC            if (y_crop_blocks + dst_blk_y < comp_height) {
703e5eaf37440b8e337ab150c017df7c03faf846c51DRC              if (x_crop_blocks + dst_blk_x < comp_width) {
704e5eaf37440b8e337ab150c017df7c03faf846c51DRC                /* Block is within the mirrorable area. */
705e5eaf37440b8e337ab150c017df7c03faf846c51DRC                src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
706e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
707e5eaf37440b8e337ab150c017df7c03faf846c51DRC                for (i = 0; i < DCTSIZE; i++) {
708e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  for (j = 0; j < DCTSIZE; j++) {
709e5eaf37440b8e337ab150c017df7c03faf846c51DRC                    dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
710e5eaf37440b8e337ab150c017df7c03faf846c51DRC                    j++;
711e5eaf37440b8e337ab150c017df7c03faf846c51DRC                    dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
712e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  }
713e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  i++;
714e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  for (j = 0; j < DCTSIZE; j++) {
715e5eaf37440b8e337ab150c017df7c03faf846c51DRC                    dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
716e5eaf37440b8e337ab150c017df7c03faf846c51DRC                    j++;
717e5eaf37440b8e337ab150c017df7c03faf846c51DRC                    dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
718e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  }
719e5eaf37440b8e337ab150c017df7c03faf846c51DRC                }
720e5eaf37440b8e337ab150c017df7c03faf846c51DRC              } else {
721e5eaf37440b8e337ab150c017df7c03faf846c51DRC                /* Right-edge blocks are mirrored in y only */
722e5eaf37440b8e337ab150c017df7c03faf846c51DRC                src_ptr = src_buffer[offset_x]
723e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
724e5eaf37440b8e337ab150c017df7c03faf846c51DRC                for (i = 0; i < DCTSIZE; i++) {
725e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  for (j = 0; j < DCTSIZE; j++) {
726e5eaf37440b8e337ab150c017df7c03faf846c51DRC                    dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
727e5eaf37440b8e337ab150c017df7c03faf846c51DRC                    j++;
728e5eaf37440b8e337ab150c017df7c03faf846c51DRC                    dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
729e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  }
730e5eaf37440b8e337ab150c017df7c03faf846c51DRC                }
731e5eaf37440b8e337ab150c017df7c03faf846c51DRC              }
732e5eaf37440b8e337ab150c017df7c03faf846c51DRC            } else {
733e5eaf37440b8e337ab150c017df7c03faf846c51DRC              if (x_crop_blocks + dst_blk_x < comp_width) {
734e5eaf37440b8e337ab150c017df7c03faf846c51DRC                /* Bottom-edge blocks are mirrored in x only */
735e5eaf37440b8e337ab150c017df7c03faf846c51DRC                src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
736e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  [dst_blk_y + offset_y + y_crop_blocks];
737e5eaf37440b8e337ab150c017df7c03faf846c51DRC                for (i = 0; i < DCTSIZE; i++) {
738e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  for (j = 0; j < DCTSIZE; j++)
739e5eaf37440b8e337ab150c017df7c03faf846c51DRC                    dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
740e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  i++;
741e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  for (j = 0; j < DCTSIZE; j++)
742e5eaf37440b8e337ab150c017df7c03faf846c51DRC                    dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
743e5eaf37440b8e337ab150c017df7c03faf846c51DRC                }
744e5eaf37440b8e337ab150c017df7c03faf846c51DRC              } else {
745e5eaf37440b8e337ab150c017df7c03faf846c51DRC                /* At lower right corner, just transpose, no mirroring */
746e5eaf37440b8e337ab150c017df7c03faf846c51DRC                src_ptr = src_buffer[offset_x]
747e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  [dst_blk_y + offset_y + y_crop_blocks];
748e5eaf37440b8e337ab150c017df7c03faf846c51DRC                for (i = 0; i < DCTSIZE; i++)
749e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  for (j = 0; j < DCTSIZE; j++)
750e5eaf37440b8e337ab150c017df7c03faf846c51DRC                    dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
751e5eaf37440b8e337ab150c017df7c03faf846c51DRC              }
752e5eaf37440b8e337ab150c017df7c03faf846c51DRC            }
753e5eaf37440b8e337ab150c017df7c03faf846c51DRC          }
754e5eaf37440b8e337ab150c017df7c03faf846c51DRC        }
7555ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      }
7565ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    }
7575ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  }
7585ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane}
7595ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
7605ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
7615996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding/* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec.
7625996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * Returns TRUE if valid integer found, FALSE if not.
7635996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * *strptr is advanced over the digit string, and *result is set to its value.
7645996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding */
7655996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
7665996a25e2f50d20d6a8f09830724035b49c3927bGuido VollbedingLOCAL(boolean)
7676eb7d3798b5a79347c62825fc4c16f7ce673bdd0Alex Naidisjt_read_integer (const char **strptr, JDIMENSION *result)
7685996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding{
7696eb7d3798b5a79347c62825fc4c16f7ce673bdd0Alex Naidis  const char *ptr = *strptr;
7705996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  JDIMENSION val = 0;
7715996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
7725996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  for (; isdigit(*ptr); ptr++) {
7735996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    val = val * 10 + (JDIMENSION) (*ptr - '0');
7745996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  }
7755996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  *result = val;
7765996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  if (ptr == *strptr)
777e5eaf37440b8e337ab150c017df7c03faf846c51DRC    return FALSE;               /* oops, no digits */
7785996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  *strptr = ptr;
7795996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  return TRUE;
7805996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding}
7815996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
7825996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
7835996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding/* Parse a crop specification (written in X11 geometry style).
7845996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * The routine returns TRUE if the spec string is valid, FALSE if not.
7855996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding *
7865996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * The crop spec string should have the format
787e5eaf37440b8e337ab150c017df7c03faf846c51DRC *      <width>[f]x<height>[f]{+-}<xoffset>{+-}<yoffset>
7885996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * where width, height, xoffset, and yoffset are unsigned integers.
7895996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * Each of the elements can be omitted to indicate a default value.
7905996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * (A weakness of this style is that it is not possible to omit xoffset
7915996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * while specifying yoffset, since they look alike.)
7925996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding *
7935996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * This code is loosely based on XParseGeometry from the X11 distribution.
7945996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding */
7955996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
7965996a25e2f50d20d6a8f09830724035b49c3927bGuido VollbedingGLOBAL(boolean)
7975996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbedingjtransform_parse_crop_spec (jpeg_transform_info *info, const char *spec)
7985996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding{
7995996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  info->crop = FALSE;
8005996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  info->crop_width_set = JCROP_UNSET;
8015996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  info->crop_height_set = JCROP_UNSET;
8025996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  info->crop_xoffset_set = JCROP_UNSET;
8035996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  info->crop_yoffset_set = JCROP_UNSET;
8045996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
8055996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  if (isdigit(*spec)) {
8065996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    /* fetch width */
8075996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (! jt_read_integer(&spec, &info->crop_width))
8085996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      return FALSE;
8095829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding    if (*spec == 'f' || *spec == 'F') {
8105829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding      spec++;
8115829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding      info->crop_width_set = JCROP_FORCE;
8125829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding    } else
8135829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding      info->crop_width_set = JCROP_POS;
8145996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  }
8155829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding  if (*spec == 'x' || *spec == 'X') {
8165996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    /* fetch height */
8175996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    spec++;
8185996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (! jt_read_integer(&spec, &info->crop_height))
8195996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      return FALSE;
8205829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding    if (*spec == 'f' || *spec == 'F') {
8215829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding      spec++;
8225829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding      info->crop_height_set = JCROP_FORCE;
8235829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding    } else
8245829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding      info->crop_height_set = JCROP_POS;
8255996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  }
8265996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  if (*spec == '+' || *spec == '-') {
8275996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    /* fetch xoffset */
8285996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
8295996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    spec++;
8305996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (! jt_read_integer(&spec, &info->crop_xoffset))
8315996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      return FALSE;
8325996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  }
8335996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  if (*spec == '+' || *spec == '-') {
8345996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    /* fetch yoffset */
8355996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
8365996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    spec++;
8375996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (! jt_read_integer(&spec, &info->crop_yoffset))
8385996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      return FALSE;
8395996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  }
8405996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  /* We had better have gotten to the end of the string. */
8415996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  if (*spec != '\0')
8425996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    return FALSE;
8435996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  info->crop = TRUE;
8445996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  return TRUE;
8455996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding}
8465996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
8475996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
8485996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding/* Trim off any partial iMCUs on the indicated destination edge */
8495996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
8505996a25e2f50d20d6a8f09830724035b49c3927bGuido VollbedingLOCAL(void)
8515996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbedingtrim_right_edge (jpeg_transform_info *info, JDIMENSION full_width)
8525996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding{
8535996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  JDIMENSION MCU_cols;
8545996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
855989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  MCU_cols = info->output_width / info->iMCU_sample_width;
8565996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  if (MCU_cols > 0 && info->x_crop_offset + MCU_cols ==
857989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding      full_width / info->iMCU_sample_width)
858989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding    info->output_width = MCU_cols * info->iMCU_sample_width;
8595996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding}
8605996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
8615996a25e2f50d20d6a8f09830724035b49c3927bGuido VollbedingLOCAL(void)
8625996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbedingtrim_bottom_edge (jpeg_transform_info *info, JDIMENSION full_height)
8635996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding{
8645996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  JDIMENSION MCU_rows;
8655996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
866989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  MCU_rows = info->output_height / info->iMCU_sample_height;
8675996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  if (MCU_rows > 0 && info->y_crop_offset + MCU_rows ==
868989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding      full_height / info->iMCU_sample_height)
869989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding    info->output_height = MCU_rows * info->iMCU_sample_height;
8705996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding}
8715996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
8725996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
8735ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* Request any required workspace.
8745ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *
8755996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * This routine figures out the size that the output image will be
8765996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * (which implies that all the transform parameters must be set before
8775996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * it is called).
8785996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding *
8795ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * We allocate the workspace virtual arrays from the source decompression
8805ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * object, so that all the arrays (both the original data and the workspace)
8815ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * will be taken into account while making memory management decisions.
8825ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * Hence, this routine must be called after jpeg_read_header (which reads
8835ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * the image dimensions) and before jpeg_read_coefficients (which realizes
8845ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * the source's virtual arrays).
885989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding *
886989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding * This function returns FALSE right away if -perfect is given
887989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding * and transformation is not perfect.  Otherwise returns TRUE.
8885ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */
8895ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
890989630f70cf1af69ebfefca8910d1647bf189712Guido VollbedingGLOBAL(boolean)
8915ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lanejtransform_request_workspace (j_decompress_ptr srcinfo,
892e5eaf37440b8e337ab150c017df7c03faf846c51DRC                              jpeg_transform_info *info)
8935ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{
894989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  jvirt_barray_ptr *coef_arrays;
8955996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  boolean need_workspace, transpose_it;
8965ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  jpeg_component_info *compptr;
897989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  JDIMENSION xoffset, yoffset;
898989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  JDIMENSION width_in_iMCUs, height_in_iMCUs;
8995996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  JDIMENSION width_in_blocks, height_in_blocks;
9005996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  int ci, h_samp_factor, v_samp_factor;
9015ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
9025996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  /* Determine number of components in output image */
9035ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  if (info->force_grayscale &&
9045ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      srcinfo->jpeg_color_space == JCS_YCbCr &&
905989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding      srcinfo->num_components == 3)
9065ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    /* We'll only process the first component */
9075ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    info->num_components = 1;
908989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  else
9095ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    /* Process all the components */
9105ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    info->num_components = srcinfo->num_components;
911989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding
912989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  /* Compute output image dimensions and related values. */
913c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#if JPEG_LIB_VERSION >= 80
914989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  jpeg_core_output_dimensions(srcinfo);
915c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#else
916c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC  srcinfo->output_width = srcinfo->image_width;
917c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC  srcinfo->output_height = srcinfo->image_height;
918c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#endif
919989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding
920989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  /* Return right away if -perfect is given and transformation is not perfect.
921989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding   */
922989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  if (info->perfect) {
923989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding    if (info->num_components == 1) {
924989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding      if (!jtransform_perfect_transform(srcinfo->output_width,
925e5eaf37440b8e337ab150c017df7c03faf846c51DRC          srcinfo->output_height,
926e5eaf37440b8e337ab150c017df7c03faf846c51DRC          srcinfo->_min_DCT_h_scaled_size,
927e5eaf37440b8e337ab150c017df7c03faf846c51DRC          srcinfo->_min_DCT_v_scaled_size,
928e5eaf37440b8e337ab150c017df7c03faf846c51DRC          info->transform))
929e5eaf37440b8e337ab150c017df7c03faf846c51DRC        return FALSE;
930989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding    } else {
931989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding      if (!jtransform_perfect_transform(srcinfo->output_width,
932e5eaf37440b8e337ab150c017df7c03faf846c51DRC          srcinfo->output_height,
933e5eaf37440b8e337ab150c017df7c03faf846c51DRC          srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size,
934e5eaf37440b8e337ab150c017df7c03faf846c51DRC          srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size,
935e5eaf37440b8e337ab150c017df7c03faf846c51DRC          info->transform))
936e5eaf37440b8e337ab150c017df7c03faf846c51DRC        return FALSE;
937989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding    }
9385ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  }
9395ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
9405996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  /* If there is only one output component, force the iMCU size to be 1;
9415996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding   * else use the source iMCU size.  (This allows us to do the right thing
9425996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding   * when reducing color to grayscale, and also provides a handy way of
9435996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding   * cleaning up "funny" grayscale images whose sampling factors are not 1x1.)
9445996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding   */
9455ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  switch (info->transform) {
9465996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  case JXFORM_TRANSPOSE:
9475996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  case JXFORM_TRANSVERSE:
9485996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  case JXFORM_ROT_90:
9495996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  case JXFORM_ROT_270:
950989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding    info->output_width = srcinfo->output_height;
951989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding    info->output_height = srcinfo->output_width;
9525996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (info->num_components == 1) {
953c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC      info->iMCU_sample_width = srcinfo->_min_DCT_v_scaled_size;
954c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC      info->iMCU_sample_height = srcinfo->_min_DCT_h_scaled_size;
9555996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    } else {
956989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding      info->iMCU_sample_width =
957e5eaf37440b8e337ab150c017df7c03faf846c51DRC        srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size;
958989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding      info->iMCU_sample_height =
959e5eaf37440b8e337ab150c017df7c03faf846c51DRC        srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size;
9605996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    }
9615996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    break;
9625996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  default:
963989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding    info->output_width = srcinfo->output_width;
964989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding    info->output_height = srcinfo->output_height;
9655996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (info->num_components == 1) {
966c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC      info->iMCU_sample_width = srcinfo->_min_DCT_h_scaled_size;
967c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC      info->iMCU_sample_height = srcinfo->_min_DCT_v_scaled_size;
9685996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    } else {
969989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding      info->iMCU_sample_width =
970e5eaf37440b8e337ab150c017df7c03faf846c51DRC        srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size;
971989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding      info->iMCU_sample_height =
972e5eaf37440b8e337ab150c017df7c03faf846c51DRC        srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size;
9735996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    }
9745996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    break;
9755996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  }
9765996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
9775996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  /* If cropping has been requested, compute the crop area's position and
9785996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding   * dimensions, ensuring that its upper left corner falls at an iMCU boundary.
9795996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding   */
9805996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  if (info->crop) {
9815996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    /* Insert default values for unset crop parameters */
9825996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (info->crop_xoffset_set == JCROP_UNSET)
983e5eaf37440b8e337ab150c017df7c03faf846c51DRC      info->crop_xoffset = 0;   /* default to +0 */
9845996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (info->crop_yoffset_set == JCROP_UNSET)
985e5eaf37440b8e337ab150c017df7c03faf846c51DRC      info->crop_yoffset = 0;   /* default to +0 */
9865996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (info->crop_xoffset >= info->output_width ||
987e5eaf37440b8e337ab150c017df7c03faf846c51DRC        info->crop_yoffset >= info->output_height)
9885996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
9895996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (info->crop_width_set == JCROP_UNSET)
9905996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      info->crop_width = info->output_width - info->crop_xoffset;
9915996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (info->crop_height_set == JCROP_UNSET)
9925996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      info->crop_height = info->output_height - info->crop_yoffset;
9935996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    /* Ensure parameters are valid */
9945996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (info->crop_width <= 0 || info->crop_width > info->output_width ||
995e5eaf37440b8e337ab150c017df7c03faf846c51DRC        info->crop_height <= 0 || info->crop_height > info->output_height ||
996e5eaf37440b8e337ab150c017df7c03faf846c51DRC        info->crop_xoffset > info->output_width - info->crop_width ||
997e5eaf37440b8e337ab150c017df7c03faf846c51DRC        info->crop_yoffset > info->output_height - info->crop_height)
9985996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
9995996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    /* Convert negative crop offsets into regular offsets */
10005996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (info->crop_xoffset_set == JCROP_NEG)
10015996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      xoffset = info->output_width - info->crop_width - info->crop_xoffset;
10025996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    else
10035996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      xoffset = info->crop_xoffset;
10045996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (info->crop_yoffset_set == JCROP_NEG)
10055996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      yoffset = info->output_height - info->crop_height - info->crop_yoffset;
10065996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    else
10075996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      yoffset = info->crop_yoffset;
10085996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    /* Now adjust so that upper left corner falls at an iMCU boundary */
10095829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding    if (info->crop_width_set == JCROP_FORCE)
10105829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding      info->output_width = info->crop_width;
10115829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding    else
10125829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding      info->output_width =
10135829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding        info->crop_width + (xoffset % info->iMCU_sample_width);
10145829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding    if (info->crop_height_set == JCROP_FORCE)
10155829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding      info->output_height = info->crop_height;
10165829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding    else
10175829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding      info->output_height =
10185829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding        info->crop_height + (yoffset % info->iMCU_sample_height);
10195996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    /* Save x/y offsets measured in iMCUs */
1020989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding    info->x_crop_offset = xoffset / info->iMCU_sample_width;
1021989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding    info->y_crop_offset = yoffset / info->iMCU_sample_height;
10225996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  } else {
10235996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    info->x_crop_offset = 0;
10245996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    info->y_crop_offset = 0;
10255996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  }
10265996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
10275996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  /* Figure out whether we need workspace arrays,
10285996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding   * and if so whether they are transposed relative to the source.
10295996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding   */
10305996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  need_workspace = FALSE;
10315996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  transpose_it = FALSE;
10325ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  switch (info->transform) {
10335ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  case JXFORM_NONE:
10345996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
10355996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      need_workspace = TRUE;
10365996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    /* No workspace needed if neither cropping nor transforming */
10375996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    break;
10385ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  case JXFORM_FLIP_H:
10395996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (info->trim)
1040989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding      trim_right_edge(info, srcinfo->output_width);
1041ba5ea5143e48b71234414139e3b4cb244599e875DRC    if (info->y_crop_offset != 0 || info->slow_hflip)
10425996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      need_workspace = TRUE;
10435996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    /* do_flip_h_no_crop doesn't need a workspace array */
10445ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    break;
10455ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  case JXFORM_FLIP_V:
10465996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (info->trim)
1047989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding      trim_bottom_edge(info, srcinfo->output_height);
10485996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    /* Need workspace arrays having same dimensions as source image. */
10495996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    need_workspace = TRUE;
10505ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    break;
10515ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  case JXFORM_TRANSPOSE:
10525996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    /* transpose does NOT have to trim anything */
10535996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    /* Need workspace arrays having transposed dimensions. */
10545996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    need_workspace = TRUE;
10555996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    transpose_it = TRUE;
10565996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    break;
10575ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  case JXFORM_TRANSVERSE:
10585996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (info->trim) {
1059989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding      trim_right_edge(info, srcinfo->output_height);
1060989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding      trim_bottom_edge(info, srcinfo->output_width);
10615996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    }
10625996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    /* Need workspace arrays having transposed dimensions. */
10635996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    need_workspace = TRUE;
10645996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    transpose_it = TRUE;
10655996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    break;
10665ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  case JXFORM_ROT_90:
10675996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (info->trim)
1068989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding      trim_right_edge(info, srcinfo->output_height);
10695996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    /* Need workspace arrays having transposed dimensions. */
10705996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    need_workspace = TRUE;
10715996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    transpose_it = TRUE;
10725996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    break;
10735996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  case JXFORM_ROT_180:
10745996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (info->trim) {
1075989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding      trim_right_edge(info, srcinfo->output_width);
1076989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding      trim_bottom_edge(info, srcinfo->output_height);
10775996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    }
10785996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    /* Need workspace arrays having same dimensions as source image. */
10795996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    need_workspace = TRUE;
10805996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    break;
10815ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  case JXFORM_ROT_270:
10825996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (info->trim)
1083989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding      trim_bottom_edge(info, srcinfo->output_width);
10845996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    /* Need workspace arrays having transposed dimensions. */
10855996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    need_workspace = TRUE;
10865996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    transpose_it = TRUE;
10875996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    break;
10885996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  }
10895996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
10905996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  /* Allocate workspace if needed.
10915996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding   * Note that we allocate arrays padded out to the next iMCU boundary,
10925996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding   * so that transform routines need not worry about missing edge blocks.
10935996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding   */
10945996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  if (need_workspace) {
10955ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    coef_arrays = (jvirt_barray_ptr *)
10965ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
10975de454b291f48382648a5d1dc2aa0fca8b5786d4DRC                sizeof(jvirt_barray_ptr) * info->num_components);
10985996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    width_in_iMCUs = (JDIMENSION)
10995996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      jdiv_round_up((long) info->output_width,
1100e5eaf37440b8e337ab150c017df7c03faf846c51DRC                    (long) info->iMCU_sample_width);
11015996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    height_in_iMCUs = (JDIMENSION)
11025996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      jdiv_round_up((long) info->output_height,
1103e5eaf37440b8e337ab150c017df7c03faf846c51DRC                    (long) info->iMCU_sample_height);
11045ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    for (ci = 0; ci < info->num_components; ci++) {
11055ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      compptr = srcinfo->comp_info + ci;
11065996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      if (info->num_components == 1) {
1107e5eaf37440b8e337ab150c017df7c03faf846c51DRC        /* we're going to force samp factors to 1x1 in this case */
1108e5eaf37440b8e337ab150c017df7c03faf846c51DRC        h_samp_factor = v_samp_factor = 1;
11095996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      } else if (transpose_it) {
1110e5eaf37440b8e337ab150c017df7c03faf846c51DRC        h_samp_factor = compptr->v_samp_factor;
1111e5eaf37440b8e337ab150c017df7c03faf846c51DRC        v_samp_factor = compptr->h_samp_factor;
11125996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      } else {
1113e5eaf37440b8e337ab150c017df7c03faf846c51DRC        h_samp_factor = compptr->h_samp_factor;
1114e5eaf37440b8e337ab150c017df7c03faf846c51DRC        v_samp_factor = compptr->v_samp_factor;
11155996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      }
11165996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      width_in_blocks = width_in_iMCUs * h_samp_factor;
11175996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      height_in_blocks = height_in_iMCUs * v_samp_factor;
11185ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
1119e5eaf37440b8e337ab150c017df7c03faf846c51DRC        ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
1120e5eaf37440b8e337ab150c017df7c03faf846c51DRC         width_in_blocks, height_in_blocks, (JDIMENSION) v_samp_factor);
11215ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    }
1122989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding    info->workspace_coef_arrays = coef_arrays;
1123989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  } else
1124989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding    info->workspace_coef_arrays = NULL;
11255996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
1126989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  return TRUE;
11275ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane}
11285ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
11295ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
11305ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* Transpose destination image parameters */
11315ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
11325ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneLOCAL(void)
11335ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lanetranspose_critical_parameters (j_compress_ptr dstinfo)
11345ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{
11355ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  int tblno, i, j, ci, itemp;
11365ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  jpeg_component_info *compptr;
11375ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  JQUANT_TBL *qtblptr;
1138989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  JDIMENSION jtemp;
11395ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  UINT16 qtemp;
11405ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
1141989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  /* Transpose image dimensions */
1142989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  jtemp = dstinfo->image_width;
11435ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  dstinfo->image_width = dstinfo->image_height;
1144989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  dstinfo->image_height = jtemp;
114536a6eec93250e390d1028b3372078810b4428eafDRC#if JPEG_LIB_VERSION >= 70
1146989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  itemp = dstinfo->min_DCT_h_scaled_size;
1147989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  dstinfo->min_DCT_h_scaled_size = dstinfo->min_DCT_v_scaled_size;
1148989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  dstinfo->min_DCT_v_scaled_size = itemp;
114936a6eec93250e390d1028b3372078810b4428eafDRC#endif
11505ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
11515ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  /* Transpose sampling factors */
11525ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  for (ci = 0; ci < dstinfo->num_components; ci++) {
11535ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    compptr = dstinfo->comp_info + ci;
11545ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    itemp = compptr->h_samp_factor;
11555ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    compptr->h_samp_factor = compptr->v_samp_factor;
11565ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    compptr->v_samp_factor = itemp;
11575ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  }
11585ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
11595ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  /* Transpose quantization tables */
11605ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
11615ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    qtblptr = dstinfo->quant_tbl_ptrs[tblno];
11625ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    if (qtblptr != NULL) {
11635ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      for (i = 0; i < DCTSIZE; i++) {
1164e5eaf37440b8e337ab150c017df7c03faf846c51DRC        for (j = 0; j < i; j++) {
1165e5eaf37440b8e337ab150c017df7c03faf846c51DRC          qtemp = qtblptr->quantval[i*DCTSIZE+j];
1166e5eaf37440b8e337ab150c017df7c03faf846c51DRC          qtblptr->quantval[i*DCTSIZE+j] = qtblptr->quantval[j*DCTSIZE+i];
1167e5eaf37440b8e337ab150c017df7c03faf846c51DRC          qtblptr->quantval[j*DCTSIZE+i] = qtemp;
1168e5eaf37440b8e337ab150c017df7c03faf846c51DRC        }
11695ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      }
11705ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    }
11715ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  }
11725ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane}
11735ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
11745ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
11755996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding/* Adjust Exif image parameters.
11765996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding *
11775996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible.
11785996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding */
11795ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
1180506a742193ed5549074f40c3e0d2f0fd2eefb22bDRC#if JPEG_LIB_VERSION >= 70
11815ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneLOCAL(void)
11826eb7d3798b5a79347c62825fc4c16f7ce673bdd0Alex Naidisadjust_exif_parameters (JOCTET *data, unsigned int length,
1183e5eaf37440b8e337ab150c017df7c03faf846c51DRC                        JDIMENSION new_width, JDIMENSION new_height)
11845ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{
11855996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  boolean is_motorola; /* Flag for byte order */
11865996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  unsigned int number_of_tags, tagnum;
11875996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  unsigned int firstoffset, offset;
11885996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  JDIMENSION new_value;
11895ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
11905996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  if (length < 12) return; /* Length of an IFD entry */
11915996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
11925996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  /* Discover byte order */
11935996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  if (GETJOCTET(data[0]) == 0x49 && GETJOCTET(data[1]) == 0x49)
11945996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    is_motorola = FALSE;
11955996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  else if (GETJOCTET(data[0]) == 0x4D && GETJOCTET(data[1]) == 0x4D)
11965996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    is_motorola = TRUE;
11975996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  else
11985996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    return;
11995996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
12005996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  /* Check Tag Mark */
12015996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  if (is_motorola) {
12025996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (GETJOCTET(data[2]) != 0) return;
12035996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (GETJOCTET(data[3]) != 0x2A) return;
12045996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  } else {
12055996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (GETJOCTET(data[3]) != 0) return;
12065996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (GETJOCTET(data[2]) != 0x2A) return;
12075ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  }
12085ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
12095996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  /* Get first IFD offset (offset to IFD0) */
12105996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  if (is_motorola) {
12115996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (GETJOCTET(data[4]) != 0) return;
12125996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (GETJOCTET(data[5]) != 0) return;
12135996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    firstoffset = GETJOCTET(data[6]);
12145996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    firstoffset <<= 8;
12155996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    firstoffset += GETJOCTET(data[7]);
12165996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  } else {
12175996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (GETJOCTET(data[7]) != 0) return;
12185996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (GETJOCTET(data[6]) != 0) return;
12195996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    firstoffset = GETJOCTET(data[5]);
12205996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    firstoffset <<= 8;
12215996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    firstoffset += GETJOCTET(data[4]);
12225996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  }
12235996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  if (firstoffset > length - 2) return; /* check end of data segment */
12245ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
12255996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  /* Get the number of directory entries contained in this IFD */
12265996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  if (is_motorola) {
12275996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    number_of_tags = GETJOCTET(data[firstoffset]);
12285996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    number_of_tags <<= 8;
12295996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    number_of_tags += GETJOCTET(data[firstoffset+1]);
12305996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  } else {
12315996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    number_of_tags = GETJOCTET(data[firstoffset+1]);
12325996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    number_of_tags <<= 8;
12335996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    number_of_tags += GETJOCTET(data[firstoffset]);
12345ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  }
12355996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  if (number_of_tags == 0) return;
12365996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  firstoffset += 2;
12375996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
12385996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  /* Search for ExifSubIFD offset Tag in IFD0 */
12395996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  for (;;) {
12405996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (firstoffset > length - 12) return; /* check end of data segment */
12415996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    /* Get Tag number */
12425996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (is_motorola) {
12435996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      tagnum = GETJOCTET(data[firstoffset]);
12445996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      tagnum <<= 8;
12455996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      tagnum += GETJOCTET(data[firstoffset+1]);
12465996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    } else {
12475996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      tagnum = GETJOCTET(data[firstoffset+1]);
12485996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      tagnum <<= 8;
12495996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      tagnum += GETJOCTET(data[firstoffset]);
12505996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    }
12515996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */
12525996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (--number_of_tags == 0) return;
12535996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    firstoffset += 12;
12545996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  }
12555996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
12565996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  /* Get the ExifSubIFD offset */
12575996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  if (is_motorola) {
12585996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (GETJOCTET(data[firstoffset+8]) != 0) return;
12595996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (GETJOCTET(data[firstoffset+9]) != 0) return;
12605996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    offset = GETJOCTET(data[firstoffset+10]);
12615996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    offset <<= 8;
12625996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    offset += GETJOCTET(data[firstoffset+11]);
12635996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  } else {
12645996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (GETJOCTET(data[firstoffset+11]) != 0) return;
12655996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (GETJOCTET(data[firstoffset+10]) != 0) return;
12665996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    offset = GETJOCTET(data[firstoffset+9]);
12675996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    offset <<= 8;
12685996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    offset += GETJOCTET(data[firstoffset+8]);
12695996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  }
12705996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  if (offset > length - 2) return; /* check end of data segment */
12715996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
12725996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  /* Get the number of directory entries contained in this SubIFD */
12735996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  if (is_motorola) {
12745996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    number_of_tags = GETJOCTET(data[offset]);
12755996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    number_of_tags <<= 8;
12765996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    number_of_tags += GETJOCTET(data[offset+1]);
12775996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  } else {
12785996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    number_of_tags = GETJOCTET(data[offset+1]);
12795996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    number_of_tags <<= 8;
12805996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    number_of_tags += GETJOCTET(data[offset]);
12815996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  }
12825996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  if (number_of_tags < 2) return;
12835996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  offset += 2;
12845996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
12855996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */
12865996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  do {
12875996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (offset > length - 12) return; /* check end of data segment */
12885996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    /* Get Tag number */
12895996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (is_motorola) {
12905996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      tagnum = GETJOCTET(data[offset]);
12915996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      tagnum <<= 8;
12925996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      tagnum += GETJOCTET(data[offset+1]);
12935996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    } else {
12945996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      tagnum = GETJOCTET(data[offset+1]);
12955996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      tagnum <<= 8;
12965996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      tagnum += GETJOCTET(data[offset]);
12975996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    }
12985996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (tagnum == 0xA002 || tagnum == 0xA003) {
12995996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      if (tagnum == 0xA002)
1300e5eaf37440b8e337ab150c017df7c03faf846c51DRC        new_value = new_width; /* ExifImageWidth Tag */
13015996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      else
1302e5eaf37440b8e337ab150c017df7c03faf846c51DRC        new_value = new_height; /* ExifImageHeight Tag */
13035996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      if (is_motorola) {
1304e5eaf37440b8e337ab150c017df7c03faf846c51DRC        data[offset+2] = 0; /* Format = unsigned long (4 octets) */
1305e5eaf37440b8e337ab150c017df7c03faf846c51DRC        data[offset+3] = 4;
1306e5eaf37440b8e337ab150c017df7c03faf846c51DRC        data[offset+4] = 0; /* Number Of Components = 1 */
1307e5eaf37440b8e337ab150c017df7c03faf846c51DRC        data[offset+5] = 0;
1308e5eaf37440b8e337ab150c017df7c03faf846c51DRC        data[offset+6] = 0;
1309e5eaf37440b8e337ab150c017df7c03faf846c51DRC        data[offset+7] = 1;
1310e5eaf37440b8e337ab150c017df7c03faf846c51DRC        data[offset+8] = 0;
1311e5eaf37440b8e337ab150c017df7c03faf846c51DRC        data[offset+9] = 0;
1312e5eaf37440b8e337ab150c017df7c03faf846c51DRC        data[offset+10] = (JOCTET)((new_value >> 8) & 0xFF);
1313e5eaf37440b8e337ab150c017df7c03faf846c51DRC        data[offset+11] = (JOCTET)(new_value & 0xFF);
13145996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      } else {
1315e5eaf37440b8e337ab150c017df7c03faf846c51DRC        data[offset+2] = 4; /* Format = unsigned long (4 octets) */
1316e5eaf37440b8e337ab150c017df7c03faf846c51DRC        data[offset+3] = 0;
1317e5eaf37440b8e337ab150c017df7c03faf846c51DRC        data[offset+4] = 1; /* Number Of Components = 1 */
1318e5eaf37440b8e337ab150c017df7c03faf846c51DRC        data[offset+5] = 0;
1319e5eaf37440b8e337ab150c017df7c03faf846c51DRC        data[offset+6] = 0;
1320e5eaf37440b8e337ab150c017df7c03faf846c51DRC        data[offset+7] = 0;
1321e5eaf37440b8e337ab150c017df7c03faf846c51DRC        data[offset+8] = (JOCTET)(new_value & 0xFF);
1322e5eaf37440b8e337ab150c017df7c03faf846c51DRC        data[offset+9] = (JOCTET)((new_value >> 8) & 0xFF);
1323e5eaf37440b8e337ab150c017df7c03faf846c51DRC        data[offset+10] = 0;
1324e5eaf37440b8e337ab150c017df7c03faf846c51DRC        data[offset+11] = 0;
13255996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      }
13265996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    }
13275996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    offset += 12;
13285996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  } while (--number_of_tags);
13295ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane}
1330506a742193ed5549074f40c3e0d2f0fd2eefb22bDRC#endif
13315ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
13325ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
13335ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* Adjust output image parameters as needed.
13345ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *
13355ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * This must be called after jpeg_copy_critical_parameters()
13365ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * and before jpeg_write_coefficients().
13375ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *
13385ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * The return value is the set of virtual coefficient arrays to be written
13395ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * (either the ones allocated by jtransform_request_workspace, or the
13405ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * original source data arrays).  The caller will need to pass this value
13415ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * to jpeg_write_coefficients().
13425ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */
13435ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
13445ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneGLOBAL(jvirt_barray_ptr *)
13455ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lanejtransform_adjust_parameters (j_decompress_ptr srcinfo,
1346e5eaf37440b8e337ab150c017df7c03faf846c51DRC                              j_compress_ptr dstinfo,
1347e5eaf37440b8e337ab150c017df7c03faf846c51DRC                              jvirt_barray_ptr *src_coef_arrays,
1348e5eaf37440b8e337ab150c017df7c03faf846c51DRC                              jpeg_transform_info *info)
13495ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{
13505ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  /* If force-to-grayscale is requested, adjust destination parameters */
13515ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  if (info->force_grayscale) {
13525996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    /* First, ensure we have YCbCr or grayscale data, and that the source's
13535996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding     * Y channel is full resolution.  (No reasonable person would make Y
13545996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding     * be less than full resolution, so actually coping with that case
13555996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding     * isn't worth extra code space.  But we check it to avoid crashing.)
13565ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane     */
13575996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (((dstinfo->jpeg_color_space == JCS_YCbCr &&
1358e5eaf37440b8e337ab150c017df7c03faf846c51DRC          dstinfo->num_components == 3) ||
1359e5eaf37440b8e337ab150c017df7c03faf846c51DRC         (dstinfo->jpeg_color_space == JCS_GRAYSCALE &&
1360e5eaf37440b8e337ab150c017df7c03faf846c51DRC          dstinfo->num_components == 1)) &&
1361e5eaf37440b8e337ab150c017df7c03faf846c51DRC        srcinfo->comp_info[0].h_samp_factor == srcinfo->max_h_samp_factor &&
1362e5eaf37440b8e337ab150c017df7c03faf846c51DRC        srcinfo->comp_info[0].v_samp_factor == srcinfo->max_v_samp_factor) {
13635996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
13645996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding       * properly.  Among other things, it sets the target h_samp_factor &
13655996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding       * v_samp_factor to 1, which typically won't match the source.
13665996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding       * We have to preserve the source's quantization table number, however.
13675996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding       */
13685ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no;
13695ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE);
13705ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no;
13715ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    } else {
13725ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      /* Sorry, can't do it */
13735ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL);
13745ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    }
13755996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  } else if (info->num_components == 1) {
13765996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    /* For a single-component source, we force the destination sampling factors
13775996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding     * to 1x1, with or without force_grayscale.  This is useful because some
13785996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding     * decoders choke on grayscale images with other sampling factors.
13795996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding     */
13805996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    dstinfo->comp_info[0].h_samp_factor = 1;
13815996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    dstinfo->comp_info[0].v_samp_factor = 1;
13825ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  }
13835ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
13845996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  /* Correct the destination's image dimensions as necessary
1385989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding   * for rotate/flip, resize, and crop operations.
13865996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding   */
1387c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#if JPEG_LIB_VERSION >= 70
1388989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  dstinfo->jpeg_width = info->output_width;
1389989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding  dstinfo->jpeg_height = info->output_height;
1390c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#endif
13915996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
13925996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  /* Transpose destination image parameters */
13935ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  switch (info->transform) {
13945ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  case JXFORM_TRANSPOSE:
13955ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  case JXFORM_TRANSVERSE:
13965ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  case JXFORM_ROT_90:
13975ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  case JXFORM_ROT_270:
13989a648cc90b77216060193466f86a3621c0bbb965DRC#if JPEG_LIB_VERSION < 70
13999a648cc90b77216060193466f86a3621c0bbb965DRC    dstinfo->image_width = info->output_height;
14009a648cc90b77216060193466f86a3621c0bbb965DRC    dstinfo->image_height = info->output_width;
14019a648cc90b77216060193466f86a3621c0bbb965DRC#endif
14025ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    transpose_critical_parameters(dstinfo);
14035ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    break;
14045996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  default:
14059a648cc90b77216060193466f86a3621c0bbb965DRC#if JPEG_LIB_VERSION < 70
14069a648cc90b77216060193466f86a3621c0bbb965DRC    dstinfo->image_width = info->output_width;
14079a648cc90b77216060193466f86a3621c0bbb965DRC    dstinfo->image_height = info->output_height;
14089a648cc90b77216060193466f86a3621c0bbb965DRC#endif
14095ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    break;
14105ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  }
14115ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
14125996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  /* Adjust Exif properties */
14135996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  if (srcinfo->marker_list != NULL &&
14145996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      srcinfo->marker_list->marker == JPEG_APP0+1 &&
14155996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      srcinfo->marker_list->data_length >= 6 &&
14165996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      GETJOCTET(srcinfo->marker_list->data[0]) == 0x45 &&
14175996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      GETJOCTET(srcinfo->marker_list->data[1]) == 0x78 &&
14185996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      GETJOCTET(srcinfo->marker_list->data[2]) == 0x69 &&
14195996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      GETJOCTET(srcinfo->marker_list->data[3]) == 0x66 &&
14205996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      GETJOCTET(srcinfo->marker_list->data[4]) == 0 &&
14215996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      GETJOCTET(srcinfo->marker_list->data[5]) == 0) {
14225996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    /* Suppress output of JFIF marker */
14235996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    dstinfo->write_JFIF_header = FALSE;
1424c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#if JPEG_LIB_VERSION >= 70
14255996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    /* Adjust Exif image parameters */
1426989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding    if (dstinfo->jpeg_width != srcinfo->image_width ||
1427e5eaf37440b8e337ab150c017df7c03faf846c51DRC        dstinfo->jpeg_height != srcinfo->image_height)
14285996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      /* Align data segment to start of TIFF structure for parsing */
14295996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      adjust_exif_parameters(srcinfo->marker_list->data + 6,
1430e5eaf37440b8e337ab150c017df7c03faf846c51DRC        srcinfo->marker_list->data_length - 6,
1431e5eaf37440b8e337ab150c017df7c03faf846c51DRC        dstinfo->jpeg_width, dstinfo->jpeg_height);
1432c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#endif
14335ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  }
14345ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
14355ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  /* Return the appropriate output data set */
14365ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  if (info->workspace_coef_arrays != NULL)
14375ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    return info->workspace_coef_arrays;
14385ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  return src_coef_arrays;
14395ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane}
14405ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
14415ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
14425ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* Execute the actual transformation, if any.
14435ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *
14445ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * This must be called *after* jpeg_write_coefficients, because it depends
14455ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * on jpeg_write_coefficients to have computed subsidiary values such as
14465ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * the per-component width and height fields in the destination object.
14475ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane *
14485ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * Note that some transformations will modify the source data arrays!
14495ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */
14505ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
14515ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneGLOBAL(void)
14525996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbedingjtransform_execute_transform (j_decompress_ptr srcinfo,
1453e5eaf37440b8e337ab150c017df7c03faf846c51DRC                              j_compress_ptr dstinfo,
1454e5eaf37440b8e337ab150c017df7c03faf846c51DRC                              jvirt_barray_ptr *src_coef_arrays,
1455e5eaf37440b8e337ab150c017df7c03faf846c51DRC                              jpeg_transform_info *info)
14565ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{
14575ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays;
14585ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
14595996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  /* Note: conditions tested here should match those in switch statement
14605996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding   * in jtransform_request_workspace()
14615996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding   */
14625ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  switch (info->transform) {
14635ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  case JXFORM_NONE:
14645996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
14655996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      do_crop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
1466e5eaf37440b8e337ab150c017df7c03faf846c51DRC              src_coef_arrays, dst_coef_arrays);
14675ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    break;
14685ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  case JXFORM_FLIP_H:
1469ba5ea5143e48b71234414139e3b4cb244599e875DRC    if (info->y_crop_offset != 0 || info->slow_hflip)
14705996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      do_flip_h(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
1471e5eaf37440b8e337ab150c017df7c03faf846c51DRC                src_coef_arrays, dst_coef_arrays);
14725996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    else
14735996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      do_flip_h_no_crop(srcinfo, dstinfo, info->x_crop_offset,
1474e5eaf37440b8e337ab150c017df7c03faf846c51DRC                        src_coef_arrays);
14755ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    break;
14765ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  case JXFORM_FLIP_V:
14775996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    do_flip_v(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
1478e5eaf37440b8e337ab150c017df7c03faf846c51DRC              src_coef_arrays, dst_coef_arrays);
14795ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    break;
14805ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  case JXFORM_TRANSPOSE:
14815996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    do_transpose(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
1482e5eaf37440b8e337ab150c017df7c03faf846c51DRC                 src_coef_arrays, dst_coef_arrays);
14835ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    break;
14845ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  case JXFORM_TRANSVERSE:
14855996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    do_transverse(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
1486e5eaf37440b8e337ab150c017df7c03faf846c51DRC                  src_coef_arrays, dst_coef_arrays);
14875ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    break;
14885ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  case JXFORM_ROT_90:
14895996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    do_rot_90(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
1490e5eaf37440b8e337ab150c017df7c03faf846c51DRC              src_coef_arrays, dst_coef_arrays);
14915ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    break;
14925ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  case JXFORM_ROT_180:
14935996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    do_rot_180(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
1494e5eaf37440b8e337ab150c017df7c03faf846c51DRC               src_coef_arrays, dst_coef_arrays);
14955996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    break;
14965996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  case JXFORM_ROT_270:
14975996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
1498e5eaf37440b8e337ab150c017df7c03faf846c51DRC               src_coef_arrays, dst_coef_arrays);
14995ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    break;
15005996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  }
15015996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding}
15025996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
15035996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding/* jtransform_perfect_transform
15045996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding *
15055996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * Determine whether lossless transformation is perfectly
15065996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * possible for a specified image and transformation.
15075996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding *
15085996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * Inputs:
15095996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding *   image_width, image_height: source image dimensions.
15105996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding *   MCU_width, MCU_height: pixel dimensions of MCU.
15115996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding *   transform: transformation identifier.
15125996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * Parameter sources from initialized jpeg_struct
15135996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * (after reading source header):
15145996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding *   image_width = cinfo.image_width
15155996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding *   image_height = cinfo.image_height
1516989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding *   MCU_width = cinfo.max_h_samp_factor * cinfo.block_size
1517989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding *   MCU_height = cinfo.max_v_samp_factor * cinfo.block_size
15185996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * Result:
15195996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding *   TRUE = perfect transformation possible
15205996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding *   FALSE = perfect transformation not possible
15215996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding *           (may use custom action then)
15225996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding */
15235996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
15245996a25e2f50d20d6a8f09830724035b49c3927bGuido VollbedingGLOBAL(boolean)
15255996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbedingjtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height,
1526e5eaf37440b8e337ab150c017df7c03faf846c51DRC                             int MCU_width, int MCU_height,
1527e5eaf37440b8e337ab150c017df7c03faf846c51DRC                             JXFORM_CODE transform)
15285996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding{
15295996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  boolean result = TRUE; /* initialize TRUE */
15305996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
15315996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  switch (transform) {
15325996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  case JXFORM_FLIP_H:
15335ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  case JXFORM_ROT_270:
15345996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (image_width % (JDIMENSION) MCU_width)
15355996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      result = FALSE;
15365996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    break;
15375996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  case JXFORM_FLIP_V:
15385996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  case JXFORM_ROT_90:
15395996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (image_height % (JDIMENSION) MCU_height)
15405996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      result = FALSE;
15415996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    break;
15425996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  case JXFORM_TRANSVERSE:
15435996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  case JXFORM_ROT_180:
15445996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (image_width % (JDIMENSION) MCU_width)
15455996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      result = FALSE;
15465996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    if (image_height % (JDIMENSION) MCU_height)
15475996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding      result = FALSE;
15485996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding    break;
15495996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  default:
15505ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    break;
15515ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  }
15525996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding
15535996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding  return result;
15545ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane}
15555ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
15565ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane#endif /* TRANSFORMS_SUPPORTED */
15575ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
15585ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
15595ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* Setup decompression object to save desired markers in memory.
15605ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * This must be called before jpeg_read_header() to have the desired effect.
15615ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */
15625ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
15635ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneGLOBAL(void)
15645ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lanejcopy_markers_setup (j_decompress_ptr srcinfo, JCOPY_OPTION option)
15655ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{
15665ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane#ifdef SAVE_MARKERS_SUPPORTED
15675ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  int m;
15685ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
15695ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  /* Save comments except under NONE option */
15705ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  if (option != JCOPYOPT_NONE) {
15715ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF);
15725ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  }
15735ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  /* Save all types of APPn markers iff ALL option */
15745ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  if (option == JCOPYOPT_ALL) {
15755ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    for (m = 0; m < 16; m++)
15765ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF);
15775ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  }
15785ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane#endif /* SAVE_MARKERS_SUPPORTED */
15795ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane}
15805ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
15815ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* Copy markers saved in the given source object to the destination object.
15825ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * This should be called just after jpeg_start_compress() or
15835ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * jpeg_write_coefficients().
15845ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * Note that those routines will have written the SOI, and also the
15855ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * JFIF APP0 or Adobe APP14 markers if selected.
15865ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */
15875ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
15885ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneGLOBAL(void)
15895ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lanejcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
1590e5eaf37440b8e337ab150c017df7c03faf846c51DRC                       JCOPY_OPTION option)
15915ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{
15925ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  jpeg_saved_marker_ptr marker;
15935ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
15945ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  /* In the current implementation, we don't actually need to examine the
15955ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   * option flag here; we just copy everything that got saved.
15965ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   * But to avoid confusion, we do not output JFIF and Adobe APP14 markers
15975ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   * if the encoder library already wrote one.
15985ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   */
15995ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) {
16005ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    if (dstinfo->write_JFIF_header &&
1601e5eaf37440b8e337ab150c017df7c03faf846c51DRC        marker->marker == JPEG_APP0 &&
1602e5eaf37440b8e337ab150c017df7c03faf846c51DRC        marker->data_length >= 5 &&
1603e5eaf37440b8e337ab150c017df7c03faf846c51DRC        GETJOCTET(marker->data[0]) == 0x4A &&
1604e5eaf37440b8e337ab150c017df7c03faf846c51DRC        GETJOCTET(marker->data[1]) == 0x46 &&
1605e5eaf37440b8e337ab150c017df7c03faf846c51DRC        GETJOCTET(marker->data[2]) == 0x49 &&
1606e5eaf37440b8e337ab150c017df7c03faf846c51DRC        GETJOCTET(marker->data[3]) == 0x46 &&
1607e5eaf37440b8e337ab150c017df7c03faf846c51DRC        GETJOCTET(marker->data[4]) == 0)
1608e5eaf37440b8e337ab150c017df7c03faf846c51DRC      continue;                 /* reject duplicate JFIF */
16095ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    if (dstinfo->write_Adobe_marker &&
1610e5eaf37440b8e337ab150c017df7c03faf846c51DRC        marker->marker == JPEG_APP0+14 &&
1611e5eaf37440b8e337ab150c017df7c03faf846c51DRC        marker->data_length >= 5 &&
1612e5eaf37440b8e337ab150c017df7c03faf846c51DRC        GETJOCTET(marker->data[0]) == 0x41 &&
1613e5eaf37440b8e337ab150c017df7c03faf846c51DRC        GETJOCTET(marker->data[1]) == 0x64 &&
1614e5eaf37440b8e337ab150c017df7c03faf846c51DRC        GETJOCTET(marker->data[2]) == 0x6F &&
1615e5eaf37440b8e337ab150c017df7c03faf846c51DRC        GETJOCTET(marker->data[3]) == 0x62 &&
1616e5eaf37440b8e337ab150c017df7c03faf846c51DRC        GETJOCTET(marker->data[4]) == 0x65)
1617e5eaf37440b8e337ab150c017df7c03faf846c51DRC      continue;                 /* reject duplicate Adobe */
16185ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    jpeg_write_marker(dstinfo, marker->marker,
1619e5eaf37440b8e337ab150c017df7c03faf846c51DRC                      marker->data, marker->data_length);
16205ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  }
16215ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane}
1622