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