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