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