Back to index

plt-scheme  4.2.1
transupp.c
Go to the documentation of this file.
00001 /*
00002  * transupp.c
00003  *
00004  * Copyright (C) 1997, Thomas G. Lane.
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 
00024 
00025 #if TRANSFORMS_SUPPORTED
00026 
00027 /*
00028  * Lossless image transformation routines.  These routines work on DCT
00029  * coefficient arrays and thus do not require any lossy decompression
00030  * or recompression of the image.
00031  * Thanks to Guido Vollbeding for the initial design and code of this feature.
00032  *
00033  * Horizontal flipping is done in-place, using a single top-to-bottom
00034  * pass through the virtual source array.  It will thus be much the
00035  * fastest option for images larger than main memory.
00036  *
00037  * The other routines require a set of destination virtual arrays, so they
00038  * need twice as much memory as jpegtran normally does.  The destination
00039  * arrays are always written in normal scan order (top to bottom) because
00040  * the virtual array manager expects this.  The source arrays will be scanned
00041  * in the corresponding order, which means multiple passes through the source
00042  * arrays for most of the transforms.  That could result in much thrashing
00043  * if the image is larger than main memory.
00044  *
00045  * Some notes about the operating environment of the individual transform
00046  * routines:
00047  * 1. Both the source and destination virtual arrays are allocated from the
00048  *    source JPEG object, and therefore should be manipulated by calling the
00049  *    source's memory manager.
00050  * 2. The destination's component count should be used.  It may be smaller
00051  *    than the source's when forcing to grayscale.
00052  * 3. Likewise the destination's sampling factors should be used.  When
00053  *    forcing to grayscale the destination's sampling factors will be all 1,
00054  *    and we may as well take that as the effective iMCU size.
00055  * 4. When "trim" is in effect, the destination's dimensions will be the
00056  *    trimmed values but the source's will be untrimmed.
00057  * 5. All the routines assume that the source and destination buffers are
00058  *    padded out to a full iMCU boundary.  This is true, although for the
00059  *    source buffer it is an undocumented property of jdcoefct.c.
00060  * Notes 2,3,4 boil down to this: generally we should use the destination's
00061  * dimensions and ignore the source's.
00062  */
00063 
00064 
00065 LOCAL(void)
00066 do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
00067           jvirt_barray_ptr *src_coef_arrays)
00068 /* Horizontal flip; done in-place, so no separate dest array is required */
00069 {
00070   JDIMENSION MCU_cols, comp_width, blk_x, blk_y;
00071   int ci, k, offset_y;
00072   JBLOCKARRAY buffer;
00073   JCOEFPTR ptr1, ptr2;
00074   JCOEF temp1, temp2;
00075   jpeg_component_info *compptr;
00076 
00077   /* Horizontal mirroring of DCT blocks is accomplished by swapping
00078    * pairs of blocks in-place.  Within a DCT block, we perform horizontal
00079    * mirroring by changing the signs of odd-numbered columns.
00080    * Partial iMCUs at the right edge are left untouched.
00081    */
00082   MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
00083 
00084   for (ci = 0; ci < dstinfo->num_components; ci++) {
00085     compptr = dstinfo->comp_info + ci;
00086     comp_width = MCU_cols * compptr->h_samp_factor;
00087     for (blk_y = 0; blk_y < compptr->height_in_blocks;
00088         blk_y += compptr->v_samp_factor) {
00089       buffer = (*srcinfo->mem->access_virt_barray)
00090        ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y,
00091         (JDIMENSION) compptr->v_samp_factor, TRUE);
00092       for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
00093        for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) {
00094          ptr1 = buffer[offset_y][blk_x];
00095          ptr2 = buffer[offset_y][comp_width - blk_x - 1];
00096          /* this unrolled loop doesn't need to know which row it's on... */
00097          for (k = 0; k < DCTSIZE2; k += 2) {
00098            temp1 = *ptr1;   /* swap even column */
00099            temp2 = *ptr2;
00100            *ptr1++ = temp2;
00101            *ptr2++ = temp1;
00102            temp1 = *ptr1;   /* swap odd column with sign change */
00103            temp2 = *ptr2;
00104            *ptr1++ = -temp2;
00105            *ptr2++ = -temp1;
00106          }
00107        }
00108       }
00109     }
00110   }
00111 }
00112 
00113 
00114 LOCAL(void)
00115 do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
00116           jvirt_barray_ptr *src_coef_arrays,
00117           jvirt_barray_ptr *dst_coef_arrays)
00118 /* Vertical flip */
00119 {
00120   JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
00121   int ci, i, j, offset_y;
00122   JBLOCKARRAY src_buffer, dst_buffer;
00123   JBLOCKROW src_row_ptr, dst_row_ptr;
00124   JCOEFPTR src_ptr, dst_ptr;
00125   jpeg_component_info *compptr;
00126 
00127   /* We output into a separate array because we can't touch different
00128    * rows of the source virtual array simultaneously.  Otherwise, this
00129    * is a pretty straightforward analog of horizontal flip.
00130    * Within a DCT block, vertical mirroring is done by changing the signs
00131    * of odd-numbered rows.
00132    * Partial iMCUs at the bottom edge are copied verbatim.
00133    */
00134   MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
00135 
00136   for (ci = 0; ci < dstinfo->num_components; ci++) {
00137     compptr = dstinfo->comp_info + ci;
00138     comp_height = MCU_rows * compptr->v_samp_factor;
00139     for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
00140         dst_blk_y += compptr->v_samp_factor) {
00141       dst_buffer = (*srcinfo->mem->access_virt_barray)
00142        ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
00143         (JDIMENSION) compptr->v_samp_factor, TRUE);
00144       if (dst_blk_y < comp_height) {
00145        /* Row is within the mirrorable area. */
00146        src_buffer = (*srcinfo->mem->access_virt_barray)
00147          ((j_common_ptr) srcinfo, src_coef_arrays[ci],
00148           comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor,
00149           (JDIMENSION) compptr->v_samp_factor, FALSE);
00150       } else {
00151        /* Bottom-edge blocks will be copied verbatim. */
00152        src_buffer = (*srcinfo->mem->access_virt_barray)
00153          ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y,
00154           (JDIMENSION) compptr->v_samp_factor, FALSE);
00155       }
00156       for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
00157        if (dst_blk_y < comp_height) {
00158          /* Row is within the mirrorable area. */
00159          dst_row_ptr = dst_buffer[offset_y];
00160          src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
00161          for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
00162               dst_blk_x++) {
00163            dst_ptr = dst_row_ptr[dst_blk_x];
00164            src_ptr = src_row_ptr[dst_blk_x];
00165            for (i = 0; i < DCTSIZE; i += 2) {
00166              /* copy even row */
00167              for (j = 0; j < DCTSIZE; j++)
00168               *dst_ptr++ = *src_ptr++;
00169              /* copy odd row with sign change */
00170              for (j = 0; j < DCTSIZE; j++)
00171               *dst_ptr++ = - *src_ptr++;
00172            }
00173          }
00174        } else {
00175          /* Just copy row verbatim. */
00176          jcopy_block_row(src_buffer[offset_y], dst_buffer[offset_y],
00177                        compptr->width_in_blocks);
00178        }
00179       }
00180     }
00181   }
00182 }
00183 
00184 
00185 LOCAL(void)
00186 do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
00187              jvirt_barray_ptr *src_coef_arrays,
00188              jvirt_barray_ptr *dst_coef_arrays)
00189 /* Transpose source into destination */
00190 {
00191   JDIMENSION dst_blk_x, dst_blk_y;
00192   int ci, i, j, offset_x, offset_y;
00193   JBLOCKARRAY src_buffer, dst_buffer;
00194   JCOEFPTR src_ptr, dst_ptr;
00195   jpeg_component_info *compptr;
00196 
00197   /* Transposing pixels within a block just requires transposing the
00198    * DCT coefficients.
00199    * Partial iMCUs at the edges require no special treatment; we simply
00200    * process all the available DCT blocks for every component.
00201    */
00202   for (ci = 0; ci < dstinfo->num_components; ci++) {
00203     compptr = dstinfo->comp_info + ci;
00204     for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
00205         dst_blk_y += compptr->v_samp_factor) {
00206       dst_buffer = (*srcinfo->mem->access_virt_barray)
00207        ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
00208         (JDIMENSION) compptr->v_samp_factor, TRUE);
00209       for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
00210        for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
00211             dst_blk_x += compptr->h_samp_factor) {
00212          src_buffer = (*srcinfo->mem->access_virt_barray)
00213            ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
00214             (JDIMENSION) compptr->h_samp_factor, FALSE);
00215          for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
00216            src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
00217            dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
00218            for (i = 0; i < DCTSIZE; i++)
00219              for (j = 0; j < DCTSIZE; j++)
00220               dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
00221          }
00222        }
00223       }
00224     }
00225   }
00226 }
00227 
00228 
00229 LOCAL(void)
00230 do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
00231           jvirt_barray_ptr *src_coef_arrays,
00232           jvirt_barray_ptr *dst_coef_arrays)
00233 /* 90 degree rotation is equivalent to
00234  *   1. Transposing the image;
00235  *   2. Horizontal mirroring.
00236  * These two steps are merged into a single processing routine.
00237  */
00238 {
00239   JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
00240   int ci, i, j, offset_x, offset_y;
00241   JBLOCKARRAY src_buffer, dst_buffer;
00242   JCOEFPTR src_ptr, dst_ptr;
00243   jpeg_component_info *compptr;
00244 
00245   /* Because of the horizontal mirror step, we can't process partial iMCUs
00246    * at the (output) right edge properly.  They just get transposed and
00247    * not mirrored.
00248    */
00249   MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
00250 
00251   for (ci = 0; ci < dstinfo->num_components; ci++) {
00252     compptr = dstinfo->comp_info + ci;
00253     comp_width = MCU_cols * compptr->h_samp_factor;
00254     for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
00255         dst_blk_y += compptr->v_samp_factor) {
00256       dst_buffer = (*srcinfo->mem->access_virt_barray)
00257        ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
00258         (JDIMENSION) compptr->v_samp_factor, TRUE);
00259       for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
00260        for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
00261             dst_blk_x += compptr->h_samp_factor) {
00262          src_buffer = (*srcinfo->mem->access_virt_barray)
00263            ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
00264             (JDIMENSION) compptr->h_samp_factor, FALSE);
00265          for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
00266            src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
00267            if (dst_blk_x < comp_width) {
00268              /* Block is within the mirrorable area. */
00269              dst_ptr = dst_buffer[offset_y]
00270               [comp_width - dst_blk_x - offset_x - 1];
00271              for (i = 0; i < DCTSIZE; i++) {
00272               for (j = 0; j < DCTSIZE; j++)
00273                 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
00274               i++;
00275               for (j = 0; j < DCTSIZE; j++)
00276                 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
00277              }
00278            } else {
00279              /* Edge blocks are transposed but not mirrored. */
00280              dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
00281              for (i = 0; i < DCTSIZE; i++)
00282               for (j = 0; j < DCTSIZE; j++)
00283                 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
00284            }
00285          }
00286        }
00287       }
00288     }
00289   }
00290 }
00291 
00292 
00293 LOCAL(void)
00294 do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
00295            jvirt_barray_ptr *src_coef_arrays,
00296            jvirt_barray_ptr *dst_coef_arrays)
00297 /* 270 degree rotation is equivalent to
00298  *   1. Horizontal mirroring;
00299  *   2. Transposing the image.
00300  * These two steps are merged into a single processing routine.
00301  */
00302 {
00303   JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
00304   int ci, i, j, offset_x, offset_y;
00305   JBLOCKARRAY src_buffer, dst_buffer;
00306   JCOEFPTR src_ptr, dst_ptr;
00307   jpeg_component_info *compptr;
00308 
00309   /* Because of the horizontal mirror step, we can't process partial iMCUs
00310    * at the (output) bottom edge properly.  They just get transposed and
00311    * not mirrored.
00312    */
00313   MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
00314 
00315   for (ci = 0; ci < dstinfo->num_components; ci++) {
00316     compptr = dstinfo->comp_info + ci;
00317     comp_height = MCU_rows * compptr->v_samp_factor;
00318     for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
00319         dst_blk_y += compptr->v_samp_factor) {
00320       dst_buffer = (*srcinfo->mem->access_virt_barray)
00321        ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
00322         (JDIMENSION) compptr->v_samp_factor, TRUE);
00323       for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
00324        for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
00325             dst_blk_x += compptr->h_samp_factor) {
00326          src_buffer = (*srcinfo->mem->access_virt_barray)
00327            ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
00328             (JDIMENSION) compptr->h_samp_factor, FALSE);
00329          for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
00330            dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
00331            if (dst_blk_y < comp_height) {
00332              /* Block is within the mirrorable area. */
00333              src_ptr = src_buffer[offset_x]
00334               [comp_height - dst_blk_y - offset_y - 1];
00335              for (i = 0; i < DCTSIZE; i++) {
00336               for (j = 0; j < DCTSIZE; j++) {
00337                 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
00338                 j++;
00339                 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
00340               }
00341              }
00342            } else {
00343              /* Edge blocks are transposed but not mirrored. */
00344              src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
00345              for (i = 0; i < DCTSIZE; i++)
00346               for (j = 0; j < DCTSIZE; j++)
00347                 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
00348            }
00349          }
00350        }
00351       }
00352     }
00353   }
00354 }
00355 
00356 
00357 LOCAL(void)
00358 do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
00359            jvirt_barray_ptr *src_coef_arrays,
00360            jvirt_barray_ptr *dst_coef_arrays)
00361 /* 180 degree rotation is equivalent to
00362  *   1. Vertical mirroring;
00363  *   2. Horizontal mirroring.
00364  * These two steps are merged into a single processing routine.
00365  */
00366 {
00367   JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
00368   int ci, i, j, offset_y;
00369   JBLOCKARRAY src_buffer, dst_buffer;
00370   JBLOCKROW src_row_ptr, dst_row_ptr;
00371   JCOEFPTR src_ptr, dst_ptr;
00372   jpeg_component_info *compptr;
00373 
00374   MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
00375   MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
00376 
00377   for (ci = 0; ci < dstinfo->num_components; ci++) {
00378     compptr = dstinfo->comp_info + ci;
00379     comp_width = MCU_cols * compptr->h_samp_factor;
00380     comp_height = MCU_rows * compptr->v_samp_factor;
00381     for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
00382         dst_blk_y += compptr->v_samp_factor) {
00383       dst_buffer = (*srcinfo->mem->access_virt_barray)
00384        ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
00385         (JDIMENSION) compptr->v_samp_factor, TRUE);
00386       if (dst_blk_y < comp_height) {
00387        /* Row is within the vertically mirrorable area. */
00388        src_buffer = (*srcinfo->mem->access_virt_barray)
00389          ((j_common_ptr) srcinfo, src_coef_arrays[ci],
00390           comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor,
00391           (JDIMENSION) compptr->v_samp_factor, FALSE);
00392       } else {
00393        /* Bottom-edge rows are only mirrored horizontally. */
00394        src_buffer = (*srcinfo->mem->access_virt_barray)
00395          ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y,
00396           (JDIMENSION) compptr->v_samp_factor, FALSE);
00397       }
00398       for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
00399        if (dst_blk_y < comp_height) {
00400          /* Row is within the mirrorable area. */
00401          dst_row_ptr = dst_buffer[offset_y];
00402          src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
00403          /* Process the blocks that can be mirrored both ways. */
00404          for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) {
00405            dst_ptr = dst_row_ptr[dst_blk_x];
00406            src_ptr = src_row_ptr[comp_width - dst_blk_x - 1];
00407            for (i = 0; i < DCTSIZE; i += 2) {
00408              /* For even row, negate every odd column. */
00409              for (j = 0; j < DCTSIZE; j += 2) {
00410               *dst_ptr++ = *src_ptr++;
00411               *dst_ptr++ = - *src_ptr++;
00412              }
00413              /* For odd row, negate every even column. */
00414              for (j = 0; j < DCTSIZE; j += 2) {
00415               *dst_ptr++ = - *src_ptr++;
00416               *dst_ptr++ = *src_ptr++;
00417              }
00418            }
00419          }
00420          /* Any remaining right-edge blocks are only mirrored vertically. */
00421          for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
00422            dst_ptr = dst_row_ptr[dst_blk_x];
00423            src_ptr = src_row_ptr[dst_blk_x];
00424            for (i = 0; i < DCTSIZE; i += 2) {
00425              for (j = 0; j < DCTSIZE; j++)
00426               *dst_ptr++ = *src_ptr++;
00427              for (j = 0; j < DCTSIZE; j++)
00428               *dst_ptr++ = - *src_ptr++;
00429            }
00430          }
00431        } else {
00432          /* Remaining rows are just mirrored horizontally. */
00433          dst_row_ptr = dst_buffer[offset_y];
00434          src_row_ptr = src_buffer[offset_y];
00435          /* Process the blocks that can be mirrored. */
00436          for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) {
00437            dst_ptr = dst_row_ptr[dst_blk_x];
00438            src_ptr = src_row_ptr[comp_width - dst_blk_x - 1];
00439            for (i = 0; i < DCTSIZE2; i += 2) {
00440              *dst_ptr++ = *src_ptr++;
00441              *dst_ptr++ = - *src_ptr++;
00442            }
00443          }
00444          /* Any remaining right-edge blocks are only copied. */
00445          for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
00446            dst_ptr = dst_row_ptr[dst_blk_x];
00447            src_ptr = src_row_ptr[dst_blk_x];
00448            for (i = 0; i < DCTSIZE2; i++)
00449              *dst_ptr++ = *src_ptr++;
00450          }
00451        }
00452       }
00453     }
00454   }
00455 }
00456 
00457 
00458 LOCAL(void)
00459 do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
00460               jvirt_barray_ptr *src_coef_arrays,
00461               jvirt_barray_ptr *dst_coef_arrays)
00462 /* Transverse transpose is equivalent to
00463  *   1. 180 degree rotation;
00464  *   2. Transposition;
00465  * or
00466  *   1. Horizontal mirroring;
00467  *   2. Transposition;
00468  *   3. Horizontal mirroring.
00469  * These steps are merged into a single processing routine.
00470  */
00471 {
00472   JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
00473   int ci, i, j, offset_x, offset_y;
00474   JBLOCKARRAY src_buffer, dst_buffer;
00475   JCOEFPTR src_ptr, dst_ptr;
00476   jpeg_component_info *compptr;
00477 
00478   MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
00479   MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
00480 
00481   for (ci = 0; ci < dstinfo->num_components; ci++) {
00482     compptr = dstinfo->comp_info + ci;
00483     comp_width = MCU_cols * compptr->h_samp_factor;
00484     comp_height = MCU_rows * compptr->v_samp_factor;
00485     for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
00486         dst_blk_y += compptr->v_samp_factor) {
00487       dst_buffer = (*srcinfo->mem->access_virt_barray)
00488        ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
00489         (JDIMENSION) compptr->v_samp_factor, TRUE);
00490       for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
00491        for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
00492             dst_blk_x += compptr->h_samp_factor) {
00493          src_buffer = (*srcinfo->mem->access_virt_barray)
00494            ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
00495             (JDIMENSION) compptr->h_samp_factor, FALSE);
00496          for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
00497            if (dst_blk_y < comp_height) {
00498              src_ptr = src_buffer[offset_x]
00499               [comp_height - dst_blk_y - offset_y - 1];
00500              if (dst_blk_x < comp_width) {
00501               /* Block is within the mirrorable area. */
00502               dst_ptr = dst_buffer[offset_y]
00503                 [comp_width - dst_blk_x - offset_x - 1];
00504               for (i = 0; i < DCTSIZE; i++) {
00505                 for (j = 0; j < DCTSIZE; j++) {
00506                   dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
00507                   j++;
00508                   dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
00509                 }
00510                 i++;
00511                 for (j = 0; j < DCTSIZE; j++) {
00512                   dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
00513                   j++;
00514                   dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
00515                 }
00516               }
00517              } else {
00518               /* Right-edge blocks are mirrored in y only */
00519               dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
00520               for (i = 0; i < DCTSIZE; i++) {
00521                 for (j = 0; j < DCTSIZE; j++) {
00522                   dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
00523                   j++;
00524                   dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
00525                 }
00526               }
00527              }
00528            } else {
00529              src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
00530              if (dst_blk_x < comp_width) {
00531               /* Bottom-edge blocks are mirrored in x only */
00532               dst_ptr = dst_buffer[offset_y]
00533                 [comp_width - dst_blk_x - offset_x - 1];
00534               for (i = 0; i < DCTSIZE; i++) {
00535                 for (j = 0; j < DCTSIZE; j++)
00536                   dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
00537                 i++;
00538                 for (j = 0; j < DCTSIZE; j++)
00539                   dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
00540               }
00541              } else {
00542               /* At lower right corner, just transpose, no mirroring */
00543               dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
00544               for (i = 0; i < DCTSIZE; i++)
00545                 for (j = 0; j < DCTSIZE; j++)
00546                   dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
00547              }
00548            }
00549          }
00550        }
00551       }
00552     }
00553   }
00554 }
00555 
00556 
00557 /* Request any required workspace.
00558  *
00559  * We allocate the workspace virtual arrays from the source decompression
00560  * object, so that all the arrays (both the original data and the workspace)
00561  * will be taken into account while making memory management decisions.
00562  * Hence, this routine must be called after jpeg_read_header (which reads
00563  * the image dimensions) and before jpeg_read_coefficients (which realizes
00564  * the source's virtual arrays).
00565  */
00566 
00567 GLOBAL(void)
00568 jtransform_request_workspace (j_decompress_ptr srcinfo,
00569                            jpeg_transform_info *info)
00570 {
00571   jvirt_barray_ptr *coef_arrays = NULL;
00572   jpeg_component_info *compptr;
00573   int ci;
00574 
00575   if (info->force_grayscale &&
00576       srcinfo->jpeg_color_space == JCS_YCbCr &&
00577       srcinfo->num_components == 3) {
00578     /* We'll only process the first component */
00579     info->num_components = 1;
00580   } else {
00581     /* Process all the components */
00582     info->num_components = srcinfo->num_components;
00583   }
00584 
00585   switch (info->transform) {
00586   case JXFORM_NONE:
00587   case JXFORM_FLIP_H:
00588     /* Don't need a workspace array */
00589     break;
00590   case JXFORM_FLIP_V:
00591   case JXFORM_ROT_180:
00592     /* Need workspace arrays having same dimensions as source image.
00593      * Note that we allocate arrays padded out to the next iMCU boundary,
00594      * so that transform routines need not worry about missing edge blocks.
00595      */
00596     coef_arrays = (jvirt_barray_ptr *)
00597       (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
00598        SIZEOF(jvirt_barray_ptr) * info->num_components);
00599     for (ci = 0; ci < info->num_components; ci++) {
00600       compptr = srcinfo->comp_info + ci;
00601       coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
00602        ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
00603         (JDIMENSION) jround_up((long) compptr->width_in_blocks,
00604                             (long) compptr->h_samp_factor),
00605         (JDIMENSION) jround_up((long) compptr->height_in_blocks,
00606                             (long) compptr->v_samp_factor),
00607         (JDIMENSION) compptr->v_samp_factor);
00608     }
00609     break;
00610   case JXFORM_TRANSPOSE:
00611   case JXFORM_TRANSVERSE:
00612   case JXFORM_ROT_90:
00613   case JXFORM_ROT_270:
00614     /* Need workspace arrays having transposed dimensions.
00615      * Note that we allocate arrays padded out to the next iMCU boundary,
00616      * so that transform routines need not worry about missing edge blocks.
00617      */
00618     coef_arrays = (jvirt_barray_ptr *)
00619       (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
00620        SIZEOF(jvirt_barray_ptr) * info->num_components);
00621     for (ci = 0; ci < info->num_components; ci++) {
00622       compptr = srcinfo->comp_info + ci;
00623       coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
00624        ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
00625         (JDIMENSION) jround_up((long) compptr->height_in_blocks,
00626                             (long) compptr->v_samp_factor),
00627         (JDIMENSION) jround_up((long) compptr->width_in_blocks,
00628                             (long) compptr->h_samp_factor),
00629         (JDIMENSION) compptr->h_samp_factor);
00630     }
00631     break;
00632   }
00633   info->workspace_coef_arrays = coef_arrays;
00634 }
00635 
00636 
00637 /* Transpose destination image parameters */
00638 
00639 LOCAL(void)
00640 transpose_critical_parameters (j_compress_ptr dstinfo)
00641 {
00642   int tblno, i, j, ci, itemp;
00643   jpeg_component_info *compptr;
00644   JQUANT_TBL *qtblptr;
00645   JDIMENSION dtemp;
00646   UINT16 qtemp;
00647 
00648   /* Transpose basic image dimensions */
00649   dtemp = dstinfo->image_width;
00650   dstinfo->image_width = dstinfo->image_height;
00651   dstinfo->image_height = dtemp;
00652 
00653   /* Transpose sampling factors */
00654   for (ci = 0; ci < dstinfo->num_components; ci++) {
00655     compptr = dstinfo->comp_info + ci;
00656     itemp = compptr->h_samp_factor;
00657     compptr->h_samp_factor = compptr->v_samp_factor;
00658     compptr->v_samp_factor = itemp;
00659   }
00660 
00661   /* Transpose quantization tables */
00662   for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
00663     qtblptr = dstinfo->quant_tbl_ptrs[tblno];
00664     if (qtblptr != NULL) {
00665       for (i = 0; i < DCTSIZE; i++) {
00666        for (j = 0; j < i; j++) {
00667          qtemp = qtblptr->quantval[i*DCTSIZE+j];
00668          qtblptr->quantval[i*DCTSIZE+j] = qtblptr->quantval[j*DCTSIZE+i];
00669          qtblptr->quantval[j*DCTSIZE+i] = qtemp;
00670        }
00671       }
00672     }
00673   }
00674 }
00675 
00676 
00677 /* Trim off any partial iMCUs on the indicated destination edge */
00678 
00679 LOCAL(void)
00680 trim_right_edge (j_compress_ptr dstinfo)
00681 {
00682   int ci, max_h_samp_factor;
00683   JDIMENSION MCU_cols;
00684 
00685   /* We have to compute max_h_samp_factor ourselves,
00686    * because it hasn't been set yet in the destination
00687    * (and we don't want to use the source's value).
00688    */
00689   max_h_samp_factor = 1;
00690   for (ci = 0; ci < dstinfo->num_components; ci++) {
00691     int h_samp_factor = dstinfo->comp_info[ci].h_samp_factor;
00692     max_h_samp_factor = MAX(max_h_samp_factor, h_samp_factor);
00693   }
00694   MCU_cols = dstinfo->image_width / (max_h_samp_factor * DCTSIZE);
00695   if (MCU_cols > 0)         /* can't trim to 0 pixels */
00696     dstinfo->image_width = MCU_cols * (max_h_samp_factor * DCTSIZE);
00697 }
00698 
00699 LOCAL(void)
00700 trim_bottom_edge (j_compress_ptr dstinfo)
00701 {
00702   int ci, max_v_samp_factor;
00703   JDIMENSION MCU_rows;
00704 
00705   /* We have to compute max_v_samp_factor ourselves,
00706    * because it hasn't been set yet in the destination
00707    * (and we don't want to use the source's value).
00708    */
00709   max_v_samp_factor = 1;
00710   for (ci = 0; ci < dstinfo->num_components; ci++) {
00711     int v_samp_factor = dstinfo->comp_info[ci].v_samp_factor;
00712     max_v_samp_factor = MAX(max_v_samp_factor, v_samp_factor);
00713   }
00714   MCU_rows = dstinfo->image_height / (max_v_samp_factor * DCTSIZE);
00715   if (MCU_rows > 0)         /* can't trim to 0 pixels */
00716     dstinfo->image_height = MCU_rows * (max_v_samp_factor * DCTSIZE);
00717 }
00718 
00719 
00720 /* Adjust output image parameters as needed.
00721  *
00722  * This must be called after jpeg_copy_critical_parameters()
00723  * and before jpeg_write_coefficients().
00724  *
00725  * The return value is the set of virtual coefficient arrays to be written
00726  * (either the ones allocated by jtransform_request_workspace, or the
00727  * original source data arrays).  The caller will need to pass this value
00728  * to jpeg_write_coefficients().
00729  */
00730 
00731 GLOBAL(jvirt_barray_ptr *)
00732 jtransform_adjust_parameters (j_decompress_ptr srcinfo,
00733                            j_compress_ptr dstinfo,
00734                            jvirt_barray_ptr *src_coef_arrays,
00735                            jpeg_transform_info *info)
00736 {
00737   /* If force-to-grayscale is requested, adjust destination parameters */
00738   if (info->force_grayscale) {
00739     /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
00740      * properly.  Among other things, the target h_samp_factor & v_samp_factor
00741      * will get set to 1, which typically won't match the source.
00742      * In fact we do this even if the source is already grayscale; that
00743      * provides an easy way of coercing a grayscale JPEG with funny sampling
00744      * factors to the customary 1,1.  (Some decoders fail on other factors.)
00745      */
00746     if ((dstinfo->jpeg_color_space == JCS_YCbCr &&
00747         dstinfo->num_components == 3) ||
00748        (dstinfo->jpeg_color_space == JCS_GRAYSCALE &&
00749         dstinfo->num_components == 1)) {
00750       /* We have to preserve the source's quantization table number. */
00751       int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no;
00752       jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE);
00753       dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no;
00754     } else {
00755       /* Sorry, can't do it */
00756       ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL);
00757     }
00758   }
00759 
00760   /* Correct the destination's image dimensions etc if necessary */
00761   switch (info->transform) {
00762   case JXFORM_NONE:
00763     /* Nothing to do */
00764     break;
00765   case JXFORM_FLIP_H:
00766     if (info->trim)
00767       trim_right_edge(dstinfo);
00768     break;
00769   case JXFORM_FLIP_V:
00770     if (info->trim)
00771       trim_bottom_edge(dstinfo);
00772     break;
00773   case JXFORM_TRANSPOSE:
00774     transpose_critical_parameters(dstinfo);
00775     /* transpose does NOT have to trim anything */
00776     break;
00777   case JXFORM_TRANSVERSE:
00778     transpose_critical_parameters(dstinfo);
00779     if (info->trim) {
00780       trim_right_edge(dstinfo);
00781       trim_bottom_edge(dstinfo);
00782     }
00783     break;
00784   case JXFORM_ROT_90:
00785     transpose_critical_parameters(dstinfo);
00786     if (info->trim)
00787       trim_right_edge(dstinfo);
00788     break;
00789   case JXFORM_ROT_180:
00790     if (info->trim) {
00791       trim_right_edge(dstinfo);
00792       trim_bottom_edge(dstinfo);
00793     }
00794     break;
00795   case JXFORM_ROT_270:
00796     transpose_critical_parameters(dstinfo);
00797     if (info->trim)
00798       trim_bottom_edge(dstinfo);
00799     break;
00800   }
00801 
00802   /* Return the appropriate output data set */
00803   if (info->workspace_coef_arrays != NULL)
00804     return info->workspace_coef_arrays;
00805   return src_coef_arrays;
00806 }
00807 
00808 
00809 /* Execute the actual transformation, if any.
00810  *
00811  * This must be called *after* jpeg_write_coefficients, because it depends
00812  * on jpeg_write_coefficients to have computed subsidiary values such as
00813  * the per-component width and height fields in the destination object.
00814  *
00815  * Note that some transformations will modify the source data arrays!
00816  */
00817 
00818 GLOBAL(void)
00819 jtransform_execute_transformation (j_decompress_ptr srcinfo,
00820                                j_compress_ptr dstinfo,
00821                                jvirt_barray_ptr *src_coef_arrays,
00822                                jpeg_transform_info *info)
00823 {
00824   jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays;
00825 
00826   switch (info->transform) {
00827   case JXFORM_NONE:
00828     break;
00829   case JXFORM_FLIP_H:
00830     do_flip_h(srcinfo, dstinfo, src_coef_arrays);
00831     break;
00832   case JXFORM_FLIP_V:
00833     do_flip_v(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
00834     break;
00835   case JXFORM_TRANSPOSE:
00836     do_transpose(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
00837     break;
00838   case JXFORM_TRANSVERSE:
00839     do_transverse(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
00840     break;
00841   case JXFORM_ROT_90:
00842     do_rot_90(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
00843     break;
00844   case JXFORM_ROT_180:
00845     do_rot_180(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
00846     break;
00847   case JXFORM_ROT_270:
00848     do_rot_270(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
00849     break;
00850   }
00851 }
00852 
00853 #endif /* TRANSFORMS_SUPPORTED */
00854 
00855 
00856 /* Setup decompression object to save desired markers in memory.
00857  * This must be called before jpeg_read_header() to have the desired effect.
00858  */
00859 
00860 GLOBAL(void)
00861 jcopy_markers_setup (j_decompress_ptr srcinfo, JCOPY_OPTION option)
00862 {
00863 #ifdef SAVE_MARKERS_SUPPORTED
00864   int m;
00865 
00866   /* Save comments except under NONE option */
00867   if (option != JCOPYOPT_NONE) {
00868     jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF);
00869   }
00870   /* Save all types of APPn markers iff ALL option */
00871   if (option == JCOPYOPT_ALL) {
00872     for (m = 0; m < 16; m++)
00873       jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF);
00874   }
00875 #endif /* SAVE_MARKERS_SUPPORTED */
00876 }
00877 
00878 /* Copy markers saved in the given source object to the destination object.
00879  * This should be called just after jpeg_start_compress() or
00880  * jpeg_write_coefficients().
00881  * Note that those routines will have written the SOI, and also the
00882  * JFIF APP0 or Adobe APP14 markers if selected.
00883  */
00884 
00885 GLOBAL(void)
00886 jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
00887                      JCOPY_OPTION option)
00888 {
00889   jpeg_saved_marker_ptr marker;
00890 
00891   /* In the current implementation, we don't actually need to examine the
00892    * option flag here; we just copy everything that got saved.
00893    * But to avoid confusion, we do not output JFIF and Adobe APP14 markers
00894    * if the encoder library already wrote one.
00895    */
00896   for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) {
00897     if (dstinfo->write_JFIF_header &&
00898        marker->marker == JPEG_APP0 &&
00899        marker->data_length >= 5 &&
00900        GETJOCTET(marker->data[0]) == 0x4A &&
00901        GETJOCTET(marker->data[1]) == 0x46 &&
00902        GETJOCTET(marker->data[2]) == 0x49 &&
00903        GETJOCTET(marker->data[3]) == 0x46 &&
00904        GETJOCTET(marker->data[4]) == 0)
00905       continue;                    /* reject duplicate JFIF */
00906     if (dstinfo->write_Adobe_marker &&
00907        marker->marker == JPEG_APP0+14 &&
00908        marker->data_length >= 5 &&
00909        GETJOCTET(marker->data[0]) == 0x41 &&
00910        GETJOCTET(marker->data[1]) == 0x64 &&
00911        GETJOCTET(marker->data[2]) == 0x6F &&
00912        GETJOCTET(marker->data[3]) == 0x62 &&
00913        GETJOCTET(marker->data[4]) == 0x65)
00914       continue;                    /* reject duplicate Adobe */
00915 #ifdef NEED_FAR_POINTERS
00916     /* We could use jpeg_write_marker if the data weren't FAR... */
00917     {
00918       unsigned int i;
00919       jpeg_write_m_header(dstinfo, marker->marker, marker->data_length);
00920       for (i = 0; i < marker->data_length; i++)
00921        jpeg_write_m_byte(dstinfo, marker->data[i]);
00922     }
00923 #else
00924     jpeg_write_marker(dstinfo, marker->marker,
00925                     marker->data, marker->data_length);
00926 #endif
00927   }
00928 }