LCOV - code coverage report
Current view: top level - vcl/source/filter/jpeg - transupp.c (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 0 658 0.0 %
Date: 2014-04-11 Functions: 0 22 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10