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

Generated by: LCOV version 1.11