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