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