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