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