1 /* 2 * transupp.c 3 * 4 * Copyright (C) 1997-2017, Thomas G. Lane, Guido Vollbeding. 5 * This file is part of the Independent JPEG Group's software. 6 * For conditions of distribution and use, see the accompanying README file. 7 * 8 * This file contains image transformation routines and other utility code 9 * used by the jpegtran sample application. These are NOT part of the core 10 * JPEG library. But we keep these routines separate from jpegtran.c to 11 * ease the task of maintaining jpegtran-like programs that have other user 12 * interfaces. 13 */ 14 15 /* Although this file really shouldn't have access to the library internals, 16 * it's helpful to let it call jround_up() and jcopy_block_row(). 17 */ 18 #define JPEG_INTERNALS 19 20 #include "jinclude.h" 21 #include "jpeglib.h" 22 #include "transupp.h" /* My own external interface */ 23 #include <ctype.h> /* to declare isdigit() */ 24 25 26 #if TRANSFORMS_SUPPORTED 27 28 /* 29 * Lossless image transformation routines. These routines work on DCT 30 * coefficient arrays and thus do not require any lossy decompression 31 * or recompression of the image. 32 * Thanks to Guido Vollbeding for the initial design and code of this feature, 33 * and to Ben Jackson for introducing the cropping feature. 34 * 35 * Horizontal flipping is done in-place, using a single top-to-bottom 36 * pass through the virtual source array. It will thus be much the 37 * fastest option for images larger than main memory. 38 * 39 * The other routines require a set of destination virtual arrays, so they 40 * need twice as much memory as jpegtran normally does. The destination 41 * arrays are always written in normal scan order (top to bottom) because 42 * the virtual array manager expects this. The source arrays will be scanned 43 * in the corresponding order, which means multiple passes through the source 44 * arrays for most of the transforms. That could result in much thrashing 45 * if the image is larger than main memory. 46 * 47 * If cropping or trimming is involved, the destination arrays may be smaller 48 * than the source arrays. Note it is not possible to do horizontal flip 49 * in-place when a nonzero Y crop offset is specified, since we'd have to move 50 * data from one block row to another but the virtual array manager doesn't 51 * guarantee we can touch more than one row at a time. So in that case, 52 * we have to use a separate destination array. 53 * 54 * Some notes about the operating environment of the individual transform 55 * routines: 56 * 1. Both the source and destination virtual arrays are allocated from the 57 * source JPEG object, and therefore should be manipulated by calling the 58 * source's memory manager. 59 * 2. The destination's component count should be used. It may be smaller 60 * than the source's when forcing to grayscale. 61 * 3. Likewise the destination's sampling factors should be used. When 62 * forcing to grayscale the destination's sampling factors will be all 1, 63 * and we may as well take that as the effective iMCU size. 64 * 4. When "trim" is in effect, the destination's dimensions will be the 65 * trimmed values but the source's will be untrimmed. 66 * 5. When "crop" is in effect, the destination's dimensions will be the 67 * cropped values but the source's will be uncropped. Each transform 68 * routine is responsible for picking up source data starting at the 69 * correct X and Y offset for the crop region. (The X and Y offsets 70 * passed to the transform routines are measured in iMCU blocks of the 71 * destination.) 72 * 6. All the routines assume that the source and destination buffers are 73 * padded out to a full iMCU boundary. This is true, although for the 74 * source buffer it is an undocumented property of jdcoefct.c. 75 */ 76 77 78 LOCAL(void) 79 do_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 80 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 81 jvirt_barray_ptr *src_coef_arrays, 82 jvirt_barray_ptr *dst_coef_arrays) 83 /* Crop. This is only used when no rotate/flip is requested with the crop. */ 84 { 85 JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks; 86 int ci, offset_y; 87 JBLOCKARRAY src_buffer, dst_buffer; 88 jpeg_component_info *compptr; 89 90 /* We simply have to copy the right amount of data (the destination's 91 * image size) starting at the given X and Y offsets in the source. 92 */ 93 for (ci = 0; ci < dstinfo->num_components; ci++) { 94 compptr = dstinfo->comp_info + ci; 95 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 96 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 97 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 98 dst_blk_y += compptr->v_samp_factor) { 99 dst_buffer = (*srcinfo->mem->access_virt_barray) 100 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 101 (JDIMENSION) compptr->v_samp_factor, TRUE); 102 src_buffer = (*srcinfo->mem->access_virt_barray) 103 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 104 dst_blk_y + y_crop_blocks, 105 (JDIMENSION) compptr->v_samp_factor, FALSE); 106 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 107 jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, 108 dst_buffer[offset_y], 109 compptr->width_in_blocks); 110 } 111 } 112 } 113 } 114 115 116 LOCAL(void) 117 do_crop_ext (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 118 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 119 jvirt_barray_ptr *src_coef_arrays, 120 jvirt_barray_ptr *dst_coef_arrays) 121 /* Crop. This is only used when no rotate/flip is requested with the crop. 122 * Extension: If the destination size is larger than the source, we fill in 123 * the extra area with zero (neutral gray). Note we also have to zero partial 124 * iMCUs at the right and bottom edge of the source image area in this case. 125 */ 126 { 127 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height; 128 JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks; 129 int ci, offset_y; 130 JBLOCKARRAY src_buffer, dst_buffer; 131 jpeg_component_info *compptr; 132 133 MCU_cols = srcinfo->output_width / 134 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); 135 MCU_rows = srcinfo->output_height / 136 (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); 137 138 for (ci = 0; ci < dstinfo->num_components; ci++) { 139 compptr = dstinfo->comp_info + ci; 140 comp_width = MCU_cols * compptr->h_samp_factor; 141 comp_height = MCU_rows * compptr->v_samp_factor; 142 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 143 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 144 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 145 dst_blk_y += compptr->v_samp_factor) { 146 dst_buffer = (*srcinfo->mem->access_virt_barray) 147 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 148 (JDIMENSION) compptr->v_samp_factor, TRUE); 149 if (dstinfo->jpeg_height > srcinfo->output_height) { 150 if (dst_blk_y < y_crop_blocks || 151 dst_blk_y >= comp_height + y_crop_blocks) { 152 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 153 FMEMZERO(dst_buffer[offset_y], 154 compptr->width_in_blocks * SIZEOF(JBLOCK)); 155 } 156 continue; 157 } 158 src_buffer = (*srcinfo->mem->access_virt_barray) 159 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 160 dst_blk_y - y_crop_blocks, 161 (JDIMENSION) compptr->v_samp_factor, FALSE); 162 } else { 163 src_buffer = (*srcinfo->mem->access_virt_barray) 164 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 165 dst_blk_y + y_crop_blocks, 166 (JDIMENSION) compptr->v_samp_factor, FALSE); 167 } 168 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 169 if (dstinfo->jpeg_width > srcinfo->output_width) { 170 if (x_crop_blocks > 0) { 171 FMEMZERO(dst_buffer[offset_y], 172 x_crop_blocks * SIZEOF(JBLOCK)); 173 } 174 jcopy_block_row(src_buffer[offset_y], 175 dst_buffer[offset_y] + x_crop_blocks, 176 comp_width); 177 if (compptr->width_in_blocks > comp_width + x_crop_blocks) { 178 FMEMZERO(dst_buffer[offset_y] + 179 comp_width + x_crop_blocks, 180 (compptr->width_in_blocks - 181 comp_width - x_crop_blocks) * SIZEOF(JBLOCK)); 182 } 183 } else { 184 jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, 185 dst_buffer[offset_y], 186 compptr->width_in_blocks); 187 } 188 } 189 } 190 } 191 } 192 193 194 LOCAL(void) 195 do_wipe (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 196 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 197 jvirt_barray_ptr *src_coef_arrays, 198 JDIMENSION drop_width, JDIMENSION drop_height) 199 /* Wipe - drop content of specified area, fill with zero (neutral gray) */ 200 { 201 JDIMENSION x_wipe_blocks, wipe_width; 202 JDIMENSION y_wipe_blocks, wipe_bottom; 203 int ci, offset_y; 204 JBLOCKARRAY buffer; 205 jpeg_component_info *compptr; 206 207 for (ci = 0; ci < dstinfo->num_components; ci++) { 208 compptr = dstinfo->comp_info + ci; 209 x_wipe_blocks = x_crop_offset * compptr->h_samp_factor; 210 wipe_width = drop_width * compptr->h_samp_factor; 211 y_wipe_blocks = y_crop_offset * compptr->v_samp_factor; 212 wipe_bottom = drop_height * compptr->v_samp_factor + y_wipe_blocks; 213 for (; y_wipe_blocks < wipe_bottom; 214 y_wipe_blocks += compptr->v_samp_factor) { 215 buffer = (*srcinfo->mem->access_virt_barray) 216 ((j_common_ptr) srcinfo, src_coef_arrays[ci], y_wipe_blocks, 217 (JDIMENSION) compptr->v_samp_factor, TRUE); 218 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 219 FMEMZERO(buffer[offset_y] + x_wipe_blocks, 220 wipe_width * SIZEOF(JBLOCK)); 221 } 222 } 223 } 224 } 225 226 227 LOCAL(void) 228 do_flatten (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 229 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 230 jvirt_barray_ptr *src_coef_arrays, 231 JDIMENSION drop_width, JDIMENSION drop_height) 232 /* Flatten - drop content of specified area, similar to wipe, 233 * but fill with average of adjacent blocks, instead of zero. 234 */ 235 { 236 JDIMENSION x_wipe_blocks, wipe_width, wipe_right; 237 JDIMENSION y_wipe_blocks, wipe_bottom, blk_x; 238 int ci, offset_y, dc_left_value, dc_right_value, average; 239 JBLOCKARRAY buffer; 240 jpeg_component_info *compptr; 241 242 for (ci = 0; ci < dstinfo->num_components; ci++) { 243 compptr = dstinfo->comp_info + ci; 244 x_wipe_blocks = x_crop_offset * compptr->h_samp_factor; 245 wipe_width = drop_width * compptr->h_samp_factor; 246 wipe_right = wipe_width + x_wipe_blocks; 247 y_wipe_blocks = y_crop_offset * compptr->v_samp_factor; 248 wipe_bottom = drop_height * compptr->v_samp_factor + y_wipe_blocks; 249 for (; y_wipe_blocks < wipe_bottom; 250 y_wipe_blocks += compptr->v_samp_factor) { 251 buffer = (*srcinfo->mem->access_virt_barray) 252 ((j_common_ptr) srcinfo, src_coef_arrays[ci], y_wipe_blocks, 253 (JDIMENSION) compptr->v_samp_factor, TRUE); 254 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 255 FMEMZERO(buffer[offset_y] + x_wipe_blocks, 256 wipe_width * SIZEOF(JBLOCK)); 257 if (x_wipe_blocks > 0) { 258 dc_left_value = buffer[offset_y][x_wipe_blocks - 1][0]; 259 if (wipe_right < compptr->width_in_blocks) { 260 dc_right_value = buffer[offset_y][wipe_right][0]; 261 average = (dc_left_value + dc_right_value) >> 1; 262 } else { 263 average = dc_left_value; 264 } 265 } else if (wipe_right < compptr->width_in_blocks) { 266 average = buffer[offset_y][wipe_right][0]; 267 } else continue; 268 for (blk_x = x_wipe_blocks; blk_x < wipe_right; blk_x++) { 269 buffer[offset_y][blk_x][0] = (JCOEF) average; 270 } 271 } 272 } 273 } 274 } 275 276 277 LOCAL(void) 278 do_flip_h_no_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 279 JDIMENSION x_crop_offset, 280 jvirt_barray_ptr *src_coef_arrays) 281 /* Horizontal flip; done in-place, so no separate dest array is required. 282 * NB: this only works when y_crop_offset is zero. 283 */ 284 { 285 JDIMENSION MCU_cols, comp_width, blk_x, blk_y, x_crop_blocks; 286 int ci, k, offset_y; 287 JBLOCKARRAY buffer; 288 JCOEFPTR ptr1, ptr2; 289 JCOEF temp1, temp2; 290 jpeg_component_info *compptr; 291 292 /* Horizontal mirroring of DCT blocks is accomplished by swapping 293 * pairs of blocks in-place. Within a DCT block, we perform horizontal 294 * mirroring by changing the signs of odd-numbered columns. 295 * Partial iMCUs at the right edge are left untouched. 296 */ 297 MCU_cols = srcinfo->output_width / 298 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); 299 300 for (ci = 0; ci < dstinfo->num_components; ci++) { 301 compptr = dstinfo->comp_info + ci; 302 comp_width = MCU_cols * compptr->h_samp_factor; 303 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 304 for (blk_y = 0; blk_y < compptr->height_in_blocks; 305 blk_y += compptr->v_samp_factor) { 306 buffer = (*srcinfo->mem->access_virt_barray) 307 ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y, 308 (JDIMENSION) compptr->v_samp_factor, TRUE); 309 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 310 /* Do the mirroring */ 311 for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) { 312 ptr1 = buffer[offset_y][blk_x]; 313 ptr2 = buffer[offset_y][comp_width - blk_x - 1]; 314 /* this unrolled loop doesn't need to know which row it's on... */ 315 for (k = 0; k < DCTSIZE2; k += 2) { 316 temp1 = *ptr1; /* swap even column */ 317 temp2 = *ptr2; 318 *ptr1++ = temp2; 319 *ptr2++ = temp1; 320 temp1 = *ptr1; /* swap odd column with sign change */ 321 temp2 = *ptr2; 322 *ptr1++ = -temp2; 323 *ptr2++ = -temp1; 324 } 325 } 326 if (x_crop_blocks > 0) { 327 /* Now left-justify the portion of the data to be kept. 328 * We can't use a single jcopy_block_row() call because that routine 329 * depends on memcpy(), whose behavior is unspecified for overlapping 330 * source and destination areas. Sigh. 331 */ 332 for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) { 333 jcopy_block_row(buffer[offset_y] + blk_x + x_crop_blocks, 334 buffer[offset_y] + blk_x, 335 (JDIMENSION) 1); 336 } 337 } 338 } 339 } 340 } 341 } 342 343 344 LOCAL(void) 345 do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 346 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 347 jvirt_barray_ptr *src_coef_arrays, 348 jvirt_barray_ptr *dst_coef_arrays) 349 /* Horizontal flip in general cropping case */ 350 { 351 JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y; 352 JDIMENSION x_crop_blocks, y_crop_blocks; 353 int ci, k, offset_y; 354 JBLOCKARRAY src_buffer, dst_buffer; 355 JBLOCKROW src_row_ptr, dst_row_ptr; 356 JCOEFPTR src_ptr, dst_ptr; 357 jpeg_component_info *compptr; 358 359 /* Here we must output into a separate array because we can't touch 360 * different rows of a single virtual array simultaneously. Otherwise, 361 * this is essentially the same as the routine above. 362 */ 363 MCU_cols = srcinfo->output_width / 364 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); 365 366 for (ci = 0; ci < dstinfo->num_components; ci++) { 367 compptr = dstinfo->comp_info + ci; 368 comp_width = MCU_cols * compptr->h_samp_factor; 369 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 370 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 371 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 372 dst_blk_y += compptr->v_samp_factor) { 373 dst_buffer = (*srcinfo->mem->access_virt_barray) 374 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 375 (JDIMENSION) compptr->v_samp_factor, TRUE); 376 src_buffer = (*srcinfo->mem->access_virt_barray) 377 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 378 dst_blk_y + y_crop_blocks, 379 (JDIMENSION) compptr->v_samp_factor, FALSE); 380 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 381 dst_row_ptr = dst_buffer[offset_y]; 382 src_row_ptr = src_buffer[offset_y]; 383 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { 384 if (x_crop_blocks + dst_blk_x < comp_width) { 385 /* Do the mirrorable blocks */ 386 dst_ptr = dst_row_ptr[dst_blk_x]; 387 src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; 388 /* this unrolled loop doesn't need to know which row it's on... */ 389 for (k = 0; k < DCTSIZE2; k += 2) { 390 *dst_ptr++ = *src_ptr++; /* copy even column */ 391 *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */ 392 } 393 } else { 394 /* Copy last partial block(s) verbatim */ 395 jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks, 396 dst_row_ptr + dst_blk_x, 397 (JDIMENSION) 1); 398 } 399 } 400 } 401 } 402 } 403 } 404 405 406 LOCAL(void) 407 do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 408 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 409 jvirt_barray_ptr *src_coef_arrays, 410 jvirt_barray_ptr *dst_coef_arrays) 411 /* Vertical flip */ 412 { 413 JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; 414 JDIMENSION x_crop_blocks, y_crop_blocks; 415 int ci, i, j, offset_y; 416 JBLOCKARRAY src_buffer, dst_buffer; 417 JBLOCKROW src_row_ptr, dst_row_ptr; 418 JCOEFPTR src_ptr, dst_ptr; 419 jpeg_component_info *compptr; 420 421 /* We output into a separate array because we can't touch different 422 * rows of the source virtual array simultaneously. Otherwise, this 423 * is a pretty straightforward analog of horizontal flip. 424 * Within a DCT block, vertical mirroring is done by changing the signs 425 * of odd-numbered rows. 426 * Partial iMCUs at the bottom edge are copied verbatim. 427 */ 428 MCU_rows = srcinfo->output_height / 429 (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); 430 431 for (ci = 0; ci < dstinfo->num_components; ci++) { 432 compptr = dstinfo->comp_info + ci; 433 comp_height = MCU_rows * compptr->v_samp_factor; 434 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 435 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 436 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 437 dst_blk_y += compptr->v_samp_factor) { 438 dst_buffer = (*srcinfo->mem->access_virt_barray) 439 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 440 (JDIMENSION) compptr->v_samp_factor, TRUE); 441 if (y_crop_blocks + dst_blk_y < comp_height) { 442 /* Row is within the mirrorable area. */ 443 src_buffer = (*srcinfo->mem->access_virt_barray) 444 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 445 comp_height - y_crop_blocks - dst_blk_y - 446 (JDIMENSION) compptr->v_samp_factor, 447 (JDIMENSION) compptr->v_samp_factor, FALSE); 448 } else { 449 /* Bottom-edge blocks will be copied verbatim. */ 450 src_buffer = (*srcinfo->mem->access_virt_barray) 451 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 452 dst_blk_y + y_crop_blocks, 453 (JDIMENSION) compptr->v_samp_factor, FALSE); 454 } 455 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 456 if (y_crop_blocks + dst_blk_y < comp_height) { 457 /* Row is within the mirrorable area. */ 458 dst_row_ptr = dst_buffer[offset_y]; 459 src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; 460 src_row_ptr += x_crop_blocks; 461 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; 462 dst_blk_x++) { 463 dst_ptr = dst_row_ptr[dst_blk_x]; 464 src_ptr = src_row_ptr[dst_blk_x]; 465 for (i = 0; i < DCTSIZE; i += 2) { 466 /* copy even row */ 467 for (j = 0; j < DCTSIZE; j++) 468 *dst_ptr++ = *src_ptr++; 469 /* copy odd row with sign change */ 470 for (j = 0; j < DCTSIZE; j++) 471 *dst_ptr++ = - *src_ptr++; 472 } 473 } 474 } else { 475 /* Just copy row verbatim. */ 476 jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, 477 dst_buffer[offset_y], 478 compptr->width_in_blocks); 479 } 480 } 481 } 482 } 483 } 484 485 486 LOCAL(void) 487 do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 488 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 489 jvirt_barray_ptr *src_coef_arrays, 490 jvirt_barray_ptr *dst_coef_arrays) 491 /* Transpose source into destination */ 492 { 493 JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks; 494 int ci, i, j, offset_x, offset_y; 495 JBLOCKARRAY src_buffer, dst_buffer; 496 JCOEFPTR src_ptr, dst_ptr; 497 jpeg_component_info *compptr; 498 499 /* Transposing pixels within a block just requires transposing the 500 * DCT coefficients. 501 * Partial iMCUs at the edges require no special treatment; we simply 502 * process all the available DCT blocks for every component. 503 */ 504 for (ci = 0; ci < dstinfo->num_components; ci++) { 505 compptr = dstinfo->comp_info + ci; 506 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 507 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 508 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 509 dst_blk_y += compptr->v_samp_factor) { 510 dst_buffer = (*srcinfo->mem->access_virt_barray) 511 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 512 (JDIMENSION) compptr->v_samp_factor, TRUE); 513 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 514 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; 515 dst_blk_x += compptr->h_samp_factor) { 516 src_buffer = (*srcinfo->mem->access_virt_barray) 517 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 518 dst_blk_x + x_crop_blocks, 519 (JDIMENSION) compptr->h_samp_factor, FALSE); 520 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { 521 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; 522 src_ptr = src_buffer[offset_x][dst_blk_y + offset_y + y_crop_blocks]; 523 for (i = 0; i < DCTSIZE; i++) 524 for (j = 0; j < DCTSIZE; j++) 525 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 526 } 527 } 528 } 529 } 530 } 531 } 532 533 534 LOCAL(void) 535 do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 536 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 537 jvirt_barray_ptr *src_coef_arrays, 538 jvirt_barray_ptr *dst_coef_arrays) 539 /* 90 degree rotation is equivalent to 540 * 1. Transposing the image; 541 * 2. Horizontal mirroring. 542 * These two steps are merged into a single processing routine. 543 */ 544 { 545 JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y; 546 JDIMENSION x_crop_blocks, y_crop_blocks; 547 int ci, i, j, offset_x, offset_y; 548 JBLOCKARRAY src_buffer, dst_buffer; 549 JCOEFPTR src_ptr, dst_ptr; 550 jpeg_component_info *compptr; 551 552 /* Because of the horizontal mirror step, we can't process partial iMCUs 553 * at the (output) right edge properly. They just get transposed and 554 * not mirrored. 555 */ 556 MCU_cols = srcinfo->output_height / 557 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); 558 559 for (ci = 0; ci < dstinfo->num_components; ci++) { 560 compptr = dstinfo->comp_info + ci; 561 comp_width = MCU_cols * compptr->h_samp_factor; 562 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 563 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 564 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 565 dst_blk_y += compptr->v_samp_factor) { 566 dst_buffer = (*srcinfo->mem->access_virt_barray) 567 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 568 (JDIMENSION) compptr->v_samp_factor, TRUE); 569 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 570 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; 571 dst_blk_x += compptr->h_samp_factor) { 572 if (x_crop_blocks + dst_blk_x < comp_width) { 573 /* Block is within the mirrorable area. */ 574 src_buffer = (*srcinfo->mem->access_virt_barray) 575 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 576 comp_width - x_crop_blocks - dst_blk_x - 577 (JDIMENSION) compptr->h_samp_factor, 578 (JDIMENSION) compptr->h_samp_factor, FALSE); 579 } else { 580 /* Edge blocks are transposed but not mirrored. */ 581 src_buffer = (*srcinfo->mem->access_virt_barray) 582 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 583 dst_blk_x + x_crop_blocks, 584 (JDIMENSION) compptr->h_samp_factor, FALSE); 585 } 586 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { 587 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; 588 if (x_crop_blocks + dst_blk_x < comp_width) { 589 /* Block is within the mirrorable area. */ 590 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] 591 [dst_blk_y + offset_y + y_crop_blocks]; 592 for (i = 0; i < DCTSIZE; i++) { 593 for (j = 0; j < DCTSIZE; j++) 594 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 595 i++; 596 for (j = 0; j < DCTSIZE; j++) 597 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 598 } 599 } else { 600 /* Edge blocks are transposed but not mirrored. */ 601 src_ptr = src_buffer[offset_x] 602 [dst_blk_y + offset_y + y_crop_blocks]; 603 for (i = 0; i < DCTSIZE; i++) 604 for (j = 0; j < DCTSIZE; j++) 605 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 606 } 607 } 608 } 609 } 610 } 611 } 612 } 613 614 615 LOCAL(void) 616 do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 617 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 618 jvirt_barray_ptr *src_coef_arrays, 619 jvirt_barray_ptr *dst_coef_arrays) 620 /* 270 degree rotation is equivalent to 621 * 1. Horizontal mirroring; 622 * 2. Transposing the image. 623 * These two steps are merged into a single processing routine. 624 */ 625 { 626 JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; 627 JDIMENSION x_crop_blocks, y_crop_blocks; 628 int ci, i, j, offset_x, offset_y; 629 JBLOCKARRAY src_buffer, dst_buffer; 630 JCOEFPTR src_ptr, dst_ptr; 631 jpeg_component_info *compptr; 632 633 /* Because of the horizontal mirror step, we can't process partial iMCUs 634 * at the (output) bottom edge properly. They just get transposed and 635 * not mirrored. 636 */ 637 MCU_rows = srcinfo->output_width / 638 (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); 639 640 for (ci = 0; ci < dstinfo->num_components; ci++) { 641 compptr = dstinfo->comp_info + ci; 642 comp_height = MCU_rows * compptr->v_samp_factor; 643 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 644 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 645 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 646 dst_blk_y += compptr->v_samp_factor) { 647 dst_buffer = (*srcinfo->mem->access_virt_barray) 648 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 649 (JDIMENSION) compptr->v_samp_factor, TRUE); 650 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 651 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; 652 dst_blk_x += compptr->h_samp_factor) { 653 src_buffer = (*srcinfo->mem->access_virt_barray) 654 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 655 dst_blk_x + x_crop_blocks, 656 (JDIMENSION) compptr->h_samp_factor, FALSE); 657 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { 658 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; 659 if (y_crop_blocks + dst_blk_y < comp_height) { 660 /* Block is within the mirrorable area. */ 661 src_ptr = src_buffer[offset_x] 662 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; 663 for (i = 0; i < DCTSIZE; i++) { 664 for (j = 0; j < DCTSIZE; j++) { 665 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 666 j++; 667 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 668 } 669 } 670 } else { 671 /* Edge blocks are transposed but not mirrored. */ 672 src_ptr = src_buffer[offset_x] 673 [dst_blk_y + offset_y + y_crop_blocks]; 674 for (i = 0; i < DCTSIZE; i++) 675 for (j = 0; j < DCTSIZE; j++) 676 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 677 } 678 } 679 } 680 } 681 } 682 } 683 } 684 685 686 LOCAL(void) 687 do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 688 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 689 jvirt_barray_ptr *src_coef_arrays, 690 jvirt_barray_ptr *dst_coef_arrays) 691 /* 180 degree rotation is equivalent to 692 * 1. Vertical mirroring; 693 * 2. Horizontal mirroring. 694 * These two steps are merged into a single processing routine. 695 */ 696 { 697 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; 698 JDIMENSION x_crop_blocks, y_crop_blocks; 699 int ci, i, j, offset_y; 700 JBLOCKARRAY src_buffer, dst_buffer; 701 JBLOCKROW src_row_ptr, dst_row_ptr; 702 JCOEFPTR src_ptr, dst_ptr; 703 jpeg_component_info *compptr; 704 705 MCU_cols = srcinfo->output_width / 706 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); 707 MCU_rows = srcinfo->output_height / 708 (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); 709 710 for (ci = 0; ci < dstinfo->num_components; ci++) { 711 compptr = dstinfo->comp_info + ci; 712 comp_width = MCU_cols * compptr->h_samp_factor; 713 comp_height = MCU_rows * compptr->v_samp_factor; 714 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 715 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 716 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 717 dst_blk_y += compptr->v_samp_factor) { 718 dst_buffer = (*srcinfo->mem->access_virt_barray) 719 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 720 (JDIMENSION) compptr->v_samp_factor, TRUE); 721 if (y_crop_blocks + dst_blk_y < comp_height) { 722 /* Row is within the vertically mirrorable area. */ 723 src_buffer = (*srcinfo->mem->access_virt_barray) 724 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 725 comp_height - y_crop_blocks - dst_blk_y - 726 (JDIMENSION) compptr->v_samp_factor, 727 (JDIMENSION) compptr->v_samp_factor, FALSE); 728 } else { 729 /* Bottom-edge rows are only mirrored horizontally. */ 730 src_buffer = (*srcinfo->mem->access_virt_barray) 731 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 732 dst_blk_y + y_crop_blocks, 733 (JDIMENSION) compptr->v_samp_factor, FALSE); 734 } 735 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 736 dst_row_ptr = dst_buffer[offset_y]; 737 if (y_crop_blocks + dst_blk_y < comp_height) { 738 /* Row is within the mirrorable area. */ 739 src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; 740 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { 741 dst_ptr = dst_row_ptr[dst_blk_x]; 742 if (x_crop_blocks + dst_blk_x < comp_width) { 743 /* Process the blocks that can be mirrored both ways. */ 744 src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; 745 for (i = 0; i < DCTSIZE; i += 2) { 746 /* For even row, negate every odd column. */ 747 for (j = 0; j < DCTSIZE; j += 2) { 748 *dst_ptr++ = *src_ptr++; 749 *dst_ptr++ = - *src_ptr++; 750 } 751 /* For odd row, negate every even column. */ 752 for (j = 0; j < DCTSIZE; j += 2) { 753 *dst_ptr++ = - *src_ptr++; 754 *dst_ptr++ = *src_ptr++; 755 } 756 } 757 } else { 758 /* Any remaining right-edge blocks are only mirrored vertically. */ 759 src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x]; 760 for (i = 0; i < DCTSIZE; i += 2) { 761 for (j = 0; j < DCTSIZE; j++) 762 *dst_ptr++ = *src_ptr++; 763 for (j = 0; j < DCTSIZE; j++) 764 *dst_ptr++ = - *src_ptr++; 765 } 766 } 767 } 768 } else { 769 /* Remaining rows are just mirrored horizontally. */ 770 src_row_ptr = src_buffer[offset_y]; 771 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { 772 if (x_crop_blocks + dst_blk_x < comp_width) { 773 /* Process the blocks that can be mirrored. */ 774 dst_ptr = dst_row_ptr[dst_blk_x]; 775 src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; 776 for (i = 0; i < DCTSIZE2; i += 2) { 777 *dst_ptr++ = *src_ptr++; 778 *dst_ptr++ = - *src_ptr++; 779 } 780 } else { 781 /* Any remaining right-edge blocks are only copied. */ 782 jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks, 783 dst_row_ptr + dst_blk_x, 784 (JDIMENSION) 1); 785 } 786 } 787 } 788 } 789 } 790 } 791 } 792 793 794 LOCAL(void) 795 do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 796 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 797 jvirt_barray_ptr *src_coef_arrays, 798 jvirt_barray_ptr *dst_coef_arrays) 799 /* Transverse transpose is equivalent to 800 * 1. 180 degree rotation; 801 * 2. Transposition; 802 * or 803 * 1. Horizontal mirroring; 804 * 2. Transposition; 805 * 3. Horizontal mirroring. 806 * These steps are merged into a single processing routine. 807 */ 808 { 809 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; 810 JDIMENSION x_crop_blocks, y_crop_blocks; 811 int ci, i, j, offset_x, offset_y; 812 JBLOCKARRAY src_buffer, dst_buffer; 813 JCOEFPTR src_ptr, dst_ptr; 814 jpeg_component_info *compptr; 815 816 MCU_cols = srcinfo->output_height / 817 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); 818 MCU_rows = srcinfo->output_width / 819 (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); 820 821 for (ci = 0; ci < dstinfo->num_components; ci++) { 822 compptr = dstinfo->comp_info + ci; 823 comp_width = MCU_cols * compptr->h_samp_factor; 824 comp_height = MCU_rows * compptr->v_samp_factor; 825 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 826 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 827 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 828 dst_blk_y += compptr->v_samp_factor) { 829 dst_buffer = (*srcinfo->mem->access_virt_barray) 830 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 831 (JDIMENSION) compptr->v_samp_factor, TRUE); 832 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 833 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; 834 dst_blk_x += compptr->h_samp_factor) { 835 if (x_crop_blocks + dst_blk_x < comp_width) { 836 /* Block is within the mirrorable area. */ 837 src_buffer = (*srcinfo->mem->access_virt_barray) 838 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 839 comp_width - x_crop_blocks - dst_blk_x - 840 (JDIMENSION) compptr->h_samp_factor, 841 (JDIMENSION) compptr->h_samp_factor, FALSE); 842 } else { 843 src_buffer = (*srcinfo->mem->access_virt_barray) 844 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 845 dst_blk_x + x_crop_blocks, 846 (JDIMENSION) compptr->h_samp_factor, FALSE); 847 } 848 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { 849 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; 850 if (y_crop_blocks + dst_blk_y < comp_height) { 851 if (x_crop_blocks + dst_blk_x < comp_width) { 852 /* Block is within the mirrorable area. */ 853 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] 854 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; 855 for (i = 0; i < DCTSIZE; i++) { 856 for (j = 0; j < DCTSIZE; j++) { 857 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 858 j++; 859 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 860 } 861 i++; 862 for (j = 0; j < DCTSIZE; j++) { 863 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 864 j++; 865 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 866 } 867 } 868 } else { 869 /* Right-edge blocks are mirrored in y only */ 870 src_ptr = src_buffer[offset_x] 871 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; 872 for (i = 0; i < DCTSIZE; i++) { 873 for (j = 0; j < DCTSIZE; j++) { 874 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 875 j++; 876 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 877 } 878 } 879 } 880 } else { 881 if (x_crop_blocks + dst_blk_x < comp_width) { 882 /* Bottom-edge blocks are mirrored in x only */ 883 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] 884 [dst_blk_y + offset_y + y_crop_blocks]; 885 for (i = 0; i < DCTSIZE; i++) { 886 for (j = 0; j < DCTSIZE; j++) 887 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 888 i++; 889 for (j = 0; j < DCTSIZE; j++) 890 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 891 } 892 } else { 893 /* At lower right corner, just transpose, no mirroring */ 894 src_ptr = src_buffer[offset_x] 895 [dst_blk_y + offset_y + y_crop_blocks]; 896 for (i = 0; i < DCTSIZE; i++) 897 for (j = 0; j < DCTSIZE; j++) 898 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 899 } 900 } 901 } 902 } 903 } 904 } 905 } 906 } 907 908 909 /* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec. 910 * Returns TRUE if valid integer found, FALSE if not. 911 * *strptr is advanced over the digit string, and *result is set to its value. 912 */ 913 914 LOCAL(boolean) 915 jt_read_integer (const char ** strptr, JDIMENSION * result) 916 { 917 const char * ptr = *strptr; 918 JDIMENSION val = 0; 919 920 for (; isdigit(*ptr); ptr++) { 921 val = val * 10 + (JDIMENSION) (*ptr - '0'); 922 } 923 *result = val; 924 if (ptr == *strptr) 925 return FALSE; /* oops, no digits */ 926 *strptr = ptr; 927 return TRUE; 928 } 929 930 931 /* Parse a crop specification (written in X11 geometry style). 932 * The routine returns TRUE if the spec string is valid, FALSE if not. 933 * 934 * The crop spec string should have the format 935 * <width>[f]x<height>[f]{+-}<xoffset>{+-}<yoffset> 936 * where width, height, xoffset, and yoffset are unsigned integers. 937 * Each of the elements can be omitted to indicate a default value. 938 * (A weakness of this style is that it is not possible to omit xoffset 939 * while specifying yoffset, since they look alike.) 940 * 941 * This code is loosely based on XParseGeometry from the X11 distribution. 942 */ 943 944 GLOBAL(boolean) 945 jtransform_parse_crop_spec (jpeg_transform_info *info, const char *spec) 946 { 947 info->crop = FALSE; 948 info->crop_width_set = JCROP_UNSET; 949 info->crop_height_set = JCROP_UNSET; 950 info->crop_xoffset_set = JCROP_UNSET; 951 info->crop_yoffset_set = JCROP_UNSET; 952 953 if (isdigit(*spec)) { 954 /* fetch width */ 955 if (! jt_read_integer(&spec, &info->crop_width)) 956 return FALSE; 957 if (*spec == 'f' || *spec == 'F') { 958 spec++; 959 info->crop_width_set = JCROP_FORCE; 960 } else 961 info->crop_width_set = JCROP_POS; 962 } 963 if (*spec == 'x' || *spec == 'X') { 964 /* fetch height */ 965 spec++; 966 if (! jt_read_integer(&spec, &info->crop_height)) 967 return FALSE; 968 if (*spec == 'f' || *spec == 'F') { 969 spec++; 970 info->crop_height_set = JCROP_FORCE; 971 } else 972 info->crop_height_set = JCROP_POS; 973 } 974 if (*spec == '+' || *spec == '-') { 975 /* fetch xoffset */ 976 info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS; 977 spec++; 978 if (! jt_read_integer(&spec, &info->crop_xoffset)) 979 return FALSE; 980 } 981 if (*spec == '+' || *spec == '-') { 982 /* fetch yoffset */ 983 info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS; 984 spec++; 985 if (! jt_read_integer(&spec, &info->crop_yoffset)) 986 return FALSE; 987 } 988 /* We had better have gotten to the end of the string. */ 989 if (*spec != '\0') 990 return FALSE; 991 info->crop = TRUE; 992 return TRUE; 993 } 994 995 996 /* Trim off any partial iMCUs on the indicated destination edge */ 997 998 LOCAL(void) 999 trim_right_edge (jpeg_transform_info *info, JDIMENSION full_width) 1000 { 1001 JDIMENSION MCU_cols; 1002 1003 MCU_cols = info->output_width / info->iMCU_sample_width; 1004 if (MCU_cols > 0 && info->x_crop_offset + MCU_cols == 1005 full_width / info->iMCU_sample_width) 1006 info->output_width = MCU_cols * info->iMCU_sample_width; 1007 } 1008 1009 LOCAL(void) 1010 trim_bottom_edge (jpeg_transform_info *info, JDIMENSION full_height) 1011 { 1012 JDIMENSION MCU_rows; 1013 1014 MCU_rows = info->output_height / info->iMCU_sample_height; 1015 if (MCU_rows > 0 && info->y_crop_offset + MCU_rows == 1016 full_height / info->iMCU_sample_height) 1017 info->output_height = MCU_rows * info->iMCU_sample_height; 1018 } 1019 1020 1021 /* Request any required workspace. 1022 * 1023 * This routine figures out the size that the output image will be 1024 * (which implies that all the transform parameters must be set before 1025 * it is called). 1026 * 1027 * We allocate the workspace virtual arrays from the source decompression 1028 * object, so that all the arrays (both the original data and the workspace) 1029 * will be taken into account while making memory management decisions. 1030 * Hence, this routine must be called after jpeg_read_header (which reads 1031 * the image dimensions) and before jpeg_read_coefficients (which realizes 1032 * the source's virtual arrays). 1033 * 1034 * This function returns FALSE right away if -perfect is given 1035 * and transformation is not perfect. Otherwise returns TRUE. 1036 */ 1037 1038 GLOBAL(boolean) 1039 jtransform_request_workspace (j_decompress_ptr srcinfo, 1040 jpeg_transform_info *info) 1041 { 1042 jvirt_barray_ptr *coef_arrays; 1043 boolean need_workspace, transpose_it; 1044 jpeg_component_info *compptr; 1045 JDIMENSION xoffset, yoffset; 1046 JDIMENSION width_in_iMCUs, height_in_iMCUs; 1047 JDIMENSION width_in_blocks, height_in_blocks; 1048 int ci, h_samp_factor, v_samp_factor; 1049 1050 /* Determine number of components in output image */ 1051 if (info->force_grayscale && 1052 (srcinfo->jpeg_color_space == JCS_YCbCr || 1053 srcinfo->jpeg_color_space == JCS_BG_YCC) && 1054 srcinfo->num_components == 3) 1055 /* We'll only process the first component */ 1056 info->num_components = 1; 1057 else 1058 /* Process all the components */ 1059 info->num_components = srcinfo->num_components; 1060 1061 /* Compute output image dimensions and related values. */ 1062 jpeg_core_output_dimensions(srcinfo); 1063 1064 /* Return right away if -perfect is given and transformation is not perfect. 1065 */ 1066 if (info->perfect) { 1067 if (info->num_components == 1) { 1068 if (!jtransform_perfect_transform(srcinfo->output_width, 1069 srcinfo->output_height, 1070 srcinfo->min_DCT_h_scaled_size, 1071 srcinfo->min_DCT_v_scaled_size, 1072 info->transform)) 1073 return FALSE; 1074 } else { 1075 if (!jtransform_perfect_transform(srcinfo->output_width, 1076 srcinfo->output_height, 1077 srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size, 1078 srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size, 1079 info->transform)) 1080 return FALSE; 1081 } 1082 } 1083 1084 /* If there is only one output component, force the iMCU size to be 1; 1085 * else use the source iMCU size. (This allows us to do the right thing 1086 * when reducing color to grayscale, and also provides a handy way of 1087 * cleaning up "funny" grayscale images whose sampling factors are not 1x1.) 1088 */ 1089 switch (info->transform) { 1090 case JXFORM_TRANSPOSE: 1091 case JXFORM_TRANSVERSE: 1092 case JXFORM_ROT_90: 1093 case JXFORM_ROT_270: 1094 info->output_width = srcinfo->output_height; 1095 info->output_height = srcinfo->output_width; 1096 if (info->num_components == 1) { 1097 info->iMCU_sample_width = srcinfo->min_DCT_v_scaled_size; 1098 info->iMCU_sample_height = srcinfo->min_DCT_h_scaled_size; 1099 } else { 1100 info->iMCU_sample_width = 1101 srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size; 1102 info->iMCU_sample_height = 1103 srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size; 1104 } 1105 break; 1106 default: 1107 info->output_width = srcinfo->output_width; 1108 info->output_height = srcinfo->output_height; 1109 if (info->num_components == 1) { 1110 info->iMCU_sample_width = srcinfo->min_DCT_h_scaled_size; 1111 info->iMCU_sample_height = srcinfo->min_DCT_v_scaled_size; 1112 } else { 1113 info->iMCU_sample_width = 1114 srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size; 1115 info->iMCU_sample_height = 1116 srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size; 1117 } 1118 break; 1119 } 1120 1121 /* If cropping has been requested, compute the crop area's position and 1122 * dimensions, ensuring that its upper left corner falls at an iMCU boundary. 1123 */ 1124 if (info->crop) { 1125 /* Insert default values for unset crop parameters */ 1126 if (info->crop_xoffset_set == JCROP_UNSET) 1127 info->crop_xoffset = 0; /* default to +0 */ 1128 if (info->crop_yoffset_set == JCROP_UNSET) 1129 info->crop_yoffset = 0; /* default to +0 */ 1130 if (info->crop_width_set == JCROP_UNSET) { 1131 if (info->crop_xoffset >= info->output_width) 1132 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); 1133 info->crop_width = info->output_width - info->crop_xoffset; 1134 } else { 1135 /* Check for crop extension */ 1136 if (info->crop_width > info->output_width) { 1137 /* Crop extension does not work when transforming! */ 1138 if (info->transform != JXFORM_NONE || 1139 info->crop_xoffset >= info->crop_width || 1140 info->crop_xoffset > info->crop_width - info->output_width) 1141 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); 1142 } else { 1143 if (info->crop_xoffset >= info->output_width || 1144 info->crop_width <= 0 || 1145 info->crop_xoffset > info->output_width - info->crop_width) 1146 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); 1147 } 1148 } 1149 if (info->crop_height_set == JCROP_UNSET) { 1150 if (info->crop_yoffset >= info->output_height) 1151 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); 1152 info->crop_height = info->output_height - info->crop_yoffset; 1153 } else { 1154 /* Check for crop extension */ 1155 if (info->crop_height > info->output_height) { 1156 /* Crop extension does not work when transforming! */ 1157 if (info->transform != JXFORM_NONE || 1158 info->crop_yoffset >= info->crop_height || 1159 info->crop_yoffset > info->crop_height - info->output_height) 1160 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); 1161 } else { 1162 if (info->crop_yoffset >= info->output_height || 1163 info->crop_height <= 0 || 1164 info->crop_yoffset > info->output_height - info->crop_height) 1165 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); 1166 } 1167 } 1168 /* Convert negative crop offsets into regular offsets */ 1169 if (info->crop_xoffset_set != JCROP_NEG) 1170 xoffset = info->crop_xoffset; 1171 else if (info->crop_width > info->output_width) /* crop extension */ 1172 xoffset = info->crop_width - info->output_width - info->crop_xoffset; 1173 else 1174 xoffset = info->output_width - info->crop_width - info->crop_xoffset; 1175 if (info->crop_yoffset_set != JCROP_NEG) 1176 yoffset = info->crop_yoffset; 1177 else if (info->crop_height > info->output_height) /* crop extension */ 1178 yoffset = info->crop_height - info->output_height - info->crop_yoffset; 1179 else 1180 yoffset = info->output_height - info->crop_height - info->crop_yoffset; 1181 /* Now adjust so that upper left corner falls at an iMCU boundary */ 1182 if (info->transform == JXFORM_WIPE) { 1183 /* Ensure the effective wipe region will cover the requested */ 1184 info->drop_width = (JDIMENSION) jdiv_round_up 1185 ((long) (info->crop_width + (xoffset % info->iMCU_sample_width)), 1186 (long) info->iMCU_sample_width); 1187 info->drop_height = (JDIMENSION) jdiv_round_up 1188 ((long) (info->crop_height + (yoffset % info->iMCU_sample_height)), 1189 (long) info->iMCU_sample_height); 1190 } else { 1191 /* Ensure the effective crop region will cover the requested */ 1192 if (info->crop_width_set == JCROP_FORCE || 1193 info->crop_width > info->output_width) 1194 info->output_width = info->crop_width; 1195 else 1196 info->output_width = 1197 info->crop_width + (xoffset % info->iMCU_sample_width); 1198 if (info->crop_height_set == JCROP_FORCE || 1199 info->crop_height > info->output_height) 1200 info->output_height = info->crop_height; 1201 else 1202 info->output_height = 1203 info->crop_height + (yoffset % info->iMCU_sample_height); 1204 } 1205 /* Save x/y offsets measured in iMCUs */ 1206 info->x_crop_offset = xoffset / info->iMCU_sample_width; 1207 info->y_crop_offset = yoffset / info->iMCU_sample_height; 1208 } else { 1209 info->x_crop_offset = 0; 1210 info->y_crop_offset = 0; 1211 } 1212 1213 /* Figure out whether we need workspace arrays, 1214 * and if so whether they are transposed relative to the source. 1215 */ 1216 need_workspace = FALSE; 1217 transpose_it = FALSE; 1218 switch (info->transform) { 1219 case JXFORM_NONE: 1220 if (info->x_crop_offset != 0 || info->y_crop_offset != 0 || 1221 info->output_width > srcinfo->output_width || 1222 info->output_height > srcinfo->output_height) 1223 need_workspace = TRUE; 1224 /* No workspace needed if neither cropping nor transforming */ 1225 break; 1226 case JXFORM_FLIP_H: 1227 if (info->trim) 1228 trim_right_edge(info, srcinfo->output_width); 1229 if (info->y_crop_offset != 0) 1230 need_workspace = TRUE; 1231 /* do_flip_h_no_crop doesn't need a workspace array */ 1232 break; 1233 case JXFORM_FLIP_V: 1234 if (info->trim) 1235 trim_bottom_edge(info, srcinfo->output_height); 1236 /* Need workspace arrays having same dimensions as source image. */ 1237 need_workspace = TRUE; 1238 break; 1239 case JXFORM_TRANSPOSE: 1240 /* transpose does NOT have to trim anything */ 1241 /* Need workspace arrays having transposed dimensions. */ 1242 need_workspace = TRUE; 1243 transpose_it = TRUE; 1244 break; 1245 case JXFORM_TRANSVERSE: 1246 if (info->trim) { 1247 trim_right_edge(info, srcinfo->output_height); 1248 trim_bottom_edge(info, srcinfo->output_width); 1249 } 1250 /* Need workspace arrays having transposed dimensions. */ 1251 need_workspace = TRUE; 1252 transpose_it = TRUE; 1253 break; 1254 case JXFORM_ROT_90: 1255 if (info->trim) 1256 trim_right_edge(info, srcinfo->output_height); 1257 /* Need workspace arrays having transposed dimensions. */ 1258 need_workspace = TRUE; 1259 transpose_it = TRUE; 1260 break; 1261 case JXFORM_ROT_180: 1262 if (info->trim) { 1263 trim_right_edge(info, srcinfo->output_width); 1264 trim_bottom_edge(info, srcinfo->output_height); 1265 } 1266 /* Need workspace arrays having same dimensions as source image. */ 1267 need_workspace = TRUE; 1268 break; 1269 case JXFORM_ROT_270: 1270 if (info->trim) 1271 trim_bottom_edge(info, srcinfo->output_width); 1272 /* Need workspace arrays having transposed dimensions. */ 1273 need_workspace = TRUE; 1274 transpose_it = TRUE; 1275 break; 1276 case JXFORM_WIPE: 1277 break; 1278 } 1279 1280 /* Allocate workspace if needed. 1281 * Note that we allocate arrays padded out to the next iMCU boundary, 1282 * so that transform routines need not worry about missing edge blocks. 1283 */ 1284 if (need_workspace) { 1285 coef_arrays = (jvirt_barray_ptr *) 1286 (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE, 1287 SIZEOF(jvirt_barray_ptr) * info->num_components); 1288 width_in_iMCUs = (JDIMENSION) 1289 jdiv_round_up((long) info->output_width, 1290 (long) info->iMCU_sample_width); 1291 height_in_iMCUs = (JDIMENSION) 1292 jdiv_round_up((long) info->output_height, 1293 (long) info->iMCU_sample_height); 1294 for (ci = 0; ci < info->num_components; ci++) { 1295 compptr = srcinfo->comp_info + ci; 1296 if (info->num_components == 1) { 1297 /* we're going to force samp factors to 1x1 in this case */ 1298 h_samp_factor = v_samp_factor = 1; 1299 } else if (transpose_it) { 1300 h_samp_factor = compptr->v_samp_factor; 1301 v_samp_factor = compptr->h_samp_factor; 1302 } else { 1303 h_samp_factor = compptr->h_samp_factor; 1304 v_samp_factor = compptr->v_samp_factor; 1305 } 1306 width_in_blocks = width_in_iMCUs * h_samp_factor; 1307 height_in_blocks = height_in_iMCUs * v_samp_factor; 1308 coef_arrays[ci] = (*srcinfo->mem->request_virt_barray) 1309 ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE, 1310 width_in_blocks, height_in_blocks, (JDIMENSION) v_samp_factor); 1311 } 1312 info->workspace_coef_arrays = coef_arrays; 1313 } else 1314 info->workspace_coef_arrays = NULL; 1315 1316 return TRUE; 1317 } 1318 1319 1320 /* Transpose destination image parameters */ 1321 1322 LOCAL(void) 1323 transpose_critical_parameters (j_compress_ptr dstinfo) 1324 { 1325 int tblno, i, j, ci, itemp; 1326 jpeg_component_info *compptr; 1327 JQUANT_TBL *qtblptr; 1328 JDIMENSION jtemp; 1329 UINT16 qtemp; 1330 1331 /* Transpose image dimensions */ 1332 jtemp = dstinfo->image_width; 1333 dstinfo->image_width = dstinfo->image_height; 1334 dstinfo->image_height = jtemp; 1335 itemp = dstinfo->min_DCT_h_scaled_size; 1336 dstinfo->min_DCT_h_scaled_size = dstinfo->min_DCT_v_scaled_size; 1337 dstinfo->min_DCT_v_scaled_size = itemp; 1338 1339 /* Transpose sampling factors */ 1340 for (ci = 0; ci < dstinfo->num_components; ci++) { 1341 compptr = dstinfo->comp_info + ci; 1342 itemp = compptr->h_samp_factor; 1343 compptr->h_samp_factor = compptr->v_samp_factor; 1344 compptr->v_samp_factor = itemp; 1345 } 1346 1347 /* Transpose quantization tables */ 1348 for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { 1349 qtblptr = dstinfo->quant_tbl_ptrs[tblno]; 1350 if (qtblptr != NULL) { 1351 for (i = 0; i < DCTSIZE; i++) { 1352 for (j = 0; j < i; j++) { 1353 qtemp = qtblptr->quantval[i*DCTSIZE+j]; 1354 qtblptr->quantval[i*DCTSIZE+j] = qtblptr->quantval[j*DCTSIZE+i]; 1355 qtblptr->quantval[j*DCTSIZE+i] = qtemp; 1356 } 1357 } 1358 } 1359 } 1360 } 1361 1362 1363 /* Adjust Exif image parameters. 1364 * 1365 * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible. 1366 */ 1367 1368 LOCAL(void) 1369 adjust_exif_parameters (JOCTET FAR * data, unsigned int length, 1370 JDIMENSION new_width, JDIMENSION new_height) 1371 { 1372 boolean is_motorola; /* Flag for byte order */ 1373 unsigned int number_of_tags, tagnum; 1374 unsigned int firstoffset, offset; 1375 JDIMENSION new_value; 1376 1377 if (length < 12) return; /* Length of an IFD entry */ 1378 1379 /* Discover byte order */ 1380 if (GETJOCTET(data[0]) == 0x49 && GETJOCTET(data[1]) == 0x49) 1381 is_motorola = FALSE; 1382 else if (GETJOCTET(data[0]) == 0x4D && GETJOCTET(data[1]) == 0x4D) 1383 is_motorola = TRUE; 1384 else 1385 return; 1386 1387 /* Check Tag Mark */ 1388 if (is_motorola) { 1389 if (GETJOCTET(data[2]) != 0) return; 1390 if (GETJOCTET(data[3]) != 0x2A) return; 1391 } else { 1392 if (GETJOCTET(data[3]) != 0) return; 1393 if (GETJOCTET(data[2]) != 0x2A) return; 1394 } 1395 1396 /* Get first IFD offset (offset to IFD0) */ 1397 if (is_motorola) { 1398 if (GETJOCTET(data[4]) != 0) return; 1399 if (GETJOCTET(data[5]) != 0) return; 1400 firstoffset = GETJOCTET(data[6]); 1401 firstoffset <<= 8; 1402 firstoffset += GETJOCTET(data[7]); 1403 } else { 1404 if (GETJOCTET(data[7]) != 0) return; 1405 if (GETJOCTET(data[6]) != 0) return; 1406 firstoffset = GETJOCTET(data[5]); 1407 firstoffset <<= 8; 1408 firstoffset += GETJOCTET(data[4]); 1409 } 1410 if (firstoffset > length - 2) return; /* check end of data segment */ 1411 1412 /* Get the number of directory entries contained in this IFD */ 1413 if (is_motorola) { 1414 number_of_tags = GETJOCTET(data[firstoffset]); 1415 number_of_tags <<= 8; 1416 number_of_tags += GETJOCTET(data[firstoffset+1]); 1417 } else { 1418 number_of_tags = GETJOCTET(data[firstoffset+1]); 1419 number_of_tags <<= 8; 1420 number_of_tags += GETJOCTET(data[firstoffset]); 1421 } 1422 if (number_of_tags == 0) return; 1423 firstoffset += 2; 1424 1425 /* Search for ExifSubIFD offset Tag in IFD0 */ 1426 for (;;) { 1427 if (firstoffset > length - 12) return; /* check end of data segment */ 1428 /* Get Tag number */ 1429 if (is_motorola) { 1430 tagnum = GETJOCTET(data[firstoffset]); 1431 tagnum <<= 8; 1432 tagnum += GETJOCTET(data[firstoffset+1]); 1433 } else { 1434 tagnum = GETJOCTET(data[firstoffset+1]); 1435 tagnum <<= 8; 1436 tagnum += GETJOCTET(data[firstoffset]); 1437 } 1438 if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */ 1439 if (--number_of_tags == 0) return; 1440 firstoffset += 12; 1441 } 1442 1443 /* Get the ExifSubIFD offset */ 1444 if (is_motorola) { 1445 if (GETJOCTET(data[firstoffset+8]) != 0) return; 1446 if (GETJOCTET(data[firstoffset+9]) != 0) return; 1447 offset = GETJOCTET(data[firstoffset+10]); 1448 offset <<= 8; 1449 offset += GETJOCTET(data[firstoffset+11]); 1450 } else { 1451 if (GETJOCTET(data[firstoffset+11]) != 0) return; 1452 if (GETJOCTET(data[firstoffset+10]) != 0) return; 1453 offset = GETJOCTET(data[firstoffset+9]); 1454 offset <<= 8; 1455 offset += GETJOCTET(data[firstoffset+8]); 1456 } 1457 if (offset > length - 2) return; /* check end of data segment */ 1458 1459 /* Get the number of directory entries contained in this SubIFD */ 1460 if (is_motorola) { 1461 number_of_tags = GETJOCTET(data[offset]); 1462 number_of_tags <<= 8; 1463 number_of_tags += GETJOCTET(data[offset+1]); 1464 } else { 1465 number_of_tags = GETJOCTET(data[offset+1]); 1466 number_of_tags <<= 8; 1467 number_of_tags += GETJOCTET(data[offset]); 1468 } 1469 if (number_of_tags < 2) return; 1470 offset += 2; 1471 1472 /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */ 1473 do { 1474 if (offset > length - 12) return; /* check end of data segment */ 1475 /* Get Tag number */ 1476 if (is_motorola) { 1477 tagnum = GETJOCTET(data[offset]); 1478 tagnum <<= 8; 1479 tagnum += GETJOCTET(data[offset+1]); 1480 } else { 1481 tagnum = GETJOCTET(data[offset+1]); 1482 tagnum <<= 8; 1483 tagnum += GETJOCTET(data[offset]); 1484 } 1485 if (tagnum == 0xA002 || tagnum == 0xA003) { 1486 if (tagnum == 0xA002) 1487 new_value = new_width; /* ExifImageWidth Tag */ 1488 else 1489 new_value = new_height; /* ExifImageHeight Tag */ 1490 if (is_motorola) { 1491 data[offset+2] = 0; /* Format = unsigned long (4 octets) */ 1492 data[offset+3] = 4; 1493 data[offset+4] = 0; /* Number Of Components = 1 */ 1494 data[offset+5] = 0; 1495 data[offset+6] = 0; 1496 data[offset+7] = 1; 1497 data[offset+8] = 0; 1498 data[offset+9] = 0; 1499 data[offset+10] = (JOCTET)((new_value >> 8) & 0xFF); 1500 data[offset+11] = (JOCTET)(new_value & 0xFF); 1501 } else { 1502 data[offset+2] = 4; /* Format = unsigned long (4 octets) */ 1503 data[offset+3] = 0; 1504 data[offset+4] = 1; /* Number Of Components = 1 */ 1505 data[offset+5] = 0; 1506 data[offset+6] = 0; 1507 data[offset+7] = 0; 1508 data[offset+8] = (JOCTET)(new_value & 0xFF); 1509 data[offset+9] = (JOCTET)((new_value >> 8) & 0xFF); 1510 data[offset+10] = 0; 1511 data[offset+11] = 0; 1512 } 1513 } 1514 offset += 12; 1515 } while (--number_of_tags); 1516 } 1517 1518 1519 /* Adjust output image parameters as needed. 1520 * 1521 * This must be called after jpeg_copy_critical_parameters() 1522 * and before jpeg_write_coefficients(). 1523 * 1524 * The return value is the set of virtual coefficient arrays to be written 1525 * (either the ones allocated by jtransform_request_workspace, or the 1526 * original source data arrays). The caller will need to pass this value 1527 * to jpeg_write_coefficients(). 1528 */ 1529 1530 GLOBAL(jvirt_barray_ptr *) 1531 jtransform_adjust_parameters (j_decompress_ptr srcinfo, 1532 j_compress_ptr dstinfo, 1533 jvirt_barray_ptr *src_coef_arrays, 1534 jpeg_transform_info *info) 1535 { 1536 /* If force-to-grayscale is requested, adjust destination parameters */ 1537 if (info->force_grayscale) { 1538 /* First, ensure we have YCC or grayscale data, and that the source's 1539 * Y channel is full resolution. (No reasonable person would make Y 1540 * be less than full resolution, so actually coping with that case 1541 * isn't worth extra code space. But we check it to avoid crashing.) 1542 */ 1543 if ((((dstinfo->jpeg_color_space == JCS_YCbCr || 1544 dstinfo->jpeg_color_space == JCS_BG_YCC) && 1545 dstinfo->num_components == 3) || 1546 (dstinfo->jpeg_color_space == JCS_GRAYSCALE && 1547 dstinfo->num_components == 1)) && 1548 srcinfo->comp_info[0].h_samp_factor == srcinfo->max_h_samp_factor && 1549 srcinfo->comp_info[0].v_samp_factor == srcinfo->max_v_samp_factor) { 1550 /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed 1551 * properly. Among other things, it sets the target h_samp_factor & 1552 * v_samp_factor to 1, which typically won't match the source. 1553 * We have to preserve the source's quantization table number, however. 1554 */ 1555 int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no; 1556 jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE); 1557 dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no; 1558 } else { 1559 /* Sorry, can't do it */ 1560 ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL); 1561 } 1562 } else if (info->num_components == 1) { 1563 /* For a single-component source, we force the destination sampling factors 1564 * to 1x1, with or without force_grayscale. This is useful because some 1565 * decoders choke on grayscale images with other sampling factors. 1566 */ 1567 dstinfo->comp_info[0].h_samp_factor = 1; 1568 dstinfo->comp_info[0].v_samp_factor = 1; 1569 } 1570 1571 /* Correct the destination's image dimensions as necessary 1572 * for rotate/flip, resize, and crop operations. 1573 */ 1574 dstinfo->jpeg_width = info->output_width; 1575 dstinfo->jpeg_height = info->output_height; 1576 1577 /* Transpose destination image parameters */ 1578 switch (info->transform) { 1579 case JXFORM_TRANSPOSE: 1580 case JXFORM_TRANSVERSE: 1581 case JXFORM_ROT_90: 1582 case JXFORM_ROT_270: 1583 transpose_critical_parameters(dstinfo); 1584 break; 1585 default: 1586 break; 1587 } 1588 1589 /* Adjust Exif properties */ 1590 if (srcinfo->marker_list != NULL && 1591 srcinfo->marker_list->marker == JPEG_APP0+1 && 1592 srcinfo->marker_list->data_length >= 6 && 1593 GETJOCTET(srcinfo->marker_list->data[0]) == 0x45 && 1594 GETJOCTET(srcinfo->marker_list->data[1]) == 0x78 && 1595 GETJOCTET(srcinfo->marker_list->data[2]) == 0x69 && 1596 GETJOCTET(srcinfo->marker_list->data[3]) == 0x66 && 1597 GETJOCTET(srcinfo->marker_list->data[4]) == 0 && 1598 GETJOCTET(srcinfo->marker_list->data[5]) == 0) { 1599 /* Suppress output of JFIF marker */ 1600 dstinfo->write_JFIF_header = FALSE; 1601 /* Adjust Exif image parameters */ 1602 if (dstinfo->jpeg_width != srcinfo->image_width || 1603 dstinfo->jpeg_height != srcinfo->image_height) 1604 /* Align data segment to start of TIFF structure for parsing */ 1605 adjust_exif_parameters(srcinfo->marker_list->data + 6, 1606 srcinfo->marker_list->data_length - 6, 1607 dstinfo->jpeg_width, dstinfo->jpeg_height); 1608 } 1609 1610 /* Return the appropriate output data set */ 1611 if (info->workspace_coef_arrays != NULL) 1612 return info->workspace_coef_arrays; 1613 return src_coef_arrays; 1614 } 1615 1616 1617 /* Execute the actual transformation, if any. 1618 * 1619 * This must be called *after* jpeg_write_coefficients, because it depends 1620 * on jpeg_write_coefficients to have computed subsidiary values such as 1621 * the per-component width and height fields in the destination object. 1622 * 1623 * Note that some transformations will modify the source data arrays! 1624 */ 1625 1626 GLOBAL(void) 1627 jtransform_execute_transform (j_decompress_ptr srcinfo, 1628 j_compress_ptr dstinfo, 1629 jvirt_barray_ptr *src_coef_arrays, 1630 jpeg_transform_info *info) 1631 { 1632 jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays; 1633 1634 /* Note: conditions tested here should match those in switch statement 1635 * in jtransform_request_workspace() 1636 */ 1637 switch (info->transform) { 1638 case JXFORM_NONE: 1639 if (info->output_width > srcinfo->output_width || 1640 info->output_height > srcinfo->output_height) 1641 do_crop_ext(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1642 src_coef_arrays, dst_coef_arrays); 1643 else if (info->x_crop_offset != 0 || info->y_crop_offset != 0) 1644 do_crop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1645 src_coef_arrays, dst_coef_arrays); 1646 break; 1647 case JXFORM_FLIP_H: 1648 if (info->y_crop_offset != 0) 1649 do_flip_h(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1650 src_coef_arrays, dst_coef_arrays); 1651 else 1652 do_flip_h_no_crop(srcinfo, dstinfo, info->x_crop_offset, 1653 src_coef_arrays); 1654 break; 1655 case JXFORM_FLIP_V: 1656 do_flip_v(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1657 src_coef_arrays, dst_coef_arrays); 1658 break; 1659 case JXFORM_TRANSPOSE: 1660 do_transpose(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1661 src_coef_arrays, dst_coef_arrays); 1662 break; 1663 case JXFORM_TRANSVERSE: 1664 do_transverse(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1665 src_coef_arrays, dst_coef_arrays); 1666 break; 1667 case JXFORM_ROT_90: 1668 do_rot_90(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1669 src_coef_arrays, dst_coef_arrays); 1670 break; 1671 case JXFORM_ROT_180: 1672 do_rot_180(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1673 src_coef_arrays, dst_coef_arrays); 1674 break; 1675 case JXFORM_ROT_270: 1676 do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1677 src_coef_arrays, dst_coef_arrays); 1678 break; 1679 case JXFORM_WIPE: 1680 if (info->crop_width_set != JCROP_FORCE) 1681 do_wipe(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1682 src_coef_arrays, info->drop_width, info->drop_height); 1683 else 1684 do_flatten(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1685 src_coef_arrays, info->drop_width, info->drop_height); 1686 break; 1687 } 1688 } 1689 1690 /* jtransform_perfect_transform 1691 * 1692 * Determine whether lossless transformation is perfectly 1693 * possible for a specified image and transformation. 1694 * 1695 * Inputs: 1696 * image_width, image_height: source image dimensions. 1697 * MCU_width, MCU_height: pixel dimensions of MCU. 1698 * transform: transformation identifier. 1699 * Parameter sources from initialized jpeg_struct 1700 * (after reading source header): 1701 * image_width = cinfo.image_width 1702 * image_height = cinfo.image_height 1703 * MCU_width = cinfo.max_h_samp_factor * cinfo.block_size 1704 * MCU_height = cinfo.max_v_samp_factor * cinfo.block_size 1705 * Result: 1706 * TRUE = perfect transformation possible 1707 * FALSE = perfect transformation not possible 1708 * (may use custom action then) 1709 */ 1710 1711 GLOBAL(boolean) 1712 jtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height, 1713 int MCU_width, int MCU_height, 1714 JXFORM_CODE transform) 1715 { 1716 boolean result = TRUE; /* initialize TRUE */ 1717 1718 switch (transform) { 1719 case JXFORM_FLIP_H: 1720 case JXFORM_ROT_270: 1721 if (image_width % (JDIMENSION) MCU_width) 1722 result = FALSE; 1723 break; 1724 case JXFORM_FLIP_V: 1725 case JXFORM_ROT_90: 1726 if (image_height % (JDIMENSION) MCU_height) 1727 result = FALSE; 1728 break; 1729 case JXFORM_TRANSVERSE: 1730 case JXFORM_ROT_180: 1731 if (image_width % (JDIMENSION) MCU_width) 1732 result = FALSE; 1733 if (image_height % (JDIMENSION) MCU_height) 1734 result = FALSE; 1735 break; 1736 default: 1737 break; 1738 } 1739 1740 return result; 1741 } 1742 1743 #endif /* TRANSFORMS_SUPPORTED */ 1744 1745 1746 /* Setup decompression object to save desired markers in memory. 1747 * This must be called before jpeg_read_header() to have the desired effect. 1748 */ 1749 1750 GLOBAL(void) 1751 jcopy_markers_setup (j_decompress_ptr srcinfo, JCOPY_OPTION option) 1752 { 1753 #ifdef SAVE_MARKERS_SUPPORTED 1754 int m; 1755 1756 /* Save comments except under NONE option */ 1757 if (option != JCOPYOPT_NONE) { 1758 jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF); 1759 } 1760 /* Save all types of APPn markers iff ALL option */ 1761 if (option == JCOPYOPT_ALL) { 1762 for (m = 0; m < 16; m++) 1763 jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF); 1764 } 1765 #endif /* SAVE_MARKERS_SUPPORTED */ 1766 } 1767 1768 /* Copy markers saved in the given source object to the destination object. 1769 * This should be called just after jpeg_start_compress() or 1770 * jpeg_write_coefficients(). 1771 * Note that those routines will have written the SOI, and also the 1772 * JFIF APP0 or Adobe APP14 markers if selected. 1773 */ 1774 1775 GLOBAL(void) 1776 jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 1777 JCOPY_OPTION option) 1778 { 1779 jpeg_saved_marker_ptr marker; 1780 1781 /* In the current implementation, we don't actually need to examine the 1782 * option flag here; we just copy everything that got saved. 1783 * But to avoid confusion, we do not output JFIF and Adobe APP14 markers 1784 * if the encoder library already wrote one. 1785 */ 1786 for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) { 1787 if (dstinfo->write_JFIF_header && 1788 marker->marker == JPEG_APP0 && 1789 marker->data_length >= 5 && 1790 GETJOCTET(marker->data[0]) == 0x4A && 1791 GETJOCTET(marker->data[1]) == 0x46 && 1792 GETJOCTET(marker->data[2]) == 0x49 && 1793 GETJOCTET(marker->data[3]) == 0x46 && 1794 GETJOCTET(marker->data[4]) == 0) 1795 continue; /* reject duplicate JFIF */ 1796 if (dstinfo->write_Adobe_marker && 1797 marker->marker == JPEG_APP0+14 && 1798 marker->data_length >= 5 && 1799 GETJOCTET(marker->data[0]) == 0x41 && 1800 GETJOCTET(marker->data[1]) == 0x64 && 1801 GETJOCTET(marker->data[2]) == 0x6F && 1802 GETJOCTET(marker->data[3]) == 0x62 && 1803 GETJOCTET(marker->data[4]) == 0x65) 1804 continue; /* reject duplicate Adobe */ 1805 #ifdef NEED_FAR_POINTERS 1806 /* We could use jpeg_write_marker if the data weren't FAR... */ 1807 { 1808 unsigned int i; 1809 jpeg_write_m_header(dstinfo, marker->marker, marker->data_length); 1810 for (i = 0; i < marker->data_length; i++) 1811 jpeg_write_m_byte(dstinfo, marker->data[i]); 1812 } 1813 #else 1814 jpeg_write_marker(dstinfo, marker->marker, 1815 marker->data, marker->data_length); 1816 #endif 1817 } 1818 } 1819