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 Tue Jul 5 14:13:30 2011 for ROOT_528-00b_version by  doxygen 1.5.1