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