File indexing completed on 2025-03-09 03:55:08
0001 /* 0002 * transupp.c 0003 * 0004 * SPDX-FileCopyrightText: 1997-2011, Thomas G. Lane, Guido Vollbeding. 0005 * This file is part of the Independent JPEG Group's software. 0006 * For conditions of distribution and use, see the accompanying README file. 0007 * 0008 * This file contains image transformation routines and other utility code 0009 * used by the jpegtran sample application. These are NOT part of the core 0010 * JPEG library. But we keep these routines separate from jpegtran.c to 0011 * ease the task of maintaining jpegtran-like programs that have other user 0012 * interfaces. 0013 */ 0014 0015 /* Although this file really shouldn't have access to the library internals, 0016 * it's helpful to let it call jround_up() and jcopy_block_row(). 0017 */ 0018 #define JPEG_INTERNALS 0019 0020 #include "jinclude.h" 0021 #include "jpeglib.h" 0022 #include "transupp.h" /* My own external interface */ 0023 #include <ctype.h> /* to declare isdigit() */ 0024 0025 0026 #if TRANSFORMS_SUPPORTED 0027 0028 /* 0029 * Lossless image transformation routines. These routines work on DCT 0030 * coefficient arrays and thus do not require any lossy decompression 0031 * or recompression of the image. 0032 * Thanks to Guido Vollbeding for the initial design and code of this feature, 0033 * and to Ben Jackson for introducing the cropping feature. 0034 * 0035 * Horizontal flipping is done in-place, using a single top-to-bottom 0036 * pass through the virtual source array. It will thus be much the 0037 * fastest option for images larger than main memory. 0038 * 0039 * The other routines require a set of destination virtual arrays, so they 0040 * need twice as much memory as jpegtran normally does. The destination 0041 * arrays are always written in normal scan order (top to bottom) because 0042 * the virtual array manager expects this. The source arrays will be scanned 0043 * in the corresponding order, which means multiple passes through the source 0044 * arrays for most of the transforms. That could result in much thrashing 0045 * if the image is larger than main memory. 0046 * 0047 * If cropping or trimming is involved, the destination arrays may be smaller 0048 * than the source arrays. Note it is not possible to do horizontal flip 0049 * in-place when a nonzero Y crop offset is specified, since we'd have to move 0050 * data from one block row to another but the virtual array manager doesn't 0051 * guarantee we can touch more than one row at a time. So in that case, 0052 * we have to use a separate destination array. 0053 * 0054 * Some notes about the operating environment of the individual transform 0055 * routines: 0056 * 1. Both the source and destination virtual arrays are allocated from the 0057 * source JPEG object, and therefore should be manipulated by calling the 0058 * source's memory manager. 0059 * 2. The destination's component count should be used. It may be smaller 0060 * than the source's when forcing to grayscale. 0061 * 3. Likewise the destination's sampling factors should be used. When 0062 * forcing to grayscale the destination's sampling factors will be all 1, 0063 * and we may as well take that as the effective iMCU size. 0064 * 4. When "trim" is in effect, the destination's dimensions will be the 0065 * trimmed values but the source's will be untrimmed. 0066 * 5. When "crop" is in effect, the destination's dimensions will be the 0067 * cropped values but the source's will be uncropped. Each transform 0068 * routine is responsible for picking up source data starting at the 0069 * correct X and Y offset for the crop region. (The X and Y offsets 0070 * passed to the transform routines are measured in iMCU blocks of the 0071 * destination.) 0072 * 6. All the routines assume that the source and destination buffers are 0073 * padded out to a full iMCU boundary. This is true, although for the 0074 * source buffer it is an undocumented property of jdcoefct.c. 0075 */ 0076 0077 0078 LOCAL(void) 0079 do_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 0080 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 0081 jvirt_barray_ptr *src_coef_arrays, 0082 jvirt_barray_ptr *dst_coef_arrays) 0083 /* Crop. This is only used when no rotate/flip is requested with the crop. */ 0084 { 0085 JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks; 0086 int ci, offset_y; 0087 JBLOCKARRAY src_buffer, dst_buffer; 0088 jpeg_component_info *compptr; 0089 0090 /* We simply have to copy the right amount of data (the destination's 0091 * image size) starting at the given X and Y offsets in the source. 0092 */ 0093 for (ci = 0; ci < dstinfo->num_components; ci++) { 0094 compptr = dstinfo->comp_info + ci; 0095 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 0096 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 0097 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 0098 dst_blk_y += compptr->v_samp_factor) { 0099 dst_buffer = (*srcinfo->mem->access_virt_barray) 0100 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 0101 (JDIMENSION) compptr->v_samp_factor, TRUE); 0102 src_buffer = (*srcinfo->mem->access_virt_barray) 0103 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 0104 dst_blk_y + y_crop_blocks, 0105 (JDIMENSION) compptr->v_samp_factor, FALSE); 0106 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 0107 jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, 0108 dst_buffer[offset_y], 0109 compptr->width_in_blocks); 0110 } 0111 } 0112 } 0113 } 0114 0115 0116 LOCAL(void) 0117 do_flip_h_no_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 0118 JDIMENSION x_crop_offset, 0119 jvirt_barray_ptr *src_coef_arrays) 0120 /* Horizontal flip; done in-place, so no separate dest array is required. 0121 * NB: this only works when y_crop_offset is zero. 0122 */ 0123 { 0124 JDIMENSION MCU_cols, comp_width, blk_x, blk_y, x_crop_blocks; 0125 int ci, k, offset_y; 0126 JBLOCKARRAY buffer; 0127 JCOEFPTR ptr1, ptr2; 0128 JCOEF temp1, temp2; 0129 jpeg_component_info *compptr; 0130 0131 /* Horizontal mirroring of DCT blocks is accomplished by swapping 0132 * pairs of blocks in-place. Within a DCT block, we perform horizontal 0133 * mirroring by changing the signs of odd-numbered columns. 0134 * Partial iMCUs at the right edge are left untouched. 0135 */ 0136 MCU_cols = srcinfo->output_width / 0137 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); 0138 0139 for (ci = 0; ci < dstinfo->num_components; ci++) { 0140 compptr = dstinfo->comp_info + ci; 0141 comp_width = MCU_cols * compptr->h_samp_factor; 0142 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 0143 for (blk_y = 0; blk_y < compptr->height_in_blocks; 0144 blk_y += compptr->v_samp_factor) { 0145 buffer = (*srcinfo->mem->access_virt_barray) 0146 ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y, 0147 (JDIMENSION) compptr->v_samp_factor, TRUE); 0148 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 0149 /* Do the mirroring */ 0150 for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) { 0151 ptr1 = buffer[offset_y][blk_x]; 0152 ptr2 = buffer[offset_y][comp_width - blk_x - 1]; 0153 /* this unrolled loop doesn't need to know which row it's on... */ 0154 for (k = 0; k < DCTSIZE2; k += 2) { 0155 temp1 = *ptr1; /* swap even column */ 0156 temp2 = *ptr2; 0157 *ptr1++ = temp2; 0158 *ptr2++ = temp1; 0159 temp1 = *ptr1; /* swap odd column with sign change */ 0160 temp2 = *ptr2; 0161 *ptr1++ = -temp2; 0162 *ptr2++ = -temp1; 0163 } 0164 } 0165 if (x_crop_blocks > 0) { 0166 /* Now left-justify the portion of the data to be kept. 0167 * We can't use a single jcopy_block_row() call because that routine 0168 * depends on memcpy(), whose behavior is unspecified for overlapping 0169 * source and destination areas. Sigh. 0170 */ 0171 for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) { 0172 jcopy_block_row(buffer[offset_y] + blk_x + x_crop_blocks, 0173 buffer[offset_y] + blk_x, 0174 (JDIMENSION) 1); 0175 } 0176 } 0177 } 0178 } 0179 } 0180 } 0181 0182 0183 LOCAL(void) 0184 do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 0185 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 0186 jvirt_barray_ptr *src_coef_arrays, 0187 jvirt_barray_ptr *dst_coef_arrays) 0188 /* Horizontal flip in general cropping case */ 0189 { 0190 JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y; 0191 JDIMENSION x_crop_blocks, y_crop_blocks; 0192 int ci, k, offset_y; 0193 JBLOCKARRAY src_buffer, dst_buffer; 0194 JBLOCKROW src_row_ptr, dst_row_ptr; 0195 JCOEFPTR src_ptr, dst_ptr; 0196 jpeg_component_info *compptr; 0197 0198 /* Here we must output into a separate array because we can't touch 0199 * different rows of a single virtual array simultaneously. Otherwise, 0200 * this is essentially the same as the routine above. 0201 */ 0202 MCU_cols = srcinfo->output_width / 0203 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); 0204 0205 for (ci = 0; ci < dstinfo->num_components; ci++) { 0206 compptr = dstinfo->comp_info + ci; 0207 comp_width = MCU_cols * compptr->h_samp_factor; 0208 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 0209 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 0210 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 0211 dst_blk_y += compptr->v_samp_factor) { 0212 dst_buffer = (*srcinfo->mem->access_virt_barray) 0213 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 0214 (JDIMENSION) compptr->v_samp_factor, TRUE); 0215 src_buffer = (*srcinfo->mem->access_virt_barray) 0216 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 0217 dst_blk_y + y_crop_blocks, 0218 (JDIMENSION) compptr->v_samp_factor, FALSE); 0219 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 0220 dst_row_ptr = dst_buffer[offset_y]; 0221 src_row_ptr = src_buffer[offset_y]; 0222 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { 0223 if (x_crop_blocks + dst_blk_x < comp_width) { 0224 /* Do the mirrorable blocks */ 0225 dst_ptr = dst_row_ptr[dst_blk_x]; 0226 src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; 0227 /* this unrolled loop doesn't need to know which row it's on... */ 0228 for (k = 0; k < DCTSIZE2; k += 2) { 0229 *dst_ptr++ = *src_ptr++; /* copy even column */ 0230 *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */ 0231 } 0232 } else { 0233 /* Copy last partial block(s) verbatim */ 0234 jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks, 0235 dst_row_ptr + dst_blk_x, 0236 (JDIMENSION) 1); 0237 } 0238 } 0239 } 0240 } 0241 } 0242 } 0243 0244 0245 LOCAL(void) 0246 do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 0247 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 0248 jvirt_barray_ptr *src_coef_arrays, 0249 jvirt_barray_ptr *dst_coef_arrays) 0250 /* Vertical flip */ 0251 { 0252 JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; 0253 JDIMENSION x_crop_blocks, y_crop_blocks; 0254 int ci, i, j, offset_y; 0255 JBLOCKARRAY src_buffer, dst_buffer; 0256 JBLOCKROW src_row_ptr, dst_row_ptr; 0257 JCOEFPTR src_ptr, dst_ptr; 0258 jpeg_component_info *compptr; 0259 0260 /* We output into a separate array because we can't touch different 0261 * rows of the source virtual array simultaneously. Otherwise, this 0262 * is a pretty straightforward analog of horizontal flip. 0263 * Within a DCT block, vertical mirroring is done by changing the signs 0264 * of odd-numbered rows. 0265 * Partial iMCUs at the bottom edge are copied verbatim. 0266 */ 0267 MCU_rows = srcinfo->output_height / 0268 (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); 0269 0270 for (ci = 0; ci < dstinfo->num_components; ci++) { 0271 compptr = dstinfo->comp_info + ci; 0272 comp_height = MCU_rows * compptr->v_samp_factor; 0273 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 0274 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 0275 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 0276 dst_blk_y += compptr->v_samp_factor) { 0277 dst_buffer = (*srcinfo->mem->access_virt_barray) 0278 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 0279 (JDIMENSION) compptr->v_samp_factor, TRUE); 0280 if (y_crop_blocks + dst_blk_y < comp_height) { 0281 /* Row is within the mirrorable area. */ 0282 src_buffer = (*srcinfo->mem->access_virt_barray) 0283 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 0284 comp_height - y_crop_blocks - dst_blk_y - 0285 (JDIMENSION) compptr->v_samp_factor, 0286 (JDIMENSION) compptr->v_samp_factor, FALSE); 0287 } else { 0288 /* Bottom-edge blocks will be copied verbatim. */ 0289 src_buffer = (*srcinfo->mem->access_virt_barray) 0290 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 0291 dst_blk_y + y_crop_blocks, 0292 (JDIMENSION) compptr->v_samp_factor, FALSE); 0293 } 0294 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 0295 if (y_crop_blocks + dst_blk_y < comp_height) { 0296 /* Row is within the mirrorable area. */ 0297 dst_row_ptr = dst_buffer[offset_y]; 0298 src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; 0299 src_row_ptr += x_crop_blocks; 0300 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; 0301 dst_blk_x++) { 0302 dst_ptr = dst_row_ptr[dst_blk_x]; 0303 src_ptr = src_row_ptr[dst_blk_x]; 0304 for (i = 0; i < DCTSIZE; i += 2) { 0305 /* copy even row */ 0306 for (j = 0; j < DCTSIZE; j++) 0307 *dst_ptr++ = *src_ptr++; 0308 /* copy odd row with sign change */ 0309 for (j = 0; j < DCTSIZE; j++) 0310 *dst_ptr++ = - *src_ptr++; 0311 } 0312 } 0313 } else { 0314 /* Just copy row verbatim. */ 0315 jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, 0316 dst_buffer[offset_y], 0317 compptr->width_in_blocks); 0318 } 0319 } 0320 } 0321 } 0322 } 0323 0324 0325 LOCAL(void) 0326 do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 0327 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 0328 jvirt_barray_ptr *src_coef_arrays, 0329 jvirt_barray_ptr *dst_coef_arrays) 0330 /* Transpose source into destination */ 0331 { 0332 JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks; 0333 int ci, i, j, offset_x, offset_y; 0334 JBLOCKARRAY src_buffer, dst_buffer; 0335 JCOEFPTR src_ptr, dst_ptr; 0336 jpeg_component_info *compptr; 0337 0338 /* Transposing pixels within a block just requires transposing the 0339 * DCT coefficients. 0340 * Partial iMCUs at the edges require no special treatment; we simply 0341 * process all the available DCT blocks for every component. 0342 */ 0343 for (ci = 0; ci < dstinfo->num_components; ci++) { 0344 compptr = dstinfo->comp_info + ci; 0345 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 0346 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 0347 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 0348 dst_blk_y += compptr->v_samp_factor) { 0349 dst_buffer = (*srcinfo->mem->access_virt_barray) 0350 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 0351 (JDIMENSION) compptr->v_samp_factor, TRUE); 0352 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 0353 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; 0354 dst_blk_x += compptr->h_samp_factor) { 0355 src_buffer = (*srcinfo->mem->access_virt_barray) 0356 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 0357 dst_blk_x + x_crop_blocks, 0358 (JDIMENSION) compptr->h_samp_factor, FALSE); 0359 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { 0360 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; 0361 src_ptr = src_buffer[offset_x][dst_blk_y + offset_y + y_crop_blocks]; 0362 for (i = 0; i < DCTSIZE; i++) 0363 for (j = 0; j < DCTSIZE; j++) 0364 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 0365 } 0366 } 0367 } 0368 } 0369 } 0370 } 0371 0372 0373 LOCAL(void) 0374 do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 0375 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 0376 jvirt_barray_ptr *src_coef_arrays, 0377 jvirt_barray_ptr *dst_coef_arrays) 0378 /* 90 degree rotation is equivalent to 0379 * 1. Transposing the image; 0380 * 2. Horizontal mirroring. 0381 * These two steps are merged into a single processing routine. 0382 */ 0383 { 0384 JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y; 0385 JDIMENSION x_crop_blocks, y_crop_blocks; 0386 int ci, i, j, offset_x, offset_y; 0387 JBLOCKARRAY src_buffer, dst_buffer; 0388 JCOEFPTR src_ptr, dst_ptr; 0389 jpeg_component_info *compptr; 0390 0391 /* Because of the horizontal mirror step, we can't process partial iMCUs 0392 * at the (output) right edge properly. They just get transposed and 0393 * not mirrored. 0394 */ 0395 MCU_cols = srcinfo->output_height / 0396 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); 0397 0398 for (ci = 0; ci < dstinfo->num_components; ci++) { 0399 compptr = dstinfo->comp_info + ci; 0400 comp_width = MCU_cols * compptr->h_samp_factor; 0401 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 0402 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 0403 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 0404 dst_blk_y += compptr->v_samp_factor) { 0405 dst_buffer = (*srcinfo->mem->access_virt_barray) 0406 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 0407 (JDIMENSION) compptr->v_samp_factor, TRUE); 0408 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 0409 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; 0410 dst_blk_x += compptr->h_samp_factor) { 0411 if (x_crop_blocks + dst_blk_x < comp_width) { 0412 /* Block is within the mirrorable area. */ 0413 src_buffer = (*srcinfo->mem->access_virt_barray) 0414 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 0415 comp_width - x_crop_blocks - dst_blk_x - 0416 (JDIMENSION) compptr->h_samp_factor, 0417 (JDIMENSION) compptr->h_samp_factor, FALSE); 0418 } else { 0419 /* Edge blocks are transposed but not mirrored. */ 0420 src_buffer = (*srcinfo->mem->access_virt_barray) 0421 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 0422 dst_blk_x + x_crop_blocks, 0423 (JDIMENSION) compptr->h_samp_factor, FALSE); 0424 } 0425 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { 0426 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; 0427 if (x_crop_blocks + dst_blk_x < comp_width) { 0428 /* Block is within the mirrorable area. */ 0429 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] 0430 [dst_blk_y + offset_y + y_crop_blocks]; 0431 for (i = 0; i < DCTSIZE; i++) { 0432 for (j = 0; j < DCTSIZE; j++) 0433 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 0434 i++; 0435 for (j = 0; j < DCTSIZE; j++) 0436 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 0437 } 0438 } else { 0439 /* Edge blocks are transposed but not mirrored. */ 0440 src_ptr = src_buffer[offset_x] 0441 [dst_blk_y + offset_y + y_crop_blocks]; 0442 for (i = 0; i < DCTSIZE; i++) 0443 for (j = 0; j < DCTSIZE; j++) 0444 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 0445 } 0446 } 0447 } 0448 } 0449 } 0450 } 0451 } 0452 0453 0454 LOCAL(void) 0455 do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 0456 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 0457 jvirt_barray_ptr *src_coef_arrays, 0458 jvirt_barray_ptr *dst_coef_arrays) 0459 /* 270 degree rotation is equivalent to 0460 * 1. Horizontal mirroring; 0461 * 2. Transposing the image. 0462 * These two steps are merged into a single processing routine. 0463 */ 0464 { 0465 JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; 0466 JDIMENSION x_crop_blocks, y_crop_blocks; 0467 int ci, i, j, offset_x, offset_y; 0468 JBLOCKARRAY src_buffer, dst_buffer; 0469 JCOEFPTR src_ptr, dst_ptr; 0470 jpeg_component_info *compptr; 0471 0472 /* Because of the horizontal mirror step, we can't process partial iMCUs 0473 * at the (output) bottom edge properly. They just get transposed and 0474 * not mirrored. 0475 */ 0476 MCU_rows = srcinfo->output_width / 0477 (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); 0478 0479 for (ci = 0; ci < dstinfo->num_components; ci++) { 0480 compptr = dstinfo->comp_info + ci; 0481 comp_height = MCU_rows * compptr->v_samp_factor; 0482 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 0483 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 0484 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 0485 dst_blk_y += compptr->v_samp_factor) { 0486 dst_buffer = (*srcinfo->mem->access_virt_barray) 0487 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 0488 (JDIMENSION) compptr->v_samp_factor, TRUE); 0489 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 0490 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; 0491 dst_blk_x += compptr->h_samp_factor) { 0492 src_buffer = (*srcinfo->mem->access_virt_barray) 0493 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 0494 dst_blk_x + x_crop_blocks, 0495 (JDIMENSION) compptr->h_samp_factor, FALSE); 0496 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { 0497 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; 0498 if (y_crop_blocks + dst_blk_y < comp_height) { 0499 /* Block is within the mirrorable area. */ 0500 src_ptr = src_buffer[offset_x] 0501 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; 0502 for (i = 0; i < DCTSIZE; i++) { 0503 for (j = 0; j < DCTSIZE; j++) { 0504 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 0505 j++; 0506 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 0507 } 0508 } 0509 } else { 0510 /* Edge blocks are transposed but not mirrored. */ 0511 src_ptr = src_buffer[offset_x] 0512 [dst_blk_y + offset_y + y_crop_blocks]; 0513 for (i = 0; i < DCTSIZE; i++) 0514 for (j = 0; j < DCTSIZE; j++) 0515 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 0516 } 0517 } 0518 } 0519 } 0520 } 0521 } 0522 } 0523 0524 0525 LOCAL(void) 0526 do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 0527 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 0528 jvirt_barray_ptr *src_coef_arrays, 0529 jvirt_barray_ptr *dst_coef_arrays) 0530 /* 180 degree rotation is equivalent to 0531 * 1. Vertical mirroring; 0532 * 2. Horizontal mirroring. 0533 * These two steps are merged into a single processing routine. 0534 */ 0535 { 0536 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; 0537 JDIMENSION x_crop_blocks, y_crop_blocks; 0538 int ci, i, j, offset_y; 0539 JBLOCKARRAY src_buffer, dst_buffer; 0540 JBLOCKROW src_row_ptr, dst_row_ptr; 0541 JCOEFPTR src_ptr, dst_ptr; 0542 jpeg_component_info *compptr; 0543 0544 MCU_cols = srcinfo->output_width / 0545 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); 0546 MCU_rows = srcinfo->output_height / 0547 (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); 0548 0549 for (ci = 0; ci < dstinfo->num_components; ci++) { 0550 compptr = dstinfo->comp_info + ci; 0551 comp_width = MCU_cols * compptr->h_samp_factor; 0552 comp_height = MCU_rows * compptr->v_samp_factor; 0553 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 0554 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 0555 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 0556 dst_blk_y += compptr->v_samp_factor) { 0557 dst_buffer = (*srcinfo->mem->access_virt_barray) 0558 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 0559 (JDIMENSION) compptr->v_samp_factor, TRUE); 0560 if (y_crop_blocks + dst_blk_y < comp_height) { 0561 /* Row is within the vertically mirrorable area. */ 0562 src_buffer = (*srcinfo->mem->access_virt_barray) 0563 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 0564 comp_height - y_crop_blocks - dst_blk_y - 0565 (JDIMENSION) compptr->v_samp_factor, 0566 (JDIMENSION) compptr->v_samp_factor, FALSE); 0567 } else { 0568 /* Bottom-edge rows are only mirrored horizontally. */ 0569 src_buffer = (*srcinfo->mem->access_virt_barray) 0570 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 0571 dst_blk_y + y_crop_blocks, 0572 (JDIMENSION) compptr->v_samp_factor, FALSE); 0573 } 0574 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 0575 dst_row_ptr = dst_buffer[offset_y]; 0576 if (y_crop_blocks + dst_blk_y < comp_height) { 0577 /* Row is within the mirrorable area. */ 0578 src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; 0579 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { 0580 dst_ptr = dst_row_ptr[dst_blk_x]; 0581 if (x_crop_blocks + dst_blk_x < comp_width) { 0582 /* Process the blocks that can be mirrored both ways. */ 0583 src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; 0584 for (i = 0; i < DCTSIZE; i += 2) { 0585 /* For even row, negate every odd column. */ 0586 for (j = 0; j < DCTSIZE; j += 2) { 0587 *dst_ptr++ = *src_ptr++; 0588 *dst_ptr++ = - *src_ptr++; 0589 } 0590 /* For odd row, negate every even column. */ 0591 for (j = 0; j < DCTSIZE; j += 2) { 0592 *dst_ptr++ = - *src_ptr++; 0593 *dst_ptr++ = *src_ptr++; 0594 } 0595 } 0596 } else { 0597 /* Any remaining right-edge blocks are only mirrored vertically. */ 0598 src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x]; 0599 for (i = 0; i < DCTSIZE; i += 2) { 0600 for (j = 0; j < DCTSIZE; j++) 0601 *dst_ptr++ = *src_ptr++; 0602 for (j = 0; j < DCTSIZE; j++) 0603 *dst_ptr++ = - *src_ptr++; 0604 } 0605 } 0606 } 0607 } else { 0608 /* Remaining rows are just mirrored horizontally. */ 0609 src_row_ptr = src_buffer[offset_y]; 0610 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { 0611 if (x_crop_blocks + dst_blk_x < comp_width) { 0612 /* Process the blocks that can be mirrored. */ 0613 dst_ptr = dst_row_ptr[dst_blk_x]; 0614 src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; 0615 for (i = 0; i < DCTSIZE2; i += 2) { 0616 *dst_ptr++ = *src_ptr++; 0617 *dst_ptr++ = - *src_ptr++; 0618 } 0619 } else { 0620 /* Any remaining right-edge blocks are only copied. */ 0621 jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks, 0622 dst_row_ptr + dst_blk_x, 0623 (JDIMENSION) 1); 0624 } 0625 } 0626 } 0627 } 0628 } 0629 } 0630 } 0631 0632 0633 LOCAL(void) 0634 do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 0635 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 0636 jvirt_barray_ptr *src_coef_arrays, 0637 jvirt_barray_ptr *dst_coef_arrays) 0638 /* Transverse transpose is equivalent to 0639 * 1. 180 degree rotation; 0640 * 2. Transposition; 0641 * or 0642 * 1. Horizontal mirroring; 0643 * 2. Transposition; 0644 * 3. Horizontal mirroring. 0645 * These steps are merged into a single processing routine. 0646 */ 0647 { 0648 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; 0649 JDIMENSION x_crop_blocks, y_crop_blocks; 0650 int ci, i, j, offset_x, offset_y; 0651 JBLOCKARRAY src_buffer, dst_buffer; 0652 JCOEFPTR src_ptr, dst_ptr; 0653 jpeg_component_info *compptr; 0654 0655 MCU_cols = srcinfo->output_height / 0656 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); 0657 MCU_rows = srcinfo->output_width / 0658 (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); 0659 0660 for (ci = 0; ci < dstinfo->num_components; ci++) { 0661 compptr = dstinfo->comp_info + ci; 0662 comp_width = MCU_cols * compptr->h_samp_factor; 0663 comp_height = MCU_rows * compptr->v_samp_factor; 0664 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 0665 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 0666 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 0667 dst_blk_y += compptr->v_samp_factor) { 0668 dst_buffer = (*srcinfo->mem->access_virt_barray) 0669 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 0670 (JDIMENSION) compptr->v_samp_factor, TRUE); 0671 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 0672 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; 0673 dst_blk_x += compptr->h_samp_factor) { 0674 if (x_crop_blocks + dst_blk_x < comp_width) { 0675 /* Block is within the mirrorable area. */ 0676 src_buffer = (*srcinfo->mem->access_virt_barray) 0677 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 0678 comp_width - x_crop_blocks - dst_blk_x - 0679 (JDIMENSION) compptr->h_samp_factor, 0680 (JDIMENSION) compptr->h_samp_factor, FALSE); 0681 } else { 0682 src_buffer = (*srcinfo->mem->access_virt_barray) 0683 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 0684 dst_blk_x + x_crop_blocks, 0685 (JDIMENSION) compptr->h_samp_factor, FALSE); 0686 } 0687 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { 0688 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; 0689 if (y_crop_blocks + dst_blk_y < comp_height) { 0690 if (x_crop_blocks + dst_blk_x < comp_width) { 0691 /* Block is within the mirrorable area. */ 0692 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] 0693 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; 0694 for (i = 0; i < DCTSIZE; i++) { 0695 for (j = 0; j < DCTSIZE; j++) { 0696 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 0697 j++; 0698 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 0699 } 0700 i++; 0701 for (j = 0; j < DCTSIZE; j++) { 0702 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 0703 j++; 0704 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 0705 } 0706 } 0707 } else { 0708 /* Right-edge blocks are mirrored in y only */ 0709 src_ptr = src_buffer[offset_x] 0710 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; 0711 for (i = 0; i < DCTSIZE; i++) { 0712 for (j = 0; j < DCTSIZE; j++) { 0713 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 0714 j++; 0715 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 0716 } 0717 } 0718 } 0719 } else { 0720 if (x_crop_blocks + dst_blk_x < comp_width) { 0721 /* Bottom-edge blocks are mirrored in x only */ 0722 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] 0723 [dst_blk_y + offset_y + y_crop_blocks]; 0724 for (i = 0; i < DCTSIZE; i++) { 0725 for (j = 0; j < DCTSIZE; j++) 0726 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 0727 i++; 0728 for (j = 0; j < DCTSIZE; j++) 0729 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 0730 } 0731 } else { 0732 /* At lower right corner, just transpose, no mirroring */ 0733 src_ptr = src_buffer[offset_x] 0734 [dst_blk_y + offset_y + y_crop_blocks]; 0735 for (i = 0; i < DCTSIZE; i++) 0736 for (j = 0; j < DCTSIZE; j++) 0737 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 0738 } 0739 } 0740 } 0741 } 0742 } 0743 } 0744 } 0745 } 0746 0747 0748 /* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec. 0749 * Returns TRUE if valid integer found, FALSE if not. 0750 * *strptr is advanced over the digit string, and *result is set to its value. 0751 */ 0752 0753 LOCAL(boolean) 0754 jt_read_integer (const char ** strptr, JDIMENSION * result) 0755 { 0756 const char * ptr = *strptr; 0757 JDIMENSION val = 0; 0758 0759 for (; isdigit(*ptr); ptr++) { 0760 val = val * 10 + (JDIMENSION) (*ptr - '0'); 0761 } 0762 *result = val; 0763 if (ptr == *strptr) 0764 return FALSE; /* oops, no digits */ 0765 *strptr = ptr; 0766 return TRUE; 0767 } 0768 0769 0770 /* Parse a crop specification (written in X11 geometry style). 0771 * The routine returns TRUE if the spec string is valid, FALSE if not. 0772 * 0773 * The crop spec string should have the format 0774 * <width>[f]x<height>[f]{+-}<xoffset>{+-}<yoffset> 0775 * where width, height, xoffset, and yoffset are unsigned integers. 0776 * Each of the elements can be omitted to indicate a default value. 0777 * (A weakness of this style is that it is not possible to omit xoffset 0778 * while specifying yoffset, since they look alike.) 0779 * 0780 * This code is loosely based on XParseGeometry from the X11 distribution. 0781 */ 0782 0783 GLOBAL(boolean) 0784 jtransform_parse_crop_spec (jpeg_transform_info *info, const char *spec) 0785 { 0786 info->crop = FALSE; 0787 info->crop_width_set = JCROP_UNSET; 0788 info->crop_height_set = JCROP_UNSET; 0789 info->crop_xoffset_set = JCROP_UNSET; 0790 info->crop_yoffset_set = JCROP_UNSET; 0791 0792 if (isdigit(*spec)) { 0793 /* fetch width */ 0794 if (! jt_read_integer(&spec, &info->crop_width)) 0795 return FALSE; 0796 if (*spec == 'f' || *spec == 'F') { 0797 spec++; 0798 info->crop_width_set = JCROP_FORCE; 0799 } else 0800 info->crop_width_set = JCROP_POS; 0801 } 0802 if (*spec == 'x' || *spec == 'X') { 0803 /* fetch height */ 0804 spec++; 0805 if (! jt_read_integer(&spec, &info->crop_height)) 0806 return FALSE; 0807 if (*spec == 'f' || *spec == 'F') { 0808 spec++; 0809 info->crop_height_set = JCROP_FORCE; 0810 } else 0811 info->crop_height_set = JCROP_POS; 0812 } 0813 if (*spec == '+' || *spec == '-') { 0814 /* fetch xoffset */ 0815 info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS; 0816 spec++; 0817 if (! jt_read_integer(&spec, &info->crop_xoffset)) 0818 return FALSE; 0819 } 0820 if (*spec == '+' || *spec == '-') { 0821 /* fetch yoffset */ 0822 info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS; 0823 spec++; 0824 if (! jt_read_integer(&spec, &info->crop_yoffset)) 0825 return FALSE; 0826 } 0827 /* We had better have gotten to the end of the string. */ 0828 if (*spec != '\0') 0829 return FALSE; 0830 info->crop = TRUE; 0831 return TRUE; 0832 } 0833 0834 0835 /* Trim off any partial iMCUs on the indicated destination edge */ 0836 0837 LOCAL(void) 0838 trim_right_edge (jpeg_transform_info *info, JDIMENSION full_width) 0839 { 0840 JDIMENSION MCU_cols; 0841 0842 MCU_cols = info->output_width / info->iMCU_sample_width; 0843 if (MCU_cols > 0 && info->x_crop_offset + MCU_cols == 0844 full_width / info->iMCU_sample_width) 0845 info->output_width = MCU_cols * info->iMCU_sample_width; 0846 } 0847 0848 LOCAL(void) 0849 trim_bottom_edge (jpeg_transform_info *info, JDIMENSION full_height) 0850 { 0851 JDIMENSION MCU_rows; 0852 0853 MCU_rows = info->output_height / info->iMCU_sample_height; 0854 if (MCU_rows > 0 && info->y_crop_offset + MCU_rows == 0855 full_height / info->iMCU_sample_height) 0856 info->output_height = MCU_rows * info->iMCU_sample_height; 0857 } 0858 0859 0860 /* Request any required workspace. 0861 * 0862 * This routine figures out the size that the output image will be 0863 * (which implies that all the transform parameters must be set before 0864 * it is called). 0865 * 0866 * We allocate the workspace virtual arrays from the source decompression 0867 * object, so that all the arrays (both the original data and the workspace) 0868 * will be taken into account while making memory management decisions. 0869 * Hence, this routine must be called after jpeg_read_header (which reads 0870 * the image dimensions) and before jpeg_read_coefficients (which realizes 0871 * the source's virtual arrays). 0872 * 0873 * This function returns FALSE right away if -perfect is given 0874 * and transformation is not perfect. Otherwise returns TRUE. 0875 */ 0876 0877 GLOBAL(boolean) 0878 jtransform_request_workspace (j_decompress_ptr srcinfo, 0879 jpeg_transform_info *info) 0880 { 0881 jvirt_barray_ptr *coef_arrays; 0882 boolean need_workspace, transpose_it; 0883 jpeg_component_info *compptr; 0884 JDIMENSION xoffset, yoffset; 0885 JDIMENSION width_in_iMCUs, height_in_iMCUs; 0886 JDIMENSION width_in_blocks, height_in_blocks; 0887 int ci, h_samp_factor, v_samp_factor; 0888 0889 /* Determine number of components in output image */ 0890 if (info->force_grayscale && 0891 srcinfo->jpeg_color_space == JCS_YCbCr && 0892 srcinfo->num_components == 3) 0893 /* We'll only process the first component */ 0894 info->num_components = 1; 0895 else 0896 /* Process all the components */ 0897 info->num_components = srcinfo->num_components; 0898 0899 /* Compute output image dimensions and related values. */ 0900 jpeg_core_output_dimensions(srcinfo); 0901 0902 /* Return right away if -perfect is given and transformation is not perfect. 0903 */ 0904 if (info->perfect) { 0905 if (info->num_components == 1) { 0906 if (!jtransform_perfect_transform(srcinfo->output_width, 0907 srcinfo->output_height, 0908 srcinfo->min_DCT_h_scaled_size, 0909 srcinfo->min_DCT_v_scaled_size, 0910 info->transform)) 0911 return FALSE; 0912 } else { 0913 if (!jtransform_perfect_transform(srcinfo->output_width, 0914 srcinfo->output_height, 0915 srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size, 0916 srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size, 0917 info->transform)) 0918 return FALSE; 0919 } 0920 } 0921 0922 /* If there is only one output component, force the iMCU size to be 1; 0923 * else use the source iMCU size. (This allows us to do the right thing 0924 * when reducing color to grayscale, and also provides a handy way of 0925 * cleaning up "funny" grayscale images whose sampling factors are not 1x1.) 0926 */ 0927 switch (info->transform) { 0928 case JXFORM_TRANSPOSE: 0929 case JXFORM_TRANSVERSE: 0930 case JXFORM_ROT_90: 0931 case JXFORM_ROT_270: 0932 info->output_width = srcinfo->output_height; 0933 info->output_height = srcinfo->output_width; 0934 if (info->num_components == 1) { 0935 info->iMCU_sample_width = srcinfo->min_DCT_v_scaled_size; 0936 info->iMCU_sample_height = srcinfo->min_DCT_h_scaled_size; 0937 } else { 0938 info->iMCU_sample_width = 0939 srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size; 0940 info->iMCU_sample_height = 0941 srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size; 0942 } 0943 break; 0944 default: 0945 info->output_width = srcinfo->output_width; 0946 info->output_height = srcinfo->output_height; 0947 if (info->num_components == 1) { 0948 info->iMCU_sample_width = srcinfo->min_DCT_h_scaled_size; 0949 info->iMCU_sample_height = srcinfo->min_DCT_v_scaled_size; 0950 } else { 0951 info->iMCU_sample_width = 0952 srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size; 0953 info->iMCU_sample_height = 0954 srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size; 0955 } 0956 break; 0957 } 0958 0959 /* If cropping has been requested, compute the crop area's position and 0960 * dimensions, ensuring that its upper left corner falls at an iMCU boundary. 0961 */ 0962 if (info->crop) { 0963 /* Insert default values for unset crop parameters */ 0964 if (info->crop_xoffset_set == JCROP_UNSET) 0965 info->crop_xoffset = 0; /* default to +0 */ 0966 if (info->crop_yoffset_set == JCROP_UNSET) 0967 info->crop_yoffset = 0; /* default to +0 */ 0968 if (info->crop_xoffset >= info->output_width || 0969 info->crop_yoffset >= info->output_height) 0970 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); 0971 if (info->crop_width_set == JCROP_UNSET) 0972 info->crop_width = info->output_width - info->crop_xoffset; 0973 if (info->crop_height_set == JCROP_UNSET) 0974 info->crop_height = info->output_height - info->crop_yoffset; 0975 /* Ensure parameters are valid */ 0976 if (info->crop_width <= 0 || info->crop_width > info->output_width || 0977 info->crop_height <= 0 || info->crop_height > info->output_height || 0978 info->crop_xoffset > info->output_width - info->crop_width || 0979 info->crop_yoffset > info->output_height - info->crop_height) 0980 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); 0981 /* Convert negative crop offsets into regular offsets */ 0982 if (info->crop_xoffset_set == JCROP_NEG) 0983 xoffset = info->output_width - info->crop_width - info->crop_xoffset; 0984 else 0985 xoffset = info->crop_xoffset; 0986 if (info->crop_yoffset_set == JCROP_NEG) 0987 yoffset = info->output_height - info->crop_height - info->crop_yoffset; 0988 else 0989 yoffset = info->crop_yoffset; 0990 /* Now adjust so that upper left corner falls at an iMCU boundary */ 0991 if (info->crop_width_set == JCROP_FORCE) 0992 info->output_width = info->crop_width; 0993 else 0994 info->output_width = 0995 info->crop_width + (xoffset % info->iMCU_sample_width); 0996 if (info->crop_height_set == JCROP_FORCE) 0997 info->output_height = info->crop_height; 0998 else 0999 info->output_height = 1000 info->crop_height + (yoffset % info->iMCU_sample_height); 1001 /* Save x/y offsets measured in iMCUs */ 1002 info->x_crop_offset = xoffset / info->iMCU_sample_width; 1003 info->y_crop_offset = yoffset / info->iMCU_sample_height; 1004 } else { 1005 info->x_crop_offset = 0; 1006 info->y_crop_offset = 0; 1007 } 1008 1009 /* Figure out whether we need workspace arrays, 1010 * and if so whether they are transposed relative to the source. 1011 */ 1012 need_workspace = FALSE; 1013 transpose_it = FALSE; 1014 switch (info->transform) { 1015 case JXFORM_NONE: 1016 if (info->x_crop_offset != 0 || info->y_crop_offset != 0) 1017 need_workspace = TRUE; 1018 /* No workspace needed if neither cropping nor transforming */ 1019 break; 1020 case JXFORM_FLIP_H: 1021 if (info->trim) 1022 trim_right_edge(info, srcinfo->output_width); 1023 if (info->y_crop_offset != 0) 1024 need_workspace = TRUE; 1025 /* do_flip_h_no_crop doesn't need a workspace array */ 1026 break; 1027 case JXFORM_FLIP_V: 1028 if (info->trim) 1029 trim_bottom_edge(info, srcinfo->output_height); 1030 /* Need workspace arrays having same dimensions as source image. */ 1031 need_workspace = TRUE; 1032 break; 1033 case JXFORM_TRANSPOSE: 1034 /* transpose does NOT have to trim anything */ 1035 /* Need workspace arrays having transposed dimensions. */ 1036 need_workspace = TRUE; 1037 transpose_it = TRUE; 1038 break; 1039 case JXFORM_TRANSVERSE: 1040 if (info->trim) { 1041 trim_right_edge(info, srcinfo->output_height); 1042 trim_bottom_edge(info, srcinfo->output_width); 1043 } 1044 /* Need workspace arrays having transposed dimensions. */ 1045 need_workspace = TRUE; 1046 transpose_it = TRUE; 1047 break; 1048 case JXFORM_ROT_90: 1049 if (info->trim) 1050 trim_right_edge(info, srcinfo->output_height); 1051 /* Need workspace arrays having transposed dimensions. */ 1052 need_workspace = TRUE; 1053 transpose_it = TRUE; 1054 break; 1055 case JXFORM_ROT_180: 1056 if (info->trim) { 1057 trim_right_edge(info, srcinfo->output_width); 1058 trim_bottom_edge(info, srcinfo->output_height); 1059 } 1060 /* Need workspace arrays having same dimensions as source image. */ 1061 need_workspace = TRUE; 1062 break; 1063 case JXFORM_ROT_270: 1064 if (info->trim) 1065 trim_bottom_edge(info, srcinfo->output_width); 1066 /* Need workspace arrays having transposed dimensions. */ 1067 need_workspace = TRUE; 1068 transpose_it = TRUE; 1069 break; 1070 } 1071 1072 /* Allocate workspace if needed. 1073 * Note that we allocate arrays padded out to the next iMCU boundary, 1074 * so that transform routines need not worry about missing edge blocks. 1075 */ 1076 if (need_workspace) { 1077 coef_arrays = (jvirt_barray_ptr *) 1078 (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE, 1079 SIZEOF(jvirt_barray_ptr) * info->num_components); 1080 width_in_iMCUs = (JDIMENSION) 1081 jdiv_round_up((long) info->output_width, 1082 (long) info->iMCU_sample_width); 1083 height_in_iMCUs = (JDIMENSION) 1084 jdiv_round_up((long) info->output_height, 1085 (long) info->iMCU_sample_height); 1086 for (ci = 0; ci < info->num_components; ci++) { 1087 compptr = srcinfo->comp_info + ci; 1088 if (info->num_components == 1) { 1089 /* we're going to force samp factors to 1x1 in this case */ 1090 h_samp_factor = v_samp_factor = 1; 1091 } else if (transpose_it) { 1092 h_samp_factor = compptr->v_samp_factor; 1093 v_samp_factor = compptr->h_samp_factor; 1094 } else { 1095 h_samp_factor = compptr->h_samp_factor; 1096 v_samp_factor = compptr->v_samp_factor; 1097 } 1098 width_in_blocks = width_in_iMCUs * h_samp_factor; 1099 height_in_blocks = height_in_iMCUs * v_samp_factor; 1100 coef_arrays[ci] = (*srcinfo->mem->request_virt_barray) 1101 ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE, 1102 width_in_blocks, height_in_blocks, (JDIMENSION) v_samp_factor); 1103 } 1104 info->workspace_coef_arrays = coef_arrays; 1105 } else 1106 info->workspace_coef_arrays = NULL; 1107 1108 return TRUE; 1109 } 1110 1111 1112 /* Transpose destination image parameters */ 1113 1114 LOCAL(void) 1115 transpose_critical_parameters (j_compress_ptr dstinfo) 1116 { 1117 int tblno, i, j, ci, itemp; 1118 jpeg_component_info *compptr; 1119 JQUANT_TBL *qtblptr; 1120 JDIMENSION jtemp; 1121 UINT16 qtemp; 1122 1123 /* Transpose image dimensions */ 1124 jtemp = dstinfo->image_width; 1125 dstinfo->image_width = dstinfo->image_height; 1126 dstinfo->image_height = jtemp; 1127 itemp = dstinfo->min_DCT_h_scaled_size; 1128 dstinfo->min_DCT_h_scaled_size = dstinfo->min_DCT_v_scaled_size; 1129 dstinfo->min_DCT_v_scaled_size = itemp; 1130 1131 /* Transpose sampling factors */ 1132 for (ci = 0; ci < dstinfo->num_components; ci++) { 1133 compptr = dstinfo->comp_info + ci; 1134 itemp = compptr->h_samp_factor; 1135 compptr->h_samp_factor = compptr->v_samp_factor; 1136 compptr->v_samp_factor = itemp; 1137 } 1138 1139 /* Transpose quantization tables */ 1140 for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { 1141 qtblptr = dstinfo->quant_tbl_ptrs[tblno]; 1142 if (qtblptr != NULL) { 1143 for (i = 0; i < DCTSIZE; i++) { 1144 for (j = 0; j < i; j++) { 1145 qtemp = qtblptr->quantval[i*DCTSIZE+j]; 1146 qtblptr->quantval[i*DCTSIZE+j] = qtblptr->quantval[j*DCTSIZE+i]; 1147 qtblptr->quantval[j*DCTSIZE+i] = qtemp; 1148 } 1149 } 1150 } 1151 } 1152 } 1153 1154 1155 /* Adjust Exif image parameters. 1156 * 1157 * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible. 1158 */ 1159 1160 LOCAL(void) 1161 adjust_exif_parameters (JOCTET FAR * data, unsigned int length, 1162 JDIMENSION new_width, JDIMENSION new_height) 1163 { 1164 boolean is_motorola; /* Flag for byte order */ 1165 unsigned int number_of_tags, tagnum; 1166 unsigned int firstoffset, offset; 1167 JDIMENSION new_value; 1168 1169 if (length < 12) return; /* Length of an IFD entry */ 1170 1171 /* Discover byte order */ 1172 if (GETJOCTET(data[0]) == 0x49 && GETJOCTET(data[1]) == 0x49) 1173 is_motorola = FALSE; 1174 else if (GETJOCTET(data[0]) == 0x4D && GETJOCTET(data[1]) == 0x4D) 1175 is_motorola = TRUE; 1176 else 1177 return; 1178 1179 /* Check Tag Mark */ 1180 if (is_motorola) { 1181 if (GETJOCTET(data[2]) != 0) return; 1182 if (GETJOCTET(data[3]) != 0x2A) return; 1183 } else { 1184 if (GETJOCTET(data[3]) != 0) return; 1185 if (GETJOCTET(data[2]) != 0x2A) return; 1186 } 1187 1188 /* Get first IFD offset (offset to IFD0) */ 1189 if (is_motorola) { 1190 if (GETJOCTET(data[4]) != 0) return; 1191 if (GETJOCTET(data[5]) != 0) return; 1192 firstoffset = GETJOCTET(data[6]); 1193 firstoffset <<= 8; 1194 firstoffset += GETJOCTET(data[7]); 1195 } else { 1196 if (GETJOCTET(data[7]) != 0) return; 1197 if (GETJOCTET(data[6]) != 0) return; 1198 firstoffset = GETJOCTET(data[5]); 1199 firstoffset <<= 8; 1200 firstoffset += GETJOCTET(data[4]); 1201 } 1202 if (firstoffset > length - 2) return; /* check end of data segment */ 1203 1204 /* Get the number of directory entries contained in this IFD */ 1205 if (is_motorola) { 1206 number_of_tags = GETJOCTET(data[firstoffset]); 1207 number_of_tags <<= 8; 1208 number_of_tags += GETJOCTET(data[firstoffset+1]); 1209 } else { 1210 number_of_tags = GETJOCTET(data[firstoffset+1]); 1211 number_of_tags <<= 8; 1212 number_of_tags += GETJOCTET(data[firstoffset]); 1213 } 1214 if (number_of_tags == 0) return; 1215 firstoffset += 2; 1216 1217 /* Search for ExifSubIFD offset Tag in IFD0 */ 1218 for (;;) { 1219 if (firstoffset > length - 12) return; /* check end of data segment */ 1220 /* Get Tag number */ 1221 if (is_motorola) { 1222 tagnum = GETJOCTET(data[firstoffset]); 1223 tagnum <<= 8; 1224 tagnum += GETJOCTET(data[firstoffset+1]); 1225 } else { 1226 tagnum = GETJOCTET(data[firstoffset+1]); 1227 tagnum <<= 8; 1228 tagnum += GETJOCTET(data[firstoffset]); 1229 } 1230 if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */ 1231 if (--number_of_tags == 0) return; 1232 firstoffset += 12; 1233 } 1234 1235 /* Get the ExifSubIFD offset */ 1236 if (is_motorola) { 1237 if (GETJOCTET(data[firstoffset+8]) != 0) return; 1238 if (GETJOCTET(data[firstoffset+9]) != 0) return; 1239 offset = GETJOCTET(data[firstoffset+10]); 1240 offset <<= 8; 1241 offset += GETJOCTET(data[firstoffset+11]); 1242 } else { 1243 if (GETJOCTET(data[firstoffset+11]) != 0) return; 1244 if (GETJOCTET(data[firstoffset+10]) != 0) return; 1245 offset = GETJOCTET(data[firstoffset+9]); 1246 offset <<= 8; 1247 offset += GETJOCTET(data[firstoffset+8]); 1248 } 1249 if (offset > length - 2) return; /* check end of data segment */ 1250 1251 /* Get the number of directory entries contained in this SubIFD */ 1252 if (is_motorola) { 1253 number_of_tags = GETJOCTET(data[offset]); 1254 number_of_tags <<= 8; 1255 number_of_tags += GETJOCTET(data[offset+1]); 1256 } else { 1257 number_of_tags = GETJOCTET(data[offset+1]); 1258 number_of_tags <<= 8; 1259 number_of_tags += GETJOCTET(data[offset]); 1260 } 1261 if (number_of_tags < 2) return; 1262 offset += 2; 1263 1264 /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */ 1265 do { 1266 if (offset > length - 12) return; /* check end of data segment */ 1267 /* Get Tag number */ 1268 if (is_motorola) { 1269 tagnum = GETJOCTET(data[offset]); 1270 tagnum <<= 8; 1271 tagnum += GETJOCTET(data[offset+1]); 1272 } else { 1273 tagnum = GETJOCTET(data[offset+1]); 1274 tagnum <<= 8; 1275 tagnum += GETJOCTET(data[offset]); 1276 } 1277 if (tagnum == 0xA002 || tagnum == 0xA003) { 1278 if (tagnum == 0xA002) 1279 new_value = new_width; /* ExifImageWidth Tag */ 1280 else 1281 new_value = new_height; /* ExifImageHeight Tag */ 1282 if (is_motorola) { 1283 data[offset+2] = 0; /* Format = unsigned long (4 octets) */ 1284 data[offset+3] = 4; 1285 data[offset+4] = 0; /* Number Of Components = 1 */ 1286 data[offset+5] = 0; 1287 data[offset+6] = 0; 1288 data[offset+7] = 1; 1289 data[offset+8] = 0; 1290 data[offset+9] = 0; 1291 data[offset+10] = (JOCTET)((new_value >> 8) & 0xFF); 1292 data[offset+11] = (JOCTET)(new_value & 0xFF); 1293 } else { 1294 data[offset+2] = 4; /* Format = unsigned long (4 octets) */ 1295 data[offset+3] = 0; 1296 data[offset+4] = 1; /* Number Of Components = 1 */ 1297 data[offset+5] = 0; 1298 data[offset+6] = 0; 1299 data[offset+7] = 0; 1300 data[offset+8] = (JOCTET)(new_value & 0xFF); 1301 data[offset+9] = (JOCTET)((new_value >> 8) & 0xFF); 1302 data[offset+10] = 0; 1303 data[offset+11] = 0; 1304 } 1305 } 1306 offset += 12; 1307 } while (--number_of_tags); 1308 } 1309 1310 1311 /* Adjust output image parameters as needed. 1312 * 1313 * This must be called after jpeg_copy_critical_parameters() 1314 * and before jpeg_write_coefficients(). 1315 * 1316 * The return value is the set of virtual coefficient arrays to be written 1317 * (either the ones allocated by jtransform_request_workspace, or the 1318 * original source data arrays). The caller will need to pass this value 1319 * to jpeg_write_coefficients(). 1320 */ 1321 1322 GLOBAL(jvirt_barray_ptr *) 1323 jtransform_adjust_parameters (j_decompress_ptr srcinfo, 1324 j_compress_ptr dstinfo, 1325 jvirt_barray_ptr *src_coef_arrays, 1326 jpeg_transform_info *info) 1327 { 1328 /* If force-to-grayscale is requested, adjust destination parameters */ 1329 if (info->force_grayscale) { 1330 /* First, ensure we have YCbCr or grayscale data, and that the source's 1331 * Y channel is full resolution. (No reasonable person would make Y 1332 * be less than full resolution, so actually coping with that case 1333 * isn't worth extra code space. But we check it to avoid crashing.) 1334 */ 1335 if (((dstinfo->jpeg_color_space == JCS_YCbCr && 1336 dstinfo->num_components == 3) || 1337 (dstinfo->jpeg_color_space == JCS_GRAYSCALE && 1338 dstinfo->num_components == 1)) && 1339 srcinfo->comp_info[0].h_samp_factor == srcinfo->max_h_samp_factor && 1340 srcinfo->comp_info[0].v_samp_factor == srcinfo->max_v_samp_factor) { 1341 /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed 1342 * properly. Among other things, it sets the target h_samp_factor & 1343 * v_samp_factor to 1, which typically won't match the source. 1344 * We have to preserve the source's quantization table number, however. 1345 */ 1346 int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no; 1347 jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE); 1348 dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no; 1349 } else { 1350 /* Sorry, can't do it */ 1351 ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL); 1352 } 1353 } else if (info->num_components == 1) { 1354 /* For a single-component source, we force the destination sampling factors 1355 * to 1x1, with or without force_grayscale. This is useful because some 1356 * decoders choke on grayscale images with other sampling factors. 1357 */ 1358 dstinfo->comp_info[0].h_samp_factor = 1; 1359 dstinfo->comp_info[0].v_samp_factor = 1; 1360 } 1361 1362 /* Correct the destination's image dimensions as necessary 1363 * for rotate/flip, resize, and crop operations. 1364 */ 1365 dstinfo->jpeg_width = info->output_width; 1366 dstinfo->jpeg_height = info->output_height; 1367 1368 /* Transpose destination image parameters */ 1369 switch (info->transform) { 1370 case JXFORM_TRANSPOSE: 1371 case JXFORM_TRANSVERSE: 1372 case JXFORM_ROT_90: 1373 case JXFORM_ROT_270: 1374 transpose_critical_parameters(dstinfo); 1375 break; 1376 default: 1377 break; 1378 } 1379 1380 /* Adjust Exif properties */ 1381 if (srcinfo->marker_list != NULL && 1382 srcinfo->marker_list->marker == JPEG_APP0+1 && 1383 srcinfo->marker_list->data_length >= 6 && 1384 GETJOCTET(srcinfo->marker_list->data[0]) == 0x45 && 1385 GETJOCTET(srcinfo->marker_list->data[1]) == 0x78 && 1386 GETJOCTET(srcinfo->marker_list->data[2]) == 0x69 && 1387 GETJOCTET(srcinfo->marker_list->data[3]) == 0x66 && 1388 GETJOCTET(srcinfo->marker_list->data[4]) == 0 && 1389 GETJOCTET(srcinfo->marker_list->data[5]) == 0) { 1390 /* Suppress output of JFIF marker */ 1391 dstinfo->write_JFIF_header = FALSE; 1392 /* Adjust Exif image parameters */ 1393 if (dstinfo->jpeg_width != srcinfo->image_width || 1394 dstinfo->jpeg_height != srcinfo->image_height) 1395 /* Align data segment to start of TIFF structure for parsing */ 1396 adjust_exif_parameters(srcinfo->marker_list->data + 6, 1397 srcinfo->marker_list->data_length - 6, 1398 dstinfo->jpeg_width, dstinfo->jpeg_height); 1399 } 1400 1401 /* Return the appropriate output data set */ 1402 if (info->workspace_coef_arrays != NULL) 1403 return info->workspace_coef_arrays; 1404 return src_coef_arrays; 1405 } 1406 1407 1408 /* Execute the actual transformation, if any. 1409 * 1410 * This must be called *after* jpeg_write_coefficients, because it depends 1411 * on jpeg_write_coefficients to have computed subsidiary values such as 1412 * the per-component width and height fields in the destination object. 1413 * 1414 * Note that some transformations will modify the source data arrays! 1415 */ 1416 1417 GLOBAL(void) 1418 jtransform_execute_transform (j_decompress_ptr srcinfo, 1419 j_compress_ptr dstinfo, 1420 jvirt_barray_ptr *src_coef_arrays, 1421 jpeg_transform_info *info) 1422 { 1423 jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays; 1424 1425 /* Note: conditions tested here should match those in switch statement 1426 * in jtransform_request_workspace() 1427 */ 1428 switch (info->transform) { 1429 case JXFORM_NONE: 1430 if (info->x_crop_offset != 0 || info->y_crop_offset != 0) 1431 do_crop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1432 src_coef_arrays, dst_coef_arrays); 1433 break; 1434 case JXFORM_FLIP_H: 1435 if (info->y_crop_offset != 0) 1436 do_flip_h(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1437 src_coef_arrays, dst_coef_arrays); 1438 else 1439 do_flip_h_no_crop(srcinfo, dstinfo, info->x_crop_offset, 1440 src_coef_arrays); 1441 break; 1442 case JXFORM_FLIP_V: 1443 do_flip_v(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1444 src_coef_arrays, dst_coef_arrays); 1445 break; 1446 case JXFORM_TRANSPOSE: 1447 do_transpose(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1448 src_coef_arrays, dst_coef_arrays); 1449 break; 1450 case JXFORM_TRANSVERSE: 1451 do_transverse(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1452 src_coef_arrays, dst_coef_arrays); 1453 break; 1454 case JXFORM_ROT_90: 1455 do_rot_90(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1456 src_coef_arrays, dst_coef_arrays); 1457 break; 1458 case JXFORM_ROT_180: 1459 do_rot_180(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1460 src_coef_arrays, dst_coef_arrays); 1461 break; 1462 case JXFORM_ROT_270: 1463 do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1464 src_coef_arrays, dst_coef_arrays); 1465 break; 1466 } 1467 } 1468 1469 /* jtransform_perfect_transform 1470 * 1471 * Determine whether lossless transformation is perfectly 1472 * possible for a specified image and transformation. 1473 * 1474 * Inputs: 1475 * image_width, image_height: source image dimensions. 1476 * MCU_width, MCU_height: pixel dimensions of MCU. 1477 * transform: transformation identifier. 1478 * Parameter sources from initialized jpeg_struct 1479 * (after reading source header): 1480 * image_width = cinfo.image_width 1481 * image_height = cinfo.image_height 1482 * MCU_width = cinfo.max_h_samp_factor * cinfo.block_size 1483 * MCU_height = cinfo.max_v_samp_factor * cinfo.block_size 1484 * Result: 1485 * TRUE = perfect transformation possible 1486 * FALSE = perfect transformation not possible 1487 * (may use custom action then) 1488 */ 1489 1490 GLOBAL(boolean) 1491 jtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height, 1492 int MCU_width, int MCU_height, 1493 JXFORM_CODE transform) 1494 { 1495 boolean result = TRUE; /* initialize TRUE */ 1496 1497 switch (transform) { 1498 case JXFORM_FLIP_H: 1499 case JXFORM_ROT_270: 1500 if (image_width % (JDIMENSION) MCU_width) 1501 result = FALSE; 1502 break; 1503 case JXFORM_FLIP_V: 1504 case JXFORM_ROT_90: 1505 if (image_height % (JDIMENSION) MCU_height) 1506 result = FALSE; 1507 break; 1508 case JXFORM_TRANSVERSE: 1509 case JXFORM_ROT_180: 1510 if (image_width % (JDIMENSION) MCU_width) 1511 result = FALSE; 1512 if (image_height % (JDIMENSION) MCU_height) 1513 result = FALSE; 1514 break; 1515 default: 1516 break; 1517 } 1518 1519 return result; 1520 } 1521 1522 #endif /* TRANSFORMS_SUPPORTED */ 1523 1524 1525 /* Setup decompression object to save desired markers in memory. 1526 * This must be called before jpeg_read_header() to have the desired effect. 1527 */ 1528 1529 GLOBAL(void) 1530 jcopy_markers_setup (j_decompress_ptr srcinfo, JCOPY_OPTION option) 1531 { 1532 #ifdef SAVE_MARKERS_SUPPORTED 1533 int m; 1534 1535 /* Save comments except under NONE option */ 1536 if (option != JCOPYOPT_NONE) { 1537 jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF); 1538 } 1539 /* Save all types of APPn markers iff ALL option */ 1540 if (option == JCOPYOPT_ALL) { 1541 for (m = 0; m < 16; m++) 1542 jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF); 1543 } 1544 #endif /* SAVE_MARKERS_SUPPORTED */ 1545 } 1546 1547 /* Copy markers saved in the given source object to the destination object. 1548 * This should be called just after jpeg_start_compress() or 1549 * jpeg_write_coefficients(). 1550 * Note that those routines will have written the SOI, and also the 1551 * JFIF APP0 or Adobe APP14 markers if selected. 1552 */ 1553 1554 GLOBAL(void) 1555 jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 1556 JCOPY_OPTION option) 1557 { 1558 jpeg_saved_marker_ptr marker; 1559 1560 /* In the current implementation, we don't actually need to examine the 1561 * option flag here; we just copy everything that got saved. 1562 * But to avoid confusion, we do not output JFIF and Adobe APP14 markers 1563 * if the encoder library already wrote one. 1564 */ 1565 for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) { 1566 if (dstinfo->write_JFIF_header && 1567 marker->marker == JPEG_APP0 && 1568 marker->data_length >= 5 && 1569 GETJOCTET(marker->data[0]) == 0x4A && 1570 GETJOCTET(marker->data[1]) == 0x46 && 1571 GETJOCTET(marker->data[2]) == 0x49 && 1572 GETJOCTET(marker->data[3]) == 0x46 && 1573 GETJOCTET(marker->data[4]) == 0) 1574 continue; /* reject duplicate JFIF */ 1575 if (dstinfo->write_Adobe_marker && 1576 marker->marker == JPEG_APP0+14 && 1577 marker->data_length >= 5 && 1578 GETJOCTET(marker->data[0]) == 0x41 && 1579 GETJOCTET(marker->data[1]) == 0x64 && 1580 GETJOCTET(marker->data[2]) == 0x6F && 1581 GETJOCTET(marker->data[3]) == 0x62 && 1582 GETJOCTET(marker->data[4]) == 0x65) 1583 continue; /* reject duplicate Adobe */ 1584 #ifdef NEED_FAR_POINTERS 1585 /* We could use jpeg_write_marker if the data weren't FAR... */ 1586 { 1587 unsigned int i; 1588 jpeg_write_m_header(dstinfo, marker->marker, marker->data_length); 1589 for (i = 0; i < marker->data_length; i++) 1590 jpeg_write_m_byte(dstinfo, marker->data[i]); 1591 } 1592 #else 1593 jpeg_write_marker(dstinfo, marker->marker, 1594 marker->data, marker->data_length); 1595 #endif 1596 } 1597 }