ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

transupp.c
Go to the documentation of this file.
00001 /*
00002  * transupp.c
00003  *
00004  * Copyright (C) 1997-2009, Thomas G. Lane, Guido Vollbeding.
00005  * This file is part of the Independent JPEG Group's software.
00006  * For conditions of distribution and use, see the accompanying README file.
00007  *
00008  * This file contains image transformation routines and other utility code
00009  * used by the jpegtran sample application.  These are NOT part of the core
00010  * JPEG library.  But we keep these routines separate from jpegtran.c to
00011  * ease the task of maintaining jpegtran-like programs that have other user
00012  * interfaces.
00013  */
00014 
00015 /* Although this file really shouldn't have access to the library internals,
00016  * it's helpful to let it call jround_up() and jcopy_block_row().
00017  */
00018 #define JPEG_INTERNALS
00019 
00020 #include "jinclude.h"
00021 #include "jpeglib.h"
00022 #include "transupp.h"       /* My own external interface */
00023 #include <ctype.h>      /* to declare isdigit() */
00024 
00025 
00026 #if TRANSFORMS_SUPPORTED
00027 
00028 /*
00029  * Lossless image transformation routines.  These routines work on DCT
00030  * coefficient arrays and thus do not require any lossy decompression
00031  * or recompression of the image.
00032  * Thanks to Guido Vollbeding for the initial design and code of this feature,
00033  * and to Ben Jackson for introducing the cropping feature.
00034  *
00035  * Horizontal flipping is done in-place, using a single top-to-bottom
00036  * pass through the virtual source array.  It will thus be much the
00037  * fastest option for images larger than main memory.
00038  *
00039  * The other routines require a set of destination virtual arrays, so they
00040  * need twice as much memory as jpegtran normally does.  The destination
00041  * arrays are always written in normal scan order (top to bottom) because
00042  * the virtual array manager expects this.  The source arrays will be scanned
00043  * in the corresponding order, which means multiple passes through the source
00044  * arrays for most of the transforms.  That could result in much thrashing
00045  * if the image is larger than main memory.
00046  *
00047  * If cropping or trimming is involved, the destination arrays may be smaller
00048  * than the source arrays.  Note it is not possible to do horizontal flip
00049  * in-place when a nonzero Y crop offset is specified, since we'd have to move
00050  * data from one block row to another but the virtual array manager doesn't
00051  * guarantee we can touch more than one row at a time.  So in that case,
00052  * we have to use a separate destination array.
00053  *
00054  * Some notes about the operating environment of the individual transform
00055  * routines:
00056  * 1. Both the source and destination virtual arrays are allocated from the
00057  *    source JPEG object, and therefore should be manipulated by calling the
00058  *    source's memory manager.
00059  * 2. The destination's component count should be used.  It may be smaller
00060  *    than the source's when forcing to grayscale.
00061  * 3. Likewise the destination's sampling factors should be used.  When
00062  *    forcing to grayscale the destination's sampling factors will be all 1,
00063  *    and we may as well take that as the effective iMCU size.
00064  * 4. When "trim" is in effect, the destination's dimensions will be the
00065  *    trimmed values but the source's will be untrimmed.
00066  * 5. When "crop" is in effect, the destination's dimensions will be the
00067  *    cropped values but the source's will be uncropped.  Each transform
00068  *    routine is responsible for picking up source data starting at the
00069  *    correct X and Y offset for the crop region.  (The X and Y offsets
00070  *    passed to the transform routines are measured in iMCU blocks of the
00071  *    destination.)
00072  * 6. All the routines assume that the source and destination buffers are
00073  *    padded out to a full iMCU boundary.  This is true, although for the
00074  *    source buffer it is an undocumented property of jdcoefct.c.
00075  */
00076 
00077 
00078 LOCAL(void)
00079 do_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
00080      JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
00081      jvirt_barray_ptr *src_coef_arrays,
00082      jvirt_barray_ptr *dst_coef_arrays)
00083 /* Crop.  This is only used when no rotate/flip is requested with the crop. */
00084 {
00085   JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks;
00086   int ci, offset_y;
00087   JBLOCKARRAY src_buffer, dst_buffer;
00088   jpeg_component_info *compptr;
00089 
00090   /* We simply have to copy the right amount of data (the destination's
00091    * image size) starting at the given X and Y offsets in the source.
00092    */
00093   for (ci = 0; ci < dstinfo->num_components; ci++) {
00094     compptr = dstinfo->comp_info + ci;
00095     x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
00096     y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
00097     for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
00098      dst_blk_y += compptr->v_samp_factor) {
00099       dst_buffer = (*srcinfo->mem->access_virt_barray)
00100     ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
00101      (JDIMENSION) compptr->v_samp_factor, TRUE);
00102       src_buffer = (*srcinfo->mem->access_virt_barray)
00103     ((j_common_ptr) srcinfo, src_coef_arrays[ci],
00104      dst_blk_y + y_crop_blocks,
00105      (JDIMENSION) compptr->v_samp_factor, FALSE);
00106       for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
00107     jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
00108             dst_buffer[offset_y],
00109             compptr->width_in_blocks);
00110       }
00111     }
00112   }
00113 }
00114 
00115 
00116 LOCAL(void)
00117 do_flip_h_no_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
00118            JDIMENSION x_crop_offset,
00119            jvirt_barray_ptr *src_coef_arrays)
00120 /* Horizontal flip; done in-place, so no separate dest array is required.
00121  * NB: this only works when y_crop_offset is zero.
00122  */
00123 {
00124   JDIMENSION MCU_cols, comp_width, blk_x, blk_y, x_crop_blocks;
00125   int ci, k, offset_y;
00126   JBLOCKARRAY buffer;
00127   JCOEFPTR ptr1, ptr2;
00128   JCOEF temp1, temp2;
00129   jpeg_component_info *compptr;
00130 
00131   /* Horizontal mirroring of DCT blocks is accomplished by swapping
00132    * pairs of blocks in-place.  Within a DCT block, we perform horizontal
00133    * mirroring by changing the signs of odd-numbered columns.
00134    * Partial iMCUs at the right edge are left untouched.
00135    */
00136   MCU_cols = srcinfo->output_width /
00137     (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size);
00138 
00139   for (ci = 0; ci < dstinfo->num_components; ci++) {
00140     compptr = dstinfo->comp_info + ci;
00141     comp_width = MCU_cols * compptr->h_samp_factor;
00142     x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
00143     for (blk_y = 0; blk_y < compptr->height_in_blocks;
00144      blk_y += compptr->v_samp_factor) {
00145       buffer = (*srcinfo->mem->access_virt_barray)
00146     ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y,
00147      (JDIMENSION) compptr->v_samp_factor, TRUE);
00148       for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
00149     /* Do the mirroring */
00150     for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) {
00151       ptr1 = buffer[offset_y][blk_x];
00152       ptr2 = buffer[offset_y][comp_width - blk_x - 1];
00153       /* this unrolled loop doesn't need to know which row it's on... */
00154       for (k = 0; k < DCTSIZE2; k += 2) {
00155         temp1 = *ptr1;  /* swap even column */
00156         temp2 = *ptr2;
00157         *ptr1++ = temp2;
00158         *ptr2++ = temp1;
00159         temp1 = *ptr1;  /* swap odd column with sign change */
00160         temp2 = *ptr2;
00161         *ptr1++ = -temp2;
00162         *ptr2++ = -temp1;
00163       }
00164     }
00165     if (x_crop_blocks > 0) {
00166       /* Now left-justify the portion of the data to be kept.
00167        * We can't use a single jcopy_block_row() call because that routine
00168        * depends on memcpy(), whose behavior is unspecified for overlapping
00169        * source and destination areas.  Sigh.
00170        */
00171       for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
00172         jcopy_block_row(buffer[offset_y] + blk_x + x_crop_blocks,
00173                 buffer[offset_y] + blk_x,
00174                 (JDIMENSION) 1);
00175       }
00176     }
00177       }
00178     }
00179   }
00180 }
00181 
00182 
00183 LOCAL(void)
00184 do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
00185        JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
00186        jvirt_barray_ptr *src_coef_arrays,
00187        jvirt_barray_ptr *dst_coef_arrays)
00188 /* Horizontal flip in general cropping case */
00189 {
00190   JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
00191   JDIMENSION x_crop_blocks, y_crop_blocks;
00192   int ci, k, offset_y;
00193   JBLOCKARRAY src_buffer, dst_buffer;
00194   JBLOCKROW src_row_ptr, dst_row_ptr;
00195   JCOEFPTR src_ptr, dst_ptr;
00196   jpeg_component_info *compptr;
00197 
00198   /* Here we must output into a separate array because we can't touch
00199    * different rows of a single virtual array simultaneously.  Otherwise,
00200    * this is essentially the same as the routine above.
00201    */
00202   MCU_cols = srcinfo->output_width /
00203     (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size);
00204 
00205   for (ci = 0; ci < dstinfo->num_components; ci++) {
00206     compptr = dstinfo->comp_info + ci;
00207     comp_width = MCU_cols * compptr->h_samp_factor;
00208     x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
00209     y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
00210     for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
00211      dst_blk_y += compptr->v_samp_factor) {
00212       dst_buffer = (*srcinfo->mem->access_virt_barray)
00213     ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
00214      (JDIMENSION) compptr->v_samp_factor, TRUE);
00215       src_buffer = (*srcinfo->mem->access_virt_barray)
00216     ((j_common_ptr) srcinfo, src_coef_arrays[ci],
00217      dst_blk_y + y_crop_blocks,
00218      (JDIMENSION) compptr->v_samp_factor, FALSE);
00219       for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
00220     dst_row_ptr = dst_buffer[offset_y];
00221     src_row_ptr = src_buffer[offset_y];
00222     for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
00223       if (x_crop_blocks + dst_blk_x < comp_width) {
00224         /* Do the mirrorable blocks */
00225         dst_ptr = dst_row_ptr[dst_blk_x];
00226         src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
00227         /* this unrolled loop doesn't need to know which row it's on... */
00228         for (k = 0; k < DCTSIZE2; k += 2) {
00229           *dst_ptr++ = *src_ptr++;   /* copy even column */
00230           *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */
00231         }
00232       } else {
00233         /* Copy last partial block(s) verbatim */
00234         jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
00235                 dst_row_ptr + dst_blk_x,
00236                 (JDIMENSION) 1);
00237       }
00238     }
00239       }
00240     }
00241   }
00242 }
00243 
00244 
00245 LOCAL(void)
00246 do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
00247        JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
00248        jvirt_barray_ptr *src_coef_arrays,
00249        jvirt_barray_ptr *dst_coef_arrays)
00250 /* Vertical flip */
00251 {
00252   JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
00253   JDIMENSION x_crop_blocks, y_crop_blocks;
00254   int ci, i, j, offset_y;
00255   JBLOCKARRAY src_buffer, dst_buffer;
00256   JBLOCKROW src_row_ptr, dst_row_ptr;
00257   JCOEFPTR src_ptr, dst_ptr;
00258   jpeg_component_info *compptr;
00259 
00260   /* We output into a separate array because we can't touch different
00261    * rows of the source virtual array simultaneously.  Otherwise, this
00262    * is a pretty straightforward analog of horizontal flip.
00263    * Within a DCT block, vertical mirroring is done by changing the signs
00264    * of odd-numbered rows.
00265    * Partial iMCUs at the bottom edge are copied verbatim.
00266    */
00267   MCU_rows = srcinfo->output_height /
00268     (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size);
00269 
00270   for (ci = 0; ci < dstinfo->num_components; ci++) {
00271     compptr = dstinfo->comp_info + ci;
00272     comp_height = MCU_rows * compptr->v_samp_factor;
00273     x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
00274     y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
00275     for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
00276      dst_blk_y += compptr->v_samp_factor) {
00277       dst_buffer = (*srcinfo->mem->access_virt_barray)
00278     ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
00279      (JDIMENSION) compptr->v_samp_factor, TRUE);
00280       if (y_crop_blocks + dst_blk_y < comp_height) {
00281     /* Row is within the mirrorable area. */
00282     src_buffer = (*srcinfo->mem->access_virt_barray)
00283       ((j_common_ptr) srcinfo, src_coef_arrays[ci],
00284        comp_height - y_crop_blocks - dst_blk_y -
00285        (JDIMENSION) compptr->v_samp_factor,
00286        (JDIMENSION) compptr->v_samp_factor, FALSE);
00287       } else {
00288     /* Bottom-edge blocks will be copied verbatim. */
00289     src_buffer = (*srcinfo->mem->access_virt_barray)
00290       ((j_common_ptr) srcinfo, src_coef_arrays[ci],
00291        dst_blk_y + y_crop_blocks,
00292        (JDIMENSION) compptr->v_samp_factor, FALSE);
00293       }
00294       for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
00295     if (y_crop_blocks + dst_blk_y < comp_height) {
00296       /* Row is within the mirrorable area. */
00297       dst_row_ptr = dst_buffer[offset_y];
00298       src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
00299       src_row_ptr += x_crop_blocks;
00300       for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
00301            dst_blk_x++) {
00302         dst_ptr = dst_row_ptr[dst_blk_x];
00303         src_ptr = src_row_ptr[dst_blk_x];
00304         for (i = 0; i < DCTSIZE; i += 2) {
00305           /* copy even row */
00306           for (j = 0; j < DCTSIZE; j++)
00307         *dst_ptr++ = *src_ptr++;
00308           /* copy odd row with sign change */
00309           for (j = 0; j < DCTSIZE; j++)
00310         *dst_ptr++ = - *src_ptr++;
00311         }
00312       }
00313     } else {
00314       /* Just copy row verbatim. */
00315       jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
00316               dst_buffer[offset_y],
00317               compptr->width_in_blocks);
00318     }
00319       }
00320     }
00321   }
00322 }
00323 
00324 
00325 LOCAL(void)
00326 do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
00327           JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
00328           jvirt_barray_ptr *src_coef_arrays,
00329           jvirt_barray_ptr *dst_coef_arrays)
00330 /* Transpose source into destination */
00331 {
00332   JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks;
00333   int ci, i, j, offset_x, offset_y;
00334   JBLOCKARRAY src_buffer, dst_buffer;
00335   JCOEFPTR src_ptr, dst_ptr;
00336   jpeg_component_info *compptr;
00337 
00338   /* Transposing pixels within a block just requires transposing the
00339    * DCT coefficients.
00340    * Partial iMCUs at the edges require no special treatment; we simply
00341    * process all the available DCT blocks for every component.
00342    */
00343   for (ci = 0; ci < dstinfo->num_components; ci++) {
00344     compptr = dstinfo->comp_info + ci;
00345     x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
00346     y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
00347     for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
00348      dst_blk_y += compptr->v_samp_factor) {
00349       dst_buffer = (*srcinfo->mem->access_virt_barray)
00350     ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
00351      (JDIMENSION) compptr->v_samp_factor, TRUE);
00352       for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
00353     for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
00354          dst_blk_x += compptr->h_samp_factor) {
00355       src_buffer = (*srcinfo->mem->access_virt_barray)
00356         ((j_common_ptr) srcinfo, src_coef_arrays[ci],
00357          dst_blk_x + x_crop_blocks,
00358          (JDIMENSION) compptr->h_samp_factor, FALSE);
00359       for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
00360         dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
00361         src_ptr = src_buffer[offset_x][dst_blk_y + offset_y + y_crop_blocks];
00362         for (i = 0; i < DCTSIZE; i++)
00363           for (j = 0; j < DCTSIZE; j++)
00364         dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
00365       }
00366     }
00367       }
00368     }
00369   }
00370 }
00371 
00372 
00373 LOCAL(void)
00374 do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
00375        JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
00376        jvirt_barray_ptr *src_coef_arrays,
00377        jvirt_barray_ptr *dst_coef_arrays)
00378 /* 90 degree rotation is equivalent to
00379  *   1. Transposing the image;
00380  *   2. Horizontal mirroring.
00381  * These two steps are merged into a single processing routine.
00382  */
00383 {
00384   JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
00385   JDIMENSION x_crop_blocks, y_crop_blocks;
00386   int ci, i, j, offset_x, offset_y;
00387   JBLOCKARRAY src_buffer, dst_buffer;
00388   JCOEFPTR src_ptr, dst_ptr;
00389   jpeg_component_info *compptr;
00390 
00391   /* Because of the horizontal mirror step, we can't process partial iMCUs
00392    * at the (output) right edge properly.  They just get transposed and
00393    * not mirrored.
00394    */
00395   MCU_cols = srcinfo->output_height /
00396     (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size);
00397 
00398   for (ci = 0; ci < dstinfo->num_components; ci++) {
00399     compptr = dstinfo->comp_info + ci;
00400     comp_width = MCU_cols * compptr->h_samp_factor;
00401     x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
00402     y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
00403     for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
00404      dst_blk_y += compptr->v_samp_factor) {
00405       dst_buffer = (*srcinfo->mem->access_virt_barray)
00406     ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
00407      (JDIMENSION) compptr->v_samp_factor, TRUE);
00408       for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
00409     for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
00410          dst_blk_x += compptr->h_samp_factor) {
00411       if (x_crop_blocks + dst_blk_x < comp_width) {
00412         /* Block is within the mirrorable area. */
00413         src_buffer = (*srcinfo->mem->access_virt_barray)
00414           ((j_common_ptr) srcinfo, src_coef_arrays[ci],
00415            comp_width - x_crop_blocks - dst_blk_x -
00416            (JDIMENSION) compptr->h_samp_factor,
00417            (JDIMENSION) compptr->h_samp_factor, FALSE);
00418       } else {
00419         /* Edge blocks are transposed but not mirrored. */
00420         src_buffer = (*srcinfo->mem->access_virt_barray)
00421           ((j_common_ptr) srcinfo, src_coef_arrays[ci],
00422            dst_blk_x + x_crop_blocks,
00423            (JDIMENSION) compptr->h_samp_factor, FALSE);
00424       }
00425       for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
00426         dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
00427         if (x_crop_blocks + dst_blk_x < comp_width) {
00428           /* Block is within the mirrorable area. */
00429           src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
00430         [dst_blk_y + offset_y + y_crop_blocks];
00431           for (i = 0; i < DCTSIZE; i++) {
00432         for (j = 0; j < DCTSIZE; j++)
00433           dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
00434         i++;
00435         for (j = 0; j < DCTSIZE; j++)
00436           dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
00437           }
00438         } else {
00439           /* Edge blocks are transposed but not mirrored. */
00440           src_ptr = src_buffer[offset_x]
00441         [dst_blk_y + offset_y + y_crop_blocks];
00442           for (i = 0; i < DCTSIZE; i++)
00443         for (j = 0; j < DCTSIZE; j++)
00444           dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
00445         }
00446       }
00447     }
00448       }
00449     }
00450   }
00451 }
00452 
00453 
00454 LOCAL(void)
00455 do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
00456         JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
00457         jvirt_barray_ptr *src_coef_arrays,
00458         jvirt_barray_ptr *dst_coef_arrays)
00459 /* 270 degree rotation is equivalent to
00460  *   1. Horizontal mirroring;
00461  *   2. Transposing the image.
00462  * These two steps are merged into a single processing routine.
00463  */
00464 {
00465   JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
00466   JDIMENSION x_crop_blocks, y_crop_blocks;
00467   int ci, i, j, offset_x, offset_y;
00468   JBLOCKARRAY src_buffer, dst_buffer;
00469   JCOEFPTR src_ptr, dst_ptr;
00470   jpeg_component_info *compptr;
00471 
00472   /* Because of the horizontal mirror step, we can't process partial iMCUs
00473    * at the (output) bottom edge properly.  They just get transposed and
00474    * not mirrored.
00475    */
00476   MCU_rows = srcinfo->output_width /
00477     (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size);
00478 
00479   for (ci = 0; ci < dstinfo->num_components; ci++) {
00480     compptr = dstinfo->comp_info + ci;
00481     comp_height = MCU_rows * compptr->v_samp_factor;
00482     x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
00483     y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
00484     for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
00485      dst_blk_y += compptr->v_samp_factor) {
00486       dst_buffer = (*srcinfo->mem->access_virt_barray)
00487     ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
00488      (JDIMENSION) compptr->v_samp_factor, TRUE);
00489       for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
00490     for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
00491          dst_blk_x += compptr->h_samp_factor) {
00492       src_buffer = (*srcinfo->mem->access_virt_barray)
00493         ((j_common_ptr) srcinfo, src_coef_arrays[ci],
00494          dst_blk_x + x_crop_blocks,
00495          (JDIMENSION) compptr->h_samp_factor, FALSE);
00496       for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
00497         dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
00498         if (y_crop_blocks + dst_blk_y < comp_height) {
00499           /* Block is within the mirrorable area. */
00500           src_ptr = src_buffer[offset_x]
00501         [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
00502           for (i = 0; i < DCTSIZE; i++) {
00503         for (j = 0; j < DCTSIZE; j++) {
00504           dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
00505           j++;
00506           dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
00507         }
00508           }
00509         } else {
00510           /* Edge blocks are transposed but not mirrored. */
00511           src_ptr = src_buffer[offset_x]
00512         [dst_blk_y + offset_y + y_crop_blocks];
00513           for (i = 0; i < DCTSIZE; i++)
00514         for (j = 0; j < DCTSIZE; j++)
00515           dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
00516         }
00517       }
00518     }
00519       }
00520     }
00521   }
00522 }
00523 
00524 
00525 LOCAL(void)
00526 do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
00527         JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
00528         jvirt_barray_ptr *src_coef_arrays,
00529         jvirt_barray_ptr *dst_coef_arrays)
00530 /* 180 degree rotation is equivalent to
00531  *   1. Vertical mirroring;
00532  *   2. Horizontal mirroring.
00533  * These two steps are merged into a single processing routine.
00534  */
00535 {
00536   JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
00537   JDIMENSION x_crop_blocks, y_crop_blocks;
00538   int ci, i, j, offset_y;
00539   JBLOCKARRAY src_buffer, dst_buffer;
00540   JBLOCKROW src_row_ptr, dst_row_ptr;
00541   JCOEFPTR src_ptr, dst_ptr;
00542   jpeg_component_info *compptr;
00543 
00544   MCU_cols = srcinfo->output_width /
00545     (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size);
00546   MCU_rows = srcinfo->output_height /
00547     (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size);
00548 
00549   for (ci = 0; ci < dstinfo->num_components; ci++) {
00550     compptr = dstinfo->comp_info + ci;
00551     comp_width = MCU_cols * compptr->h_samp_factor;
00552     comp_height = MCU_rows * compptr->v_samp_factor;
00553     x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
00554     y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
00555     for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
00556      dst_blk_y += compptr->v_samp_factor) {
00557       dst_buffer = (*srcinfo->mem->access_virt_barray)
00558     ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
00559      (JDIMENSION) compptr->v_samp_factor, TRUE);
00560       if (y_crop_blocks + dst_blk_y < comp_height) {
00561     /* Row is within the vertically mirrorable area. */
00562     src_buffer = (*srcinfo->mem->access_virt_barray)
00563       ((j_common_ptr) srcinfo, src_coef_arrays[ci],
00564        comp_height - y_crop_blocks - dst_blk_y -
00565        (JDIMENSION) compptr->v_samp_factor,
00566        (JDIMENSION) compptr->v_samp_factor, FALSE);
00567       } else {
00568     /* Bottom-edge rows are only mirrored horizontally. */
00569     src_buffer = (*srcinfo->mem->access_virt_barray)
00570       ((j_common_ptr) srcinfo, src_coef_arrays[ci],
00571        dst_blk_y + y_crop_blocks,
00572        (JDIMENSION) compptr->v_samp_factor, FALSE);
00573       }
00574       for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
00575     dst_row_ptr = dst_buffer[offset_y];
00576     if (y_crop_blocks + dst_blk_y < comp_height) {
00577       /* Row is within the mirrorable area. */
00578       src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
00579       for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
00580         dst_ptr = dst_row_ptr[dst_blk_x];
00581         if (x_crop_blocks + dst_blk_x < comp_width) {
00582           /* Process the blocks that can be mirrored both ways. */
00583           src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
00584           for (i = 0; i < DCTSIZE; i += 2) {
00585         /* For even row, negate every odd column. */
00586         for (j = 0; j < DCTSIZE; j += 2) {
00587           *dst_ptr++ = *src_ptr++;
00588           *dst_ptr++ = - *src_ptr++;
00589         }
00590         /* For odd row, negate every even column. */
00591         for (j = 0; j < DCTSIZE; j += 2) {
00592           *dst_ptr++ = - *src_ptr++;
00593           *dst_ptr++ = *src_ptr++;
00594         }
00595           }
00596         } else {
00597           /* Any remaining right-edge blocks are only mirrored vertically. */
00598           src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x];
00599           for (i = 0; i < DCTSIZE; i += 2) {
00600         for (j = 0; j < DCTSIZE; j++)
00601           *dst_ptr++ = *src_ptr++;
00602         for (j = 0; j < DCTSIZE; j++)
00603           *dst_ptr++ = - *src_ptr++;
00604           }
00605         }
00606       }
00607     } else {
00608       /* Remaining rows are just mirrored horizontally. */
00609       src_row_ptr = src_buffer[offset_y];
00610       for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
00611         if (x_crop_blocks + dst_blk_x < comp_width) {
00612           /* Process the blocks that can be mirrored. */
00613           dst_ptr = dst_row_ptr[dst_blk_x];
00614           src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
00615           for (i = 0; i < DCTSIZE2; i += 2) {
00616         *dst_ptr++ = *src_ptr++;
00617         *dst_ptr++ = - *src_ptr++;
00618           }
00619         } else {
00620           /* Any remaining right-edge blocks are only copied. */
00621           jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
00622                   dst_row_ptr + dst_blk_x,
00623                   (JDIMENSION) 1);
00624         }
00625       }
00626     }
00627       }
00628     }
00629   }
00630 }
00631 
00632 
00633 LOCAL(void)
00634 do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
00635            JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
00636            jvirt_barray_ptr *src_coef_arrays,
00637            jvirt_barray_ptr *dst_coef_arrays)
00638 /* Transverse transpose is equivalent to
00639  *   1. 180 degree rotation;
00640  *   2. Transposition;
00641  * or
00642  *   1. Horizontal mirroring;
00643  *   2. Transposition;
00644  *   3. Horizontal mirroring.
00645  * These steps are merged into a single processing routine.
00646  */
00647 {
00648   JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
00649   JDIMENSION x_crop_blocks, y_crop_blocks;
00650   int ci, i, j, offset_x, offset_y;
00651   JBLOCKARRAY src_buffer, dst_buffer;
00652   JCOEFPTR src_ptr, dst_ptr;
00653   jpeg_component_info *compptr;
00654 
00655   MCU_cols = srcinfo->output_height /
00656     (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size);
00657   MCU_rows = srcinfo->output_width /
00658     (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size);
00659 
00660   for (ci = 0; ci < dstinfo->num_components; ci++) {
00661     compptr = dstinfo->comp_info + ci;
00662     comp_width = MCU_cols * compptr->h_samp_factor;
00663     comp_height = MCU_rows * compptr->v_samp_factor;
00664     x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
00665     y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
00666     for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
00667      dst_blk_y += compptr->v_samp_factor) {
00668       dst_buffer = (*srcinfo->mem->access_virt_barray)
00669     ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
00670      (JDIMENSION) compptr->v_samp_factor, TRUE);
00671       for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
00672     for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
00673          dst_blk_x += compptr->h_samp_factor) {
00674       if (x_crop_blocks + dst_blk_x < comp_width) {
00675         /* Block is within the mirrorable area. */
00676         src_buffer = (*srcinfo->mem->access_virt_barray)
00677           ((j_common_ptr) srcinfo, src_coef_arrays[ci],
00678            comp_width - x_crop_blocks - dst_blk_x -
00679            (JDIMENSION) compptr->h_samp_factor,
00680            (JDIMENSION) compptr->h_samp_factor, FALSE);
00681       } else {
00682         src_buffer = (*srcinfo->mem->access_virt_barray)
00683           ((j_common_ptr) srcinfo, src_coef_arrays[ci],
00684            dst_blk_x + x_crop_blocks,
00685            (JDIMENSION) compptr->h_samp_factor, FALSE);
00686       }
00687       for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
00688         dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
00689         if (y_crop_blocks + dst_blk_y < comp_height) {
00690           if (x_crop_blocks + dst_blk_x < comp_width) {
00691         /* Block is within the mirrorable area. */
00692         src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
00693           [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
00694         for (i = 0; i < DCTSIZE; i++) {
00695           for (j = 0; j < DCTSIZE; j++) {
00696             dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
00697             j++;
00698             dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
00699           }
00700           i++;
00701           for (j = 0; j < DCTSIZE; j++) {
00702             dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
00703             j++;
00704             dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
00705           }
00706         }
00707           } else {
00708         /* Right-edge blocks are mirrored in y only */
00709         src_ptr = src_buffer[offset_x]
00710           [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
00711         for (i = 0; i < DCTSIZE; i++) {
00712           for (j = 0; j < DCTSIZE; j++) {
00713             dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
00714             j++;
00715             dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
00716           }
00717         }
00718           }
00719         } else {
00720           if (x_crop_blocks + dst_blk_x < comp_width) {
00721         /* Bottom-edge blocks are mirrored in x only */
00722         src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
00723           [dst_blk_y + offset_y + y_crop_blocks];
00724         for (i = 0; i < DCTSIZE; i++) {
00725           for (j = 0; j < DCTSIZE; j++)
00726             dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
00727           i++;
00728           for (j = 0; j < DCTSIZE; j++)
00729             dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
00730         }
00731           } else {
00732         /* At lower right corner, just transpose, no mirroring */
00733         src_ptr = src_buffer[offset_x]
00734           [dst_blk_y + offset_y + y_crop_blocks];
00735         for (i = 0; i < DCTSIZE; i++)
00736           for (j = 0; j < DCTSIZE; j++)
00737             dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
00738           }
00739         }
00740       }
00741     }
00742       }
00743     }
00744   }
00745 }
00746 
00747 
00748 /* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec.
00749  * Returns TRUE if valid integer found, FALSE if not.
00750  * *strptr is advanced over the digit string, and *result is set to its value.
00751  */
00752 
00753 LOCAL(boolean)
00754 jt_read_integer (const char ** strptr, JDIMENSION * result)
00755 {
00756   const char * ptr = *strptr;
00757   JDIMENSION val = 0;
00758 
00759   for (; isdigit(*ptr); ptr++) {
00760     val = val * 10 + (JDIMENSION) (*ptr - '0');
00761   }
00762   *result = val;
00763   if (ptr == *strptr)
00764     return FALSE;       /* oops, no digits */
00765   *strptr = ptr;
00766   return TRUE;
00767 }
00768 
00769 
00770 /* Parse a crop specification (written in X11 geometry style).
00771  * The routine returns TRUE if the spec string is valid, FALSE if not.
00772  *
00773  * The crop spec string should have the format
00774  *  <width>x<height>{+-}<xoffset>{+-}<yoffset>
00775  * where width, height, xoffset, and yoffset are unsigned integers.
00776  * Each of the elements can be omitted to indicate a default value.
00777  * (A weakness of this style is that it is not possible to omit xoffset
00778  * while specifying yoffset, since they look alike.)
00779  *
00780  * This code is loosely based on XParseGeometry from the X11 distribution.
00781  */
00782 
00783 GLOBAL(boolean)
00784 jtransform_parse_crop_spec (jpeg_transform_info *info, const char *spec)
00785 {
00786   info->crop = FALSE;
00787   info->crop_width_set = JCROP_UNSET;
00788   info->crop_height_set = JCROP_UNSET;
00789   info->crop_xoffset_set = JCROP_UNSET;
00790   info->crop_yoffset_set = JCROP_UNSET;
00791 
00792   if (isdigit(*spec)) {
00793     /* fetch width */
00794     if (! jt_read_integer(&spec, &info->crop_width))
00795       return FALSE;
00796     info->crop_width_set = JCROP_POS;
00797   }
00798   if (*spec == 'x' || *spec == 'X') {   
00799     /* fetch height */
00800     spec++;
00801     if (! jt_read_integer(&spec, &info->crop_height))
00802       return FALSE;
00803     info->crop_height_set = JCROP_POS;
00804   }
00805   if (*spec == '+' || *spec == '-') {
00806     /* fetch xoffset */
00807     info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
00808     spec++;
00809     if (! jt_read_integer(&spec, &info->crop_xoffset))
00810       return FALSE;
00811   }
00812   if (*spec == '+' || *spec == '-') {
00813     /* fetch yoffset */
00814     info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
00815     spec++;
00816     if (! jt_read_integer(&spec, &info->crop_yoffset))
00817       return FALSE;
00818   }
00819   /* We had better have gotten to the end of the string. */
00820   if (*spec != '\0')
00821     return FALSE;
00822   info->crop = TRUE;
00823   return TRUE;
00824 }
00825 
00826 
00827 /* Trim off any partial iMCUs on the indicated destination edge */
00828 
00829 LOCAL(void)
00830 trim_right_edge (jpeg_transform_info *info, JDIMENSION full_width)
00831 {
00832   JDIMENSION MCU_cols;
00833 
00834   MCU_cols = info->output_width / info->iMCU_sample_width;
00835   if (MCU_cols > 0 && info->x_crop_offset + MCU_cols ==
00836       full_width / info->iMCU_sample_width)
00837     info->output_width = MCU_cols * info->iMCU_sample_width;
00838 }
00839 
00840 LOCAL(void)
00841 trim_bottom_edge (jpeg_transform_info *info, JDIMENSION full_height)
00842 {
00843   JDIMENSION MCU_rows;
00844 
00845   MCU_rows = info->output_height / info->iMCU_sample_height;
00846   if (MCU_rows > 0 && info->y_crop_offset + MCU_rows ==
00847       full_height / info->iMCU_sample_height)
00848     info->output_height = MCU_rows * info->iMCU_sample_height;
00849 }
00850 
00851 
00852 /* Request any required workspace.
00853  *
00854  * This routine figures out the size that the output image will be
00855  * (which implies that all the transform parameters must be set before
00856  * it is called).
00857  *
00858  * We allocate the workspace virtual arrays from the source decompression
00859  * object, so that all the arrays (both the original data and the workspace)
00860  * will be taken into account while making memory management decisions.
00861  * Hence, this routine must be called after jpeg_read_header (which reads
00862  * the image dimensions) and before jpeg_read_coefficients (which realizes
00863  * the source's virtual arrays).
00864  *
00865  * This function returns FALSE right away if -perfect is given
00866  * and transformation is not perfect.  Otherwise returns TRUE.
00867  */
00868 
00869 GLOBAL(boolean)
00870 jtransform_request_workspace (j_decompress_ptr srcinfo,
00871                   jpeg_transform_info *info)
00872 {
00873   jvirt_barray_ptr *coef_arrays;
00874   boolean need_workspace, transpose_it;
00875   jpeg_component_info *compptr;
00876   JDIMENSION xoffset, yoffset;
00877   JDIMENSION width_in_iMCUs, height_in_iMCUs;
00878   JDIMENSION width_in_blocks, height_in_blocks;
00879   int ci, h_samp_factor, v_samp_factor;
00880 
00881   /* Determine number of components in output image */
00882   if (info->force_grayscale &&
00883       srcinfo->jpeg_color_space == JCS_YCbCr &&
00884       srcinfo->num_components == 3)
00885     /* We'll only process the first component */
00886     info->num_components = 1;
00887   else
00888     /* Process all the components */
00889     info->num_components = srcinfo->num_components;
00890 
00891   /* Compute output image dimensions and related values. */
00892   jpeg_core_output_dimensions(srcinfo);
00893 
00894   /* Return right away if -perfect is given and transformation is not perfect.
00895    */
00896   if (info->perfect) {
00897     if (info->num_components == 1) {
00898       if (!jtransform_perfect_transform(srcinfo->output_width,
00899       srcinfo->output_height,
00900       srcinfo->min_DCT_h_scaled_size,
00901       srcinfo->min_DCT_v_scaled_size,
00902       info->transform))
00903     return FALSE;
00904     } else {
00905       if (!jtransform_perfect_transform(srcinfo->output_width,
00906       srcinfo->output_height,
00907       srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size,
00908       srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size,
00909       info->transform))
00910     return FALSE;
00911     }
00912   }
00913 
00914   /* If there is only one output component, force the iMCU size to be 1;
00915    * else use the source iMCU size.  (This allows us to do the right thing
00916    * when reducing color to grayscale, and also provides a handy way of
00917    * cleaning up "funny" grayscale images whose sampling factors are not 1x1.)
00918    */
00919   switch (info->transform) {
00920   case JXFORM_TRANSPOSE:
00921   case JXFORM_TRANSVERSE:
00922   case JXFORM_ROT_90:
00923   case JXFORM_ROT_270:
00924     info->output_width = srcinfo->output_height;
00925     info->output_height = srcinfo->output_width;
00926     if (info->num_components == 1) {
00927       info->iMCU_sample_width = srcinfo->min_DCT_v_scaled_size;
00928       info->iMCU_sample_height = srcinfo->min_DCT_h_scaled_size;
00929     } else {
00930       info->iMCU_sample_width =
00931     srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size;
00932       info->iMCU_sample_height =
00933     srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size;
00934     }
00935     break;
00936   default:
00937     info->output_width = srcinfo->output_width;
00938     info->output_height = srcinfo->output_height;
00939     if (info->num_components == 1) {
00940       info->iMCU_sample_width = srcinfo->min_DCT_h_scaled_size;
00941       info->iMCU_sample_height = srcinfo->min_DCT_v_scaled_size;
00942     } else {
00943       info->iMCU_sample_width =
00944     srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size;
00945       info->iMCU_sample_height =
00946     srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size;
00947     }
00948     break;
00949   }
00950 
00951   /* If cropping has been requested, compute the crop area's position and
00952    * dimensions, ensuring that its upper left corner falls at an iMCU boundary.
00953    */
00954   if (info->crop) {
00955     /* Insert default values for unset crop parameters */
00956     if (info->crop_xoffset_set == JCROP_UNSET)
00957       info->crop_xoffset = 0;   /* default to +0 */
00958     if (info->crop_yoffset_set == JCROP_UNSET)
00959       info->crop_yoffset = 0;   /* default to +0 */
00960     if (info->crop_xoffset >= info->output_width ||
00961     info->crop_yoffset >= info->output_height)
00962       ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
00963     if (info->crop_width_set == JCROP_UNSET)
00964       info->crop_width = info->output_width - info->crop_xoffset;
00965     if (info->crop_height_set == JCROP_UNSET)
00966       info->crop_height = info->output_height - info->crop_yoffset;
00967     /* Ensure parameters are valid */
00968     if (info->crop_width <= 0 || info->crop_width > info->output_width ||
00969     info->crop_height <= 0 || info->crop_height > info->output_height ||
00970     info->crop_xoffset > info->output_width - info->crop_width ||
00971     info->crop_yoffset > info->output_height - info->crop_height)
00972       ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
00973     /* Convert negative crop offsets into regular offsets */
00974     if (info->crop_xoffset_set == JCROP_NEG)
00975       xoffset = info->output_width - info->crop_width - info->crop_xoffset;
00976     else
00977       xoffset = info->crop_xoffset;
00978     if (info->crop_yoffset_set == JCROP_NEG)
00979       yoffset = info->output_height - info->crop_height - info->crop_yoffset;
00980     else
00981       yoffset = info->crop_yoffset;
00982     /* Now adjust so that upper left corner falls at an iMCU boundary */
00983     info->output_width =
00984       info->crop_width + (xoffset % info->iMCU_sample_width);
00985     info->output_height =
00986       info->crop_height + (yoffset % info->iMCU_sample_height);
00987     /* Save x/y offsets measured in iMCUs */
00988     info->x_crop_offset = xoffset / info->iMCU_sample_width;
00989     info->y_crop_offset = yoffset / info->iMCU_sample_height;
00990   } else {
00991     info->x_crop_offset = 0;
00992     info->y_crop_offset = 0;
00993   }
00994 
00995   /* Figure out whether we need workspace arrays,
00996    * and if so whether they are transposed relative to the source.
00997    */
00998   need_workspace = FALSE;
00999   transpose_it = FALSE;
01000   switch (info->transform) {
01001   case JXFORM_NONE:
01002     if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
01003       need_workspace = TRUE;
01004     /* No workspace needed if neither cropping nor transforming */
01005     break;
01006   case JXFORM_FLIP_H:
01007     if (info->trim)
01008       trim_right_edge(info, srcinfo->output_width);
01009     if (info->y_crop_offset != 0)
01010       need_workspace = TRUE;
01011     /* do_flip_h_no_crop doesn't need a workspace array */
01012     break;
01013   case JXFORM_FLIP_V:
01014     if (info->trim)
01015       trim_bottom_edge(info, srcinfo->output_height);
01016     /* Need workspace arrays having same dimensions as source image. */
01017     need_workspace = TRUE;
01018     break;
01019   case JXFORM_TRANSPOSE:
01020     /* transpose does NOT have to trim anything */
01021     /* Need workspace arrays having transposed dimensions. */
01022     need_workspace = TRUE;
01023     transpose_it = TRUE;
01024     break;
01025   case JXFORM_TRANSVERSE:
01026     if (info->trim) {
01027       trim_right_edge(info, srcinfo->output_height);
01028       trim_bottom_edge(info, srcinfo->output_width);
01029     }
01030     /* Need workspace arrays having transposed dimensions. */
01031     need_workspace = TRUE;
01032     transpose_it = TRUE;
01033     break;
01034   case JXFORM_ROT_90:
01035     if (info->trim)
01036       trim_right_edge(info, srcinfo->output_height);
01037     /* Need workspace arrays having transposed dimensions. */
01038     need_workspace = TRUE;
01039     transpose_it = TRUE;
01040     break;
01041   case JXFORM_ROT_180:
01042     if (info->trim) {
01043       trim_right_edge(info, srcinfo->output_width);
01044       trim_bottom_edge(info, srcinfo->output_height);
01045     }
01046     /* Need workspace arrays having same dimensions as source image. */
01047     need_workspace = TRUE;
01048     break;
01049   case JXFORM_ROT_270:
01050     if (info->trim)
01051       trim_bottom_edge(info, srcinfo->output_width);
01052     /* Need workspace arrays having transposed dimensions. */
01053     need_workspace = TRUE;
01054     transpose_it = TRUE;
01055     break;
01056   }
01057 
01058   /* Allocate workspace if needed.
01059    * Note that we allocate arrays padded out to the next iMCU boundary,
01060    * so that transform routines need not worry about missing edge blocks.
01061    */
01062   if (need_workspace) {
01063     coef_arrays = (jvirt_barray_ptr *)
01064       (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
01065         SIZEOF(jvirt_barray_ptr) * info->num_components);
01066     width_in_iMCUs = (JDIMENSION)
01067       jdiv_round_up((long) info->output_width,
01068             (long) info->iMCU_sample_width);
01069     height_in_iMCUs = (JDIMENSION)
01070       jdiv_round_up((long) info->output_height,
01071             (long) info->iMCU_sample_height);
01072     for (ci = 0; ci < info->num_components; ci++) {
01073       compptr = srcinfo->comp_info + ci;
01074       if (info->num_components == 1) {
01075     /* we're going to force samp factors to 1x1 in this case */
01076     h_samp_factor = v_samp_factor = 1;
01077       } else if (transpose_it) {
01078     h_samp_factor = compptr->v_samp_factor;
01079     v_samp_factor = compptr->h_samp_factor;
01080       } else {
01081     h_samp_factor = compptr->h_samp_factor;
01082     v_samp_factor = compptr->v_samp_factor;
01083       }
01084       width_in_blocks = width_in_iMCUs * h_samp_factor;
01085       height_in_blocks = height_in_iMCUs * v_samp_factor;
01086       coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
01087     ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
01088      width_in_blocks, height_in_blocks, (JDIMENSION) v_samp_factor);
01089     }
01090     info->workspace_coef_arrays = coef_arrays;
01091   } else
01092     info->workspace_coef_arrays = NULL;
01093 
01094   return TRUE;
01095 }
01096 
01097 
01098 /* Transpose destination image parameters */
01099 
01100 LOCAL(void)
01101 transpose_critical_parameters (j_compress_ptr dstinfo)
01102 {
01103   int tblno, i, j, ci, itemp;
01104   jpeg_component_info *compptr;
01105   JQUANT_TBL *qtblptr;
01106   JDIMENSION jtemp;
01107   UINT16 qtemp;
01108 
01109   /* Transpose image dimensions */
01110   jtemp = dstinfo->image_width;
01111   dstinfo->image_width = dstinfo->image_height;
01112   dstinfo->image_height = jtemp;
01113   itemp = dstinfo->min_DCT_h_scaled_size;
01114   dstinfo->min_DCT_h_scaled_size = dstinfo->min_DCT_v_scaled_size;
01115   dstinfo->min_DCT_v_scaled_size = itemp;
01116 
01117   /* Transpose sampling factors */
01118   for (ci = 0; ci < dstinfo->num_components; ci++) {
01119     compptr = dstinfo->comp_info + ci;
01120     itemp = compptr->h_samp_factor;
01121     compptr->h_samp_factor = compptr->v_samp_factor;
01122     compptr->v_samp_factor = itemp;
01123   }
01124 
01125   /* Transpose quantization tables */
01126   for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
01127     qtblptr = dstinfo->quant_tbl_ptrs[tblno];
01128     if (qtblptr != NULL) {
01129       for (i = 0; i < DCTSIZE; i++) {
01130     for (j = 0; j < i; j++) {
01131       qtemp = qtblptr->quantval[i*DCTSIZE+j];
01132       qtblptr->quantval[i*DCTSIZE+j] = qtblptr->quantval[j*DCTSIZE+i];
01133       qtblptr->quantval[j*DCTSIZE+i] = qtemp;
01134     }
01135       }
01136     }
01137   }
01138 }
01139 
01140 
01141 /* Adjust Exif image parameters.
01142  *
01143  * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible.
01144  */
01145 
01146 LOCAL(void)
01147 adjust_exif_parameters (JOCTET FAR * data, unsigned int length,
01148             JDIMENSION new_width, JDIMENSION new_height)
01149 {
01150   boolean is_motorola; /* Flag for byte order */
01151   unsigned int number_of_tags, tagnum;
01152   unsigned int firstoffset, offset;
01153   JDIMENSION new_value;
01154 
01155   if (length < 12) return; /* Length of an IFD entry */
01156 
01157   /* Discover byte order */
01158   if (GETJOCTET(data[0]) == 0x49 && GETJOCTET(data[1]) == 0x49)
01159     is_motorola = FALSE;
01160   else if (GETJOCTET(data[0]) == 0x4D && GETJOCTET(data[1]) == 0x4D)
01161     is_motorola = TRUE;
01162   else
01163     return;
01164 
01165   /* Check Tag Mark */
01166   if (is_motorola) {
01167     if (GETJOCTET(data[2]) != 0) return;
01168     if (GETJOCTET(data[3]) != 0x2A) return;
01169   } else {
01170     if (GETJOCTET(data[3]) != 0) return;
01171     if (GETJOCTET(data[2]) != 0x2A) return;
01172   }
01173 
01174   /* Get first IFD offset (offset to IFD0) */
01175   if (is_motorola) {
01176     if (GETJOCTET(data[4]) != 0) return;
01177     if (GETJOCTET(data[5]) != 0) return;
01178     firstoffset = GETJOCTET(data[6]);
01179     firstoffset <<= 8;
01180     firstoffset += GETJOCTET(data[7]);
01181   } else {
01182     if (GETJOCTET(data[7]) != 0) return;
01183     if (GETJOCTET(data[6]) != 0) return;
01184     firstoffset = GETJOCTET(data[5]);
01185     firstoffset <<= 8;
01186     firstoffset += GETJOCTET(data[4]);
01187   }
01188   if (firstoffset > length - 2) return; /* check end of data segment */
01189 
01190   /* Get the number of directory entries contained in this IFD */
01191   if (is_motorola) {
01192     number_of_tags = GETJOCTET(data[firstoffset]);
01193     number_of_tags <<= 8;
01194     number_of_tags += GETJOCTET(data[firstoffset+1]);
01195   } else {
01196     number_of_tags = GETJOCTET(data[firstoffset+1]);
01197     number_of_tags <<= 8;
01198     number_of_tags += GETJOCTET(data[firstoffset]);
01199   }
01200   if (number_of_tags == 0) return;
01201   firstoffset += 2;
01202 
01203   /* Search for ExifSubIFD offset Tag in IFD0 */
01204   for (;;) {
01205     if (firstoffset > length - 12) return; /* check end of data segment */
01206     /* Get Tag number */
01207     if (is_motorola) {
01208       tagnum = GETJOCTET(data[firstoffset]);
01209       tagnum <<= 8;
01210       tagnum += GETJOCTET(data[firstoffset+1]);
01211     } else {
01212       tagnum = GETJOCTET(data[firstoffset+1]);
01213       tagnum <<= 8;
01214       tagnum += GETJOCTET(data[firstoffset]);
01215     }
01216     if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */
01217     if (--number_of_tags == 0) return;
01218     firstoffset += 12;
01219   }
01220 
01221   /* Get the ExifSubIFD offset */
01222   if (is_motorola) {
01223     if (GETJOCTET(data[firstoffset+8]) != 0) return;
01224     if (GETJOCTET(data[firstoffset+9]) != 0) return;
01225     offset = GETJOCTET(data[firstoffset+10]);
01226     offset <<= 8;
01227     offset += GETJOCTET(data[firstoffset+11]);
01228   } else {
01229     if (GETJOCTET(data[firstoffset+11]) != 0) return;
01230     if (GETJOCTET(data[firstoffset+10]) != 0) return;
01231     offset = GETJOCTET(data[firstoffset+9]);
01232     offset <<= 8;
01233     offset += GETJOCTET(data[firstoffset+8]);
01234   }
01235   if (offset > length - 2) return; /* check end of data segment */
01236 
01237   /* Get the number of directory entries contained in this SubIFD */
01238   if (is_motorola) {
01239     number_of_tags = GETJOCTET(data[offset]);
01240     number_of_tags <<= 8;
01241     number_of_tags += GETJOCTET(data[offset+1]);
01242   } else {
01243     number_of_tags = GETJOCTET(data[offset+1]);
01244     number_of_tags <<= 8;
01245     number_of_tags += GETJOCTET(data[offset]);
01246   }
01247   if (number_of_tags < 2) return;
01248   offset += 2;
01249 
01250   /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */
01251   do {
01252     if (offset > length - 12) return; /* check end of data segment */
01253     /* Get Tag number */
01254     if (is_motorola) {
01255       tagnum = GETJOCTET(data[offset]);
01256       tagnum <<= 8;
01257       tagnum += GETJOCTET(data[offset+1]);
01258     } else {
01259       tagnum = GETJOCTET(data[offset+1]);
01260       tagnum <<= 8;
01261       tagnum += GETJOCTET(data[offset]);
01262     }
01263     if (tagnum == 0xA002 || tagnum == 0xA003) {
01264       if (tagnum == 0xA002)
01265     new_value = new_width; /* ExifImageWidth Tag */
01266       else
01267     new_value = new_height; /* ExifImageHeight Tag */
01268       if (is_motorola) {
01269     data[offset+2] = 0; /* Format = unsigned long (4 octets) */
01270     data[offset+3] = 4;
01271     data[offset+4] = 0; /* Number Of Components = 1 */
01272     data[offset+5] = 0;
01273     data[offset+6] = 0;
01274     data[offset+7] = 1;
01275     data[offset+8] = 0;
01276     data[offset+9] = 0;
01277     data[offset+10] = (JOCTET)((new_value >> 8) & 0xFF);
01278     data[offset+11] = (JOCTET)(new_value & 0xFF);
01279       } else {
01280     data[offset+2] = 4; /* Format = unsigned long (4 octets) */
01281     data[offset+3] = 0;
01282     data[offset+4] = 1; /* Number Of Components = 1 */
01283     data[offset+5] = 0;
01284     data[offset+6] = 0;
01285     data[offset+7] = 0;
01286     data[offset+8] = (JOCTET)(new_value & 0xFF);
01287     data[offset+9] = (JOCTET)((new_value >> 8) & 0xFF);
01288     data[offset+10] = 0;
01289     data[offset+11] = 0;
01290       }
01291     }
01292     offset += 12;
01293   } while (--number_of_tags);
01294 }
01295 
01296 
01297 /* Adjust output image parameters as needed.
01298  *
01299  * This must be called after jpeg_copy_critical_parameters()
01300  * and before jpeg_write_coefficients().
01301  *
01302  * The return value is the set of virtual coefficient arrays to be written
01303  * (either the ones allocated by jtransform_request_workspace, or the
01304  * original source data arrays).  The caller will need to pass this value
01305  * to jpeg_write_coefficients().
01306  */
01307 
01308 GLOBAL(jvirt_barray_ptr *)
01309 jtransform_adjust_parameters (j_decompress_ptr srcinfo,
01310                   j_compress_ptr dstinfo,
01311                   jvirt_barray_ptr *src_coef_arrays,
01312                   jpeg_transform_info *info)
01313 {
01314   /* If force-to-grayscale is requested, adjust destination parameters */
01315   if (info->force_grayscale) {
01316     /* First, ensure we have YCbCr or grayscale data, and that the source's
01317      * Y channel is full resolution.  (No reasonable person would make Y
01318      * be less than full resolution, so actually coping with that case
01319      * isn't worth extra code space.  But we check it to avoid crashing.)
01320      */
01321     if (((dstinfo->jpeg_color_space == JCS_YCbCr &&
01322       dstinfo->num_components == 3) ||
01323      (dstinfo->jpeg_color_space == JCS_GRAYSCALE &&
01324       dstinfo->num_components == 1)) &&
01325     srcinfo->comp_info[0].h_samp_factor == srcinfo->max_h_samp_factor &&
01326     srcinfo->comp_info[0].v_samp_factor == srcinfo->max_v_samp_factor) {
01327       /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
01328        * properly.  Among other things, it sets the target h_samp_factor &
01329        * v_samp_factor to 1, which typically won't match the source.
01330        * We have to preserve the source's quantization table number, however.
01331        */
01332       int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no;
01333       jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE);
01334       dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no;
01335     } else {
01336       /* Sorry, can't do it */
01337       ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL);
01338     }
01339   } else if (info->num_components == 1) {
01340     /* For a single-component source, we force the destination sampling factors
01341      * to 1x1, with or without force_grayscale.  This is useful because some
01342      * decoders choke on grayscale images with other sampling factors.
01343      */
01344     dstinfo->comp_info[0].h_samp_factor = 1;
01345     dstinfo->comp_info[0].v_samp_factor = 1;
01346   }
01347 
01348   /* Correct the destination's image dimensions as necessary
01349    * for rotate/flip, resize, and crop operations.
01350    */
01351   dstinfo->jpeg_width = info->output_width;
01352   dstinfo->jpeg_height = info->output_height;
01353 
01354   /* Transpose destination image parameters */
01355   switch (info->transform) {
01356   case JXFORM_TRANSPOSE:
01357   case JXFORM_TRANSVERSE:
01358   case JXFORM_ROT_90:
01359   case JXFORM_ROT_270:
01360     transpose_critical_parameters(dstinfo);
01361     break;
01362   default:
01363     break;
01364   }
01365 
01366   /* Adjust Exif properties */
01367   if (srcinfo->marker_list != NULL &&
01368       srcinfo->marker_list->marker == JPEG_APP0+1 &&
01369       srcinfo->marker_list->data_length >= 6 &&
01370       GETJOCTET(srcinfo->marker_list->data[0]) == 0x45 &&
01371       GETJOCTET(srcinfo->marker_list->data[1]) == 0x78 &&
01372       GETJOCTET(srcinfo->marker_list->data[2]) == 0x69 &&
01373       GETJOCTET(srcinfo->marker_list->data[3]) == 0x66 &&
01374       GETJOCTET(srcinfo->marker_list->data[4]) == 0 &&
01375       GETJOCTET(srcinfo->marker_list->data[5]) == 0) {
01376     /* Suppress output of JFIF marker */
01377     dstinfo->write_JFIF_header = FALSE;
01378     /* Adjust Exif image parameters */
01379     if (dstinfo->jpeg_width != srcinfo->image_width ||
01380     dstinfo->jpeg_height != srcinfo->image_height)
01381       /* Align data segment to start of TIFF structure for parsing */
01382       adjust_exif_parameters(srcinfo->marker_list->data + 6,
01383     srcinfo->marker_list->data_length - 6,
01384     dstinfo->jpeg_width, dstinfo->jpeg_height);
01385   }
01386 
01387   /* Return the appropriate output data set */
01388   if (info->workspace_coef_arrays != NULL)
01389     return info->workspace_coef_arrays;
01390   return src_coef_arrays;
01391 }
01392 
01393 
01394 /* Execute the actual transformation, if any.
01395  *
01396  * This must be called *after* jpeg_write_coefficients, because it depends
01397  * on jpeg_write_coefficients to have computed subsidiary values such as
01398  * the per-component width and height fields in the destination object.
01399  *
01400  * Note that some transformations will modify the source data arrays!
01401  */
01402 
01403 GLOBAL(void)
01404 jtransform_execute_transform (j_decompress_ptr srcinfo,
01405                   j_compress_ptr dstinfo,
01406                   jvirt_barray_ptr *src_coef_arrays,
01407                   jpeg_transform_info *info)
01408 {
01409   jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays;
01410 
01411   /* Note: conditions tested here should match those in switch statement
01412    * in jtransform_request_workspace()
01413    */
01414   switch (info->transform) {
01415   case JXFORM_NONE:
01416     if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
01417       do_crop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
01418           src_coef_arrays, dst_coef_arrays);
01419     break;
01420   case JXFORM_FLIP_H:
01421     if (info->y_crop_offset != 0)
01422       do_flip_h(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
01423         src_coef_arrays, dst_coef_arrays);
01424     else
01425       do_flip_h_no_crop(srcinfo, dstinfo, info->x_crop_offset,
01426             src_coef_arrays);
01427     break;
01428   case JXFORM_FLIP_V:
01429     do_flip_v(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
01430           src_coef_arrays, dst_coef_arrays);
01431     break;
01432   case JXFORM_TRANSPOSE:
01433     do_transpose(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
01434          src_coef_arrays, dst_coef_arrays);
01435     break;
01436   case JXFORM_TRANSVERSE:
01437     do_transverse(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
01438           src_coef_arrays, dst_coef_arrays);
01439     break;
01440   case JXFORM_ROT_90:
01441     do_rot_90(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
01442           src_coef_arrays, dst_coef_arrays);
01443     break;
01444   case JXFORM_ROT_180:
01445     do_rot_180(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
01446            src_coef_arrays, dst_coef_arrays);
01447     break;
01448   case JXFORM_ROT_270:
01449     do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
01450            src_coef_arrays, dst_coef_arrays);
01451     break;
01452   }
01453 }
01454 
01455 /* jtransform_perfect_transform
01456  *
01457  * Determine whether lossless transformation is perfectly
01458  * possible for a specified image and transformation.
01459  *
01460  * Inputs:
01461  *   image_width, image_height: source image dimensions.
01462  *   MCU_width, MCU_height: pixel dimensions of MCU.
01463  *   transform: transformation identifier.
01464  * Parameter sources from initialized jpeg_struct
01465  * (after reading source header):
01466  *   image_width = cinfo.image_width
01467  *   image_height = cinfo.image_height
01468  *   MCU_width = cinfo.max_h_samp_factor * cinfo.block_size
01469  *   MCU_height = cinfo.max_v_samp_factor * cinfo.block_size
01470  * Result:
01471  *   TRUE = perfect transformation possible
01472  *   FALSE = perfect transformation not possible
01473  *           (may use custom action then)
01474  */
01475 
01476 GLOBAL(boolean)
01477 jtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height,
01478                  int MCU_width, int MCU_height,
01479                  JXFORM_CODE transform)
01480 {
01481   boolean result = TRUE; /* initialize TRUE */
01482 
01483   switch (transform) {
01484   case JXFORM_FLIP_H:
01485   case JXFORM_ROT_270:
01486     if (image_width % (JDIMENSION) MCU_width)
01487       result = FALSE;
01488     break;
01489   case JXFORM_FLIP_V:
01490   case JXFORM_ROT_90:
01491     if (image_height % (JDIMENSION) MCU_height)
01492       result = FALSE;
01493     break;
01494   case JXFORM_TRANSVERSE:
01495   case JXFORM_ROT_180:
01496     if (image_width % (JDIMENSION) MCU_width)
01497       result = FALSE;
01498     if (image_height % (JDIMENSION) MCU_height)
01499       result = FALSE;
01500     break;
01501   default:
01502     break;
01503   }
01504 
01505   return result;
01506 }
01507 
01508 #endif /* TRANSFORMS_SUPPORTED */
01509 
01510 
01511 /* Setup decompression object to save desired markers in memory.
01512  * This must be called before jpeg_read_header() to have the desired effect.
01513  */
01514 
01515 GLOBAL(void)
01516 jcopy_markers_setup (j_decompress_ptr srcinfo, JCOPY_OPTION option)
01517 {
01518 #ifdef SAVE_MARKERS_SUPPORTED
01519   int m;
01520 
01521   /* Save comments except under NONE option */
01522   if (option != JCOPYOPT_NONE) {
01523     jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF);
01524   }
01525   /* Save all types of APPn markers iff ALL option */
01526   if (option == JCOPYOPT_ALL) {
01527     for (m = 0; m < 16; m++)
01528       jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF);
01529   }
01530 #endif /* SAVE_MARKERS_SUPPORTED */
01531 }
01532 
01533 /* Copy markers saved in the given source object to the destination object.
01534  * This should be called just after jpeg_start_compress() or
01535  * jpeg_write_coefficients().
01536  * Note that those routines will have written the SOI, and also the
01537  * JFIF APP0 or Adobe APP14 markers if selected.
01538  */
01539 
01540 GLOBAL(void)
01541 jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
01542                JCOPY_OPTION option)
01543 {
01544   jpeg_saved_marker_ptr marker;
01545 
01546   /* In the current implementation, we don't actually need to examine the
01547    * option flag here; we just copy everything that got saved.
01548    * But to avoid confusion, we do not output JFIF and Adobe APP14 markers
01549    * if the encoder library already wrote one.
01550    */
01551   for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) {
01552     if (dstinfo->write_JFIF_header &&
01553     marker->marker == JPEG_APP0 &&
01554     marker->data_length >= 5 &&
01555     GETJOCTET(marker->data[0]) == 0x4A &&
01556     GETJOCTET(marker->data[1]) == 0x46 &&
01557     GETJOCTET(marker->data[2]) == 0x49 &&
01558     GETJOCTET(marker->data[3]) == 0x46 &&
01559     GETJOCTET(marker->data[4]) == 0)
01560       continue;         /* reject duplicate JFIF */
01561     if (dstinfo->write_Adobe_marker &&
01562     marker->marker == JPEG_APP0+14 &&
01563     marker->data_length >= 5 &&
01564     GETJOCTET(marker->data[0]) == 0x41 &&
01565     GETJOCTET(marker->data[1]) == 0x64 &&
01566     GETJOCTET(marker->data[2]) == 0x6F &&
01567     GETJOCTET(marker->data[3]) == 0x62 &&
01568     GETJOCTET(marker->data[4]) == 0x65)
01569       continue;         /* reject duplicate Adobe */
01570 #ifdef NEED_FAR_POINTERS
01571     /* We could use jpeg_write_marker if the data weren't FAR... */
01572     {
01573       unsigned int i;
01574       jpeg_write_m_header(dstinfo, marker->marker, marker->data_length);
01575       for (i = 0; i < marker->data_length; i++)
01576     jpeg_write_m_byte(dstinfo, marker->data[i]);
01577     }
01578 #else
01579     jpeg_write_marker(dstinfo, marker->marker,
01580               marker->data, marker->data_length);
01581 #endif
01582   }
01583 }

Generated on Sat May 26 2012 04:18:15 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.