Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: uzair Camera_LS_Y201 F7_Ethernet LCD_DISCO_F746NG NetworkAPI SDFileSystem mbed
transupp.c
00001 /* 00002 * transupp.c 00003 * 00004 * Copyright (C) 1997-2013, Thomas G. Lane, Guido Vollbeding. 00005 * This file is part of the Independent JPEG Group's software. 00006 * For conditions of distribution and use, see the accompanying README file. 00007 * 00008 * This file contains image transformation routines and other utility code 00009 * used by the jpegtran sample application. These are NOT part of the core 00010 * JPEG library. But we keep these routines separate from jpegtran.c to 00011 * ease the task of maintaining jpegtran-like programs that have other user 00012 * interfaces. 00013 */ 00014 00015 /* Although this file really shouldn't have access to the library internals, 00016 * it's helpful to let it call jround_up() and jcopy_block_row(). 00017 */ 00018 #define JPEG_INTERNALS 00019 00020 #include "jinclude.h" 00021 #include "jpeglib.h" 00022 #include "transupp.h" /* My own external interface */ 00023 #include <ctype.h> /* to declare isdigit() */ 00024 00025 00026 #if TRANSFORMS_SUPPORTED 00027 00028 /* 00029 * Lossless image transformation routines. These routines work on DCT 00030 * coefficient arrays and thus do not require any lossy decompression 00031 * or recompression of the image. 00032 * Thanks to Guido Vollbeding for the initial design and code of this feature, 00033 * and to Ben Jackson for introducing the cropping feature. 00034 * 00035 * Horizontal flipping is done in-place, using a single top-to-bottom 00036 * pass through the virtual source array. It will thus be much the 00037 * fastest option for images larger than main memory. 00038 * 00039 * The other routines require a set of destination virtual arrays, so they 00040 * need twice as much memory as jpegtran normally does. The destination 00041 * arrays are always written in normal scan order (top to bottom) because 00042 * the virtual array manager expects this. The source arrays will be scanned 00043 * in the corresponding order, which means multiple passes through the source 00044 * arrays for most of the transforms. That could result in much thrashing 00045 * if the image is larger than main memory. 00046 * 00047 * If cropping or trimming is involved, the destination arrays may be smaller 00048 * than the source arrays. Note it is not possible to do horizontal flip 00049 * in-place when a nonzero Y crop offset is specified, since we'd have to move 00050 * data from one block row to another but the virtual array manager doesn't 00051 * guarantee we can touch more than one row at a time. So in that case, 00052 * we have to use a separate destination array. 00053 * 00054 * Some notes about the operating environment of the individual transform 00055 * routines: 00056 * 1. Both the source and destination virtual arrays are allocated from the 00057 * source JPEG object, and therefore should be manipulated by calling the 00058 * source's memory manager. 00059 * 2. The destination's component count should be used. It may be smaller 00060 * than the source's when forcing to grayscale. 00061 * 3. Likewise the destination's sampling factors should be used. When 00062 * forcing to grayscale the destination's sampling factors will be all 1, 00063 * and we may as well take that as the effective iMCU size. 00064 * 4. When "trim" is in effect, the destination's dimensions will be the 00065 * trimmed values but the source's will be untrimmed. 00066 * 5. When "crop" is in effect, the destination's dimensions will be the 00067 * cropped values but the source's will be uncropped. Each transform 00068 * routine is responsible for picking up source data starting at the 00069 * correct X and Y offset for the crop region. (The X and Y offsets 00070 * passed to the transform routines are measured in iMCU blocks of the 00071 * destination.) 00072 * 6. All the routines assume that the source and destination buffers are 00073 * padded out to a full iMCU boundary. This is true, although for the 00074 * source buffer it is an undocumented property of jdcoefct.c. 00075 */ 00076 00077 00078 LOCAL(void) 00079 do_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 00080 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 00081 jvirt_barray_ptr *src_coef_arrays, 00082 jvirt_barray_ptr *dst_coef_arrays) 00083 /* Crop. This is only used when no rotate/flip is requested with the crop. */ 00084 { 00085 JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks; 00086 int ci, offset_y; 00087 JBLOCKARRAY src_buffer, dst_buffer; 00088 jpeg_component_info *compptr; 00089 00090 /* We simply have to copy the right amount of data (the destination's 00091 * image size) starting at the given X and Y offsets in the source. 00092 */ 00093 for (ci = 0; ci < dstinfo->num_components; ci++) { 00094 compptr = dstinfo->comp_info + ci; 00095 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 00096 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 00097 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 00098 dst_blk_y += compptr->v_samp_factor) { 00099 dst_buffer = (*srcinfo->mem->access_virt_barray) 00100 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 00101 (JDIMENSION) compptr->v_samp_factor, TRUE); 00102 src_buffer = (*srcinfo->mem->access_virt_barray) 00103 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 00104 dst_blk_y + y_crop_blocks, 00105 (JDIMENSION) compptr->v_samp_factor, FALSE); 00106 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 00107 jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, 00108 dst_buffer[offset_y], 00109 compptr->width_in_blocks); 00110 } 00111 } 00112 } 00113 } 00114 00115 00116 LOCAL(void) 00117 do_crop_ext (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 00118 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 00119 jvirt_barray_ptr *src_coef_arrays, 00120 jvirt_barray_ptr *dst_coef_arrays) 00121 /* Crop. This is only used when no rotate/flip is requested with the crop. 00122 * Extension: If the destination size is larger than the source, we fill in 00123 * the extra area with zero (neutral gray). Note we also have to zero partial 00124 * iMCUs at the right and bottom edge of the source image area in this case. 00125 */ 00126 { 00127 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height; 00128 JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks; 00129 int ci, offset_y; 00130 JBLOCKARRAY src_buffer, dst_buffer; 00131 jpeg_component_info *compptr; 00132 00133 MCU_cols = srcinfo->output_width / 00134 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); 00135 MCU_rows = srcinfo->output_height / 00136 (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); 00137 00138 for (ci = 0; ci < dstinfo->num_components; ci++) { 00139 compptr = dstinfo->comp_info + ci; 00140 comp_width = MCU_cols * compptr->h_samp_factor; 00141 comp_height = MCU_rows * compptr->v_samp_factor; 00142 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 00143 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 00144 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 00145 dst_blk_y += compptr->v_samp_factor) { 00146 dst_buffer = (*srcinfo->mem->access_virt_barray) 00147 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 00148 (JDIMENSION) compptr->v_samp_factor, TRUE); 00149 if (dstinfo->jpeg_height > srcinfo->output_height) { 00150 if (dst_blk_y < y_crop_blocks || 00151 dst_blk_y >= comp_height + y_crop_blocks) { 00152 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 00153 FMEMZERO(dst_buffer[offset_y], 00154 compptr->width_in_blocks * SIZEOF(JBLOCK)); 00155 } 00156 continue; 00157 } 00158 src_buffer = (*srcinfo->mem->access_virt_barray) 00159 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 00160 dst_blk_y - y_crop_blocks, 00161 (JDIMENSION) compptr->v_samp_factor, FALSE); 00162 } else { 00163 src_buffer = (*srcinfo->mem->access_virt_barray) 00164 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 00165 dst_blk_y + y_crop_blocks, 00166 (JDIMENSION) compptr->v_samp_factor, FALSE); 00167 } 00168 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 00169 if (dstinfo->jpeg_width > srcinfo->output_width) { 00170 if (x_crop_blocks > 0) { 00171 FMEMZERO(dst_buffer[offset_y], 00172 x_crop_blocks * SIZEOF(JBLOCK)); 00173 } 00174 jcopy_block_row(src_buffer[offset_y], 00175 dst_buffer[offset_y] + x_crop_blocks, 00176 comp_width); 00177 if (compptr->width_in_blocks > comp_width + x_crop_blocks) { 00178 FMEMZERO(dst_buffer[offset_y] + 00179 comp_width + x_crop_blocks, 00180 (compptr->width_in_blocks - 00181 comp_width - x_crop_blocks) * SIZEOF(JBLOCK)); 00182 } 00183 } else { 00184 jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, 00185 dst_buffer[offset_y], 00186 compptr->width_in_blocks); 00187 } 00188 } 00189 } 00190 } 00191 } 00192 00193 00194 LOCAL(void) 00195 do_wipe (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 00196 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 00197 jvirt_barray_ptr *src_coef_arrays, 00198 JDIMENSION drop_width, JDIMENSION drop_height) 00199 /* Wipe - drop content of specified area, fill with zero (neutral gray) */ 00200 { 00201 JDIMENSION comp_width, comp_height; 00202 JDIMENSION blk_y, x_wipe_blocks, y_wipe_blocks; 00203 int ci, offset_y; 00204 JBLOCKARRAY buffer; 00205 jpeg_component_info *compptr; 00206 00207 for (ci = 0; ci < dstinfo->num_components; ci++) { 00208 compptr = dstinfo->comp_info + ci; 00209 comp_width = drop_width * compptr->h_samp_factor; 00210 comp_height = drop_height * compptr->v_samp_factor; 00211 x_wipe_blocks = x_crop_offset * compptr->h_samp_factor; 00212 y_wipe_blocks = y_crop_offset * compptr->v_samp_factor; 00213 for (blk_y = 0; blk_y < comp_height; blk_y += compptr->v_samp_factor) { 00214 buffer = (*srcinfo->mem->access_virt_barray) 00215 ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y + y_wipe_blocks, 00216 (JDIMENSION) compptr->v_samp_factor, TRUE); 00217 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 00218 FMEMZERO(buffer[offset_y] + x_wipe_blocks, 00219 comp_width * SIZEOF(JBLOCK)); 00220 } 00221 } 00222 } 00223 } 00224 00225 00226 LOCAL(void) 00227 do_flip_h_no_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 00228 JDIMENSION x_crop_offset, 00229 jvirt_barray_ptr *src_coef_arrays) 00230 /* Horizontal flip; done in-place, so no separate dest array is required. 00231 * NB: this only works when y_crop_offset is zero. 00232 */ 00233 { 00234 JDIMENSION MCU_cols, comp_width, blk_x, blk_y, x_crop_blocks; 00235 int ci, k, offset_y; 00236 JBLOCKARRAY buffer; 00237 JCOEFPTR ptr1, ptr2; 00238 JCOEF temp1, temp2; 00239 jpeg_component_info *compptr; 00240 00241 /* Horizontal mirroring of DCT blocks is accomplished by swapping 00242 * pairs of blocks in-place. Within a DCT block, we perform horizontal 00243 * mirroring by changing the signs of odd-numbered columns. 00244 * Partial iMCUs at the right edge are left untouched. 00245 */ 00246 MCU_cols = srcinfo->output_width / 00247 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); 00248 00249 for (ci = 0; ci < dstinfo->num_components; ci++) { 00250 compptr = dstinfo->comp_info + ci; 00251 comp_width = MCU_cols * compptr->h_samp_factor; 00252 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 00253 for (blk_y = 0; blk_y < compptr->height_in_blocks; 00254 blk_y += compptr->v_samp_factor) { 00255 buffer = (*srcinfo->mem->access_virt_barray) 00256 ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y, 00257 (JDIMENSION) compptr->v_samp_factor, TRUE); 00258 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 00259 /* Do the mirroring */ 00260 for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) { 00261 ptr1 = buffer[offset_y][blk_x]; 00262 ptr2 = buffer[offset_y][comp_width - blk_x - 1]; 00263 /* this unrolled loop doesn't need to know which row it's on... */ 00264 for (k = 0; k < DCTSIZE2; k += 2) { 00265 temp1 = *ptr1; /* swap even column */ 00266 temp2 = *ptr2; 00267 *ptr1++ = temp2; 00268 *ptr2++ = temp1; 00269 temp1 = *ptr1; /* swap odd column with sign change */ 00270 temp2 = *ptr2; 00271 *ptr1++ = -temp2; 00272 *ptr2++ = -temp1; 00273 } 00274 } 00275 if (x_crop_blocks > 0) { 00276 /* Now left-justify the portion of the data to be kept. 00277 * We can't use a single jcopy_block_row() call because that routine 00278 * depends on memcpy(), whose behavior is unspecified for overlapping 00279 * source and destination areas. Sigh. 00280 */ 00281 for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) { 00282 jcopy_block_row(buffer[offset_y] + blk_x + x_crop_blocks, 00283 buffer[offset_y] + blk_x, 00284 (JDIMENSION) 1); 00285 } 00286 } 00287 } 00288 } 00289 } 00290 } 00291 00292 00293 LOCAL(void) 00294 do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 00295 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 00296 jvirt_barray_ptr *src_coef_arrays, 00297 jvirt_barray_ptr *dst_coef_arrays) 00298 /* Horizontal flip in general cropping case */ 00299 { 00300 JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y; 00301 JDIMENSION x_crop_blocks, y_crop_blocks; 00302 int ci, k, offset_y; 00303 JBLOCKARRAY src_buffer, dst_buffer; 00304 JBLOCKROW src_row_ptr, dst_row_ptr; 00305 JCOEFPTR src_ptr, dst_ptr; 00306 jpeg_component_info *compptr; 00307 00308 /* Here we must output into a separate array because we can't touch 00309 * different rows of a single virtual array simultaneously. Otherwise, 00310 * this is essentially the same as the routine above. 00311 */ 00312 MCU_cols = srcinfo->output_width / 00313 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); 00314 00315 for (ci = 0; ci < dstinfo->num_components; ci++) { 00316 compptr = dstinfo->comp_info + ci; 00317 comp_width = MCU_cols * compptr->h_samp_factor; 00318 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 00319 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 00320 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 00321 dst_blk_y += compptr->v_samp_factor) { 00322 dst_buffer = (*srcinfo->mem->access_virt_barray) 00323 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 00324 (JDIMENSION) compptr->v_samp_factor, TRUE); 00325 src_buffer = (*srcinfo->mem->access_virt_barray) 00326 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 00327 dst_blk_y + y_crop_blocks, 00328 (JDIMENSION) compptr->v_samp_factor, FALSE); 00329 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 00330 dst_row_ptr = dst_buffer[offset_y]; 00331 src_row_ptr = src_buffer[offset_y]; 00332 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { 00333 if (x_crop_blocks + dst_blk_x < comp_width) { 00334 /* Do the mirrorable blocks */ 00335 dst_ptr = dst_row_ptr[dst_blk_x]; 00336 src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; 00337 /* this unrolled loop doesn't need to know which row it's on... */ 00338 for (k = 0; k < DCTSIZE2; k += 2) { 00339 *dst_ptr++ = *src_ptr++; /* copy even column */ 00340 *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */ 00341 } 00342 } else { 00343 /* Copy last partial block(s) verbatim */ 00344 jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks, 00345 dst_row_ptr + dst_blk_x, 00346 (JDIMENSION) 1); 00347 } 00348 } 00349 } 00350 } 00351 } 00352 } 00353 00354 00355 LOCAL(void) 00356 do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 00357 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 00358 jvirt_barray_ptr *src_coef_arrays, 00359 jvirt_barray_ptr *dst_coef_arrays) 00360 /* Vertical flip */ 00361 { 00362 JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; 00363 JDIMENSION x_crop_blocks, y_crop_blocks; 00364 int ci, i, j, offset_y; 00365 JBLOCKARRAY src_buffer, dst_buffer; 00366 JBLOCKROW src_row_ptr, dst_row_ptr; 00367 JCOEFPTR src_ptr, dst_ptr; 00368 jpeg_component_info *compptr; 00369 00370 /* We output into a separate array because we can't touch different 00371 * rows of the source virtual array simultaneously. Otherwise, this 00372 * is a pretty straightforward analog of horizontal flip. 00373 * Within a DCT block, vertical mirroring is done by changing the signs 00374 * of odd-numbered rows. 00375 * Partial iMCUs at the bottom edge are copied verbatim. 00376 */ 00377 MCU_rows = srcinfo->output_height / 00378 (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); 00379 00380 for (ci = 0; ci < dstinfo->num_components; ci++) { 00381 compptr = dstinfo->comp_info + ci; 00382 comp_height = MCU_rows * compptr->v_samp_factor; 00383 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 00384 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 00385 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 00386 dst_blk_y += compptr->v_samp_factor) { 00387 dst_buffer = (*srcinfo->mem->access_virt_barray) 00388 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 00389 (JDIMENSION) compptr->v_samp_factor, TRUE); 00390 if (y_crop_blocks + dst_blk_y < comp_height) { 00391 /* Row is within the mirrorable area. */ 00392 src_buffer = (*srcinfo->mem->access_virt_barray) 00393 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 00394 comp_height - y_crop_blocks - dst_blk_y - 00395 (JDIMENSION) compptr->v_samp_factor, 00396 (JDIMENSION) compptr->v_samp_factor, FALSE); 00397 } else { 00398 /* Bottom-edge blocks will be copied verbatim. */ 00399 src_buffer = (*srcinfo->mem->access_virt_barray) 00400 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 00401 dst_blk_y + y_crop_blocks, 00402 (JDIMENSION) compptr->v_samp_factor, FALSE); 00403 } 00404 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 00405 if (y_crop_blocks + dst_blk_y < comp_height) { 00406 /* Row is within the mirrorable area. */ 00407 dst_row_ptr = dst_buffer[offset_y]; 00408 src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; 00409 src_row_ptr += x_crop_blocks; 00410 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; 00411 dst_blk_x++) { 00412 dst_ptr = dst_row_ptr[dst_blk_x]; 00413 src_ptr = src_row_ptr[dst_blk_x]; 00414 for (i = 0; i < DCTSIZE; i += 2) { 00415 /* copy even row */ 00416 for (j = 0; j < DCTSIZE; j++) 00417 *dst_ptr++ = *src_ptr++; 00418 /* copy odd row with sign change */ 00419 for (j = 0; j < DCTSIZE; j++) 00420 *dst_ptr++ = - *src_ptr++; 00421 } 00422 } 00423 } else { 00424 /* Just copy row verbatim. */ 00425 jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, 00426 dst_buffer[offset_y], 00427 compptr->width_in_blocks); 00428 } 00429 } 00430 } 00431 } 00432 } 00433 00434 00435 LOCAL(void) 00436 do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 00437 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 00438 jvirt_barray_ptr *src_coef_arrays, 00439 jvirt_barray_ptr *dst_coef_arrays) 00440 /* Transpose source into destination */ 00441 { 00442 JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks; 00443 int ci, i, j, offset_x, offset_y; 00444 JBLOCKARRAY src_buffer, dst_buffer; 00445 JCOEFPTR src_ptr, dst_ptr; 00446 jpeg_component_info *compptr; 00447 00448 /* Transposing pixels within a block just requires transposing the 00449 * DCT coefficients. 00450 * Partial iMCUs at the edges require no special treatment; we simply 00451 * process all the available DCT blocks for every component. 00452 */ 00453 for (ci = 0; ci < dstinfo->num_components; ci++) { 00454 compptr = dstinfo->comp_info + ci; 00455 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 00456 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 00457 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 00458 dst_blk_y += compptr->v_samp_factor) { 00459 dst_buffer = (*srcinfo->mem->access_virt_barray) 00460 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 00461 (JDIMENSION) compptr->v_samp_factor, TRUE); 00462 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 00463 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; 00464 dst_blk_x += compptr->h_samp_factor) { 00465 src_buffer = (*srcinfo->mem->access_virt_barray) 00466 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 00467 dst_blk_x + x_crop_blocks, 00468 (JDIMENSION) compptr->h_samp_factor, FALSE); 00469 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { 00470 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; 00471 src_ptr = src_buffer[offset_x][dst_blk_y + offset_y + y_crop_blocks]; 00472 for (i = 0; i < DCTSIZE; i++) 00473 for (j = 0; j < DCTSIZE; j++) 00474 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 00475 } 00476 } 00477 } 00478 } 00479 } 00480 } 00481 00482 00483 LOCAL(void) 00484 do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 00485 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 00486 jvirt_barray_ptr *src_coef_arrays, 00487 jvirt_barray_ptr *dst_coef_arrays) 00488 /* 90 degree rotation is equivalent to 00489 * 1. Transposing the image; 00490 * 2. Horizontal mirroring. 00491 * These two steps are merged into a single processing routine. 00492 */ 00493 { 00494 JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y; 00495 JDIMENSION x_crop_blocks, y_crop_blocks; 00496 int ci, i, j, offset_x, offset_y; 00497 JBLOCKARRAY src_buffer, dst_buffer; 00498 JCOEFPTR src_ptr, dst_ptr; 00499 jpeg_component_info *compptr; 00500 00501 /* Because of the horizontal mirror step, we can't process partial iMCUs 00502 * at the (output) right edge properly. They just get transposed and 00503 * not mirrored. 00504 */ 00505 MCU_cols = srcinfo->output_height / 00506 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); 00507 00508 for (ci = 0; ci < dstinfo->num_components; ci++) { 00509 compptr = dstinfo->comp_info + ci; 00510 comp_width = MCU_cols * compptr->h_samp_factor; 00511 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 00512 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 00513 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 00514 dst_blk_y += compptr->v_samp_factor) { 00515 dst_buffer = (*srcinfo->mem->access_virt_barray) 00516 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 00517 (JDIMENSION) compptr->v_samp_factor, TRUE); 00518 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 00519 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; 00520 dst_blk_x += compptr->h_samp_factor) { 00521 if (x_crop_blocks + dst_blk_x < comp_width) { 00522 /* Block is within the mirrorable area. */ 00523 src_buffer = (*srcinfo->mem->access_virt_barray) 00524 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 00525 comp_width - x_crop_blocks - dst_blk_x - 00526 (JDIMENSION) compptr->h_samp_factor, 00527 (JDIMENSION) compptr->h_samp_factor, FALSE); 00528 } else { 00529 /* Edge blocks are transposed but not mirrored. */ 00530 src_buffer = (*srcinfo->mem->access_virt_barray) 00531 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 00532 dst_blk_x + x_crop_blocks, 00533 (JDIMENSION) compptr->h_samp_factor, FALSE); 00534 } 00535 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { 00536 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; 00537 if (x_crop_blocks + dst_blk_x < comp_width) { 00538 /* Block is within the mirrorable area. */ 00539 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] 00540 [dst_blk_y + offset_y + y_crop_blocks]; 00541 for (i = 0; i < DCTSIZE; i++) { 00542 for (j = 0; j < DCTSIZE; j++) 00543 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 00544 i++; 00545 for (j = 0; j < DCTSIZE; j++) 00546 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 00547 } 00548 } else { 00549 /* Edge blocks are transposed but not mirrored. */ 00550 src_ptr = src_buffer[offset_x] 00551 [dst_blk_y + offset_y + y_crop_blocks]; 00552 for (i = 0; i < DCTSIZE; i++) 00553 for (j = 0; j < DCTSIZE; j++) 00554 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 00555 } 00556 } 00557 } 00558 } 00559 } 00560 } 00561 } 00562 00563 00564 LOCAL(void) 00565 do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 00566 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 00567 jvirt_barray_ptr *src_coef_arrays, 00568 jvirt_barray_ptr *dst_coef_arrays) 00569 /* 270 degree rotation is equivalent to 00570 * 1. Horizontal mirroring; 00571 * 2. Transposing the image. 00572 * These two steps are merged into a single processing routine. 00573 */ 00574 { 00575 JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; 00576 JDIMENSION x_crop_blocks, y_crop_blocks; 00577 int ci, i, j, offset_x, offset_y; 00578 JBLOCKARRAY src_buffer, dst_buffer; 00579 JCOEFPTR src_ptr, dst_ptr; 00580 jpeg_component_info *compptr; 00581 00582 /* Because of the horizontal mirror step, we can't process partial iMCUs 00583 * at the (output) bottom edge properly. They just get transposed and 00584 * not mirrored. 00585 */ 00586 MCU_rows = srcinfo->output_width / 00587 (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); 00588 00589 for (ci = 0; ci < dstinfo->num_components; ci++) { 00590 compptr = dstinfo->comp_info + ci; 00591 comp_height = MCU_rows * compptr->v_samp_factor; 00592 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 00593 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 00594 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 00595 dst_blk_y += compptr->v_samp_factor) { 00596 dst_buffer = (*srcinfo->mem->access_virt_barray) 00597 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 00598 (JDIMENSION) compptr->v_samp_factor, TRUE); 00599 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 00600 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; 00601 dst_blk_x += compptr->h_samp_factor) { 00602 src_buffer = (*srcinfo->mem->access_virt_barray) 00603 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 00604 dst_blk_x + x_crop_blocks, 00605 (JDIMENSION) compptr->h_samp_factor, FALSE); 00606 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { 00607 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; 00608 if (y_crop_blocks + dst_blk_y < comp_height) { 00609 /* Block is within the mirrorable area. */ 00610 src_ptr = src_buffer[offset_x] 00611 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; 00612 for (i = 0; i < DCTSIZE; i++) { 00613 for (j = 0; j < DCTSIZE; j++) { 00614 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 00615 j++; 00616 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 00617 } 00618 } 00619 } else { 00620 /* Edge blocks are transposed but not mirrored. */ 00621 src_ptr = src_buffer[offset_x] 00622 [dst_blk_y + offset_y + y_crop_blocks]; 00623 for (i = 0; i < DCTSIZE; i++) 00624 for (j = 0; j < DCTSIZE; j++) 00625 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 00626 } 00627 } 00628 } 00629 } 00630 } 00631 } 00632 } 00633 00634 00635 LOCAL(void) 00636 do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 00637 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 00638 jvirt_barray_ptr *src_coef_arrays, 00639 jvirt_barray_ptr *dst_coef_arrays) 00640 /* 180 degree rotation is equivalent to 00641 * 1. Vertical mirroring; 00642 * 2. Horizontal mirroring. 00643 * These two steps are merged into a single processing routine. 00644 */ 00645 { 00646 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; 00647 JDIMENSION x_crop_blocks, y_crop_blocks; 00648 int ci, i, j, offset_y; 00649 JBLOCKARRAY src_buffer, dst_buffer; 00650 JBLOCKROW src_row_ptr, dst_row_ptr; 00651 JCOEFPTR src_ptr, dst_ptr; 00652 jpeg_component_info *compptr; 00653 00654 MCU_cols = srcinfo->output_width / 00655 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); 00656 MCU_rows = srcinfo->output_height / 00657 (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); 00658 00659 for (ci = 0; ci < dstinfo->num_components; ci++) { 00660 compptr = dstinfo->comp_info + ci; 00661 comp_width = MCU_cols * compptr->h_samp_factor; 00662 comp_height = MCU_rows * compptr->v_samp_factor; 00663 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 00664 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 00665 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 00666 dst_blk_y += compptr->v_samp_factor) { 00667 dst_buffer = (*srcinfo->mem->access_virt_barray) 00668 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 00669 (JDIMENSION) compptr->v_samp_factor, TRUE); 00670 if (y_crop_blocks + dst_blk_y < comp_height) { 00671 /* Row is within the vertically mirrorable area. */ 00672 src_buffer = (*srcinfo->mem->access_virt_barray) 00673 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 00674 comp_height - y_crop_blocks - dst_blk_y - 00675 (JDIMENSION) compptr->v_samp_factor, 00676 (JDIMENSION) compptr->v_samp_factor, FALSE); 00677 } else { 00678 /* Bottom-edge rows are only mirrored horizontally. */ 00679 src_buffer = (*srcinfo->mem->access_virt_barray) 00680 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 00681 dst_blk_y + y_crop_blocks, 00682 (JDIMENSION) compptr->v_samp_factor, FALSE); 00683 } 00684 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 00685 dst_row_ptr = dst_buffer[offset_y]; 00686 if (y_crop_blocks + dst_blk_y < comp_height) { 00687 /* Row is within the mirrorable area. */ 00688 src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; 00689 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { 00690 dst_ptr = dst_row_ptr[dst_blk_x]; 00691 if (x_crop_blocks + dst_blk_x < comp_width) { 00692 /* Process the blocks that can be mirrored both ways. */ 00693 src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; 00694 for (i = 0; i < DCTSIZE; i += 2) { 00695 /* For even row, negate every odd column. */ 00696 for (j = 0; j < DCTSIZE; j += 2) { 00697 *dst_ptr++ = *src_ptr++; 00698 *dst_ptr++ = - *src_ptr++; 00699 } 00700 /* For odd row, negate every even column. */ 00701 for (j = 0; j < DCTSIZE; j += 2) { 00702 *dst_ptr++ = - *src_ptr++; 00703 *dst_ptr++ = *src_ptr++; 00704 } 00705 } 00706 } else { 00707 /* Any remaining right-edge blocks are only mirrored vertically. */ 00708 src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x]; 00709 for (i = 0; i < DCTSIZE; i += 2) { 00710 for (j = 0; j < DCTSIZE; j++) 00711 *dst_ptr++ = *src_ptr++; 00712 for (j = 0; j < DCTSIZE; j++) 00713 *dst_ptr++ = - *src_ptr++; 00714 } 00715 } 00716 } 00717 } else { 00718 /* Remaining rows are just mirrored horizontally. */ 00719 src_row_ptr = src_buffer[offset_y]; 00720 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { 00721 if (x_crop_blocks + dst_blk_x < comp_width) { 00722 /* Process the blocks that can be mirrored. */ 00723 dst_ptr = dst_row_ptr[dst_blk_x]; 00724 src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; 00725 for (i = 0; i < DCTSIZE2; i += 2) { 00726 *dst_ptr++ = *src_ptr++; 00727 *dst_ptr++ = - *src_ptr++; 00728 } 00729 } else { 00730 /* Any remaining right-edge blocks are only copied. */ 00731 jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks, 00732 dst_row_ptr + dst_blk_x, 00733 (JDIMENSION) 1); 00734 } 00735 } 00736 } 00737 } 00738 } 00739 } 00740 } 00741 00742 00743 LOCAL(void) 00744 do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 00745 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 00746 jvirt_barray_ptr *src_coef_arrays, 00747 jvirt_barray_ptr *dst_coef_arrays) 00748 /* Transverse transpose is equivalent to 00749 * 1. 180 degree rotation; 00750 * 2. Transposition; 00751 * or 00752 * 1. Horizontal mirroring; 00753 * 2. Transposition; 00754 * 3. Horizontal mirroring. 00755 * These steps are merged into a single processing routine. 00756 */ 00757 { 00758 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; 00759 JDIMENSION x_crop_blocks, y_crop_blocks; 00760 int ci, i, j, offset_x, offset_y; 00761 JBLOCKARRAY src_buffer, dst_buffer; 00762 JCOEFPTR src_ptr, dst_ptr; 00763 jpeg_component_info *compptr; 00764 00765 MCU_cols = srcinfo->output_height / 00766 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); 00767 MCU_rows = srcinfo->output_width / 00768 (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); 00769 00770 for (ci = 0; ci < dstinfo->num_components; ci++) { 00771 compptr = dstinfo->comp_info + ci; 00772 comp_width = MCU_cols * compptr->h_samp_factor; 00773 comp_height = MCU_rows * compptr->v_samp_factor; 00774 x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 00775 y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 00776 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 00777 dst_blk_y += compptr->v_samp_factor) { 00778 dst_buffer = (*srcinfo->mem->access_virt_barray) 00779 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 00780 (JDIMENSION) compptr->v_samp_factor, TRUE); 00781 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 00782 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; 00783 dst_blk_x += compptr->h_samp_factor) { 00784 if (x_crop_blocks + dst_blk_x < comp_width) { 00785 /* Block is within the mirrorable area. */ 00786 src_buffer = (*srcinfo->mem->access_virt_barray) 00787 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 00788 comp_width - x_crop_blocks - dst_blk_x - 00789 (JDIMENSION) compptr->h_samp_factor, 00790 (JDIMENSION) compptr->h_samp_factor, FALSE); 00791 } else { 00792 src_buffer = (*srcinfo->mem->access_virt_barray) 00793 ((j_common_ptr) srcinfo, src_coef_arrays[ci], 00794 dst_blk_x + x_crop_blocks, 00795 (JDIMENSION) compptr->h_samp_factor, FALSE); 00796 } 00797 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { 00798 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; 00799 if (y_crop_blocks + dst_blk_y < comp_height) { 00800 if (x_crop_blocks + dst_blk_x < comp_width) { 00801 /* Block is within the mirrorable area. */ 00802 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] 00803 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; 00804 for (i = 0; i < DCTSIZE; i++) { 00805 for (j = 0; j < DCTSIZE; j++) { 00806 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 00807 j++; 00808 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 00809 } 00810 i++; 00811 for (j = 0; j < DCTSIZE; j++) { 00812 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 00813 j++; 00814 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 00815 } 00816 } 00817 } else { 00818 /* Right-edge blocks are mirrored in y only */ 00819 src_ptr = src_buffer[offset_x] 00820 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; 00821 for (i = 0; i < DCTSIZE; i++) { 00822 for (j = 0; j < DCTSIZE; j++) { 00823 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 00824 j++; 00825 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 00826 } 00827 } 00828 } 00829 } else { 00830 if (x_crop_blocks + dst_blk_x < comp_width) { 00831 /* Bottom-edge blocks are mirrored in x only */ 00832 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] 00833 [dst_blk_y + offset_y + y_crop_blocks]; 00834 for (i = 0; i < DCTSIZE; i++) { 00835 for (j = 0; j < DCTSIZE; j++) 00836 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 00837 i++; 00838 for (j = 0; j < DCTSIZE; j++) 00839 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 00840 } 00841 } else { 00842 /* At lower right corner, just transpose, no mirroring */ 00843 src_ptr = src_buffer[offset_x] 00844 [dst_blk_y + offset_y + y_crop_blocks]; 00845 for (i = 0; i < DCTSIZE; i++) 00846 for (j = 0; j < DCTSIZE; j++) 00847 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 00848 } 00849 } 00850 } 00851 } 00852 } 00853 } 00854 } 00855 } 00856 00857 00858 /* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec. 00859 * Returns TRUE if valid integer found, FALSE if not. 00860 * *strptr is advanced over the digit string, and *result is set to its value. 00861 */ 00862 00863 LOCAL(boolean) 00864 jt_read_integer (const char ** strptr, JDIMENSION * result) 00865 { 00866 const char * ptr = *strptr; 00867 JDIMENSION val = 0; 00868 00869 for (; isdigit(*ptr); ptr++) { 00870 val = val * 10 + (JDIMENSION) (*ptr - '0'); 00871 } 00872 *result = val; 00873 if (ptr == *strptr) 00874 return FALSE; /* oops, no digits */ 00875 *strptr = ptr; 00876 return TRUE; 00877 } 00878 00879 00880 /* Parse a crop specification (written in X11 geometry style). 00881 * The routine returns TRUE if the spec string is valid, FALSE if not. 00882 * 00883 * The crop spec string should have the format 00884 * <width>[f]x<height>[f]{+-}<xoffset>{+-}<yoffset> 00885 * where width, height, xoffset, and yoffset are unsigned integers. 00886 * Each of the elements can be omitted to indicate a default value. 00887 * (A weakness of this style is that it is not possible to omit xoffset 00888 * while specifying yoffset, since they look alike.) 00889 * 00890 * This code is loosely based on XParseGeometry from the X11 distribution. 00891 */ 00892 00893 GLOBAL(boolean) 00894 jtransform_parse_crop_spec (jpeg_transform_info *info, const char *spec) 00895 { 00896 info->crop = FALSE; 00897 info->crop_width_set = JCROP_UNSET; 00898 info->crop_height_set = JCROP_UNSET; 00899 info->crop_xoffset_set = JCROP_UNSET; 00900 info->crop_yoffset_set = JCROP_UNSET; 00901 00902 if (isdigit(*spec)) { 00903 /* fetch width */ 00904 if (! jt_read_integer(&spec, &info->crop_width)) 00905 return FALSE; 00906 if (*spec == 'f' || *spec == 'F') { 00907 spec++; 00908 info->crop_width_set = JCROP_FORCE; 00909 } else 00910 info->crop_width_set = JCROP_POS; 00911 } 00912 if (*spec == 'x' || *spec == 'X') { 00913 /* fetch height */ 00914 spec++; 00915 if (! jt_read_integer(&spec, &info->crop_height)) 00916 return FALSE; 00917 if (*spec == 'f' || *spec == 'F') { 00918 spec++; 00919 info->crop_height_set = JCROP_FORCE; 00920 } else 00921 info->crop_height_set = JCROP_POS; 00922 } 00923 if (*spec == '+' || *spec == '-') { 00924 /* fetch xoffset */ 00925 info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS; 00926 spec++; 00927 if (! jt_read_integer(&spec, &info->crop_xoffset)) 00928 return FALSE; 00929 } 00930 if (*spec == '+' || *spec == '-') { 00931 /* fetch yoffset */ 00932 info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS; 00933 spec++; 00934 if (! jt_read_integer(&spec, &info->crop_yoffset)) 00935 return FALSE; 00936 } 00937 /* We had better have gotten to the end of the string. */ 00938 if (*spec != '\0') 00939 return FALSE; 00940 info->crop = TRUE; 00941 return TRUE; 00942 } 00943 00944 00945 /* Trim off any partial iMCUs on the indicated destination edge */ 00946 00947 LOCAL(void) 00948 trim_right_edge (jpeg_transform_info *info, JDIMENSION full_width) 00949 { 00950 JDIMENSION MCU_cols; 00951 00952 MCU_cols = info->output_width / info->iMCU_sample_width; 00953 if (MCU_cols > 0 && info->x_crop_offset + MCU_cols == 00954 full_width / info->iMCU_sample_width) 00955 info->output_width = MCU_cols * info->iMCU_sample_width; 00956 } 00957 00958 LOCAL(void) 00959 trim_bottom_edge (jpeg_transform_info *info, JDIMENSION full_height) 00960 { 00961 JDIMENSION MCU_rows; 00962 00963 MCU_rows = info->output_height / info->iMCU_sample_height; 00964 if (MCU_rows > 0 && info->y_crop_offset + MCU_rows == 00965 full_height / info->iMCU_sample_height) 00966 info->output_height = MCU_rows * info->iMCU_sample_height; 00967 } 00968 00969 00970 /* Request any required workspace. 00971 * 00972 * This routine figures out the size that the output image will be 00973 * (which implies that all the transform parameters must be set before 00974 * it is called). 00975 * 00976 * We allocate the workspace virtual arrays from the source decompression 00977 * object, so that all the arrays (both the original data and the workspace) 00978 * will be taken into account while making memory management decisions. 00979 * Hence, this routine must be called after jpeg_read_header (which reads 00980 * the image dimensions) and before jpeg_read_coefficients (which realizes 00981 * the source's virtual arrays). 00982 * 00983 * This function returns FALSE right away if -perfect is given 00984 * and transformation is not perfect. Otherwise returns TRUE. 00985 */ 00986 00987 GLOBAL(boolean) 00988 jtransform_request_workspace (j_decompress_ptr srcinfo, 00989 jpeg_transform_info *info) 00990 { 00991 jvirt_barray_ptr *coef_arrays; 00992 boolean need_workspace, transpose_it; 00993 jpeg_component_info *compptr; 00994 JDIMENSION xoffset, yoffset; 00995 JDIMENSION width_in_iMCUs, height_in_iMCUs; 00996 JDIMENSION width_in_blocks, height_in_blocks; 00997 int ci, h_samp_factor, v_samp_factor; 00998 00999 /* Determine number of components in output image */ 01000 if (info->force_grayscale && 01001 (srcinfo->jpeg_color_space == JCS_YCbCr || 01002 srcinfo->jpeg_color_space == JCS_BG_YCC) && 01003 srcinfo->num_components == 3) 01004 /* We'll only process the first component */ 01005 info->num_components = 1; 01006 else 01007 /* Process all the components */ 01008 info->num_components = srcinfo->num_components; 01009 01010 /* Compute output image dimensions and related values. */ 01011 jpeg_core_output_dimensions(srcinfo); 01012 01013 /* Return right away if -perfect is given and transformation is not perfect. 01014 */ 01015 if (info->perfect) { 01016 if (info->num_components == 1) { 01017 if (!jtransform_perfect_transform(srcinfo->output_width, 01018 srcinfo->output_height, 01019 srcinfo->min_DCT_h_scaled_size, 01020 srcinfo->min_DCT_v_scaled_size, 01021 info->transform)) 01022 return FALSE; 01023 } else { 01024 if (!jtransform_perfect_transform(srcinfo->output_width, 01025 srcinfo->output_height, 01026 srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size, 01027 srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size, 01028 info->transform)) 01029 return FALSE; 01030 } 01031 } 01032 01033 /* If there is only one output component, force the iMCU size to be 1; 01034 * else use the source iMCU size. (This allows us to do the right thing 01035 * when reducing color to grayscale, and also provides a handy way of 01036 * cleaning up "funny" grayscale images whose sampling factors are not 1x1.) 01037 */ 01038 switch (info->transform) { 01039 case JXFORM_TRANSPOSE: 01040 case JXFORM_TRANSVERSE: 01041 case JXFORM_ROT_90: 01042 case JXFORM_ROT_270: 01043 info->output_width = srcinfo->output_height; 01044 info->output_height = srcinfo->output_width; 01045 if (info->num_components == 1) { 01046 info->iMCU_sample_width = srcinfo->min_DCT_v_scaled_size; 01047 info->iMCU_sample_height = srcinfo->min_DCT_h_scaled_size; 01048 } else { 01049 info->iMCU_sample_width = 01050 srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size; 01051 info->iMCU_sample_height = 01052 srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size; 01053 } 01054 break; 01055 default: 01056 info->output_width = srcinfo->output_width; 01057 info->output_height = srcinfo->output_height; 01058 if (info->num_components == 1) { 01059 info->iMCU_sample_width = srcinfo->min_DCT_h_scaled_size; 01060 info->iMCU_sample_height = srcinfo->min_DCT_v_scaled_size; 01061 } else { 01062 info->iMCU_sample_width = 01063 srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size; 01064 info->iMCU_sample_height = 01065 srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size; 01066 } 01067 break; 01068 } 01069 01070 /* If cropping has been requested, compute the crop area's position and 01071 * dimensions, ensuring that its upper left corner falls at an iMCU boundary. 01072 */ 01073 if (info->crop) { 01074 /* Insert default values for unset crop parameters */ 01075 if (info->crop_xoffset_set == JCROP_UNSET) 01076 info->crop_xoffset = 0; /* default to +0 */ 01077 if (info->crop_yoffset_set == JCROP_UNSET) 01078 info->crop_yoffset = 0; /* default to +0 */ 01079 if (info->crop_width_set == JCROP_UNSET) { 01080 if (info->crop_xoffset >= info->output_width) 01081 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); 01082 info->crop_width = info->output_width - info->crop_xoffset; 01083 } else { 01084 /* Check for crop extension */ 01085 if (info->crop_width > info->output_width) { 01086 /* Crop extension does not work when transforming! */ 01087 if (info->transform != JXFORM_NONE || 01088 info->crop_xoffset >= info->crop_width || 01089 info->crop_xoffset > info->crop_width - info->output_width) 01090 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); 01091 } else { 01092 if (info->crop_xoffset >= info->output_width || 01093 info->crop_width <= 0 || 01094 info->crop_xoffset > info->output_width - info->crop_width) 01095 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); 01096 } 01097 } 01098 if (info->crop_height_set == JCROP_UNSET) { 01099 if (info->crop_yoffset >= info->output_height) 01100 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); 01101 info->crop_height = info->output_height - info->crop_yoffset; 01102 } else { 01103 /* Check for crop extension */ 01104 if (info->crop_height > info->output_height) { 01105 /* Crop extension does not work when transforming! */ 01106 if (info->transform != JXFORM_NONE || 01107 info->crop_yoffset >= info->crop_height || 01108 info->crop_yoffset > info->crop_height - info->output_height) 01109 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); 01110 } else { 01111 if (info->crop_yoffset >= info->output_height || 01112 info->crop_height <= 0 || 01113 info->crop_yoffset > info->output_height - info->crop_height) 01114 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); 01115 } 01116 } 01117 /* Convert negative crop offsets into regular offsets */ 01118 if (info->crop_xoffset_set != JCROP_NEG) 01119 xoffset = info->crop_xoffset; 01120 else if (info->crop_width > info->output_width) /* crop extension */ 01121 xoffset = info->crop_width - info->output_width - info->crop_xoffset; 01122 else 01123 xoffset = info->output_width - info->crop_width - info->crop_xoffset; 01124 if (info->crop_yoffset_set != JCROP_NEG) 01125 yoffset = info->crop_yoffset; 01126 else if (info->crop_height > info->output_height) /* crop extension */ 01127 yoffset = info->crop_height - info->output_height - info->crop_yoffset; 01128 else 01129 yoffset = info->output_height - info->crop_height - info->crop_yoffset; 01130 /* Now adjust so that upper left corner falls at an iMCU boundary */ 01131 if (info->transform == JXFORM_WIPE) { 01132 /* Ensure the effective wipe region will cover the requested */ 01133 info->drop_width = (JDIMENSION) jdiv_round_up 01134 ((long) (info->crop_width + (xoffset % info->iMCU_sample_width)), 01135 (long) info->iMCU_sample_width); 01136 info->drop_height = (JDIMENSION) jdiv_round_up 01137 ((long) (info->crop_height + (yoffset % info->iMCU_sample_height)), 01138 (long) info->iMCU_sample_height); 01139 } else { 01140 /* Ensure the effective crop region will cover the requested */ 01141 if (info->crop_width_set == JCROP_FORCE || 01142 info->crop_width > info->output_width) 01143 info->output_width = info->crop_width; 01144 else 01145 info->output_width = 01146 info->crop_width + (xoffset % info->iMCU_sample_width); 01147 if (info->crop_height_set == JCROP_FORCE || 01148 info->crop_height > info->output_height) 01149 info->output_height = info->crop_height; 01150 else 01151 info->output_height = 01152 info->crop_height + (yoffset % info->iMCU_sample_height); 01153 } 01154 /* Save x/y offsets measured in iMCUs */ 01155 info->x_crop_offset = xoffset / info->iMCU_sample_width; 01156 info->y_crop_offset = yoffset / info->iMCU_sample_height; 01157 } else { 01158 info->x_crop_offset = 0; 01159 info->y_crop_offset = 0; 01160 } 01161 01162 /* Figure out whether we need workspace arrays, 01163 * and if so whether they are transposed relative to the source. 01164 */ 01165 need_workspace = FALSE; 01166 transpose_it = FALSE; 01167 switch (info->transform) { 01168 case JXFORM_NONE: 01169 if (info->x_crop_offset != 0 || info->y_crop_offset != 0 || 01170 info->output_width > srcinfo->output_width || 01171 info->output_height > srcinfo->output_height) 01172 need_workspace = TRUE; 01173 /* No workspace needed if neither cropping nor transforming */ 01174 break; 01175 case JXFORM_FLIP_H: 01176 if (info->trim) 01177 trim_right_edge(info, srcinfo->output_width); 01178 if (info->y_crop_offset != 0) 01179 need_workspace = TRUE; 01180 /* do_flip_h_no_crop doesn't need a workspace array */ 01181 break; 01182 case JXFORM_FLIP_V: 01183 if (info->trim) 01184 trim_bottom_edge(info, srcinfo->output_height); 01185 /* Need workspace arrays having same dimensions as source image. */ 01186 need_workspace = TRUE; 01187 break; 01188 case JXFORM_TRANSPOSE: 01189 /* transpose does NOT have to trim anything */ 01190 /* Need workspace arrays having transposed dimensions. */ 01191 need_workspace = TRUE; 01192 transpose_it = TRUE; 01193 break; 01194 case JXFORM_TRANSVERSE: 01195 if (info->trim) { 01196 trim_right_edge(info, srcinfo->output_height); 01197 trim_bottom_edge(info, srcinfo->output_width); 01198 } 01199 /* Need workspace arrays having transposed dimensions. */ 01200 need_workspace = TRUE; 01201 transpose_it = TRUE; 01202 break; 01203 case JXFORM_ROT_90: 01204 if (info->trim) 01205 trim_right_edge(info, srcinfo->output_height); 01206 /* Need workspace arrays having transposed dimensions. */ 01207 need_workspace = TRUE; 01208 transpose_it = TRUE; 01209 break; 01210 case JXFORM_ROT_180: 01211 if (info->trim) { 01212 trim_right_edge(info, srcinfo->output_width); 01213 trim_bottom_edge(info, srcinfo->output_height); 01214 } 01215 /* Need workspace arrays having same dimensions as source image. */ 01216 need_workspace = TRUE; 01217 break; 01218 case JXFORM_ROT_270: 01219 if (info->trim) 01220 trim_bottom_edge(info, srcinfo->output_width); 01221 /* Need workspace arrays having transposed dimensions. */ 01222 need_workspace = TRUE; 01223 transpose_it = TRUE; 01224 break; 01225 case JXFORM_WIPE: 01226 break; 01227 } 01228 01229 /* Allocate workspace if needed. 01230 * Note that we allocate arrays padded out to the next iMCU boundary, 01231 * so that transform routines need not worry about missing edge blocks. 01232 */ 01233 if (need_workspace) { 01234 coef_arrays = (jvirt_barray_ptr *) 01235 (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE, 01236 SIZEOF(jvirt_barray_ptr) * info->num_components); 01237 width_in_iMCUs = (JDIMENSION) 01238 jdiv_round_up((long) info->output_width, 01239 (long) info->iMCU_sample_width); 01240 height_in_iMCUs = (JDIMENSION) 01241 jdiv_round_up((long) info->output_height, 01242 (long) info->iMCU_sample_height); 01243 for (ci = 0; ci < info->num_components; ci++) { 01244 compptr = srcinfo->comp_info + ci; 01245 if (info->num_components == 1) { 01246 /* we're going to force samp factors to 1x1 in this case */ 01247 h_samp_factor = v_samp_factor = 1; 01248 } else if (transpose_it) { 01249 h_samp_factor = compptr->v_samp_factor; 01250 v_samp_factor = compptr->h_samp_factor; 01251 } else { 01252 h_samp_factor = compptr->h_samp_factor; 01253 v_samp_factor = compptr->v_samp_factor; 01254 } 01255 width_in_blocks = width_in_iMCUs * h_samp_factor; 01256 height_in_blocks = height_in_iMCUs * v_samp_factor; 01257 coef_arrays[ci] = (*srcinfo->mem->request_virt_barray) 01258 ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE, 01259 width_in_blocks, height_in_blocks, (JDIMENSION) v_samp_factor); 01260 } 01261 info->workspace_coef_arrays = coef_arrays; 01262 } else 01263 info->workspace_coef_arrays = NULL; 01264 01265 return TRUE; 01266 } 01267 01268 01269 /* Transpose destination image parameters */ 01270 01271 LOCAL(void) 01272 transpose_critical_parameters (j_compress_ptr dstinfo) 01273 { 01274 int tblno, i, j, ci, itemp; 01275 jpeg_component_info *compptr; 01276 JQUANT_TBL *qtblptr; 01277 JDIMENSION jtemp; 01278 UINT16 qtemp; 01279 01280 /* Transpose image dimensions */ 01281 jtemp = dstinfo->image_width; 01282 dstinfo->image_width = dstinfo->image_height; 01283 dstinfo->image_height = jtemp; 01284 itemp = dstinfo->min_DCT_h_scaled_size; 01285 dstinfo->min_DCT_h_scaled_size = dstinfo->min_DCT_v_scaled_size; 01286 dstinfo->min_DCT_v_scaled_size = itemp; 01287 01288 /* Transpose sampling factors */ 01289 for (ci = 0; ci < dstinfo->num_components; ci++) { 01290 compptr = dstinfo->comp_info + ci; 01291 itemp = compptr->h_samp_factor; 01292 compptr->h_samp_factor = compptr->v_samp_factor; 01293 compptr->v_samp_factor = itemp; 01294 } 01295 01296 /* Transpose quantization tables */ 01297 for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { 01298 qtblptr = dstinfo->quant_tbl_ptrs[tblno]; 01299 if (qtblptr != NULL) { 01300 for (i = 0; i < DCTSIZE; i++) { 01301 for (j = 0; j < i; j++) { 01302 qtemp = qtblptr->quantval[i*DCTSIZE+j]; 01303 qtblptr->quantval[i*DCTSIZE+j] = qtblptr->quantval[j*DCTSIZE+i]; 01304 qtblptr->quantval[j*DCTSIZE+i] = qtemp; 01305 } 01306 } 01307 } 01308 } 01309 } 01310 01311 01312 /* Adjust Exif image parameters. 01313 * 01314 * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible. 01315 */ 01316 01317 LOCAL(void) 01318 adjust_exif_parameters (JOCTET FAR * data, unsigned int length, 01319 JDIMENSION new_width, JDIMENSION new_height) 01320 { 01321 boolean is_motorola; /* Flag for byte order */ 01322 unsigned int number_of_tags, tagnum; 01323 unsigned int firstoffset, offset; 01324 JDIMENSION new_value; 01325 01326 if (length < 12) return; /* Length of an IFD entry */ 01327 01328 /* Discover byte order */ 01329 if (GETJOCTET(data[0]) == 0x49 && GETJOCTET(data[1]) == 0x49) 01330 is_motorola = FALSE; 01331 else if (GETJOCTET(data[0]) == 0x4D && GETJOCTET(data[1]) == 0x4D) 01332 is_motorola = TRUE; 01333 else 01334 return; 01335 01336 /* Check Tag Mark */ 01337 if (is_motorola) { 01338 if (GETJOCTET(data[2]) != 0) return; 01339 if (GETJOCTET(data[3]) != 0x2A) return; 01340 } else { 01341 if (GETJOCTET(data[3]) != 0) return; 01342 if (GETJOCTET(data[2]) != 0x2A) return; 01343 } 01344 01345 /* Get first IFD offset (offset to IFD0) */ 01346 if (is_motorola) { 01347 if (GETJOCTET(data[4]) != 0) return; 01348 if (GETJOCTET(data[5]) != 0) return; 01349 firstoffset = GETJOCTET(data[6]); 01350 firstoffset <<= 8; 01351 firstoffset += GETJOCTET(data[7]); 01352 } else { 01353 if (GETJOCTET(data[7]) != 0) return; 01354 if (GETJOCTET(data[6]) != 0) return; 01355 firstoffset = GETJOCTET(data[5]); 01356 firstoffset <<= 8; 01357 firstoffset += GETJOCTET(data[4]); 01358 } 01359 if (firstoffset > length - 2) return; /* check end of data segment */ 01360 01361 /* Get the number of directory entries contained in this IFD */ 01362 if (is_motorola) { 01363 number_of_tags = GETJOCTET(data[firstoffset]); 01364 number_of_tags <<= 8; 01365 number_of_tags += GETJOCTET(data[firstoffset+1]); 01366 } else { 01367 number_of_tags = GETJOCTET(data[firstoffset+1]); 01368 number_of_tags <<= 8; 01369 number_of_tags += GETJOCTET(data[firstoffset]); 01370 } 01371 if (number_of_tags == 0) return; 01372 firstoffset += 2; 01373 01374 /* Search for ExifSubIFD offset Tag in IFD0 */ 01375 for (;;) { 01376 if (firstoffset > length - 12) return; /* check end of data segment */ 01377 /* Get Tag number */ 01378 if (is_motorola) { 01379 tagnum = GETJOCTET(data[firstoffset]); 01380 tagnum <<= 8; 01381 tagnum += GETJOCTET(data[firstoffset+1]); 01382 } else { 01383 tagnum = GETJOCTET(data[firstoffset+1]); 01384 tagnum <<= 8; 01385 tagnum += GETJOCTET(data[firstoffset]); 01386 } 01387 if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */ 01388 if (--number_of_tags == 0) return; 01389 firstoffset += 12; 01390 } 01391 01392 /* Get the ExifSubIFD offset */ 01393 if (is_motorola) { 01394 if (GETJOCTET(data[firstoffset+8]) != 0) return; 01395 if (GETJOCTET(data[firstoffset+9]) != 0) return; 01396 offset = GETJOCTET(data[firstoffset+10]); 01397 offset <<= 8; 01398 offset += GETJOCTET(data[firstoffset+11]); 01399 } else { 01400 if (GETJOCTET(data[firstoffset+11]) != 0) return; 01401 if (GETJOCTET(data[firstoffset+10]) != 0) return; 01402 offset = GETJOCTET(data[firstoffset+9]); 01403 offset <<= 8; 01404 offset += GETJOCTET(data[firstoffset+8]); 01405 } 01406 if (offset > length - 2) return; /* check end of data segment */ 01407 01408 /* Get the number of directory entries contained in this SubIFD */ 01409 if (is_motorola) { 01410 number_of_tags = GETJOCTET(data[offset]); 01411 number_of_tags <<= 8; 01412 number_of_tags += GETJOCTET(data[offset+1]); 01413 } else { 01414 number_of_tags = GETJOCTET(data[offset+1]); 01415 number_of_tags <<= 8; 01416 number_of_tags += GETJOCTET(data[offset]); 01417 } 01418 if (number_of_tags < 2) return; 01419 offset += 2; 01420 01421 /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */ 01422 do { 01423 if (offset > length - 12) return; /* check end of data segment */ 01424 /* Get Tag number */ 01425 if (is_motorola) { 01426 tagnum = GETJOCTET(data[offset]); 01427 tagnum <<= 8; 01428 tagnum += GETJOCTET(data[offset+1]); 01429 } else { 01430 tagnum = GETJOCTET(data[offset+1]); 01431 tagnum <<= 8; 01432 tagnum += GETJOCTET(data[offset]); 01433 } 01434 if (tagnum == 0xA002 || tagnum == 0xA003) { 01435 if (tagnum == 0xA002) 01436 new_value = new_width; /* ExifImageWidth Tag */ 01437 else 01438 new_value = new_height; /* ExifImageHeight Tag */ 01439 if (is_motorola) { 01440 data[offset+2] = 0; /* Format = unsigned long (4 octets) */ 01441 data[offset+3] = 4; 01442 data[offset+4] = 0; /* Number Of Components = 1 */ 01443 data[offset+5] = 0; 01444 data[offset+6] = 0; 01445 data[offset+7] = 1; 01446 data[offset+8] = 0; 01447 data[offset+9] = 0; 01448 data[offset+10] = (JOCTET)((new_value >> 8) & 0xFF); 01449 data[offset+11] = (JOCTET)(new_value & 0xFF); 01450 } else { 01451 data[offset+2] = 4; /* Format = unsigned long (4 octets) */ 01452 data[offset+3] = 0; 01453 data[offset+4] = 1; /* Number Of Components = 1 */ 01454 data[offset+5] = 0; 01455 data[offset+6] = 0; 01456 data[offset+7] = 0; 01457 data[offset+8] = (JOCTET)(new_value & 0xFF); 01458 data[offset+9] = (JOCTET)((new_value >> 8) & 0xFF); 01459 data[offset+10] = 0; 01460 data[offset+11] = 0; 01461 } 01462 } 01463 offset += 12; 01464 } while (--number_of_tags); 01465 } 01466 01467 01468 /* Adjust output image parameters as needed. 01469 * 01470 * This must be called after jpeg_copy_critical_parameters() 01471 * and before jpeg_write_coefficients(). 01472 * 01473 * The return value is the set of virtual coefficient arrays to be written 01474 * (either the ones allocated by jtransform_request_workspace, or the 01475 * original source data arrays). The caller will need to pass this value 01476 * to jpeg_write_coefficients(). 01477 */ 01478 01479 GLOBAL(jvirt_barray_ptr *) 01480 jtransform_adjust_parameters (j_decompress_ptr srcinfo, 01481 j_compress_ptr dstinfo, 01482 jvirt_barray_ptr *src_coef_arrays, 01483 jpeg_transform_info *info) 01484 { 01485 /* If force-to-grayscale is requested, adjust destination parameters */ 01486 if (info->force_grayscale) { 01487 /* First, ensure we have YCC or grayscale data, and that the source's 01488 * Y channel is full resolution. (No reasonable person would make Y 01489 * be less than full resolution, so actually coping with that case 01490 * isn't worth extra code space. But we check it to avoid crashing.) 01491 */ 01492 if ((((dstinfo->jpeg_color_space == JCS_YCbCr || 01493 dstinfo->jpeg_color_space == JCS_BG_YCC) && 01494 dstinfo->num_components == 3) || 01495 (dstinfo->jpeg_color_space == JCS_GRAYSCALE && 01496 dstinfo->num_components == 1)) && 01497 srcinfo->comp_info[0].h_samp_factor == srcinfo->max_h_samp_factor && 01498 srcinfo->comp_info[0].v_samp_factor == srcinfo->max_v_samp_factor) { 01499 /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed 01500 * properly. Among other things, it sets the target h_samp_factor & 01501 * v_samp_factor to 1, which typically won't match the source. 01502 * We have to preserve the source's quantization table number, however. 01503 */ 01504 int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no; 01505 jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE); 01506 dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no; 01507 } else { 01508 /* Sorry, can't do it */ 01509 ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL); 01510 } 01511 } else if (info->num_components == 1) { 01512 /* For a single-component source, we force the destination sampling factors 01513 * to 1x1, with or without force_grayscale. This is useful because some 01514 * decoders choke on grayscale images with other sampling factors. 01515 */ 01516 dstinfo->comp_info[0].h_samp_factor = 1; 01517 dstinfo->comp_info[0].v_samp_factor = 1; 01518 } 01519 01520 /* Correct the destination's image dimensions as necessary 01521 * for rotate/flip, resize, and crop operations. 01522 */ 01523 dstinfo->jpeg_width = info->output_width; 01524 dstinfo->jpeg_height = info->output_height; 01525 01526 /* Transpose destination image parameters */ 01527 switch (info->transform) { 01528 case JXFORM_TRANSPOSE: 01529 case JXFORM_TRANSVERSE: 01530 case JXFORM_ROT_90: 01531 case JXFORM_ROT_270: 01532 transpose_critical_parameters(dstinfo); 01533 break; 01534 default: 01535 break; 01536 } 01537 01538 /* Adjust Exif properties */ 01539 if (srcinfo->marker_list != NULL && 01540 srcinfo->marker_list->marker == JPEG_APP0+1 && 01541 srcinfo->marker_list->data_length >= 6 && 01542 GETJOCTET(srcinfo->marker_list->data[0]) == 0x45 && 01543 GETJOCTET(srcinfo->marker_list->data[1]) == 0x78 && 01544 GETJOCTET(srcinfo->marker_list->data[2]) == 0x69 && 01545 GETJOCTET(srcinfo->marker_list->data[3]) == 0x66 && 01546 GETJOCTET(srcinfo->marker_list->data[4]) == 0 && 01547 GETJOCTET(srcinfo->marker_list->data[5]) == 0) { 01548 /* Suppress output of JFIF marker */ 01549 dstinfo->write_JFIF_header = FALSE; 01550 /* Adjust Exif image parameters */ 01551 if (dstinfo->jpeg_width != srcinfo->image_width || 01552 dstinfo->jpeg_height != srcinfo->image_height) 01553 /* Align data segment to start of TIFF structure for parsing */ 01554 adjust_exif_parameters(srcinfo->marker_list->data + 6, 01555 srcinfo->marker_list->data_length - 6, 01556 dstinfo->jpeg_width, dstinfo->jpeg_height); 01557 } 01558 01559 /* Return the appropriate output data set */ 01560 if (info->workspace_coef_arrays != NULL) 01561 return info->workspace_coef_arrays; 01562 return src_coef_arrays; 01563 } 01564 01565 01566 /* Execute the actual transformation, if any. 01567 * 01568 * This must be called *after* jpeg_write_coefficients, because it depends 01569 * on jpeg_write_coefficients to have computed subsidiary values such as 01570 * the per-component width and height fields in the destination object. 01571 * 01572 * Note that some transformations will modify the source data arrays! 01573 */ 01574 01575 GLOBAL(void) 01576 jtransform_execute_transform (j_decompress_ptr srcinfo, 01577 j_compress_ptr dstinfo, 01578 jvirt_barray_ptr *src_coef_arrays, 01579 jpeg_transform_info *info) 01580 { 01581 jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays; 01582 01583 /* Note: conditions tested here should match those in switch statement 01584 * in jtransform_request_workspace() 01585 */ 01586 switch (info->transform) { 01587 case JXFORM_NONE: 01588 if (info->output_width > srcinfo->output_width || 01589 info->output_height > srcinfo->output_height) 01590 do_crop_ext(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 01591 src_coef_arrays, dst_coef_arrays); 01592 else if (info->x_crop_offset != 0 || info->y_crop_offset != 0) 01593 do_crop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 01594 src_coef_arrays, dst_coef_arrays); 01595 break; 01596 case JXFORM_FLIP_H: 01597 if (info->y_crop_offset != 0) 01598 do_flip_h(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 01599 src_coef_arrays, dst_coef_arrays); 01600 else 01601 do_flip_h_no_crop(srcinfo, dstinfo, info->x_crop_offset, 01602 src_coef_arrays); 01603 break; 01604 case JXFORM_FLIP_V: 01605 do_flip_v(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 01606 src_coef_arrays, dst_coef_arrays); 01607 break; 01608 case JXFORM_TRANSPOSE: 01609 do_transpose(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 01610 src_coef_arrays, dst_coef_arrays); 01611 break; 01612 case JXFORM_TRANSVERSE: 01613 do_transverse(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 01614 src_coef_arrays, dst_coef_arrays); 01615 break; 01616 case JXFORM_ROT_90: 01617 do_rot_90(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 01618 src_coef_arrays, dst_coef_arrays); 01619 break; 01620 case JXFORM_ROT_180: 01621 do_rot_180(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 01622 src_coef_arrays, dst_coef_arrays); 01623 break; 01624 case JXFORM_ROT_270: 01625 do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 01626 src_coef_arrays, dst_coef_arrays); 01627 break; 01628 case JXFORM_WIPE: 01629 do_wipe(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 01630 src_coef_arrays, info->drop_width, info->drop_height); 01631 break; 01632 } 01633 } 01634 01635 /* jtransform_perfect_transform 01636 * 01637 * Determine whether lossless transformation is perfectly 01638 * possible for a specified image and transformation. 01639 * 01640 * Inputs: 01641 * image_width, image_height: source image dimensions. 01642 * MCU_width, MCU_height: pixel dimensions of MCU. 01643 * transform: transformation identifier. 01644 * Parameter sources from initialized jpeg_struct 01645 * (after reading source header): 01646 * image_width = cinfo.image_width 01647 * image_height = cinfo.image_height 01648 * MCU_width = cinfo.max_h_samp_factor * cinfo.block_size 01649 * MCU_height = cinfo.max_v_samp_factor * cinfo.block_size 01650 * Result: 01651 * TRUE = perfect transformation possible 01652 * FALSE = perfect transformation not possible 01653 * (may use custom action then) 01654 */ 01655 01656 GLOBAL(boolean) 01657 jtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height, 01658 int MCU_width, int MCU_height, 01659 JXFORM_CODE transform) 01660 { 01661 boolean result = TRUE; /* initialize TRUE */ 01662 01663 switch (transform) { 01664 case JXFORM_FLIP_H: 01665 case JXFORM_ROT_270: 01666 if (image_width % (JDIMENSION) MCU_width) 01667 result = FALSE; 01668 break; 01669 case JXFORM_FLIP_V: 01670 case JXFORM_ROT_90: 01671 if (image_height % (JDIMENSION) MCU_height) 01672 result = FALSE; 01673 break; 01674 case JXFORM_TRANSVERSE: 01675 case JXFORM_ROT_180: 01676 if (image_width % (JDIMENSION) MCU_width) 01677 result = FALSE; 01678 if (image_height % (JDIMENSION) MCU_height) 01679 result = FALSE; 01680 break; 01681 default: 01682 break; 01683 } 01684 01685 return result; 01686 } 01687 01688 #endif /* TRANSFORMS_SUPPORTED */ 01689 01690 01691 /* Setup decompression object to save desired markers in memory. 01692 * This must be called before jpeg_read_header() to have the desired effect. 01693 */ 01694 01695 GLOBAL(void) 01696 jcopy_markers_setup (j_decompress_ptr srcinfo, JCOPY_OPTION option) 01697 { 01698 #ifdef SAVE_MARKERS_SUPPORTED 01699 int m; 01700 01701 /* Save comments except under NONE option */ 01702 if (option != JCOPYOPT_NONE) { 01703 jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF); 01704 } 01705 /* Save all types of APPn markers iff ALL option */ 01706 if (option == JCOPYOPT_ALL) { 01707 for (m = 0; m < 16; m++) 01708 jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF); 01709 } 01710 #endif /* SAVE_MARKERS_SUPPORTED */ 01711 } 01712 01713 /* Copy markers saved in the given source object to the destination object. 01714 * This should be called just after jpeg_start_compress() or 01715 * jpeg_write_coefficients(). 01716 * Note that those routines will have written the SOI, and also the 01717 * JFIF APP0 or Adobe APP14 markers if selected. 01718 */ 01719 01720 GLOBAL(void) 01721 jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 01722 JCOPY_OPTION option) 01723 { 01724 jpeg_saved_marker_ptr marker; 01725 01726 /* In the current implementation, we don't actually need to examine the 01727 * option flag here; we just copy everything that got saved. 01728 * But to avoid confusion, we do not output JFIF and Adobe APP14 markers 01729 * if the encoder library already wrote one. 01730 */ 01731 for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) { 01732 if (dstinfo->write_JFIF_header && 01733 marker->marker == JPEG_APP0 && 01734 marker->data_length >= 5 && 01735 GETJOCTET(marker->data[0]) == 0x4A && 01736 GETJOCTET(marker->data[1]) == 0x46 && 01737 GETJOCTET(marker->data[2]) == 0x49 && 01738 GETJOCTET(marker->data[3]) == 0x46 && 01739 GETJOCTET(marker->data[4]) == 0) 01740 continue; /* reject duplicate JFIF */ 01741 if (dstinfo->write_Adobe_marker && 01742 marker->marker == JPEG_APP0+14 && 01743 marker->data_length >= 5 && 01744 GETJOCTET(marker->data[0]) == 0x41 && 01745 GETJOCTET(marker->data[1]) == 0x64 && 01746 GETJOCTET(marker->data[2]) == 0x6F && 01747 GETJOCTET(marker->data[3]) == 0x62 && 01748 GETJOCTET(marker->data[4]) == 0x65) 01749 continue; /* reject duplicate Adobe */ 01750 #ifdef NEED_FAR_POINTERS 01751 /* We could use jpeg_write_marker if the data weren't FAR... */ 01752 { 01753 unsigned int i; 01754 jpeg_write_m_header(dstinfo, marker->marker, marker->data_length); 01755 for (i = 0; i < marker->data_length; i++) 01756 jpeg_write_m_byte(dstinfo, marker->data[i]); 01757 } 01758 #else 01759 jpeg_write_marker(dstinfo, marker->marker, 01760 marker->data, marker->data_length); 01761 #endif 01762 } 01763 }
Generated on Wed Jul 13 2022 18:56:09 by
