1 /* 2 * transupp.c 3 * 4 * Copyright (C) 1997-2019, Thomas G. Lane, Guido Vollbeding. 5 * This file is part of the Independent JPEG Group's software. 6 * For conditions of distribution and use, see the accompanying README file. 7 * 8 * This file contains image transformation routines and other utility code 9 * used by the jpegtran sample application. These are NOT part of the core 10 * JPEG library. But we keep these routines separate from jpegtran.c to 11 * ease the task of maintaining jpegtran-like programs that have other user 12 * interfaces. 13 */ 14 15 /* Although this file really shouldn't have access to the library internals, 16 * it's helpful to let it call jround_up() and jcopy_block_row(). 17 * Also, the (switchable) virtual memory adaptation code for 18 * the drop feature has dependencies on library internals. 19 */ 20 #define JPEG_INTERNALS 21 22 #include "jinclude.h" 23 #include "jpeglib.h" 24 #include "transupp.h" /* My own external interface */ 25 #include <ctype.h> /* to declare isdigit() */ 26 27 28 #if TRANSFORMS_SUPPORTED 29 30 /* 31 * Lossless image transformation routines. These routines work on DCT 32 * coefficient arrays and thus do not require any lossy decompression 33 * or recompression of the image. 34 * Thanks to Guido Vollbeding for the initial design and code of this feature, 35 * and to Ben Jackson for introducing the cropping feature. 36 * 37 * Horizontal flipping is done in-place, using a single top-to-bottom 38 * pass through the virtual source array. It will thus be much the 39 * fastest option for images larger than main memory. 40 * 41 * The other routines require a set of destination virtual arrays, so they 42 * need twice as much memory as jpegtran normally does. The destination 43 * arrays are always written in normal scan order (top to bottom) because 44 * the virtual array manager expects this. The source arrays will be scanned 45 * in the corresponding order, which means multiple passes through the source 46 * arrays for most of the transforms. That could result in much thrashing 47 * if the image is larger than main memory. 48 * 49 * If cropping or trimming is involved, the destination arrays may be smaller 50 * than the source arrays. Note it is not possible to do horizontal flip 51 * in-place when a nonzero Y crop offset is specified, since we'd have to move 52 * data from one block row to another but the virtual array manager doesn't 53 * guarantee we can touch more than one row at a time. So in that case, 54 * we have to use a separate destination array. 55 * 56 * Some notes about the operating environment of the individual transform 57 * routines: 58 * 1. Both the source and destination virtual arrays are allocated from the 59 * source JPEG object, and therefore should be manipulated by calling the 60 * source's memory manager. 61 * 2. The destination's component count should be used. It may be smaller 62 * than the source's when forcing to grayscale. 63 * 3. Likewise the destination's sampling factors should be used. When 64 * forcing to grayscale the destination's sampling factors will be all 1, 65 * and we may as well take that as the effective iMCU size. 66 * 4. When "trim" is in effect, the destination's dimensions will be the 67 * trimmed values but the source's will be untrimmed. 68 * 5. When "crop" is in effect, the destination's dimensions will be the 69 * cropped values but the source's will be uncropped. Each transform 70 * routine is responsible for picking up source data starting at the 71 * correct X and Y offset for the crop region. (The X and Y offsets 72 * passed to the transform routines are measured in iMCU blocks of the 73 * destination.) 74 * 6. All the routines assume that the source and destination buffers are 75 * padded out to a full iMCU boundary. This is true, although for the 76 * source buffer it is an undocumented property of jdcoefct.c. 77 */ 78 79 80 /* Drop code may be used with or without virtual memory adaptation code. 81 * This code has some dependencies on internal library behavior, so you 82 * may choose to disable it. For example, it doesn't make a difference 83 * if you only use jmemnobs anyway. 84 */ 85 #ifndef DROP_REQUEST_FROM_SRC 86 #define DROP_REQUEST_FROM_SRC 1 /* 0 disables adaptation */ 87 #endif 88 89 90 #if DROP_REQUEST_FROM_SRC 91 /* Force jpeg_read_coefficients to request 92 * the virtual coefficient arrays from 93 * the source decompression object. 94 */ 95 METHODDEF(jvirt_barray_ptr) 96 drop_request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero, 97 JDIMENSION blocksperrow, JDIMENSION numrows, 98 JDIMENSION maxaccess) 99 { 100 j_common_ptr srcinfo = (j_common_ptr) cinfo->client_data; 101 102 return (*srcinfo->mem->request_virt_barray) 103 (srcinfo, pool_id, pre_zero, 104 blocksperrow, numrows, maxaccess); 105 } 106 107 108 /* Force jpeg_read_coefficients to return 109 * after requesting and before accessing 110 * the virtual coefficient arrays. 111 */ 112 METHODDEF(int) 113 drop_consume_input (j_decompress_ptr cinfo) 114 { 115 return JPEG_SUSPENDED; 116 } 117 118 119 METHODDEF(void) 120 drop_start_input_pass (j_decompress_ptr cinfo) 121 { 122 cinfo->inputctl->consume_input = drop_consume_input; 123 } 124 125 126 LOCAL(void) 127 drop_request_from_src (j_decompress_ptr dropinfo, j_decompress_ptr srcinfo) 128 { 129 void *save_client_data; 130 JMETHOD(jvirt_barray_ptr, save_request_virt_barray, 131 (j_common_ptr cinfo, int pool_id, boolean pre_zero, 132 JDIMENSION blocksperrow, JDIMENSION numrows, JDIMENSION maxaccess)); 133 JMETHOD(void, save_start_input_pass, (j_decompress_ptr cinfo)); 134 135 /* Set custom method pointers, save original pointers */ 136 save_client_data = dropinfo->client_data; 137 dropinfo->client_data = (void *) srcinfo; 138 save_request_virt_barray = dropinfo->mem->request_virt_barray; 139 dropinfo->mem->request_virt_barray = drop_request_virt_barray; 140 save_start_input_pass = dropinfo->inputctl->start_input_pass; 141 dropinfo->inputctl->start_input_pass = drop_start_input_pass; 142 143 /* Execute only initialization part. 144 * Requested coefficient arrays will be realized later by the srcinfo object. 145 * Next call to the same function will then do the actual data reading. 146 * NB: since we request the coefficient arrays from another object, 147 * the inherent realization call is effectively a no-op. 148 */ 149 (void) jpeg_read_coefficients(dropinfo); 150 151 /* Reset method pointers */ 152 dropinfo->client_data = save_client_data; 153 dropinfo->mem->request_virt_barray = save_request_virt_barray; 154 dropinfo->inputctl->start_input_pass = save_start_input_pass; 155 /* Do input initialization for first scan now, 156 * which also resets the consume_input method. 157 */ 158 (*save_start_input_pass)(dropinfo); 159 } 160 #endif /* DROP_REQUEST_FROM_SRC */ 161 162 163 LOCAL(void) 164 dequant_comp (j_decompress_ptr cinfo, jpeg_component_info *compptr, 165 jvirt_barray_ptr coef_array, JQUANT_TBL *qtblptr1) 166 { 167 JDIMENSION blk_x, blk_y; 168 int offset_y, k; 169 JQUANT_TBL *qtblptr; 170 JBLOCKARRAY buffer; 171 JBLOCKROW block; 172 JCOEFPTR ptr; 173 174 qtblptr = compptr->quant_table; 175 for (blk_y = 0; blk_y < compptr->height_in_blocks; 176 blk_y += compptr->v_samp_factor) { 177 buffer = (*cinfo->mem->access_virt_barray) 178 ((j_common_ptr) cinfo, coef_array, blk_y, 179 (JDIMENSION) compptr->v_samp_factor, TRUE); 180 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 181 block = buffer[offset_y]; 182 for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) { 183 ptr = block[blk_x]; 184 for (k = 0; k < DCTSIZE2; k++) 185 if (qtblptr->quantval[k] != qtblptr1->quantval[k]) 186 ptr[k] *= qtblptr->quantval[k] / qtblptr1->quantval[k]; 187 } 188 } 189 } 190 } 191 192 193 LOCAL(void) 194 requant_comp (j_decompress_ptr cinfo, jpeg_component_info *compptr, 195 jvirt_barray_ptr coef_array, JQUANT_TBL *qtblptr1) 196 { 197 JDIMENSION blk_x, blk_y; 198 int offset_y, k; 199 JQUANT_TBL *qtblptr; 200 JBLOCKARRAY buffer; 201 JBLOCKROW block; 202 JCOEFPTR ptr; 203 JCOEF temp, qval; 204 205 qtblptr = compptr->quant_table; 206 for (blk_y = 0; blk_y < compptr->height_in_blocks; 207 blk_y += compptr->v_samp_factor) { 208 buffer = (*cinfo->mem->access_virt_barray) 209 ((j_common_ptr) cinfo, coef_array, blk_y, 210 (JDIMENSION) compptr->v_samp_factor, TRUE); 211 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 212 block = buffer[offset_y]; 213 for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) { 214 ptr = block[blk_x]; 215 for (k = 0; k < DCTSIZE2; k++) { 216 temp = qtblptr->quantval[k]; 217 qval = qtblptr1->quantval[k]; 218 if (temp != qval) { 219 temp *= ptr[k]; 220 /* The following quantization code is a copy from jcdctmgr.c */ 221 #ifdef FAST_DIVIDE 222 #define DIVIDE_BY(a,b) a /= b 223 #else 224 #define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0 225 #endif 226 if (temp < 0) { 227 temp = -temp; 228 temp += qval>>1; /* for rounding */ 229 DIVIDE_BY(temp, qval); 230 temp = -temp; 231 } else { 232 temp += qval>>1; /* for rounding */ 233 DIVIDE_BY(temp, qval); 234 } 235 ptr[k] = temp; 236 } 237 } 238 } 239 } 240 } 241 } 242 243 244 /* Calculate largest common denominator with Euclid's algorithm. 245 */ 246 LOCAL(JCOEF) 247 largest_common_denominator(JCOEF a, JCOEF b) 248 { 249 JCOEF c; 250 251 do { 252 c = a % b; 253 a = b; 254 b = c; 255 } while (c); 256 257 return a; 258 } 259 260 261 LOCAL(void) 262 adjust_quant(j_decompress_ptr srcinfo, jvirt_barray_ptr *src_coef_arrays, 263 j_decompress_ptr dropinfo, jvirt_barray_ptr *drop_coef_arrays, 264 boolean trim, j_compress_ptr dstinfo) 265 { 266 jpeg_component_info *compptr1, *compptr2; 267 JQUANT_TBL *qtblptr1, *qtblptr2, *qtblptr3; 268 int ci, k; 269 270 for (ci = 0; ci < dstinfo->num_components && 271 ci < dropinfo->num_components; ci++) { 272 compptr1 = srcinfo->comp_info + ci; 273 compptr2 = dropinfo->comp_info + ci; 274 qtblptr1 = compptr1->quant_table; 275 qtblptr2 = compptr2->quant_table; 276 for (k = 0; k < DCTSIZE2; k++) { 277 if (qtblptr1->quantval[k] != qtblptr2->quantval[k]) { 278 if (trim) 279 requant_comp(dropinfo, compptr2, drop_coef_arrays[ci], qtblptr1); 280 else { 281 qtblptr3 = dstinfo->quant_tbl_ptrs[compptr1->quant_tbl_no]; 282 for (k = 0; k < DCTSIZE2; k++) 283 if (qtblptr1->quantval[k] != qtblptr2->quantval[k]) 284 qtblptr3->quantval[k] = largest_common_denominator 285 (qtblptr1->quantval[k], qtblptr2->quantval[k]); 286 dequant_comp(srcinfo, compptr1, src_coef_arrays[ci], qtblptr3); 287 dequant_comp(dropinfo, compptr2, drop_coef_arrays[ci], qtblptr3); 288 } 289 break; 290 } 291 } 292 } 293 } 294 295 296 LOCAL(void) 297 do_drop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 298 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 299 jvirt_barray_ptr *src_coef_arrays, 300 j_decompress_ptr dropinfo, jvirt_barray_ptr *drop_coef_arrays, 301 JDIMENSION drop_width, JDIMENSION drop_height) 302 /* Drop. If the dropinfo component number is smaller than the destination's, 303 * we fill in the remaining components with zero. This provides the feature 304 * of dropping grayscale into (arbitrarily sampled) color images. 305 */ 306 { 307 JDIMENSION comp_width, comp_height; 308 JDIMENSION blk_y, x_drop_blocks, y_drop_blocks; 309 int ci, offset_y; 310 JBLOCKARRAY src_buffer, dst_buffer; 311 jpeg_component_info *compptr; 312 313 for (ci = 0; ci < dstinfo->num_components; ci++) { 314 compptr = dstinfo->comp_info + ci; 315 comp_width = drop_width * compptr->h_samp_factor; 316 comp_height = drop_height * compptr->v_samp_factor; 317 x_drop_blocks = x_crop_offset * compptr->h_samp_factor; 318 y_drop_blocks = y_crop_offset * compptr->v_samp_factor; 319 for (blk_y = 0; blk_y < comp_height; blk_y += compptr->v_samp_factor) { 320 dst_buffer = (*srcinfo->mem->access_virt_barray) 321 ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y + y_drop_blocks, 322 (JDIMENSION) compptr->v_samp_factor, TRUE); 323 if (ci < dropinfo->num_components) { 324 #if DROP_REQUEST_FROM_SRC 325 src_buffer = (*srcinfo->mem->access_virt_barray) 326 ((j_common_ptr) srcinfo, drop_coef_arrays[ci], blk_y, 327 #else 328 src_buffer = (*dropinfo->mem->access_virt_barray) 329 ((j_common_ptr) dropinfo, drop_coef_arrays[ci], blk_y, 330 #endif 331 (JDIMENSION) compptr->v_samp_factor, FALSE); 332 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 333 jcopy_block_row(src_buffer[offset_y], 334 dst_buffer[offset_y] + x_drop_blocks, 335 comp_width); 336 } 337 } else { 338 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 339 FMEMZERO(dst_buffer[offset_y] + x_drop_blocks, 340 comp_width * SIZEOF(JBLOCK)); 341 } 342 } 343 } 344 } 345 } 346 347 348 LOCAL(void) 349 do_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 350 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 351 jvirt_barray_ptr *src_coef_arrays, 352 jvirt_barray_ptr *dst_coef_arrays) 353 /* Crop. This is only used when no rotate/flip is requested with the crop. */ 354 { 355 JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks; 356 int ci, offset_y; 357 JBLOCKARRAY src_buffer, dst_buffer; 358 jpeg_component_info *compptr; 359 360 /* We simply have to copy the right amount of data (the destination's 361 * image size) starting at the given X and Y offsets in the source. 362 */ 363 for (ci = 0; ci < dstinfo->num_components; ci++) { 364 compptr = dstinfo->comp_info + ci; 365 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 366 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 367 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 368 dst_blk_y += compptr->v_samp_factor) { 369 dst_buffer = (*srcinfo->mem->access_virt_barray) 370 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 371 (JDIMENSION) compptr->v_samp_factor, TRUE); 372 src_buffer = (*srcinfo->mem->access_virt_barray) 373 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 374 dst_blk_y + y_crop_blocks, 375 (JDIMENSION) compptr->v_samp_factor, FALSE); 376 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 377 jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, 378 dst_buffer[offset_y], 379 compptr->width_in_blocks); 380 } 381 } 382 } 383 } 384 385 386 LOCAL(void) 387 do_crop_ext_zero (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 /* Crop. This is only used when no rotate/flip is requested with the crop. 392 * Extension: If the destination size is larger than the source, we fill in 393 * the extra area with zero (neutral gray). Note we also have to zero partial 394 * iMCUs at the right and bottom edge of the source image area in this case. 395 */ 396 { 397 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height; 398 JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks; 399 int ci, offset_y; 400 JBLOCKARRAY src_buffer, dst_buffer; 401 jpeg_component_info *compptr; 402 403 MCU_cols = srcinfo->output_width / 404 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); 405 MCU_rows = srcinfo->output_height / 406 (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); 407 408 for (ci = 0; ci < dstinfo->num_components; ci++) { 409 compptr = dstinfo->comp_info + ci; 410 comp_width = MCU_cols * compptr->h_samp_factor; 411 comp_height = MCU_rows * compptr->v_samp_factor; 412 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 413 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 414 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 415 dst_blk_y += compptr->v_samp_factor) { 416 dst_buffer = (*srcinfo->mem->access_virt_barray) 417 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 418 (JDIMENSION) compptr->v_samp_factor, TRUE); 419 if (dstinfo->jpeg_height > srcinfo->output_height) { 420 if (dst_blk_y < y_crop_blocks || 421 dst_blk_y >= y_crop_blocks + comp_height) { 422 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 423 FMEMZERO(dst_buffer[offset_y], 424 compptr->width_in_blocks * SIZEOF(JBLOCK)); 425 } 426 continue; 427 } 428 src_buffer = (*srcinfo->mem->access_virt_barray) 429 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 430 dst_blk_y - y_crop_blocks, 431 (JDIMENSION) compptr->v_samp_factor, FALSE); 432 } else { 433 src_buffer = (*srcinfo->mem->access_virt_barray) 434 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 435 dst_blk_y + y_crop_blocks, 436 (JDIMENSION) compptr->v_samp_factor, FALSE); 437 } 438 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 439 if (dstinfo->jpeg_width > srcinfo->output_width) { 440 if (x_crop_blocks > 0) { 441 FMEMZERO(dst_buffer[offset_y], 442 x_crop_blocks * SIZEOF(JBLOCK)); 443 } 444 jcopy_block_row(src_buffer[offset_y], 445 dst_buffer[offset_y] + x_crop_blocks, 446 comp_width); 447 if (compptr->width_in_blocks > x_crop_blocks + comp_width) { 448 FMEMZERO(dst_buffer[offset_y] + 449 x_crop_blocks + comp_width, 450 (compptr->width_in_blocks - 451 x_crop_blocks - comp_width) * SIZEOF(JBLOCK)); 452 } 453 } else { 454 jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, 455 dst_buffer[offset_y], 456 compptr->width_in_blocks); 457 } 458 } 459 } 460 } 461 } 462 463 464 LOCAL(void) 465 do_crop_ext_flat (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 466 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 467 jvirt_barray_ptr *src_coef_arrays, 468 jvirt_barray_ptr *dst_coef_arrays) 469 /* Crop. This is only used when no rotate/flip is requested with the crop. 470 * Extension: The destination width is larger than the source and we fill in 471 * the extra area with the DC of the adjacent block. Note we also have to 472 * fill partial iMCUs at the right and bottom edge of the source image area 473 * in this case. 474 */ 475 { 476 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height; 477 JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks; 478 int ci, offset_y; 479 JCOEF dc; 480 JBLOCKARRAY src_buffer, dst_buffer; 481 jpeg_component_info *compptr; 482 483 MCU_cols = srcinfo->output_width / 484 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); 485 MCU_rows = srcinfo->output_height / 486 (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); 487 488 for (ci = 0; ci < dstinfo->num_components; ci++) { 489 compptr = dstinfo->comp_info + ci; 490 comp_width = MCU_cols * compptr->h_samp_factor; 491 comp_height = MCU_rows * compptr->v_samp_factor; 492 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 493 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 494 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 495 dst_blk_y += compptr->v_samp_factor) { 496 dst_buffer = (*srcinfo->mem->access_virt_barray) 497 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 498 (JDIMENSION) compptr->v_samp_factor, TRUE); 499 if (dstinfo->jpeg_height > srcinfo->output_height) { 500 if (dst_blk_y < y_crop_blocks || 501 dst_blk_y >= y_crop_blocks + comp_height) { 502 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 503 FMEMZERO(dst_buffer[offset_y], 504 compptr->width_in_blocks * SIZEOF(JBLOCK)); 505 } 506 continue; 507 } 508 src_buffer = (*srcinfo->mem->access_virt_barray) 509 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 510 dst_blk_y - y_crop_blocks, 511 (JDIMENSION) compptr->v_samp_factor, FALSE); 512 } else { 513 src_buffer = (*srcinfo->mem->access_virt_barray) 514 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 515 dst_blk_y + y_crop_blocks, 516 (JDIMENSION) compptr->v_samp_factor, FALSE); 517 } 518 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 519 if (x_crop_blocks > 0) { 520 FMEMZERO(dst_buffer[offset_y], 521 x_crop_blocks * SIZEOF(JBLOCK)); 522 dc = src_buffer[offset_y][0][0]; 523 for (dst_blk_x = 0; dst_blk_x < x_crop_blocks; dst_blk_x++) { 524 dst_buffer[offset_y][dst_blk_x][0] = dc; 525 } 526 } 527 jcopy_block_row(src_buffer[offset_y], 528 dst_buffer[offset_y] + x_crop_blocks, 529 comp_width); 530 if (compptr->width_in_blocks > x_crop_blocks + comp_width) { 531 FMEMZERO(dst_buffer[offset_y] + 532 x_crop_blocks + comp_width, 533 (compptr->width_in_blocks - 534 x_crop_blocks - comp_width) * SIZEOF(JBLOCK)); 535 dc = src_buffer[offset_y][comp_width - 1][0]; 536 for (dst_blk_x = x_crop_blocks + comp_width; 537 dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { 538 dst_buffer[offset_y][dst_blk_x][0] = dc; 539 } 540 } 541 } 542 } 543 } 544 } 545 546 547 LOCAL(void) 548 do_crop_ext_reflect (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 549 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 550 jvirt_barray_ptr *src_coef_arrays, 551 jvirt_barray_ptr *dst_coef_arrays) 552 /* Crop. This is only used when no rotate/flip is requested with the crop. 553 * Extension: The destination width is larger than the source and we fill in 554 * the extra area with repeated reflections of the source region. Note we 555 * also have to fill partial iMCUs at the right and bottom edge of the source 556 * image area in this case. 557 */ 558 { 559 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, src_blk_x; 560 JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks; 561 int ci, k, offset_y; 562 JBLOCKARRAY src_buffer, dst_buffer; 563 JBLOCKROW src_row_ptr, dst_row_ptr; 564 JCOEFPTR src_ptr, dst_ptr; 565 jpeg_component_info *compptr; 566 567 MCU_cols = srcinfo->output_width / 568 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); 569 MCU_rows = srcinfo->output_height / 570 (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); 571 572 for (ci = 0; ci < dstinfo->num_components; ci++) { 573 compptr = dstinfo->comp_info + ci; 574 comp_width = MCU_cols * compptr->h_samp_factor; 575 comp_height = MCU_rows * compptr->v_samp_factor; 576 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 577 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 578 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 579 dst_blk_y += compptr->v_samp_factor) { 580 dst_buffer = (*srcinfo->mem->access_virt_barray) 581 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 582 (JDIMENSION) compptr->v_samp_factor, TRUE); 583 if (dstinfo->jpeg_height > srcinfo->output_height) { 584 if (dst_blk_y < y_crop_blocks || 585 dst_blk_y >= y_crop_blocks + comp_height) { 586 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 587 FMEMZERO(dst_buffer[offset_y], 588 compptr->width_in_blocks * SIZEOF(JBLOCK)); 589 } 590 continue; 591 } 592 src_buffer = (*srcinfo->mem->access_virt_barray) 593 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 594 dst_blk_y - y_crop_blocks, 595 (JDIMENSION) compptr->v_samp_factor, FALSE); 596 } else { 597 src_buffer = (*srcinfo->mem->access_virt_barray) 598 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 599 dst_blk_y + y_crop_blocks, 600 (JDIMENSION) compptr->v_samp_factor, FALSE); 601 } 602 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 603 /* Copy source region */ 604 jcopy_block_row(src_buffer[offset_y], 605 dst_buffer[offset_y] + x_crop_blocks, 606 comp_width); 607 if (x_crop_blocks > 0) { 608 /* Reflect to left */ 609 dst_row_ptr = dst_buffer[offset_y] + x_crop_blocks; 610 for (dst_blk_x = x_crop_blocks; dst_blk_x > 0;) { 611 src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */ 612 for (src_blk_x = comp_width; src_blk_x > 0 && dst_blk_x > 0; 613 src_blk_x--, dst_blk_x--) { 614 dst_ptr = *--dst_row_ptr; /* destination goes left */ 615 src_ptr = *src_row_ptr++; /* source goes right */ 616 /* this unrolled loop doesn't need to know which row it's on... */ 617 for (k = 0; k < DCTSIZE2; k += 2) { 618 *dst_ptr++ = *src_ptr++; /* copy even column */ 619 *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */ 620 } 621 } 622 } 623 } 624 if (compptr->width_in_blocks > x_crop_blocks + comp_width) { 625 /* Reflect to right */ 626 dst_row_ptr = dst_buffer[offset_y] + x_crop_blocks + comp_width; 627 for (dst_blk_x = compptr->width_in_blocks - x_crop_blocks - comp_width; 628 dst_blk_x > 0;) { 629 src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */ 630 for (src_blk_x = comp_width; src_blk_x > 0 && dst_blk_x > 0; 631 src_blk_x--, dst_blk_x--) { 632 dst_ptr = *dst_row_ptr++; /* destination goes right */ 633 src_ptr = *--src_row_ptr; /* source goes left */ 634 /* this unrolled loop doesn't need to know which row it's on... */ 635 for (k = 0; k < DCTSIZE2; k += 2) { 636 *dst_ptr++ = *src_ptr++; /* copy even column */ 637 *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */ 638 } 639 } 640 } 641 } 642 } 643 } 644 } 645 } 646 647 648 LOCAL(void) 649 do_wipe (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 650 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 651 jvirt_barray_ptr *src_coef_arrays, 652 JDIMENSION drop_width, JDIMENSION drop_height) 653 /* Wipe - drop content of specified area, fill with zero (neutral gray) */ 654 { 655 JDIMENSION x_wipe_blocks, wipe_width; 656 JDIMENSION y_wipe_blocks, wipe_bottom; 657 int ci, offset_y; 658 JBLOCKARRAY buffer; 659 jpeg_component_info *compptr; 660 661 for (ci = 0; ci < dstinfo->num_components; ci++) { 662 compptr = dstinfo->comp_info + ci; 663 x_wipe_blocks = x_crop_offset * compptr->h_samp_factor; 664 wipe_width = drop_width * compptr->h_samp_factor; 665 y_wipe_blocks = y_crop_offset * compptr->v_samp_factor; 666 wipe_bottom = drop_height * compptr->v_samp_factor + y_wipe_blocks; 667 for (; y_wipe_blocks < wipe_bottom; 668 y_wipe_blocks += compptr->v_samp_factor) { 669 buffer = (*srcinfo->mem->access_virt_barray) 670 ((j_common_ptr) srcinfo, src_coef_arrays[ci], y_wipe_blocks, 671 (JDIMENSION) compptr->v_samp_factor, TRUE); 672 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 673 FMEMZERO(buffer[offset_y] + x_wipe_blocks, 674 wipe_width * SIZEOF(JBLOCK)); 675 } 676 } 677 } 678 } 679 680 681 LOCAL(void) 682 do_flatten (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 683 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 684 jvirt_barray_ptr *src_coef_arrays, 685 JDIMENSION drop_width, JDIMENSION drop_height) 686 /* Flatten - drop content of specified area, similar to wipe, 687 * but fill with average of adjacent blocks, instead of zero. 688 */ 689 { 690 JDIMENSION x_wipe_blocks, wipe_width, wipe_right; 691 JDIMENSION y_wipe_blocks, wipe_bottom, blk_x; 692 int ci, offset_y, dc_left_value, dc_right_value, average; 693 JBLOCKARRAY buffer; 694 jpeg_component_info *compptr; 695 696 for (ci = 0; ci < dstinfo->num_components; ci++) { 697 compptr = dstinfo->comp_info + ci; 698 x_wipe_blocks = x_crop_offset * compptr->h_samp_factor; 699 wipe_width = drop_width * compptr->h_samp_factor; 700 wipe_right = wipe_width + x_wipe_blocks; 701 y_wipe_blocks = y_crop_offset * compptr->v_samp_factor; 702 wipe_bottom = drop_height * compptr->v_samp_factor + y_wipe_blocks; 703 for (; y_wipe_blocks < wipe_bottom; 704 y_wipe_blocks += compptr->v_samp_factor) { 705 buffer = (*srcinfo->mem->access_virt_barray) 706 ((j_common_ptr) srcinfo, src_coef_arrays[ci], y_wipe_blocks, 707 (JDIMENSION) compptr->v_samp_factor, TRUE); 708 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 709 FMEMZERO(buffer[offset_y] + x_wipe_blocks, 710 wipe_width * SIZEOF(JBLOCK)); 711 if (x_wipe_blocks > 0) { 712 dc_left_value = buffer[offset_y][x_wipe_blocks - 1][0]; 713 if (wipe_right < compptr->width_in_blocks) { 714 dc_right_value = buffer[offset_y][wipe_right][0]; 715 average = (dc_left_value + dc_right_value) >> 1; 716 } else { 717 average = dc_left_value; 718 } 719 } else if (wipe_right < compptr->width_in_blocks) { 720 average = buffer[offset_y][wipe_right][0]; 721 } else continue; 722 for (blk_x = x_wipe_blocks; blk_x < wipe_right; blk_x++) { 723 buffer[offset_y][blk_x][0] = (JCOEF) average; 724 } 725 } 726 } 727 } 728 } 729 730 731 LOCAL(void) 732 do_reflect (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 733 JDIMENSION x_crop_offset, 734 jvirt_barray_ptr *src_coef_arrays, 735 JDIMENSION drop_width, JDIMENSION drop_height) 736 /* Reflect - drop content of specified area, similar to wipe, but 737 * fill with repeated reflections of the outside area, instead of zero. 738 * NB: y_crop_offset is assumed to be zero. 739 */ 740 { 741 JDIMENSION x_wipe_blocks, wipe_width; 742 JDIMENSION y_wipe_blocks, wipe_bottom; 743 JDIMENSION src_blk_x, dst_blk_x; 744 int ci, k, offset_y; 745 JBLOCKARRAY buffer; 746 JBLOCKROW src_row_ptr, dst_row_ptr; 747 JCOEFPTR src_ptr, dst_ptr; 748 jpeg_component_info *compptr; 749 750 for (ci = 0; ci < dstinfo->num_components; ci++) { 751 compptr = dstinfo->comp_info + ci; 752 x_wipe_blocks = x_crop_offset * compptr->h_samp_factor; 753 wipe_width = drop_width * compptr->h_samp_factor; 754 wipe_bottom = drop_height * compptr->v_samp_factor; 755 for (y_wipe_blocks = 0; y_wipe_blocks < wipe_bottom; 756 y_wipe_blocks += compptr->v_samp_factor) { 757 buffer = (*srcinfo->mem->access_virt_barray) 758 ((j_common_ptr) srcinfo, src_coef_arrays[ci], y_wipe_blocks, 759 (JDIMENSION) compptr->v_samp_factor, TRUE); 760 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 761 if (x_wipe_blocks > 0) { 762 /* Reflect from left */ 763 dst_row_ptr = buffer[offset_y] + x_wipe_blocks; 764 for (dst_blk_x = wipe_width; dst_blk_x > 0;) { 765 src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */ 766 for (src_blk_x = x_wipe_blocks; 767 src_blk_x > 0 && dst_blk_x > 0; src_blk_x--, dst_blk_x--) { 768 dst_ptr = *dst_row_ptr++; /* destination goes right */ 769 src_ptr = *--src_row_ptr; /* source goes left */ 770 /* this unrolled loop doesn't need to know which row it's on... */ 771 for (k = 0; k < DCTSIZE2; k += 2) { 772 *dst_ptr++ = *src_ptr++; /* copy even column */ 773 *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */ 774 } 775 } 776 } 777 } else if (compptr->width_in_blocks > x_wipe_blocks + wipe_width) { 778 /* Reflect from right */ 779 dst_row_ptr = buffer[offset_y] + x_wipe_blocks + wipe_width; 780 for (dst_blk_x = wipe_width; dst_blk_x > 0;) { 781 src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */ 782 src_blk_x = compptr->width_in_blocks - x_wipe_blocks - wipe_width; 783 for (; src_blk_x > 0 && dst_blk_x > 0; src_blk_x--, dst_blk_x--) { 784 dst_ptr = *--dst_row_ptr; /* destination goes left */ 785 src_ptr = *src_row_ptr++; /* source goes right */ 786 /* this unrolled loop doesn't need to know which row it's on... */ 787 for (k = 0; k < DCTSIZE2; k += 2) { 788 *dst_ptr++ = *src_ptr++; /* copy even column */ 789 *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */ 790 } 791 } 792 } 793 } else { 794 FMEMZERO(buffer[offset_y] + x_wipe_blocks, 795 wipe_width * SIZEOF(JBLOCK)); 796 } 797 } 798 } 799 } 800 } 801 802 803 LOCAL(void) 804 do_flip_h_no_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 805 JDIMENSION x_crop_offset, 806 jvirt_barray_ptr *src_coef_arrays) 807 /* Horizontal flip; done in-place, so no separate dest array is required. 808 * NB: this only works when y_crop_offset is zero. 809 */ 810 { 811 JDIMENSION MCU_cols, comp_width, blk_x, blk_y, x_crop_blocks; 812 int ci, k, offset_y; 813 JBLOCKARRAY buffer; 814 JCOEFPTR ptr1, ptr2; 815 JCOEF temp1, temp2; 816 jpeg_component_info *compptr; 817 818 /* Horizontal mirroring of DCT blocks is accomplished by swapping 819 * pairs of blocks in-place. Within a DCT block, we perform horizontal 820 * mirroring by changing the signs of odd-numbered columns. 821 * Partial iMCUs at the right edge are left untouched. 822 */ 823 MCU_cols = srcinfo->output_width / 824 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); 825 826 for (ci = 0; ci < dstinfo->num_components; ci++) { 827 compptr = dstinfo->comp_info + ci; 828 comp_width = MCU_cols * compptr->h_samp_factor; 829 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 830 for (blk_y = 0; blk_y < compptr->height_in_blocks; 831 blk_y += compptr->v_samp_factor) { 832 buffer = (*srcinfo->mem->access_virt_barray) 833 ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y, 834 (JDIMENSION) compptr->v_samp_factor, TRUE); 835 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 836 /* Do the mirroring */ 837 for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) { 838 ptr1 = buffer[offset_y][blk_x]; 839 ptr2 = buffer[offset_y][comp_width - blk_x - 1]; 840 /* this unrolled loop doesn't need to know which row it's on... */ 841 for (k = 0; k < DCTSIZE2; k += 2) { 842 temp1 = *ptr1; /* swap even column */ 843 temp2 = *ptr2; 844 *ptr1++ = temp2; 845 *ptr2++ = temp1; 846 temp1 = *ptr1; /* swap odd column with sign change */ 847 temp2 = *ptr2; 848 *ptr1++ = -temp2; 849 *ptr2++ = -temp1; 850 } 851 } 852 if (x_crop_blocks > 0) { 853 /* Now left-justify the portion of the data to be kept. 854 * We can't use a single jcopy_block_row() call because that routine 855 * depends on memcpy(), whose behavior is unspecified for overlapping 856 * source and destination areas. Sigh. 857 */ 858 for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) { 859 jcopy_block_row(buffer[offset_y] + blk_x + x_crop_blocks, 860 buffer[offset_y] + blk_x, 861 (JDIMENSION) 1); 862 } 863 } 864 } 865 } 866 } 867 } 868 869 870 LOCAL(void) 871 do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 872 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 873 jvirt_barray_ptr *src_coef_arrays, 874 jvirt_barray_ptr *dst_coef_arrays) 875 /* Horizontal flip in general cropping case */ 876 { 877 JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y; 878 JDIMENSION x_crop_blocks, y_crop_blocks; 879 int ci, k, offset_y; 880 JBLOCKARRAY src_buffer, dst_buffer; 881 JBLOCKROW src_row_ptr, dst_row_ptr; 882 JCOEFPTR src_ptr, dst_ptr; 883 jpeg_component_info *compptr; 884 885 /* Here we must output into a separate array because we can't touch 886 * different rows of a single virtual array simultaneously. Otherwise, 887 * this is essentially the same as the routine above. 888 */ 889 MCU_cols = srcinfo->output_width / 890 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); 891 892 for (ci = 0; ci < dstinfo->num_components; ci++) { 893 compptr = dstinfo->comp_info + ci; 894 comp_width = MCU_cols * compptr->h_samp_factor; 895 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 896 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 897 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 898 dst_blk_y += compptr->v_samp_factor) { 899 dst_buffer = (*srcinfo->mem->access_virt_barray) 900 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 901 (JDIMENSION) compptr->v_samp_factor, TRUE); 902 src_buffer = (*srcinfo->mem->access_virt_barray) 903 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 904 dst_blk_y + y_crop_blocks, 905 (JDIMENSION) compptr->v_samp_factor, FALSE); 906 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 907 dst_row_ptr = dst_buffer[offset_y]; 908 src_row_ptr = src_buffer[offset_y]; 909 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { 910 if (x_crop_blocks + dst_blk_x < comp_width) { 911 /* Do the mirrorable blocks */ 912 dst_ptr = dst_row_ptr[dst_blk_x]; 913 src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; 914 /* this unrolled loop doesn't need to know which row it's on... */ 915 for (k = 0; k < DCTSIZE2; k += 2) { 916 *dst_ptr++ = *src_ptr++; /* copy even column */ 917 *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */ 918 } 919 } else { 920 /* Copy last partial block(s) verbatim */ 921 jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks, 922 dst_row_ptr + dst_blk_x, 923 (JDIMENSION) 1); 924 } 925 } 926 } 927 } 928 } 929 } 930 931 932 LOCAL(void) 933 do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 934 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 935 jvirt_barray_ptr *src_coef_arrays, 936 jvirt_barray_ptr *dst_coef_arrays) 937 /* Vertical flip */ 938 { 939 JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; 940 JDIMENSION x_crop_blocks, y_crop_blocks; 941 int ci, i, j, offset_y; 942 JBLOCKARRAY src_buffer, dst_buffer; 943 JBLOCKROW src_row_ptr, dst_row_ptr; 944 JCOEFPTR src_ptr, dst_ptr; 945 jpeg_component_info *compptr; 946 947 /* We output into a separate array because we can't touch different 948 * rows of the source virtual array simultaneously. Otherwise, this 949 * is a pretty straightforward analog of horizontal flip. 950 * Within a DCT block, vertical mirroring is done by changing the signs 951 * of odd-numbered rows. 952 * Partial iMCUs at the bottom edge are copied verbatim. 953 */ 954 MCU_rows = srcinfo->output_height / 955 (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); 956 957 for (ci = 0; ci < dstinfo->num_components; ci++) { 958 compptr = dstinfo->comp_info + ci; 959 comp_height = MCU_rows * compptr->v_samp_factor; 960 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 961 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 962 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 963 dst_blk_y += compptr->v_samp_factor) { 964 dst_buffer = (*srcinfo->mem->access_virt_barray) 965 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 966 (JDIMENSION) compptr->v_samp_factor, TRUE); 967 if (y_crop_blocks + dst_blk_y < comp_height) { 968 /* Row is within the mirrorable area. */ 969 src_buffer = (*srcinfo->mem->access_virt_barray) 970 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 971 comp_height - y_crop_blocks - dst_blk_y - 972 (JDIMENSION) compptr->v_samp_factor, 973 (JDIMENSION) compptr->v_samp_factor, FALSE); 974 } else { 975 /* Bottom-edge blocks will be copied verbatim. */ 976 src_buffer = (*srcinfo->mem->access_virt_barray) 977 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 978 dst_blk_y + y_crop_blocks, 979 (JDIMENSION) compptr->v_samp_factor, FALSE); 980 } 981 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 982 if (y_crop_blocks + dst_blk_y < comp_height) { 983 /* Row is within the mirrorable area. */ 984 dst_row_ptr = dst_buffer[offset_y]; 985 src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; 986 src_row_ptr += x_crop_blocks; 987 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; 988 dst_blk_x++) { 989 dst_ptr = dst_row_ptr[dst_blk_x]; 990 src_ptr = src_row_ptr[dst_blk_x]; 991 for (i = 0; i < DCTSIZE; i += 2) { 992 /* copy even row */ 993 for (j = 0; j < DCTSIZE; j++) 994 *dst_ptr++ = *src_ptr++; 995 /* copy odd row with sign change */ 996 for (j = 0; j < DCTSIZE; j++) 997 *dst_ptr++ = - *src_ptr++; 998 } 999 } 1000 } else { 1001 /* Just copy row verbatim. */ 1002 jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, 1003 dst_buffer[offset_y], 1004 compptr->width_in_blocks); 1005 } 1006 } 1007 } 1008 } 1009 } 1010 1011 1012 LOCAL(void) 1013 do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 1014 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 1015 jvirt_barray_ptr *src_coef_arrays, 1016 jvirt_barray_ptr *dst_coef_arrays) 1017 /* Transpose source into destination */ 1018 { 1019 JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks; 1020 int ci, i, j, offset_x, offset_y; 1021 JBLOCKARRAY src_buffer, dst_buffer; 1022 JCOEFPTR src_ptr, dst_ptr; 1023 jpeg_component_info *compptr; 1024 1025 /* Transposing pixels within a block just requires transposing the 1026 * DCT coefficients. 1027 * Partial iMCUs at the edges require no special treatment; we simply 1028 * process all the available DCT blocks for every component. 1029 */ 1030 for (ci = 0; ci < dstinfo->num_components; ci++) { 1031 compptr = dstinfo->comp_info + ci; 1032 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 1033 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 1034 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 1035 dst_blk_y += compptr->v_samp_factor) { 1036 dst_buffer = (*srcinfo->mem->access_virt_barray) 1037 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 1038 (JDIMENSION) compptr->v_samp_factor, TRUE); 1039 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 1040 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; 1041 dst_blk_x += compptr->h_samp_factor) { 1042 src_buffer = (*srcinfo->mem->access_virt_barray) 1043 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 1044 dst_blk_x + x_crop_blocks, 1045 (JDIMENSION) compptr->h_samp_factor, FALSE); 1046 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { 1047 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; 1048 src_ptr = src_buffer[offset_x][dst_blk_y + offset_y + y_crop_blocks]; 1049 for (i = 0; i < DCTSIZE; i++) 1050 for (j = 0; j < DCTSIZE; j++) 1051 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 1052 } 1053 } 1054 } 1055 } 1056 } 1057 } 1058 1059 1060 LOCAL(void) 1061 do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 1062 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 1063 jvirt_barray_ptr *src_coef_arrays, 1064 jvirt_barray_ptr *dst_coef_arrays) 1065 /* 90 degree rotation is equivalent to 1066 * 1. Transposing the image; 1067 * 2. Horizontal mirroring. 1068 * These two steps are merged into a single processing routine. 1069 */ 1070 { 1071 JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y; 1072 JDIMENSION x_crop_blocks, y_crop_blocks; 1073 int ci, i, j, offset_x, offset_y; 1074 JBLOCKARRAY src_buffer, dst_buffer; 1075 JCOEFPTR src_ptr, dst_ptr; 1076 jpeg_component_info *compptr; 1077 1078 /* Because of the horizontal mirror step, we can't process partial iMCUs 1079 * at the (output) right edge properly. They just get transposed and 1080 * not mirrored. 1081 */ 1082 MCU_cols = srcinfo->output_height / 1083 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); 1084 1085 for (ci = 0; ci < dstinfo->num_components; ci++) { 1086 compptr = dstinfo->comp_info + ci; 1087 comp_width = MCU_cols * compptr->h_samp_factor; 1088 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 1089 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 1090 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 1091 dst_blk_y += compptr->v_samp_factor) { 1092 dst_buffer = (*srcinfo->mem->access_virt_barray) 1093 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 1094 (JDIMENSION) compptr->v_samp_factor, TRUE); 1095 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 1096 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; 1097 dst_blk_x += compptr->h_samp_factor) { 1098 if (x_crop_blocks + dst_blk_x < comp_width) { 1099 /* Block is within the mirrorable area. */ 1100 src_buffer = (*srcinfo->mem->access_virt_barray) 1101 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 1102 comp_width - x_crop_blocks - dst_blk_x - 1103 (JDIMENSION) compptr->h_samp_factor, 1104 (JDIMENSION) compptr->h_samp_factor, FALSE); 1105 } else { 1106 /* Edge blocks are transposed but not mirrored. */ 1107 src_buffer = (*srcinfo->mem->access_virt_barray) 1108 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 1109 dst_blk_x + x_crop_blocks, 1110 (JDIMENSION) compptr->h_samp_factor, FALSE); 1111 } 1112 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { 1113 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; 1114 if (x_crop_blocks + dst_blk_x < comp_width) { 1115 /* Block is within the mirrorable area. */ 1116 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] 1117 [dst_blk_y + offset_y + y_crop_blocks]; 1118 for (i = 0; i < DCTSIZE; i++) { 1119 for (j = 0; j < DCTSIZE; j++) 1120 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 1121 i++; 1122 for (j = 0; j < DCTSIZE; j++) 1123 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 1124 } 1125 } else { 1126 /* Edge blocks are transposed but not mirrored. */ 1127 src_ptr = src_buffer[offset_x] 1128 [dst_blk_y + offset_y + y_crop_blocks]; 1129 for (i = 0; i < DCTSIZE; i++) 1130 for (j = 0; j < DCTSIZE; j++) 1131 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 1132 } 1133 } 1134 } 1135 } 1136 } 1137 } 1138 } 1139 1140 1141 LOCAL(void) 1142 do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 1143 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 1144 jvirt_barray_ptr *src_coef_arrays, 1145 jvirt_barray_ptr *dst_coef_arrays) 1146 /* 270 degree rotation is equivalent to 1147 * 1. Horizontal mirroring; 1148 * 2. Transposing the image. 1149 * These two steps are merged into a single processing routine. 1150 */ 1151 { 1152 JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; 1153 JDIMENSION x_crop_blocks, y_crop_blocks; 1154 int ci, i, j, offset_x, offset_y; 1155 JBLOCKARRAY src_buffer, dst_buffer; 1156 JCOEFPTR src_ptr, dst_ptr; 1157 jpeg_component_info *compptr; 1158 1159 /* Because of the horizontal mirror step, we can't process partial iMCUs 1160 * at the (output) bottom edge properly. They just get transposed and 1161 * not mirrored. 1162 */ 1163 MCU_rows = srcinfo->output_width / 1164 (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); 1165 1166 for (ci = 0; ci < dstinfo->num_components; ci++) { 1167 compptr = dstinfo->comp_info + ci; 1168 comp_height = MCU_rows * compptr->v_samp_factor; 1169 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 1170 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 1171 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 1172 dst_blk_y += compptr->v_samp_factor) { 1173 dst_buffer = (*srcinfo->mem->access_virt_barray) 1174 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 1175 (JDIMENSION) compptr->v_samp_factor, TRUE); 1176 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 1177 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; 1178 dst_blk_x += compptr->h_samp_factor) { 1179 src_buffer = (*srcinfo->mem->access_virt_barray) 1180 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 1181 dst_blk_x + x_crop_blocks, 1182 (JDIMENSION) compptr->h_samp_factor, FALSE); 1183 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { 1184 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; 1185 if (y_crop_blocks + dst_blk_y < comp_height) { 1186 /* Block is within the mirrorable area. */ 1187 src_ptr = src_buffer[offset_x] 1188 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; 1189 for (i = 0; i < DCTSIZE; i++) { 1190 for (j = 0; j < DCTSIZE; j++) { 1191 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 1192 j++; 1193 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 1194 } 1195 } 1196 } else { 1197 /* Edge blocks are transposed but not mirrored. */ 1198 src_ptr = src_buffer[offset_x] 1199 [dst_blk_y + offset_y + y_crop_blocks]; 1200 for (i = 0; i < DCTSIZE; i++) 1201 for (j = 0; j < DCTSIZE; j++) 1202 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 1203 } 1204 } 1205 } 1206 } 1207 } 1208 } 1209 } 1210 1211 1212 LOCAL(void) 1213 do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 1214 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 1215 jvirt_barray_ptr *src_coef_arrays, 1216 jvirt_barray_ptr *dst_coef_arrays) 1217 /* 180 degree rotation is equivalent to 1218 * 1. Vertical mirroring; 1219 * 2. Horizontal mirroring. 1220 * These two steps are merged into a single processing routine. 1221 */ 1222 { 1223 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; 1224 JDIMENSION x_crop_blocks, y_crop_blocks; 1225 int ci, i, j, offset_y; 1226 JBLOCKARRAY src_buffer, dst_buffer; 1227 JBLOCKROW src_row_ptr, dst_row_ptr; 1228 JCOEFPTR src_ptr, dst_ptr; 1229 jpeg_component_info *compptr; 1230 1231 MCU_cols = srcinfo->output_width / 1232 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); 1233 MCU_rows = srcinfo->output_height / 1234 (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); 1235 1236 for (ci = 0; ci < dstinfo->num_components; ci++) { 1237 compptr = dstinfo->comp_info + ci; 1238 comp_width = MCU_cols * compptr->h_samp_factor; 1239 comp_height = MCU_rows * compptr->v_samp_factor; 1240 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 1241 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 1242 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 1243 dst_blk_y += compptr->v_samp_factor) { 1244 dst_buffer = (*srcinfo->mem->access_virt_barray) 1245 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 1246 (JDIMENSION) compptr->v_samp_factor, TRUE); 1247 if (y_crop_blocks + dst_blk_y < comp_height) { 1248 /* Row is within the vertically mirrorable area. */ 1249 src_buffer = (*srcinfo->mem->access_virt_barray) 1250 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 1251 comp_height - y_crop_blocks - dst_blk_y - 1252 (JDIMENSION) compptr->v_samp_factor, 1253 (JDIMENSION) compptr->v_samp_factor, FALSE); 1254 } else { 1255 /* Bottom-edge rows are only mirrored horizontally. */ 1256 src_buffer = (*srcinfo->mem->access_virt_barray) 1257 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 1258 dst_blk_y + y_crop_blocks, 1259 (JDIMENSION) compptr->v_samp_factor, FALSE); 1260 } 1261 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 1262 dst_row_ptr = dst_buffer[offset_y]; 1263 if (y_crop_blocks + dst_blk_y < comp_height) { 1264 /* Row is within the mirrorable area. */ 1265 src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; 1266 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { 1267 dst_ptr = dst_row_ptr[dst_blk_x]; 1268 if (x_crop_blocks + dst_blk_x < comp_width) { 1269 /* Process the blocks that can be mirrored both ways. */ 1270 src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; 1271 for (i = 0; i < DCTSIZE; i += 2) { 1272 /* For even row, negate every odd column. */ 1273 for (j = 0; j < DCTSIZE; j += 2) { 1274 *dst_ptr++ = *src_ptr++; 1275 *dst_ptr++ = - *src_ptr++; 1276 } 1277 /* For odd row, negate every even column. */ 1278 for (j = 0; j < DCTSIZE; j += 2) { 1279 *dst_ptr++ = - *src_ptr++; 1280 *dst_ptr++ = *src_ptr++; 1281 } 1282 } 1283 } else { 1284 /* Any remaining right-edge blocks are only mirrored vertically. */ 1285 src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x]; 1286 for (i = 0; i < DCTSIZE; i += 2) { 1287 for (j = 0; j < DCTSIZE; j++) 1288 *dst_ptr++ = *src_ptr++; 1289 for (j = 0; j < DCTSIZE; j++) 1290 *dst_ptr++ = - *src_ptr++; 1291 } 1292 } 1293 } 1294 } else { 1295 /* Remaining rows are just mirrored horizontally. */ 1296 src_row_ptr = src_buffer[offset_y]; 1297 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { 1298 if (x_crop_blocks + dst_blk_x < comp_width) { 1299 /* Process the blocks that can be mirrored. */ 1300 dst_ptr = dst_row_ptr[dst_blk_x]; 1301 src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; 1302 for (i = 0; i < DCTSIZE2; i += 2) { 1303 *dst_ptr++ = *src_ptr++; 1304 *dst_ptr++ = - *src_ptr++; 1305 } 1306 } else { 1307 /* Any remaining right-edge blocks are only copied. */ 1308 jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks, 1309 dst_row_ptr + dst_blk_x, 1310 (JDIMENSION) 1); 1311 } 1312 } 1313 } 1314 } 1315 } 1316 } 1317 } 1318 1319 1320 LOCAL(void) 1321 do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 1322 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 1323 jvirt_barray_ptr *src_coef_arrays, 1324 jvirt_barray_ptr *dst_coef_arrays) 1325 /* Transverse transpose is equivalent to 1326 * 1. 180 degree rotation; 1327 * 2. Transposition; 1328 * or 1329 * 1. Horizontal mirroring; 1330 * 2. Transposition; 1331 * 3. Horizontal mirroring. 1332 * These steps are merged into a single processing routine. 1333 */ 1334 { 1335 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; 1336 JDIMENSION x_crop_blocks, y_crop_blocks; 1337 int ci, i, j, offset_x, offset_y; 1338 JBLOCKARRAY src_buffer, dst_buffer; 1339 JCOEFPTR src_ptr, dst_ptr; 1340 jpeg_component_info *compptr; 1341 1342 MCU_cols = srcinfo->output_height / 1343 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); 1344 MCU_rows = srcinfo->output_width / 1345 (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); 1346 1347 for (ci = 0; ci < dstinfo->num_components; ci++) { 1348 compptr = dstinfo->comp_info + ci; 1349 comp_width = MCU_cols * compptr->h_samp_factor; 1350 comp_height = MCU_rows * compptr->v_samp_factor; 1351 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 1352 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 1353 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 1354 dst_blk_y += compptr->v_samp_factor) { 1355 dst_buffer = (*srcinfo->mem->access_virt_barray) 1356 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 1357 (JDIMENSION) compptr->v_samp_factor, TRUE); 1358 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 1359 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; 1360 dst_blk_x += compptr->h_samp_factor) { 1361 if (x_crop_blocks + dst_blk_x < comp_width) { 1362 /* Block is within the mirrorable area. */ 1363 src_buffer = (*srcinfo->mem->access_virt_barray) 1364 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 1365 comp_width - x_crop_blocks - dst_blk_x - 1366 (JDIMENSION) compptr->h_samp_factor, 1367 (JDIMENSION) compptr->h_samp_factor, FALSE); 1368 } else { 1369 src_buffer = (*srcinfo->mem->access_virt_barray) 1370 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 1371 dst_blk_x + x_crop_blocks, 1372 (JDIMENSION) compptr->h_samp_factor, FALSE); 1373 } 1374 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { 1375 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; 1376 if (y_crop_blocks + dst_blk_y < comp_height) { 1377 if (x_crop_blocks + dst_blk_x < comp_width) { 1378 /* Block is within the mirrorable area. */ 1379 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] 1380 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; 1381 for (i = 0; i < DCTSIZE; i++) { 1382 for (j = 0; j < DCTSIZE; j++) { 1383 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 1384 j++; 1385 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 1386 } 1387 i++; 1388 for (j = 0; j < DCTSIZE; j++) { 1389 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 1390 j++; 1391 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 1392 } 1393 } 1394 } else { 1395 /* Right-edge blocks are mirrored in y only */ 1396 src_ptr = src_buffer[offset_x] 1397 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; 1398 for (i = 0; i < DCTSIZE; i++) { 1399 for (j = 0; j < DCTSIZE; j++) { 1400 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 1401 j++; 1402 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 1403 } 1404 } 1405 } 1406 } else { 1407 if (x_crop_blocks + dst_blk_x < comp_width) { 1408 /* Bottom-edge blocks are mirrored in x only */ 1409 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] 1410 [dst_blk_y + offset_y + y_crop_blocks]; 1411 for (i = 0; i < DCTSIZE; i++) { 1412 for (j = 0; j < DCTSIZE; j++) 1413 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 1414 i++; 1415 for (j = 0; j < DCTSIZE; j++) 1416 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 1417 } 1418 } else { 1419 /* At lower right corner, just transpose, no mirroring */ 1420 src_ptr = src_buffer[offset_x] 1421 [dst_blk_y + offset_y + y_crop_blocks]; 1422 for (i = 0; i < DCTSIZE; i++) 1423 for (j = 0; j < DCTSIZE; j++) 1424 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 1425 } 1426 } 1427 } 1428 } 1429 } 1430 } 1431 } 1432 } 1433 1434 1435 /* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec. 1436 * Returns TRUE if valid integer found, FALSE if not. 1437 * *strptr is advanced over the digit string, and *result is set to its value. 1438 */ 1439 1440 LOCAL(boolean) 1441 jt_read_integer (const char ** strptr, JDIMENSION * result) 1442 { 1443 const char * ptr = *strptr; 1444 JDIMENSION val = 0; 1445 1446 for (; isdigit(*ptr); ptr++) { 1447 val = val * 10 + (JDIMENSION) (*ptr - '0'); 1448 } 1449 *result = val; 1450 if (ptr == *strptr) 1451 return FALSE; /* oops, no digits */ 1452 *strptr = ptr; 1453 return TRUE; 1454 } 1455 1456 1457 /* Parse a crop specification (written in X11 geometry style). 1458 * The routine returns TRUE if the spec string is valid, FALSE if not. 1459 * 1460 * The crop spec string should have the format 1461 * <width>[{fr}]x<height>[{fr}]{+-}<xoffset>{+-}<yoffset> 1462 * where width, height, xoffset, and yoffset are unsigned integers. 1463 * Each of the elements can be omitted to indicate a default value. 1464 * (A weakness of this style is that it is not possible to omit xoffset 1465 * while specifying yoffset, since they look alike.) 1466 * 1467 * This code is loosely based on XParseGeometry from the X11 distribution. 1468 */ 1469 1470 GLOBAL(boolean) 1471 jtransform_parse_crop_spec (jpeg_transform_info *info, const char *spec) 1472 { 1473 info->crop = FALSE; 1474 info->crop_width_set = JCROP_UNSET; 1475 info->crop_height_set = JCROP_UNSET; 1476 info->crop_xoffset_set = JCROP_UNSET; 1477 info->crop_yoffset_set = JCROP_UNSET; 1478 1479 if (isdigit(*spec)) { 1480 /* fetch width */ 1481 if (! jt_read_integer(&spec, &info->crop_width)) 1482 return FALSE; 1483 if (*spec == 'f' || *spec == 'F') { 1484 spec++; 1485 info->crop_width_set = JCROP_FORCE; 1486 } else if (*spec == 'r' || *spec == 'R') { 1487 spec++; 1488 info->crop_width_set = JCROP_REFLECT; 1489 } else 1490 info->crop_width_set = JCROP_POS; 1491 } 1492 if (*spec == 'x' || *spec == 'X') { 1493 /* fetch height */ 1494 spec++; 1495 if (! jt_read_integer(&spec, &info->crop_height)) 1496 return FALSE; 1497 if (*spec == 'f' || *spec == 'F') { 1498 spec++; 1499 info->crop_height_set = JCROP_FORCE; 1500 } else if (*spec == 'r' || *spec == 'R') { 1501 spec++; 1502 info->crop_height_set = JCROP_REFLECT; 1503 } else 1504 info->crop_height_set = JCROP_POS; 1505 } 1506 if (*spec == '+' || *spec == '-') { 1507 /* fetch xoffset */ 1508 info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS; 1509 spec++; 1510 if (! jt_read_integer(&spec, &info->crop_xoffset)) 1511 return FALSE; 1512 } 1513 if (*spec == '+' || *spec == '-') { 1514 /* fetch yoffset */ 1515 info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS; 1516 spec++; 1517 if (! jt_read_integer(&spec, &info->crop_yoffset)) 1518 return FALSE; 1519 } 1520 /* We had better have gotten to the end of the string. */ 1521 if (*spec != '\0') 1522 return FALSE; 1523 info->crop = TRUE; 1524 return TRUE; 1525 } 1526 1527 1528 /* Trim off any partial iMCUs on the indicated destination edge */ 1529 1530 LOCAL(void) 1531 trim_right_edge (jpeg_transform_info *info, JDIMENSION full_width) 1532 { 1533 JDIMENSION MCU_cols; 1534 1535 MCU_cols = info->output_width / info->iMCU_sample_width; 1536 if (MCU_cols > 0 && info->x_crop_offset + MCU_cols == 1537 full_width / info->iMCU_sample_width) 1538 info->output_width = MCU_cols * info->iMCU_sample_width; 1539 } 1540 1541 LOCAL(void) 1542 trim_bottom_edge (jpeg_transform_info *info, JDIMENSION full_height) 1543 { 1544 JDIMENSION MCU_rows; 1545 1546 MCU_rows = info->output_height / info->iMCU_sample_height; 1547 if (MCU_rows > 0 && info->y_crop_offset + MCU_rows == 1548 full_height / info->iMCU_sample_height) 1549 info->output_height = MCU_rows * info->iMCU_sample_height; 1550 } 1551 1552 1553 /* Request any required workspace. 1554 * 1555 * This routine figures out the size that the output image will be 1556 * (which implies that all the transform parameters must be set before 1557 * it is called). 1558 * 1559 * We allocate the workspace virtual arrays from the source decompression 1560 * object, so that all the arrays (both the original data and the workspace) 1561 * will be taken into account while making memory management decisions. 1562 * Hence, this routine must be called after jpeg_read_header (which reads 1563 * the image dimensions) and before jpeg_read_coefficients (which realizes 1564 * the source's virtual arrays). 1565 * 1566 * This function returns FALSE right away if -perfect is given 1567 * and transformation is not perfect. Otherwise returns TRUE. 1568 */ 1569 1570 GLOBAL(boolean) 1571 jtransform_request_workspace (j_decompress_ptr srcinfo, 1572 jpeg_transform_info *info) 1573 { 1574 jvirt_barray_ptr *coef_arrays; 1575 boolean need_workspace, transpose_it; 1576 jpeg_component_info *compptr; 1577 JDIMENSION xoffset, yoffset, dtemp; 1578 JDIMENSION width_in_iMCUs, height_in_iMCUs; 1579 JDIMENSION width_in_blocks, height_in_blocks; 1580 int itemp, ci, h_samp_factor, v_samp_factor; 1581 1582 /* Determine number of components in output image */ 1583 if (info->force_grayscale && 1584 (srcinfo->jpeg_color_space == JCS_YCbCr || 1585 srcinfo->jpeg_color_space == JCS_BG_YCC) && 1586 srcinfo->num_components == 3) 1587 /* We'll only process the first component */ 1588 info->num_components = 1; 1589 else 1590 /* Process all the components */ 1591 info->num_components = srcinfo->num_components; 1592 1593 /* Compute output image dimensions and related values. */ 1594 jpeg_core_output_dimensions(srcinfo); 1595 1596 /* Return right away if -perfect is given and transformation is not perfect. 1597 */ 1598 if (info->perfect) { 1599 if (info->num_components == 1) { 1600 if (!jtransform_perfect_transform(srcinfo->output_width, 1601 srcinfo->output_height, 1602 srcinfo->min_DCT_h_scaled_size, 1603 srcinfo->min_DCT_v_scaled_size, 1604 info->transform)) 1605 return FALSE; 1606 } else { 1607 if (!jtransform_perfect_transform(srcinfo->output_width, 1608 srcinfo->output_height, 1609 srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size, 1610 srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size, 1611 info->transform)) 1612 return FALSE; 1613 } 1614 } 1615 1616 /* If there is only one output component, force the iMCU size to be 1; 1617 * else use the source iMCU size. (This allows us to do the right thing 1618 * when reducing color to grayscale, and also provides a handy way of 1619 * cleaning up "funny" grayscale images whose sampling factors are not 1x1.) 1620 */ 1621 switch (info->transform) { 1622 case JXFORM_TRANSPOSE: 1623 case JXFORM_TRANSVERSE: 1624 case JXFORM_ROT_90: 1625 case JXFORM_ROT_270: 1626 info->output_width = srcinfo->output_height; 1627 info->output_height = srcinfo->output_width; 1628 if (info->num_components == 1) { 1629 info->iMCU_sample_width = srcinfo->min_DCT_v_scaled_size; 1630 info->iMCU_sample_height = srcinfo->min_DCT_h_scaled_size; 1631 } else { 1632 info->iMCU_sample_width = 1633 srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size; 1634 info->iMCU_sample_height = 1635 srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size; 1636 } 1637 break; 1638 default: 1639 info->output_width = srcinfo->output_width; 1640 info->output_height = srcinfo->output_height; 1641 if (info->num_components == 1) { 1642 info->iMCU_sample_width = srcinfo->min_DCT_h_scaled_size; 1643 info->iMCU_sample_height = srcinfo->min_DCT_v_scaled_size; 1644 } else { 1645 info->iMCU_sample_width = 1646 srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size; 1647 info->iMCU_sample_height = 1648 srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size; 1649 } 1650 } 1651 1652 /* If cropping has been requested, compute the crop area's position and 1653 * dimensions, ensuring that its upper left corner falls at an iMCU boundary. 1654 */ 1655 if (info->crop) { 1656 /* Insert default values for unset crop parameters */ 1657 if (info->crop_xoffset_set == JCROP_UNSET) 1658 info->crop_xoffset = 0; /* default to +0 */ 1659 if (info->crop_yoffset_set == JCROP_UNSET) 1660 info->crop_yoffset = 0; /* default to +0 */ 1661 if (info->crop_width_set == JCROP_UNSET) { 1662 if (info->crop_xoffset >= info->output_width) 1663 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); 1664 info->crop_width = info->output_width - info->crop_xoffset; 1665 } else { 1666 /* Check for crop extension */ 1667 if (info->crop_width > info->output_width) { 1668 /* Crop extension does not work when transforming! */ 1669 if (info->transform != JXFORM_NONE || 1670 info->crop_xoffset >= info->crop_width || 1671 info->crop_xoffset > info->crop_width - info->output_width) 1672 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); 1673 } else { 1674 if (info->crop_xoffset >= info->output_width || 1675 info->crop_width <= 0 || 1676 info->crop_xoffset > info->output_width - info->crop_width) 1677 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); 1678 } 1679 } 1680 if (info->crop_height_set == JCROP_UNSET) { 1681 if (info->crop_yoffset >= info->output_height) 1682 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); 1683 info->crop_height = info->output_height - info->crop_yoffset; 1684 } else { 1685 /* Check for crop extension */ 1686 if (info->crop_height > info->output_height) { 1687 /* Crop extension does not work when transforming! */ 1688 if (info->transform != JXFORM_NONE || 1689 info->crop_yoffset >= info->crop_height || 1690 info->crop_yoffset > info->crop_height - info->output_height) 1691 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); 1692 } else { 1693 if (info->crop_yoffset >= info->output_height || 1694 info->crop_height <= 0 || 1695 info->crop_yoffset > info->output_height - info->crop_height) 1696 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); 1697 } 1698 } 1699 /* Convert negative crop offsets into regular offsets */ 1700 if (info->crop_xoffset_set != JCROP_NEG) 1701 xoffset = info->crop_xoffset; 1702 else if (info->crop_width > info->output_width) /* crop extension */ 1703 xoffset = info->crop_width - info->output_width - info->crop_xoffset; 1704 else 1705 xoffset = info->output_width - info->crop_width - info->crop_xoffset; 1706 if (info->crop_yoffset_set != JCROP_NEG) 1707 yoffset = info->crop_yoffset; 1708 else if (info->crop_height > info->output_height) /* crop extension */ 1709 yoffset = info->crop_height - info->output_height - info->crop_yoffset; 1710 else 1711 yoffset = info->output_height - info->crop_height - info->crop_yoffset; 1712 /* Now adjust so that upper left corner falls at an iMCU boundary */ 1713 switch (info->transform) { 1714 case JXFORM_DROP: 1715 /* Ensure the effective drop region will not exceed the requested */ 1716 itemp = info->iMCU_sample_width; 1717 dtemp = itemp - 1 - ((xoffset + itemp - 1) % itemp); 1718 xoffset += dtemp; 1719 if (info->crop_width <= dtemp) 1720 info->drop_width = 0; 1721 else if (xoffset + info->crop_width - dtemp == info->output_width) 1722 /* Matching right edge: include partial iMCU */ 1723 info->drop_width = (info->crop_width - dtemp + itemp - 1) / itemp; 1724 else 1725 info->drop_width = (info->crop_width - dtemp) / itemp; 1726 itemp = info->iMCU_sample_height; 1727 dtemp = itemp - 1 - ((yoffset + itemp - 1) % itemp); 1728 yoffset += dtemp; 1729 if (info->crop_height <= dtemp) 1730 info->drop_height = 0; 1731 else if (yoffset + info->crop_height - dtemp == info->output_height) 1732 /* Matching bottom edge: include partial iMCU */ 1733 info->drop_height = (info->crop_height - dtemp + itemp - 1) / itemp; 1734 else 1735 info->drop_height = (info->crop_height - dtemp) / itemp; 1736 /* Check if sampling factors match for dropping */ 1737 if (info->drop_width != 0 && info->drop_height != 0) 1738 for (ci = 0; ci < info->num_components && 1739 ci < info->drop_ptr->num_components; ci++) { 1740 if (info->drop_ptr->comp_info[ci].h_samp_factor * 1741 srcinfo->max_h_samp_factor != 1742 srcinfo->comp_info[ci].h_samp_factor * 1743 info->drop_ptr->max_h_samp_factor) 1744 ERREXIT6(srcinfo, JERR_BAD_DROP_SAMPLING, ci, 1745 info->drop_ptr->comp_info[ci].h_samp_factor, 1746 info->drop_ptr->max_h_samp_factor, 1747 srcinfo->comp_info[ci].h_samp_factor, 1748 srcinfo->max_h_samp_factor, 'h'); 1749 if (info->drop_ptr->comp_info[ci].v_samp_factor * 1750 srcinfo->max_v_samp_factor != 1751 srcinfo->comp_info[ci].v_samp_factor * 1752 info->drop_ptr->max_v_samp_factor) 1753 ERREXIT6(srcinfo, JERR_BAD_DROP_SAMPLING, ci, 1754 info->drop_ptr->comp_info[ci].v_samp_factor, 1755 info->drop_ptr->max_v_samp_factor, 1756 srcinfo->comp_info[ci].v_samp_factor, 1757 srcinfo->max_v_samp_factor, 'v'); 1758 } 1759 break; 1760 case JXFORM_WIPE: 1761 /* Ensure the effective wipe region will cover the requested */ 1762 info->drop_width = (JDIMENSION) jdiv_round_up 1763 ((long) (info->crop_width + (xoffset % info->iMCU_sample_width)), 1764 (long) info->iMCU_sample_width); 1765 info->drop_height = (JDIMENSION) jdiv_round_up 1766 ((long) (info->crop_height + (yoffset % info->iMCU_sample_height)), 1767 (long) info->iMCU_sample_height); 1768 break; 1769 default: 1770 /* Ensure the effective crop region will cover the requested */ 1771 if (info->crop_width_set == JCROP_FORCE || 1772 info->crop_width > info->output_width) 1773 info->output_width = info->crop_width; 1774 else 1775 info->output_width = 1776 info->crop_width + (xoffset % info->iMCU_sample_width); 1777 if (info->crop_height_set == JCROP_FORCE || 1778 info->crop_height > info->output_height) 1779 info->output_height = info->crop_height; 1780 else 1781 info->output_height = 1782 info->crop_height + (yoffset % info->iMCU_sample_height); 1783 } 1784 /* Save x/y offsets measured in iMCUs */ 1785 info->x_crop_offset = xoffset / info->iMCU_sample_width; 1786 info->y_crop_offset = yoffset / info->iMCU_sample_height; 1787 } else { 1788 info->x_crop_offset = 0; 1789 info->y_crop_offset = 0; 1790 } 1791 1792 /* Figure out whether we need workspace arrays, 1793 * and if so whether they are transposed relative to the source. 1794 */ 1795 need_workspace = FALSE; 1796 transpose_it = FALSE; 1797 switch (info->transform) { 1798 case JXFORM_NONE: 1799 if (info->x_crop_offset != 0 || info->y_crop_offset != 0 || 1800 info->output_width > srcinfo->output_width || 1801 info->output_height > srcinfo->output_height) 1802 need_workspace = TRUE; 1803 /* No workspace needed if neither cropping nor transforming */ 1804 break; 1805 case JXFORM_FLIP_H: 1806 if (info->trim) 1807 trim_right_edge(info, srcinfo->output_width); 1808 if (info->y_crop_offset != 0) 1809 need_workspace = TRUE; 1810 /* do_flip_h_no_crop doesn't need a workspace array */ 1811 break; 1812 case JXFORM_FLIP_V: 1813 if (info->trim) 1814 trim_bottom_edge(info, srcinfo->output_height); 1815 /* Need workspace arrays having same dimensions as source image. */ 1816 need_workspace = TRUE; 1817 break; 1818 case JXFORM_TRANSPOSE: 1819 /* transpose does NOT have to trim anything */ 1820 /* Need workspace arrays having transposed dimensions. */ 1821 need_workspace = TRUE; 1822 transpose_it = TRUE; 1823 break; 1824 case JXFORM_TRANSVERSE: 1825 if (info->trim) { 1826 trim_right_edge(info, srcinfo->output_height); 1827 trim_bottom_edge(info, srcinfo->output_width); 1828 } 1829 /* Need workspace arrays having transposed dimensions. */ 1830 need_workspace = TRUE; 1831 transpose_it = TRUE; 1832 break; 1833 case JXFORM_ROT_90: 1834 if (info->trim) 1835 trim_right_edge(info, srcinfo->output_height); 1836 /* Need workspace arrays having transposed dimensions. */ 1837 need_workspace = TRUE; 1838 transpose_it = TRUE; 1839 break; 1840 case JXFORM_ROT_180: 1841 if (info->trim) { 1842 trim_right_edge(info, srcinfo->output_width); 1843 trim_bottom_edge(info, srcinfo->output_height); 1844 } 1845 /* Need workspace arrays having same dimensions as source image. */ 1846 need_workspace = TRUE; 1847 break; 1848 case JXFORM_ROT_270: 1849 if (info->trim) 1850 trim_bottom_edge(info, srcinfo->output_width); 1851 /* Need workspace arrays having transposed dimensions. */ 1852 need_workspace = TRUE; 1853 transpose_it = TRUE; 1854 break; 1855 case JXFORM_WIPE: 1856 break; 1857 case JXFORM_DROP: 1858 #if DROP_REQUEST_FROM_SRC 1859 drop_request_from_src(info->drop_ptr, srcinfo); 1860 #endif 1861 break; 1862 } 1863 1864 /* Allocate workspace if needed. 1865 * Note that we allocate arrays padded out to the next iMCU boundary, 1866 * so that transform routines need not worry about missing edge blocks. 1867 */ 1868 if (need_workspace) { 1869 coef_arrays = (jvirt_barray_ptr *) (*srcinfo->mem->alloc_small) 1870 ((j_common_ptr) srcinfo, JPOOL_IMAGE, 1871 SIZEOF(jvirt_barray_ptr) * info->num_components); 1872 width_in_iMCUs = (JDIMENSION) jdiv_round_up 1873 ((long) info->output_width, (long) info->iMCU_sample_width); 1874 height_in_iMCUs = (JDIMENSION) jdiv_round_up 1875 ((long) info->output_height, (long) info->iMCU_sample_height); 1876 for (ci = 0; ci < info->num_components; ci++) { 1877 compptr = srcinfo->comp_info + ci; 1878 if (info->num_components == 1) { 1879 /* we're going to force samp factors to 1x1 in this case */ 1880 h_samp_factor = v_samp_factor = 1; 1881 } else if (transpose_it) { 1882 h_samp_factor = compptr->v_samp_factor; 1883 v_samp_factor = compptr->h_samp_factor; 1884 } else { 1885 h_samp_factor = compptr->h_samp_factor; 1886 v_samp_factor = compptr->v_samp_factor; 1887 } 1888 width_in_blocks = width_in_iMCUs * h_samp_factor; 1889 height_in_blocks = height_in_iMCUs * v_samp_factor; 1890 coef_arrays[ci] = (*srcinfo->mem->request_virt_barray) 1891 ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE, 1892 width_in_blocks, height_in_blocks, (JDIMENSION) v_samp_factor); 1893 } 1894 info->workspace_coef_arrays = coef_arrays; 1895 } else 1896 info->workspace_coef_arrays = NULL; 1897 1898 return TRUE; 1899 } 1900 1901 1902 /* Transpose destination image parameters */ 1903 1904 LOCAL(void) 1905 transpose_critical_parameters (j_compress_ptr dstinfo) 1906 { 1907 int tblno, i, j, ci, itemp; 1908 jpeg_component_info *compptr; 1909 JQUANT_TBL *qtblptr; 1910 JDIMENSION jtemp; 1911 UINT16 qtemp; 1912 1913 /* Transpose image dimensions */ 1914 jtemp = dstinfo->image_width; 1915 dstinfo->image_width = dstinfo->image_height; 1916 dstinfo->image_height = jtemp; 1917 itemp = dstinfo->min_DCT_h_scaled_size; 1918 dstinfo->min_DCT_h_scaled_size = dstinfo->min_DCT_v_scaled_size; 1919 dstinfo->min_DCT_v_scaled_size = itemp; 1920 1921 /* Transpose sampling factors */ 1922 for (ci = 0; ci < dstinfo->num_components; ci++) { 1923 compptr = dstinfo->comp_info + ci; 1924 itemp = compptr->h_samp_factor; 1925 compptr->h_samp_factor = compptr->v_samp_factor; 1926 compptr->v_samp_factor = itemp; 1927 } 1928 1929 /* Transpose quantization tables */ 1930 for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { 1931 qtblptr = dstinfo->quant_tbl_ptrs[tblno]; 1932 if (qtblptr != NULL) { 1933 for (i = 0; i < DCTSIZE; i++) { 1934 for (j = 0; j < i; j++) { 1935 qtemp = qtblptr->quantval[i*DCTSIZE+j]; 1936 qtblptr->quantval[i*DCTSIZE+j] = qtblptr->quantval[j*DCTSIZE+i]; 1937 qtblptr->quantval[j*DCTSIZE+i] = qtemp; 1938 } 1939 } 1940 } 1941 } 1942 } 1943 1944 1945 /* Adjust Exif image parameters. 1946 * 1947 * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible. 1948 */ 1949 1950 LOCAL(void) 1951 adjust_exif_parameters (JOCTET FAR * data, unsigned int length, 1952 JDIMENSION new_width, JDIMENSION new_height) 1953 { 1954 boolean is_motorola; /* Flag for byte order */ 1955 unsigned int number_of_tags, tagnum; 1956 unsigned int firstoffset, offset; 1957 JDIMENSION new_value; 1958 1959 if (length < 12) return; /* Length of an IFD entry */ 1960 1961 /* Discover byte order */ 1962 if (GETJOCTET(data[0]) == 0x49 && GETJOCTET(data[1]) == 0x49) 1963 is_motorola = FALSE; 1964 else if (GETJOCTET(data[0]) == 0x4D && GETJOCTET(data[1]) == 0x4D) 1965 is_motorola = TRUE; 1966 else 1967 return; 1968 1969 /* Check Tag Mark */ 1970 if (is_motorola) { 1971 if (GETJOCTET(data[2]) != 0) return; 1972 if (GETJOCTET(data[3]) != 0x2A) return; 1973 } else { 1974 if (GETJOCTET(data[3]) != 0) return; 1975 if (GETJOCTET(data[2]) != 0x2A) return; 1976 } 1977 1978 /* Get first IFD offset (offset to IFD0) */ 1979 if (is_motorola) { 1980 if (GETJOCTET(data[4]) != 0) return; 1981 if (GETJOCTET(data[5]) != 0) return; 1982 firstoffset = GETJOCTET(data[6]); 1983 firstoffset <<= 8; 1984 firstoffset += GETJOCTET(data[7]); 1985 } else { 1986 if (GETJOCTET(data[7]) != 0) return; 1987 if (GETJOCTET(data[6]) != 0) return; 1988 firstoffset = GETJOCTET(data[5]); 1989 firstoffset <<= 8; 1990 firstoffset += GETJOCTET(data[4]); 1991 } 1992 if (firstoffset > length - 2) return; /* check end of data segment */ 1993 1994 /* Get the number of directory entries contained in this IFD */ 1995 if (is_motorola) { 1996 number_of_tags = GETJOCTET(data[firstoffset]); 1997 number_of_tags <<= 8; 1998 number_of_tags += GETJOCTET(data[firstoffset+1]); 1999 } else { 2000 number_of_tags = GETJOCTET(data[firstoffset+1]); 2001 number_of_tags <<= 8; 2002 number_of_tags += GETJOCTET(data[firstoffset]); 2003 } 2004 if (number_of_tags == 0) return; 2005 firstoffset += 2; 2006 2007 /* Search for ExifSubIFD offset Tag in IFD0 */ 2008 for (;;) { 2009 if (firstoffset > length - 12) return; /* check end of data segment */ 2010 /* Get Tag number */ 2011 if (is_motorola) { 2012 tagnum = GETJOCTET(data[firstoffset]); 2013 tagnum <<= 8; 2014 tagnum += GETJOCTET(data[firstoffset+1]); 2015 } else { 2016 tagnum = GETJOCTET(data[firstoffset+1]); 2017 tagnum <<= 8; 2018 tagnum += GETJOCTET(data[firstoffset]); 2019 } 2020 if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */ 2021 if (--number_of_tags == 0) return; 2022 firstoffset += 12; 2023 } 2024 2025 /* Get the ExifSubIFD offset */ 2026 if (is_motorola) { 2027 if (GETJOCTET(data[firstoffset+8]) != 0) return; 2028 if (GETJOCTET(data[firstoffset+9]) != 0) return; 2029 offset = GETJOCTET(data[firstoffset+10]); 2030 offset <<= 8; 2031 offset += GETJOCTET(data[firstoffset+11]); 2032 } else { 2033 if (GETJOCTET(data[firstoffset+11]) != 0) return; 2034 if (GETJOCTET(data[firstoffset+10]) != 0) return; 2035 offset = GETJOCTET(data[firstoffset+9]); 2036 offset <<= 8; 2037 offset += GETJOCTET(data[firstoffset+8]); 2038 } 2039 if (offset > length - 2) return; /* check end of data segment */ 2040 2041 /* Get the number of directory entries contained in this SubIFD */ 2042 if (is_motorola) { 2043 number_of_tags = GETJOCTET(data[offset]); 2044 number_of_tags <<= 8; 2045 number_of_tags += GETJOCTET(data[offset+1]); 2046 } else { 2047 number_of_tags = GETJOCTET(data[offset+1]); 2048 number_of_tags <<= 8; 2049 number_of_tags += GETJOCTET(data[offset]); 2050 } 2051 if (number_of_tags < 2) return; 2052 offset += 2; 2053 2054 /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */ 2055 do { 2056 if (offset > length - 12) return; /* check end of data segment */ 2057 /* Get Tag number */ 2058 if (is_motorola) { 2059 tagnum = GETJOCTET(data[offset]); 2060 tagnum <<= 8; 2061 tagnum += GETJOCTET(data[offset+1]); 2062 } else { 2063 tagnum = GETJOCTET(data[offset+1]); 2064 tagnum <<= 8; 2065 tagnum += GETJOCTET(data[offset]); 2066 } 2067 if (tagnum == 0xA002 || tagnum == 0xA003) { 2068 if (tagnum == 0xA002) 2069 new_value = new_width; /* ExifImageWidth Tag */ 2070 else 2071 new_value = new_height; /* ExifImageHeight Tag */ 2072 if (is_motorola) { 2073 data[offset+2] = 0; /* Format = unsigned long (4 octets) */ 2074 data[offset+3] = 4; 2075 data[offset+4] = 0; /* Number Of Components = 1 */ 2076 data[offset+5] = 0; 2077 data[offset+6] = 0; 2078 data[offset+7] = 1; 2079 data[offset+8] = 0; 2080 data[offset+9] = 0; 2081 data[offset+10] = (JOCTET)((new_value >> 8) & 0xFF); 2082 data[offset+11] = (JOCTET)(new_value & 0xFF); 2083 } else { 2084 data[offset+2] = 4; /* Format = unsigned long (4 octets) */ 2085 data[offset+3] = 0; 2086 data[offset+4] = 1; /* Number Of Components = 1 */ 2087 data[offset+5] = 0; 2088 data[offset+6] = 0; 2089 data[offset+7] = 0; 2090 data[offset+8] = (JOCTET)(new_value & 0xFF); 2091 data[offset+9] = (JOCTET)((new_value >> 8) & 0xFF); 2092 data[offset+10] = 0; 2093 data[offset+11] = 0; 2094 } 2095 } 2096 offset += 12; 2097 } while (--number_of_tags); 2098 } 2099 2100 2101 /* Adjust output image parameters as needed. 2102 * 2103 * This must be called after jpeg_copy_critical_parameters() 2104 * and before jpeg_write_coefficients(). 2105 * 2106 * The return value is the set of virtual coefficient arrays to be written 2107 * (either the ones allocated by jtransform_request_workspace, or the 2108 * original source data arrays). The caller will need to pass this value 2109 * to jpeg_write_coefficients(). 2110 */ 2111 2112 GLOBAL(jvirt_barray_ptr *) 2113 jtransform_adjust_parameters (j_decompress_ptr srcinfo, 2114 j_compress_ptr dstinfo, 2115 jvirt_barray_ptr *src_coef_arrays, 2116 jpeg_transform_info *info) 2117 { 2118 /* If force-to-grayscale is requested, adjust destination parameters */ 2119 if (info->force_grayscale) { 2120 /* First, ensure we have YCC or grayscale data, and that the source's 2121 * Y channel is full resolution. (No reasonable person would make Y 2122 * be less than full resolution, so actually coping with that case 2123 * isn't worth extra code space. But we check it to avoid crashing.) 2124 */ 2125 if ((((dstinfo->jpeg_color_space == JCS_YCbCr || 2126 dstinfo->jpeg_color_space == JCS_BG_YCC) && 2127 dstinfo->num_components == 3) || 2128 (dstinfo->jpeg_color_space == JCS_GRAYSCALE && 2129 dstinfo->num_components == 1)) && 2130 srcinfo->comp_info[0].h_samp_factor == srcinfo->max_h_samp_factor && 2131 srcinfo->comp_info[0].v_samp_factor == srcinfo->max_v_samp_factor) { 2132 /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed 2133 * properly. Among other things, it sets the target h_samp_factor & 2134 * v_samp_factor to 1, which typically won't match the source. 2135 * We have to preserve the source's quantization table number, however. 2136 */ 2137 int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no; 2138 jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE); 2139 dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no; 2140 } else { 2141 /* Sorry, can't do it */ 2142 ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL); 2143 } 2144 } else if (info->num_components == 1) { 2145 /* For a single-component source, we force the destination sampling factors 2146 * to 1x1, with or without force_grayscale. This is useful because some 2147 * decoders choke on grayscale images with other sampling factors. 2148 */ 2149 dstinfo->comp_info[0].h_samp_factor = 1; 2150 dstinfo->comp_info[0].v_samp_factor = 1; 2151 } 2152 2153 /* Correct the destination's image dimensions as necessary 2154 * for rotate/flip, resize, and crop operations. 2155 */ 2156 dstinfo->jpeg_width = info->output_width; 2157 dstinfo->jpeg_height = info->output_height; 2158 2159 /* Transpose destination image parameters, adjust quantization */ 2160 switch (info->transform) { 2161 case JXFORM_TRANSPOSE: 2162 case JXFORM_TRANSVERSE: 2163 case JXFORM_ROT_90: 2164 case JXFORM_ROT_270: 2165 transpose_critical_parameters(dstinfo); 2166 break; 2167 case JXFORM_DROP: 2168 if (info->drop_width != 0 && info->drop_height != 0) 2169 adjust_quant(srcinfo, src_coef_arrays, 2170 info->drop_ptr, info->drop_coef_arrays, 2171 info->trim, dstinfo); 2172 break; 2173 default: 2174 break; 2175 } 2176 2177 /* Adjust Exif properties */ 2178 if (srcinfo->marker_list != NULL && 2179 srcinfo->marker_list->marker == JPEG_APP0+1 && 2180 srcinfo->marker_list->data_length >= 6 && 2181 GETJOCTET(srcinfo->marker_list->data[0]) == 0x45 && 2182 GETJOCTET(srcinfo->marker_list->data[1]) == 0x78 && 2183 GETJOCTET(srcinfo->marker_list->data[2]) == 0x69 && 2184 GETJOCTET(srcinfo->marker_list->data[3]) == 0x66 && 2185 GETJOCTET(srcinfo->marker_list->data[4]) == 0 && 2186 GETJOCTET(srcinfo->marker_list->data[5]) == 0) { 2187 /* Suppress output of JFIF marker */ 2188 dstinfo->write_JFIF_header = FALSE; 2189 /* Adjust Exif image parameters */ 2190 if (dstinfo->jpeg_width != srcinfo->image_width || 2191 dstinfo->jpeg_height != srcinfo->image_height) 2192 /* Align data segment to start of TIFF structure for parsing */ 2193 adjust_exif_parameters(srcinfo->marker_list->data + 6, 2194 srcinfo->marker_list->data_length - 6, 2195 dstinfo->jpeg_width, dstinfo->jpeg_height); 2196 } 2197 2198 /* Return the appropriate output data set */ 2199 if (info->workspace_coef_arrays != NULL) 2200 return info->workspace_coef_arrays; 2201 return src_coef_arrays; 2202 } 2203 2204 2205 /* Execute the actual transformation, if any. 2206 * 2207 * This must be called *after* jpeg_write_coefficients, because it depends 2208 * on jpeg_write_coefficients to have computed subsidiary values such as 2209 * the per-component width and height fields in the destination object. 2210 * 2211 * Note that some transformations will modify the source data arrays! 2212 */ 2213 2214 GLOBAL(void) 2215 jtransform_execute_transform (j_decompress_ptr srcinfo, 2216 j_compress_ptr dstinfo, 2217 jvirt_barray_ptr *src_coef_arrays, 2218 jpeg_transform_info *info) 2219 { 2220 jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays; 2221 2222 /* Note: conditions tested here should match those in switch statement 2223 * in jtransform_request_workspace() 2224 */ 2225 switch (info->transform) { 2226 case JXFORM_NONE: 2227 if (info->output_width > srcinfo->output_width || 2228 info->output_height > srcinfo->output_height) { 2229 if (info->output_width > srcinfo->output_width && 2230 info->crop_width_set == JCROP_REFLECT) 2231 do_crop_ext_reflect(srcinfo, dstinfo, 2232 info->x_crop_offset, info->y_crop_offset, 2233 src_coef_arrays, dst_coef_arrays); 2234 else if (info->output_width > srcinfo->output_width && 2235 info->crop_width_set == JCROP_FORCE) 2236 do_crop_ext_flat(srcinfo, dstinfo, 2237 info->x_crop_offset, info->y_crop_offset, 2238 src_coef_arrays, dst_coef_arrays); 2239 else 2240 do_crop_ext_zero(srcinfo, dstinfo, 2241 info->x_crop_offset, info->y_crop_offset, 2242 src_coef_arrays, dst_coef_arrays); 2243 } else if (info->x_crop_offset != 0 || info->y_crop_offset != 0) 2244 do_crop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 2245 src_coef_arrays, dst_coef_arrays); 2246 break; 2247 case JXFORM_FLIP_H: 2248 if (info->y_crop_offset != 0) 2249 do_flip_h(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 2250 src_coef_arrays, dst_coef_arrays); 2251 else 2252 do_flip_h_no_crop(srcinfo, dstinfo, info->x_crop_offset, 2253 src_coef_arrays); 2254 break; 2255 case JXFORM_FLIP_V: 2256 do_flip_v(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 2257 src_coef_arrays, dst_coef_arrays); 2258 break; 2259 case JXFORM_TRANSPOSE: 2260 do_transpose(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 2261 src_coef_arrays, dst_coef_arrays); 2262 break; 2263 case JXFORM_TRANSVERSE: 2264 do_transverse(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 2265 src_coef_arrays, dst_coef_arrays); 2266 break; 2267 case JXFORM_ROT_90: 2268 do_rot_90(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 2269 src_coef_arrays, dst_coef_arrays); 2270 break; 2271 case JXFORM_ROT_180: 2272 do_rot_180(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 2273 src_coef_arrays, dst_coef_arrays); 2274 break; 2275 case JXFORM_ROT_270: 2276 do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 2277 src_coef_arrays, dst_coef_arrays); 2278 break; 2279 case JXFORM_WIPE: 2280 if (info->crop_width_set == JCROP_REFLECT && 2281 info->y_crop_offset == 0 && info->drop_height == 2282 (JDIMENSION) jdiv_round_up 2283 ((long) info->output_height, (long) info->iMCU_sample_height) && 2284 (info->x_crop_offset == 0 || 2285 info->x_crop_offset + info->drop_width == 2286 (JDIMENSION) jdiv_round_up 2287 ((long) info->output_width, (long) info->iMCU_sample_width))) 2288 do_reflect(srcinfo, dstinfo, info->x_crop_offset, 2289 src_coef_arrays, info->drop_width, info->drop_height); 2290 else if (info->crop_width_set == JCROP_FORCE) 2291 do_flatten(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 2292 src_coef_arrays, info->drop_width, info->drop_height); 2293 else 2294 do_wipe(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 2295 src_coef_arrays, info->drop_width, info->drop_height); 2296 break; 2297 case JXFORM_DROP: 2298 if (info->drop_width != 0 && info->drop_height != 0) 2299 do_drop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 2300 src_coef_arrays, info->drop_ptr, info->drop_coef_arrays, 2301 info->drop_width, info->drop_height); 2302 break; 2303 } 2304 } 2305 2306 /* jtransform_perfect_transform 2307 * 2308 * Determine whether lossless transformation is perfectly 2309 * possible for a specified image and transformation. 2310 * 2311 * Inputs: 2312 * image_width, image_height: source image dimensions. 2313 * MCU_width, MCU_height: pixel dimensions of MCU. 2314 * transform: transformation identifier. 2315 * Parameter sources from initialized jpeg_struct 2316 * (after reading source header): 2317 * image_width = cinfo.image_width 2318 * image_height = cinfo.image_height 2319 * MCU_width = cinfo.max_h_samp_factor * cinfo.block_size 2320 * MCU_height = cinfo.max_v_samp_factor * cinfo.block_size 2321 * Result: 2322 * TRUE = perfect transformation possible 2323 * FALSE = perfect transformation not possible 2324 * (may use custom action then) 2325 */ 2326 2327 GLOBAL(boolean) 2328 jtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height, 2329 int MCU_width, int MCU_height, 2330 JXFORM_CODE transform) 2331 { 2332 boolean result = TRUE; /* initialize TRUE */ 2333 2334 switch (transform) { 2335 case JXFORM_FLIP_H: 2336 case JXFORM_ROT_270: 2337 if (image_width % (JDIMENSION) MCU_width) 2338 result = FALSE; 2339 break; 2340 case JXFORM_FLIP_V: 2341 case JXFORM_ROT_90: 2342 if (image_height % (JDIMENSION) MCU_height) 2343 result = FALSE; 2344 break; 2345 case JXFORM_TRANSVERSE: 2346 case JXFORM_ROT_180: 2347 if (image_width % (JDIMENSION) MCU_width) 2348 result = FALSE; 2349 if (image_height % (JDIMENSION) MCU_height) 2350 result = FALSE; 2351 break; 2352 default: 2353 break; 2354 } 2355 2356 return result; 2357 } 2358 2359 #endif /* TRANSFORMS_SUPPORTED */ 2360 2361 2362 /* Setup decompression object to save desired markers in memory. 2363 * This must be called before jpeg_read_header() to have the desired effect. 2364 */ 2365 2366 GLOBAL(void) 2367 jcopy_markers_setup (j_decompress_ptr srcinfo, JCOPY_OPTION option) 2368 { 2369 #ifdef SAVE_MARKERS_SUPPORTED 2370 int m; 2371 2372 /* Save comments except under NONE option */ 2373 if (option != JCOPYOPT_NONE) { 2374 jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF); 2375 } 2376 /* Save all types of APPn markers iff ALL option */ 2377 if (option == JCOPYOPT_ALL) { 2378 for (m = 0; m < 16; m++) 2379 jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF); 2380 } 2381 #endif /* SAVE_MARKERS_SUPPORTED */ 2382 } 2383 2384 /* Copy markers saved in the given source object to the destination object. 2385 * This should be called just after jpeg_start_compress() or 2386 * jpeg_write_coefficients(). 2387 * Note that those routines will have written the SOI, and also the 2388 * JFIF APP0 or Adobe APP14 markers if selected. 2389 */ 2390 2391 GLOBAL(void) 2392 jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 2393 JCOPY_OPTION option) 2394 { 2395 jpeg_saved_marker_ptr marker; 2396 2397 /* In the current implementation, we don't actually need to examine the 2398 * option flag here; we just copy everything that got saved. 2399 * But to avoid confusion, we do not output JFIF and Adobe APP14 markers 2400 * if the encoder library already wrote one. 2401 */ 2402 for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) { 2403 if (dstinfo->write_JFIF_header && 2404 marker->marker == JPEG_APP0 && 2405 marker->data_length >= 5 && 2406 GETJOCTET(marker->data[0]) == 0x4A && 2407 GETJOCTET(marker->data[1]) == 0x46 && 2408 GETJOCTET(marker->data[2]) == 0x49 && 2409 GETJOCTET(marker->data[3]) == 0x46 && 2410 GETJOCTET(marker->data[4]) == 0) 2411 continue; /* reject duplicate JFIF */ 2412 if (dstinfo->write_Adobe_marker && 2413 marker->marker == JPEG_APP0+14 && 2414 marker->data_length >= 5 && 2415 GETJOCTET(marker->data[0]) == 0x41 && 2416 GETJOCTET(marker->data[1]) == 0x64 && 2417 GETJOCTET(marker->data[2]) == 0x6F && 2418 GETJOCTET(marker->data[3]) == 0x62 && 2419 GETJOCTET(marker->data[4]) == 0x65) 2420 continue; /* reject duplicate Adobe */ 2421 #ifdef NEED_FAR_POINTERS 2422 /* We could use jpeg_write_marker if the data weren't FAR... */ 2423 { 2424 unsigned int i; 2425 jpeg_write_m_header(dstinfo, marker->marker, marker->data_length); 2426 for (i = 0; i < marker->data_length; i++) 2427 jpeg_write_m_byte(dstinfo, marker->data[i]); 2428 } 2429 #else 2430 jpeg_write_marker(dstinfo, marker->marker, 2431 marker->data, marker->data_length); 2432 #endif 2433 } 2434 } 2435