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