15ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* 25ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * transupp.c 35ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 4cf763c0cd8116ac225bd2d36a71da33a3c7fcc46DRC * This file was part of the Independent JPEG Group's software: 55829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding * Copyright (C) 1997-2011, Thomas G. Lane, Guido Vollbeding. 6a6ef282a49f2d7d1b4d19cc89f63e81fd66b35b7DRC * libjpeg-turbo Modifications: 7c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC * Copyright (C) 2010, D. R. Commander. 86eb7d3798b5a79347c62825fc4c16f7ce673bdd0Alex Naidis * For conditions of distribution and use, see the accompanying README.ijg 96eb7d3798b5a79347c62825fc4c16f7ce673bdd0Alex Naidis * file. 105ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 115ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * This file contains image transformation routines and other utility code 125ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * used by the jpegtran sample application. These are NOT part of the core 135ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * JPEG library. But we keep these routines separate from jpegtran.c to 145ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * ease the task of maintaining jpegtran-like programs that have other user 155ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * interfaces. 165ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */ 175ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 185ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* Although this file really shouldn't have access to the library internals, 195ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * it's helpful to let it call jround_up() and jcopy_block_row(). 205ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */ 215ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane#define JPEG_INTERNALS 225ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 235ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane#include "jinclude.h" 245ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane#include "jpeglib.h" 25e5eaf37440b8e337ab150c017df7c03faf846c51DRC#include "transupp.h" /* My own external interface */ 26c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#include "jpegcomp.h" 27e5eaf37440b8e337ab150c017df7c03faf846c51DRC#include <ctype.h> /* to declare isdigit() */ 285ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 295ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 30c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#if JPEG_LIB_VERSION >= 70 31c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#define dstinfo_min_DCT_h_scaled_size dstinfo->min_DCT_h_scaled_size 32c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#define dstinfo_min_DCT_v_scaled_size dstinfo->min_DCT_v_scaled_size 33c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#else 34c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#define dstinfo_min_DCT_h_scaled_size DCTSIZE 35c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#define dstinfo_min_DCT_v_scaled_size DCTSIZE 36c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#endif 375ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 385ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 395ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane#if TRANSFORMS_SUPPORTED 405ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 415ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* 425ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * Lossless image transformation routines. These routines work on DCT 435ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * coefficient arrays and thus do not require any lossy decompression 445ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * or recompression of the image. 455996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * Thanks to Guido Vollbeding for the initial design and code of this feature, 465996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * and to Ben Jackson for introducing the cropping feature. 475ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 485ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * Horizontal flipping is done in-place, using a single top-to-bottom 495ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * pass through the virtual source array. It will thus be much the 505ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * fastest option for images larger than main memory. 515ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 525ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * The other routines require a set of destination virtual arrays, so they 535ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * need twice as much memory as jpegtran normally does. The destination 545ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * arrays are always written in normal scan order (top to bottom) because 555ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * the virtual array manager expects this. The source arrays will be scanned 565ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * in the corresponding order, which means multiple passes through the source 575ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * arrays for most of the transforms. That could result in much thrashing 585ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * if the image is larger than main memory. 595ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 605996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * If cropping or trimming is involved, the destination arrays may be smaller 615996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * than the source arrays. Note it is not possible to do horizontal flip 625996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * in-place when a nonzero Y crop offset is specified, since we'd have to move 635996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * data from one block row to another but the virtual array manager doesn't 645996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * guarantee we can touch more than one row at a time. So in that case, 655996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * we have to use a separate destination array. 665996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * 675ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * Some notes about the operating environment of the individual transform 685ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * routines: 695ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 1. Both the source and destination virtual arrays are allocated from the 705ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * source JPEG object, and therefore should be manipulated by calling the 715ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * source's memory manager. 725ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 2. The destination's component count should be used. It may be smaller 735ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * than the source's when forcing to grayscale. 745ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 3. Likewise the destination's sampling factors should be used. When 755ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * forcing to grayscale the destination's sampling factors will be all 1, 765ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * and we may as well take that as the effective iMCU size. 775ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 4. When "trim" is in effect, the destination's dimensions will be the 785ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * trimmed values but the source's will be untrimmed. 795996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * 5. When "crop" is in effect, the destination's dimensions will be the 805996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * cropped values but the source's will be uncropped. Each transform 815996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * routine is responsible for picking up source data starting at the 825996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * correct X and Y offset for the crop region. (The X and Y offsets 835996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * passed to the transform routines are measured in iMCU blocks of the 845996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * destination.) 855996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * 6. All the routines assume that the source and destination buffers are 865ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * padded out to a full iMCU boundary. This is true, although for the 875ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * source buffer it is an undocumented property of jdcoefct.c. 885ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */ 895ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 905ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 915ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneLOCAL(void) 925996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbedingdo_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 93e5eaf37440b8e337ab150c017df7c03faf846c51DRC JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 94e5eaf37440b8e337ab150c017df7c03faf846c51DRC jvirt_barray_ptr *src_coef_arrays, 95e5eaf37440b8e337ab150c017df7c03faf846c51DRC jvirt_barray_ptr *dst_coef_arrays) 965996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding/* Crop. This is only used when no rotate/flip is requested with the crop. */ 975ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{ 985996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks; 995996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding int ci, offset_y; 1005996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding JBLOCKARRAY src_buffer, dst_buffer; 1015996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding jpeg_component_info *compptr; 1025996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 1035996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* We simply have to copy the right amount of data (the destination's 1045996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * image size) starting at the given X and Y offsets in the source. 1055996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding */ 1065996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding for (ci = 0; ci < dstinfo->num_components; ci++) { 1075996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding compptr = dstinfo->comp_info + ci; 1085996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 1095996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 1105996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 111e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_blk_y += compptr->v_samp_factor) { 1125996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding dst_buffer = (*srcinfo->mem->access_virt_barray) 113e5eaf37440b8e337ab150c017df7c03faf846c51DRC ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 114e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) compptr->v_samp_factor, TRUE); 1155996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding src_buffer = (*srcinfo->mem->access_virt_barray) 116e5eaf37440b8e337ab150c017df7c03faf846c51DRC ((j_common_ptr) srcinfo, src_coef_arrays[ci], 117e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_blk_y + y_crop_blocks, 118e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) compptr->v_samp_factor, FALSE); 1195996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 120e5eaf37440b8e337ab150c017df7c03faf846c51DRC jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, 121e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_buffer[offset_y], 122e5eaf37440b8e337ab150c017df7c03faf846c51DRC compptr->width_in_blocks); 1235996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 1245996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 1255996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 1265996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding} 1275996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 1285996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 1295996a25e2f50d20d6a8f09830724035b49c3927bGuido VollbedingLOCAL(void) 1305996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbedingdo_flip_h_no_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 131e5eaf37440b8e337ab150c017df7c03faf846c51DRC JDIMENSION x_crop_offset, 132e5eaf37440b8e337ab150c017df7c03faf846c51DRC jvirt_barray_ptr *src_coef_arrays) 1335996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding/* Horizontal flip; done in-place, so no separate dest array is required. 1345996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * NB: this only works when y_crop_offset is zero. 1355996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding */ 1365996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding{ 1375996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding JDIMENSION MCU_cols, comp_width, blk_x, blk_y, x_crop_blocks; 1385ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane int ci, k, offset_y; 1395ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane JBLOCKARRAY buffer; 1405ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane JCOEFPTR ptr1, ptr2; 1415ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane JCOEF temp1, temp2; 1425ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane jpeg_component_info *compptr; 1435ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 1445ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane /* Horizontal mirroring of DCT blocks is accomplished by swapping 1455ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * pairs of blocks in-place. Within a DCT block, we perform horizontal 1465ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * mirroring by changing the signs of odd-numbered columns. 1475ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * Partial iMCUs at the right edge are left untouched. 1485ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */ 149989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding MCU_cols = srcinfo->output_width / 150c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size); 1515ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 1525ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (ci = 0; ci < dstinfo->num_components; ci++) { 1535ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane compptr = dstinfo->comp_info + ci; 1545ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane comp_width = MCU_cols * compptr->h_samp_factor; 1555996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 1565ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (blk_y = 0; blk_y < compptr->height_in_blocks; 157e5eaf37440b8e337ab150c017df7c03faf846c51DRC blk_y += compptr->v_samp_factor) { 1585ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane buffer = (*srcinfo->mem->access_virt_barray) 159e5eaf37440b8e337ab150c017df7c03faf846c51DRC ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y, 160e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) compptr->v_samp_factor, TRUE); 1615ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 162e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Do the mirroring */ 163e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) { 164e5eaf37440b8e337ab150c017df7c03faf846c51DRC ptr1 = buffer[offset_y][blk_x]; 165e5eaf37440b8e337ab150c017df7c03faf846c51DRC ptr2 = buffer[offset_y][comp_width - blk_x - 1]; 166e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* this unrolled loop doesn't need to know which row it's on... */ 167e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (k = 0; k < DCTSIZE2; k += 2) { 168e5eaf37440b8e337ab150c017df7c03faf846c51DRC temp1 = *ptr1; /* swap even column */ 169e5eaf37440b8e337ab150c017df7c03faf846c51DRC temp2 = *ptr2; 170e5eaf37440b8e337ab150c017df7c03faf846c51DRC *ptr1++ = temp2; 171e5eaf37440b8e337ab150c017df7c03faf846c51DRC *ptr2++ = temp1; 172e5eaf37440b8e337ab150c017df7c03faf846c51DRC temp1 = *ptr1; /* swap odd column with sign change */ 173e5eaf37440b8e337ab150c017df7c03faf846c51DRC temp2 = *ptr2; 174e5eaf37440b8e337ab150c017df7c03faf846c51DRC *ptr1++ = -temp2; 175e5eaf37440b8e337ab150c017df7c03faf846c51DRC *ptr2++ = -temp1; 176e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 177e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 178e5eaf37440b8e337ab150c017df7c03faf846c51DRC if (x_crop_blocks > 0) { 179e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Now left-justify the portion of the data to be kept. 180e5eaf37440b8e337ab150c017df7c03faf846c51DRC * We can't use a single jcopy_block_row() call because that routine 181e5eaf37440b8e337ab150c017df7c03faf846c51DRC * depends on memcpy(), whose behavior is unspecified for overlapping 182e5eaf37440b8e337ab150c017df7c03faf846c51DRC * source and destination areas. Sigh. 183e5eaf37440b8e337ab150c017df7c03faf846c51DRC */ 184e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) { 185e5eaf37440b8e337ab150c017df7c03faf846c51DRC jcopy_block_row(buffer[offset_y] + blk_x + x_crop_blocks, 186e5eaf37440b8e337ab150c017df7c03faf846c51DRC buffer[offset_y] + blk_x, 187e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) 1); 188e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 189e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 1905996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 1915996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 1925996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 1935996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding} 1945996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 1955996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 1965996a25e2f50d20d6a8f09830724035b49c3927bGuido VollbedingLOCAL(void) 1975996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbedingdo_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 198e5eaf37440b8e337ab150c017df7c03faf846c51DRC JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 199e5eaf37440b8e337ab150c017df7c03faf846c51DRC jvirt_barray_ptr *src_coef_arrays, 200e5eaf37440b8e337ab150c017df7c03faf846c51DRC jvirt_barray_ptr *dst_coef_arrays) 2015996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding/* Horizontal flip in general cropping case */ 2025996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding{ 2035996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y; 2045996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding JDIMENSION x_crop_blocks, y_crop_blocks; 2055996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding int ci, k, offset_y; 2065996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding JBLOCKARRAY src_buffer, dst_buffer; 2075996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding JBLOCKROW src_row_ptr, dst_row_ptr; 2085996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding JCOEFPTR src_ptr, dst_ptr; 2095996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding jpeg_component_info *compptr; 2105996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 2115996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Here we must output into a separate array because we can't touch 2125996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * different rows of a single virtual array simultaneously. Otherwise, 2135996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * this is essentially the same as the routine above. 2145996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding */ 215989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding MCU_cols = srcinfo->output_width / 216c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size); 2175996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 2185996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding for (ci = 0; ci < dstinfo->num_components; ci++) { 2195996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding compptr = dstinfo->comp_info + ci; 2205996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding comp_width = MCU_cols * compptr->h_samp_factor; 2215996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 2225996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 2235996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 224e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_blk_y += compptr->v_samp_factor) { 2255996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding dst_buffer = (*srcinfo->mem->access_virt_barray) 226e5eaf37440b8e337ab150c017df7c03faf846c51DRC ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 227e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) compptr->v_samp_factor, TRUE); 2285996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding src_buffer = (*srcinfo->mem->access_virt_barray) 229e5eaf37440b8e337ab150c017df7c03faf846c51DRC ((j_common_ptr) srcinfo, src_coef_arrays[ci], 230e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_blk_y + y_crop_blocks, 231e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) compptr->v_samp_factor, FALSE); 2325996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 233e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_row_ptr = dst_buffer[offset_y]; 234e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_row_ptr = src_buffer[offset_y]; 235e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { 236e5eaf37440b8e337ab150c017df7c03faf846c51DRC if (x_crop_blocks + dst_blk_x < comp_width) { 237e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Do the mirrorable blocks */ 238e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_ptr = dst_row_ptr[dst_blk_x]; 239e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; 240e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* this unrolled loop doesn't need to know which row it's on... */ 241e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (k = 0; k < DCTSIZE2; k += 2) { 242e5eaf37440b8e337ab150c017df7c03faf846c51DRC *dst_ptr++ = *src_ptr++; /* copy even column */ 243e5eaf37440b8e337ab150c017df7c03faf846c51DRC *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */ 244e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 245e5eaf37440b8e337ab150c017df7c03faf846c51DRC } else { 246e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Copy last partial block(s) verbatim */ 247e5eaf37440b8e337ab150c017df7c03faf846c51DRC jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks, 248e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_row_ptr + dst_blk_x, 249e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) 1); 250e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 251e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 2525ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 2535ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 2545ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 2555ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane} 2565ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 2575ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 2585ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneLOCAL(void) 2595ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lanedo_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 260e5eaf37440b8e337ab150c017df7c03faf846c51DRC JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 261e5eaf37440b8e337ab150c017df7c03faf846c51DRC jvirt_barray_ptr *src_coef_arrays, 262e5eaf37440b8e337ab150c017df7c03faf846c51DRC jvirt_barray_ptr *dst_coef_arrays) 2635ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* Vertical flip */ 2645ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{ 2655ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; 2665996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding JDIMENSION x_crop_blocks, y_crop_blocks; 2675ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane int ci, i, j, offset_y; 2685ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane JBLOCKARRAY src_buffer, dst_buffer; 2695ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane JBLOCKROW src_row_ptr, dst_row_ptr; 2705ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane JCOEFPTR src_ptr, dst_ptr; 2715ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane jpeg_component_info *compptr; 2725ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 2735ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane /* We output into a separate array because we can't touch different 2745ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * rows of the source virtual array simultaneously. Otherwise, this 2755ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * is a pretty straightforward analog of horizontal flip. 2765ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * Within a DCT block, vertical mirroring is done by changing the signs 2775ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * of odd-numbered rows. 2785ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * Partial iMCUs at the bottom edge are copied verbatim. 2795ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */ 280989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding MCU_rows = srcinfo->output_height / 281c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size); 2825ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 2835ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (ci = 0; ci < dstinfo->num_components; ci++) { 2845ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane compptr = dstinfo->comp_info + ci; 2855ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane comp_height = MCU_rows * compptr->v_samp_factor; 2865996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 2875996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 2885ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 289e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_blk_y += compptr->v_samp_factor) { 2905ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane dst_buffer = (*srcinfo->mem->access_virt_barray) 291e5eaf37440b8e337ab150c017df7c03faf846c51DRC ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 292e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) compptr->v_samp_factor, TRUE); 2935996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (y_crop_blocks + dst_blk_y < comp_height) { 294e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Row is within the mirrorable area. */ 295e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_buffer = (*srcinfo->mem->access_virt_barray) 296e5eaf37440b8e337ab150c017df7c03faf846c51DRC ((j_common_ptr) srcinfo, src_coef_arrays[ci], 297e5eaf37440b8e337ab150c017df7c03faf846c51DRC comp_height - y_crop_blocks - dst_blk_y - 298e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) compptr->v_samp_factor, 299e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) compptr->v_samp_factor, FALSE); 3005ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } else { 301e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Bottom-edge blocks will be copied verbatim. */ 302e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_buffer = (*srcinfo->mem->access_virt_barray) 303e5eaf37440b8e337ab150c017df7c03faf846c51DRC ((j_common_ptr) srcinfo, src_coef_arrays[ci], 304e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_blk_y + y_crop_blocks, 305e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) compptr->v_samp_factor, FALSE); 3065ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 3075ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 308e5eaf37440b8e337ab150c017df7c03faf846c51DRC if (y_crop_blocks + dst_blk_y < comp_height) { 309e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Row is within the mirrorable area. */ 310e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_row_ptr = dst_buffer[offset_y]; 311e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; 312e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_row_ptr += x_crop_blocks; 313e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; 314e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_blk_x++) { 315e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_ptr = dst_row_ptr[dst_blk_x]; 316e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_ptr = src_row_ptr[dst_blk_x]; 317e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (i = 0; i < DCTSIZE; i += 2) { 318e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* copy even row */ 319e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (j = 0; j < DCTSIZE; j++) 320e5eaf37440b8e337ab150c017df7c03faf846c51DRC *dst_ptr++ = *src_ptr++; 321e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* copy odd row with sign change */ 322e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (j = 0; j < DCTSIZE; j++) 323e5eaf37440b8e337ab150c017df7c03faf846c51DRC *dst_ptr++ = - *src_ptr++; 324e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 325e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 326e5eaf37440b8e337ab150c017df7c03faf846c51DRC } else { 327e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Just copy row verbatim. */ 328e5eaf37440b8e337ab150c017df7c03faf846c51DRC jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, 329e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_buffer[offset_y], 330e5eaf37440b8e337ab150c017df7c03faf846c51DRC compptr->width_in_blocks); 331e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 3325ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 3335ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 3345ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 3355ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane} 3365ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 3375ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 3385ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneLOCAL(void) 3395ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lanedo_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 340e5eaf37440b8e337ab150c017df7c03faf846c51DRC JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 341e5eaf37440b8e337ab150c017df7c03faf846c51DRC jvirt_barray_ptr *src_coef_arrays, 342e5eaf37440b8e337ab150c017df7c03faf846c51DRC jvirt_barray_ptr *dst_coef_arrays) 3435ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* Transpose source into destination */ 3445ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{ 3455996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks; 3465ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane int ci, i, j, offset_x, offset_y; 3475ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane JBLOCKARRAY src_buffer, dst_buffer; 3485ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane JCOEFPTR src_ptr, dst_ptr; 3495ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane jpeg_component_info *compptr; 3505ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 3515ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane /* Transposing pixels within a block just requires transposing the 3525ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * DCT coefficients. 3535ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * Partial iMCUs at the edges require no special treatment; we simply 3545ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * process all the available DCT blocks for every component. 3555ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */ 3565ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (ci = 0; ci < dstinfo->num_components; ci++) { 3575ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane compptr = dstinfo->comp_info + ci; 3585996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 3595996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 3605ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 361e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_blk_y += compptr->v_samp_factor) { 3625ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane dst_buffer = (*srcinfo->mem->access_virt_barray) 363e5eaf37440b8e337ab150c017df7c03faf846c51DRC ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 364e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) compptr->v_samp_factor, TRUE); 3655ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 366e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; 367e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_blk_x += compptr->h_samp_factor) { 368e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_buffer = (*srcinfo->mem->access_virt_barray) 369e5eaf37440b8e337ab150c017df7c03faf846c51DRC ((j_common_ptr) srcinfo, src_coef_arrays[ci], 370e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_blk_x + x_crop_blocks, 371e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) compptr->h_samp_factor, FALSE); 372e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { 373e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; 374e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_ptr = src_buffer[offset_x][dst_blk_y + offset_y + y_crop_blocks]; 375e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (i = 0; i < DCTSIZE; i++) 376e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (j = 0; j < DCTSIZE; j++) 377e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 378e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 379e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 3805ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 3815ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 3825ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 3835ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane} 3845ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 3855ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 3865ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneLOCAL(void) 3875ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lanedo_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 388e5eaf37440b8e337ab150c017df7c03faf846c51DRC JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 389e5eaf37440b8e337ab150c017df7c03faf846c51DRC jvirt_barray_ptr *src_coef_arrays, 390e5eaf37440b8e337ab150c017df7c03faf846c51DRC jvirt_barray_ptr *dst_coef_arrays) 3915ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* 90 degree rotation is equivalent to 3925ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 1. Transposing the image; 3935ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 2. Horizontal mirroring. 3945ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * These two steps are merged into a single processing routine. 3955ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */ 3965ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{ 3975ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y; 3985996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding JDIMENSION x_crop_blocks, y_crop_blocks; 3995ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane int ci, i, j, offset_x, offset_y; 4005ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane JBLOCKARRAY src_buffer, dst_buffer; 4015ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane JCOEFPTR src_ptr, dst_ptr; 4025ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane jpeg_component_info *compptr; 4035ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 4045ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane /* Because of the horizontal mirror step, we can't process partial iMCUs 4055ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * at the (output) right edge properly. They just get transposed and 4065ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * not mirrored. 4075ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */ 408989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding MCU_cols = srcinfo->output_height / 409c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size); 4105ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 4115ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (ci = 0; ci < dstinfo->num_components; ci++) { 4125ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane compptr = dstinfo->comp_info + ci; 4135ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane comp_width = MCU_cols * compptr->h_samp_factor; 4145996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 4155996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 4165ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 417e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_blk_y += compptr->v_samp_factor) { 4185ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane dst_buffer = (*srcinfo->mem->access_virt_barray) 419e5eaf37440b8e337ab150c017df7c03faf846c51DRC ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 420e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) compptr->v_samp_factor, TRUE); 4215ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 422e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; 423e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_blk_x += compptr->h_samp_factor) { 424e5eaf37440b8e337ab150c017df7c03faf846c51DRC if (x_crop_blocks + dst_blk_x < comp_width) { 425e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Block is within the mirrorable area. */ 426e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_buffer = (*srcinfo->mem->access_virt_barray) 427e5eaf37440b8e337ab150c017df7c03faf846c51DRC ((j_common_ptr) srcinfo, src_coef_arrays[ci], 428e5eaf37440b8e337ab150c017df7c03faf846c51DRC comp_width - x_crop_blocks - dst_blk_x - 429e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) compptr->h_samp_factor, 430e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) compptr->h_samp_factor, FALSE); 431e5eaf37440b8e337ab150c017df7c03faf846c51DRC } else { 432e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Edge blocks are transposed but not mirrored. */ 433e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_buffer = (*srcinfo->mem->access_virt_barray) 434e5eaf37440b8e337ab150c017df7c03faf846c51DRC ((j_common_ptr) srcinfo, src_coef_arrays[ci], 435e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_blk_x + x_crop_blocks, 436e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) compptr->h_samp_factor, FALSE); 437e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 438e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { 439e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; 440e5eaf37440b8e337ab150c017df7c03faf846c51DRC if (x_crop_blocks + dst_blk_x < comp_width) { 441e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Block is within the mirrorable area. */ 442e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] 443e5eaf37440b8e337ab150c017df7c03faf846c51DRC [dst_blk_y + offset_y + y_crop_blocks]; 444e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (i = 0; i < DCTSIZE; i++) { 445e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (j = 0; j < DCTSIZE; j++) 446e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 447e5eaf37440b8e337ab150c017df7c03faf846c51DRC i++; 448e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (j = 0; j < DCTSIZE; j++) 449e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 450e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 451e5eaf37440b8e337ab150c017df7c03faf846c51DRC } else { 452e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Edge blocks are transposed but not mirrored. */ 453e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_ptr = src_buffer[offset_x] 454e5eaf37440b8e337ab150c017df7c03faf846c51DRC [dst_blk_y + offset_y + y_crop_blocks]; 455e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (i = 0; i < DCTSIZE; i++) 456e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (j = 0; j < DCTSIZE; j++) 457e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 458e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 459e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 460e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 4615ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 4625ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 4635ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 4645ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane} 4655ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 4665ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 4675ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneLOCAL(void) 4685ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lanedo_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 469e5eaf37440b8e337ab150c017df7c03faf846c51DRC JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 470e5eaf37440b8e337ab150c017df7c03faf846c51DRC jvirt_barray_ptr *src_coef_arrays, 471e5eaf37440b8e337ab150c017df7c03faf846c51DRC jvirt_barray_ptr *dst_coef_arrays) 4725ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* 270 degree rotation is equivalent to 4735ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 1. Horizontal mirroring; 4745ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 2. Transposing the image. 4755ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * These two steps are merged into a single processing routine. 4765ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */ 4775ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{ 4785ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; 4795996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding JDIMENSION x_crop_blocks, y_crop_blocks; 4805ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane int ci, i, j, offset_x, offset_y; 4815ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane JBLOCKARRAY src_buffer, dst_buffer; 4825ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane JCOEFPTR src_ptr, dst_ptr; 4835ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane jpeg_component_info *compptr; 4845ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 4855ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane /* Because of the horizontal mirror step, we can't process partial iMCUs 4865ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * at the (output) bottom edge properly. They just get transposed and 4875ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * not mirrored. 4885ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */ 489989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding MCU_rows = srcinfo->output_width / 490c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size); 4915ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 4925ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (ci = 0; ci < dstinfo->num_components; ci++) { 4935ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane compptr = dstinfo->comp_info + ci; 4945ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane comp_height = MCU_rows * compptr->v_samp_factor; 4955996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 4965996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 4975ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 498e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_blk_y += compptr->v_samp_factor) { 4995ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane dst_buffer = (*srcinfo->mem->access_virt_barray) 500e5eaf37440b8e337ab150c017df7c03faf846c51DRC ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 501e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) compptr->v_samp_factor, TRUE); 5025ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 503e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; 504e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_blk_x += compptr->h_samp_factor) { 505e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_buffer = (*srcinfo->mem->access_virt_barray) 506e5eaf37440b8e337ab150c017df7c03faf846c51DRC ((j_common_ptr) srcinfo, src_coef_arrays[ci], 507e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_blk_x + x_crop_blocks, 508e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) compptr->h_samp_factor, FALSE); 509e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { 510e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; 511e5eaf37440b8e337ab150c017df7c03faf846c51DRC if (y_crop_blocks + dst_blk_y < comp_height) { 512e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Block is within the mirrorable area. */ 513e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_ptr = src_buffer[offset_x] 514e5eaf37440b8e337ab150c017df7c03faf846c51DRC [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; 515e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (i = 0; i < DCTSIZE; i++) { 516e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (j = 0; j < DCTSIZE; j++) { 517e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 518e5eaf37440b8e337ab150c017df7c03faf846c51DRC j++; 519e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 520e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 521e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 522e5eaf37440b8e337ab150c017df7c03faf846c51DRC } else { 523e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Edge blocks are transposed but not mirrored. */ 524e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_ptr = src_buffer[offset_x] 525e5eaf37440b8e337ab150c017df7c03faf846c51DRC [dst_blk_y + offset_y + y_crop_blocks]; 526e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (i = 0; i < DCTSIZE; i++) 527e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (j = 0; j < DCTSIZE; j++) 528e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 529e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 530e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 531e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 5325ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 5335ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 5345ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 5355ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane} 5365ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 5375ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 5385ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneLOCAL(void) 5395ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lanedo_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 540e5eaf37440b8e337ab150c017df7c03faf846c51DRC JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 541e5eaf37440b8e337ab150c017df7c03faf846c51DRC jvirt_barray_ptr *src_coef_arrays, 542e5eaf37440b8e337ab150c017df7c03faf846c51DRC jvirt_barray_ptr *dst_coef_arrays) 5435ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* 180 degree rotation is equivalent to 5445ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 1. Vertical mirroring; 5455ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 2. Horizontal mirroring. 5465ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * These two steps are merged into a single processing routine. 5475ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */ 5485ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{ 5495ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; 5505996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding JDIMENSION x_crop_blocks, y_crop_blocks; 5515ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane int ci, i, j, offset_y; 5525ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane JBLOCKARRAY src_buffer, dst_buffer; 5535ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane JBLOCKROW src_row_ptr, dst_row_ptr; 5545ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane JCOEFPTR src_ptr, dst_ptr; 5555ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane jpeg_component_info *compptr; 5565ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 557989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding MCU_cols = srcinfo->output_width / 558c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size); 559989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding MCU_rows = srcinfo->output_height / 560c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size); 5615ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 5625ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (ci = 0; ci < dstinfo->num_components; ci++) { 5635ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane compptr = dstinfo->comp_info + ci; 5645ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane comp_width = MCU_cols * compptr->h_samp_factor; 5655ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane comp_height = MCU_rows * compptr->v_samp_factor; 5665996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 5675996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 5685ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 569e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_blk_y += compptr->v_samp_factor) { 5705ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane dst_buffer = (*srcinfo->mem->access_virt_barray) 571e5eaf37440b8e337ab150c017df7c03faf846c51DRC ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 572e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) compptr->v_samp_factor, TRUE); 5735996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (y_crop_blocks + dst_blk_y < comp_height) { 574e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Row is within the vertically mirrorable area. */ 575e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_buffer = (*srcinfo->mem->access_virt_barray) 576e5eaf37440b8e337ab150c017df7c03faf846c51DRC ((j_common_ptr) srcinfo, src_coef_arrays[ci], 577e5eaf37440b8e337ab150c017df7c03faf846c51DRC comp_height - y_crop_blocks - dst_blk_y - 578e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) compptr->v_samp_factor, 579e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) compptr->v_samp_factor, FALSE); 5805ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } else { 581e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Bottom-edge rows are only mirrored horizontally. */ 582e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_buffer = (*srcinfo->mem->access_virt_barray) 583e5eaf37440b8e337ab150c017df7c03faf846c51DRC ((j_common_ptr) srcinfo, src_coef_arrays[ci], 584e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_blk_y + y_crop_blocks, 585e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) compptr->v_samp_factor, FALSE); 5865ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 5875ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 588e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_row_ptr = dst_buffer[offset_y]; 589e5eaf37440b8e337ab150c017df7c03faf846c51DRC if (y_crop_blocks + dst_blk_y < comp_height) { 590e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Row is within the mirrorable area. */ 591e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; 592e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { 593e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_ptr = dst_row_ptr[dst_blk_x]; 594e5eaf37440b8e337ab150c017df7c03faf846c51DRC if (x_crop_blocks + dst_blk_x < comp_width) { 595e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Process the blocks that can be mirrored both ways. */ 596e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; 597e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (i = 0; i < DCTSIZE; i += 2) { 598e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* For even row, negate every odd column. */ 599e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (j = 0; j < DCTSIZE; j += 2) { 600e5eaf37440b8e337ab150c017df7c03faf846c51DRC *dst_ptr++ = *src_ptr++; 601e5eaf37440b8e337ab150c017df7c03faf846c51DRC *dst_ptr++ = - *src_ptr++; 602e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 603e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* For odd row, negate every even column. */ 604e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (j = 0; j < DCTSIZE; j += 2) { 605e5eaf37440b8e337ab150c017df7c03faf846c51DRC *dst_ptr++ = - *src_ptr++; 606e5eaf37440b8e337ab150c017df7c03faf846c51DRC *dst_ptr++ = *src_ptr++; 607e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 608e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 609e5eaf37440b8e337ab150c017df7c03faf846c51DRC } else { 610e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Any remaining right-edge blocks are only mirrored vertically. */ 611e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x]; 612e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (i = 0; i < DCTSIZE; i += 2) { 613e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (j = 0; j < DCTSIZE; j++) 614e5eaf37440b8e337ab150c017df7c03faf846c51DRC *dst_ptr++ = *src_ptr++; 615e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (j = 0; j < DCTSIZE; j++) 616e5eaf37440b8e337ab150c017df7c03faf846c51DRC *dst_ptr++ = - *src_ptr++; 617e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 618e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 619e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 620e5eaf37440b8e337ab150c017df7c03faf846c51DRC } else { 621e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Remaining rows are just mirrored horizontally. */ 622e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_row_ptr = src_buffer[offset_y]; 623e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { 624e5eaf37440b8e337ab150c017df7c03faf846c51DRC if (x_crop_blocks + dst_blk_x < comp_width) { 625e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Process the blocks that can be mirrored. */ 626e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_ptr = dst_row_ptr[dst_blk_x]; 627e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; 628e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (i = 0; i < DCTSIZE2; i += 2) { 629e5eaf37440b8e337ab150c017df7c03faf846c51DRC *dst_ptr++ = *src_ptr++; 630e5eaf37440b8e337ab150c017df7c03faf846c51DRC *dst_ptr++ = - *src_ptr++; 631e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 632e5eaf37440b8e337ab150c017df7c03faf846c51DRC } else { 633e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Any remaining right-edge blocks are only copied. */ 634e5eaf37440b8e337ab150c017df7c03faf846c51DRC jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks, 635e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_row_ptr + dst_blk_x, 636e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) 1); 637e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 638e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 639e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 6405ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 6415ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 6425ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 6435ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane} 6445ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 6455ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 6465ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneLOCAL(void) 6475ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lanedo_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 648e5eaf37440b8e337ab150c017df7c03faf846c51DRC JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, 649e5eaf37440b8e337ab150c017df7c03faf846c51DRC jvirt_barray_ptr *src_coef_arrays, 650e5eaf37440b8e337ab150c017df7c03faf846c51DRC jvirt_barray_ptr *dst_coef_arrays) 6515ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* Transverse transpose is equivalent to 6525ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 1. 180 degree rotation; 6535ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 2. Transposition; 6545ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * or 6555ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 1. Horizontal mirroring; 6565ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 2. Transposition; 6575ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 3. Horizontal mirroring. 6585ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * These steps are merged into a single processing routine. 6595ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */ 6605ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{ 6615ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; 6625996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding JDIMENSION x_crop_blocks, y_crop_blocks; 6635ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane int ci, i, j, offset_x, offset_y; 6645ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane JBLOCKARRAY src_buffer, dst_buffer; 6655ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane JCOEFPTR src_ptr, dst_ptr; 6665ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane jpeg_component_info *compptr; 6675ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 668989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding MCU_cols = srcinfo->output_height / 669c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size); 670989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding MCU_rows = srcinfo->output_width / 671c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size); 6725ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 6735ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (ci = 0; ci < dstinfo->num_components; ci++) { 6745ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane compptr = dstinfo->comp_info + ci; 6755ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane comp_width = MCU_cols * compptr->h_samp_factor; 6765ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane comp_height = MCU_rows * compptr->v_samp_factor; 6775996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding x_crop_blocks = x_crop_offset * compptr->h_samp_factor; 6785996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding y_crop_blocks = y_crop_offset * compptr->v_samp_factor; 6795ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; 680e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_blk_y += compptr->v_samp_factor) { 6815ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane dst_buffer = (*srcinfo->mem->access_virt_barray) 682e5eaf37440b8e337ab150c017df7c03faf846c51DRC ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, 683e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) compptr->v_samp_factor, TRUE); 6845ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { 685e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; 686e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_blk_x += compptr->h_samp_factor) { 687e5eaf37440b8e337ab150c017df7c03faf846c51DRC if (x_crop_blocks + dst_blk_x < comp_width) { 688e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Block is within the mirrorable area. */ 689e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_buffer = (*srcinfo->mem->access_virt_barray) 690e5eaf37440b8e337ab150c017df7c03faf846c51DRC ((j_common_ptr) srcinfo, src_coef_arrays[ci], 691e5eaf37440b8e337ab150c017df7c03faf846c51DRC comp_width - x_crop_blocks - dst_blk_x - 692e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) compptr->h_samp_factor, 693e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) compptr->h_samp_factor, FALSE); 694e5eaf37440b8e337ab150c017df7c03faf846c51DRC } else { 695e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_buffer = (*srcinfo->mem->access_virt_barray) 696e5eaf37440b8e337ab150c017df7c03faf846c51DRC ((j_common_ptr) srcinfo, src_coef_arrays[ci], 697e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_blk_x + x_crop_blocks, 698e5eaf37440b8e337ab150c017df7c03faf846c51DRC (JDIMENSION) compptr->h_samp_factor, FALSE); 699e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 700e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { 701e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; 702e5eaf37440b8e337ab150c017df7c03faf846c51DRC if (y_crop_blocks + dst_blk_y < comp_height) { 703e5eaf37440b8e337ab150c017df7c03faf846c51DRC if (x_crop_blocks + dst_blk_x < comp_width) { 704e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Block is within the mirrorable area. */ 705e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] 706e5eaf37440b8e337ab150c017df7c03faf846c51DRC [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; 707e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (i = 0; i < DCTSIZE; i++) { 708e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (j = 0; j < DCTSIZE; j++) { 709e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 710e5eaf37440b8e337ab150c017df7c03faf846c51DRC j++; 711e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 712e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 713e5eaf37440b8e337ab150c017df7c03faf846c51DRC i++; 714e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (j = 0; j < DCTSIZE; j++) { 715e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 716e5eaf37440b8e337ab150c017df7c03faf846c51DRC j++; 717e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 718e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 719e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 720e5eaf37440b8e337ab150c017df7c03faf846c51DRC } else { 721e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Right-edge blocks are mirrored in y only */ 722e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_ptr = src_buffer[offset_x] 723e5eaf37440b8e337ab150c017df7c03faf846c51DRC [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; 724e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (i = 0; i < DCTSIZE; i++) { 725e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (j = 0; j < DCTSIZE; j++) { 726e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 727e5eaf37440b8e337ab150c017df7c03faf846c51DRC j++; 728e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 729e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 730e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 731e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 732e5eaf37440b8e337ab150c017df7c03faf846c51DRC } else { 733e5eaf37440b8e337ab150c017df7c03faf846c51DRC if (x_crop_blocks + dst_blk_x < comp_width) { 734e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* Bottom-edge blocks are mirrored in x only */ 735e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] 736e5eaf37440b8e337ab150c017df7c03faf846c51DRC [dst_blk_y + offset_y + y_crop_blocks]; 737e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (i = 0; i < DCTSIZE; i++) { 738e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (j = 0; j < DCTSIZE; j++) 739e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 740e5eaf37440b8e337ab150c017df7c03faf846c51DRC i++; 741e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (j = 0; j < DCTSIZE; j++) 742e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; 743e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 744e5eaf37440b8e337ab150c017df7c03faf846c51DRC } else { 745e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* At lower right corner, just transpose, no mirroring */ 746e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_ptr = src_buffer[offset_x] 747e5eaf37440b8e337ab150c017df7c03faf846c51DRC [dst_blk_y + offset_y + y_crop_blocks]; 748e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (i = 0; i < DCTSIZE; i++) 749e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (j = 0; j < DCTSIZE; j++) 750e5eaf37440b8e337ab150c017df7c03faf846c51DRC dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; 751e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 752e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 753e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 754e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 7555ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 7565ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 7575ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 7585ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane} 7595ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 7605ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 7615996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding/* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec. 7625996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * Returns TRUE if valid integer found, FALSE if not. 7635996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * *strptr is advanced over the digit string, and *result is set to its value. 7645996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding */ 7655996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 7665996a25e2f50d20d6a8f09830724035b49c3927bGuido VollbedingLOCAL(boolean) 7676eb7d3798b5a79347c62825fc4c16f7ce673bdd0Alex Naidisjt_read_integer (const char **strptr, JDIMENSION *result) 7685996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding{ 7696eb7d3798b5a79347c62825fc4c16f7ce673bdd0Alex Naidis const char *ptr = *strptr; 7705996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding JDIMENSION val = 0; 7715996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 7725996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding for (; isdigit(*ptr); ptr++) { 7735996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding val = val * 10 + (JDIMENSION) (*ptr - '0'); 7745996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 7755996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding *result = val; 7765996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (ptr == *strptr) 777e5eaf37440b8e337ab150c017df7c03faf846c51DRC return FALSE; /* oops, no digits */ 7785996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding *strptr = ptr; 7795996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding return TRUE; 7805996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding} 7815996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 7825996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 7835996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding/* Parse a crop specification (written in X11 geometry style). 7845996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * The routine returns TRUE if the spec string is valid, FALSE if not. 7855996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * 7865996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * The crop spec string should have the format 787e5eaf37440b8e337ab150c017df7c03faf846c51DRC * <width>[f]x<height>[f]{+-}<xoffset>{+-}<yoffset> 7885996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * where width, height, xoffset, and yoffset are unsigned integers. 7895996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * Each of the elements can be omitted to indicate a default value. 7905996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * (A weakness of this style is that it is not possible to omit xoffset 7915996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * while specifying yoffset, since they look alike.) 7925996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * 7935996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * This code is loosely based on XParseGeometry from the X11 distribution. 7945996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding */ 7955996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 7965996a25e2f50d20d6a8f09830724035b49c3927bGuido VollbedingGLOBAL(boolean) 7975996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbedingjtransform_parse_crop_spec (jpeg_transform_info *info, const char *spec) 7985996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding{ 7995996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding info->crop = FALSE; 8005996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding info->crop_width_set = JCROP_UNSET; 8015996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding info->crop_height_set = JCROP_UNSET; 8025996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding info->crop_xoffset_set = JCROP_UNSET; 8035996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding info->crop_yoffset_set = JCROP_UNSET; 8045996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 8055996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (isdigit(*spec)) { 8065996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* fetch width */ 8075996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (! jt_read_integer(&spec, &info->crop_width)) 8085996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding return FALSE; 8095829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding if (*spec == 'f' || *spec == 'F') { 8105829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding spec++; 8115829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding info->crop_width_set = JCROP_FORCE; 8125829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding } else 8135829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding info->crop_width_set = JCROP_POS; 8145996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 8155829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding if (*spec == 'x' || *spec == 'X') { 8165996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* fetch height */ 8175996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding spec++; 8185996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (! jt_read_integer(&spec, &info->crop_height)) 8195996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding return FALSE; 8205829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding if (*spec == 'f' || *spec == 'F') { 8215829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding spec++; 8225829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding info->crop_height_set = JCROP_FORCE; 8235829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding } else 8245829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding info->crop_height_set = JCROP_POS; 8255996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 8265996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (*spec == '+' || *spec == '-') { 8275996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* fetch xoffset */ 8285996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS; 8295996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding spec++; 8305996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (! jt_read_integer(&spec, &info->crop_xoffset)) 8315996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding return FALSE; 8325996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 8335996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (*spec == '+' || *spec == '-') { 8345996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* fetch yoffset */ 8355996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS; 8365996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding spec++; 8375996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (! jt_read_integer(&spec, &info->crop_yoffset)) 8385996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding return FALSE; 8395996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 8405996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* We had better have gotten to the end of the string. */ 8415996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (*spec != '\0') 8425996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding return FALSE; 8435996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding info->crop = TRUE; 8445996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding return TRUE; 8455996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding} 8465996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 8475996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 8485996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding/* Trim off any partial iMCUs on the indicated destination edge */ 8495996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 8505996a25e2f50d20d6a8f09830724035b49c3927bGuido VollbedingLOCAL(void) 8515996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbedingtrim_right_edge (jpeg_transform_info *info, JDIMENSION full_width) 8525996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding{ 8535996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding JDIMENSION MCU_cols; 8545996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 855989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding MCU_cols = info->output_width / info->iMCU_sample_width; 8565996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (MCU_cols > 0 && info->x_crop_offset + MCU_cols == 857989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding full_width / info->iMCU_sample_width) 858989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding info->output_width = MCU_cols * info->iMCU_sample_width; 8595996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding} 8605996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 8615996a25e2f50d20d6a8f09830724035b49c3927bGuido VollbedingLOCAL(void) 8625996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbedingtrim_bottom_edge (jpeg_transform_info *info, JDIMENSION full_height) 8635996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding{ 8645996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding JDIMENSION MCU_rows; 8655996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 866989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding MCU_rows = info->output_height / info->iMCU_sample_height; 8675996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (MCU_rows > 0 && info->y_crop_offset + MCU_rows == 868989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding full_height / info->iMCU_sample_height) 869989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding info->output_height = MCU_rows * info->iMCU_sample_height; 8705996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding} 8715996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 8725996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 8735ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* Request any required workspace. 8745ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 8755996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * This routine figures out the size that the output image will be 8765996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * (which implies that all the transform parameters must be set before 8775996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * it is called). 8785996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * 8795ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * We allocate the workspace virtual arrays from the source decompression 8805ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * object, so that all the arrays (both the original data and the workspace) 8815ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * will be taken into account while making memory management decisions. 8825ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * Hence, this routine must be called after jpeg_read_header (which reads 8835ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * the image dimensions) and before jpeg_read_coefficients (which realizes 8845ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * the source's virtual arrays). 885989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding * 886989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding * This function returns FALSE right away if -perfect is given 887989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding * and transformation is not perfect. Otherwise returns TRUE. 8885ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */ 8895ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 890989630f70cf1af69ebfefca8910d1647bf189712Guido VollbedingGLOBAL(boolean) 8915ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lanejtransform_request_workspace (j_decompress_ptr srcinfo, 892e5eaf37440b8e337ab150c017df7c03faf846c51DRC jpeg_transform_info *info) 8935ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{ 894989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding jvirt_barray_ptr *coef_arrays; 8955996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding boolean need_workspace, transpose_it; 8965ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane jpeg_component_info *compptr; 897989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding JDIMENSION xoffset, yoffset; 898989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding JDIMENSION width_in_iMCUs, height_in_iMCUs; 8995996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding JDIMENSION width_in_blocks, height_in_blocks; 9005996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding int ci, h_samp_factor, v_samp_factor; 9015ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 9025996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Determine number of components in output image */ 9035ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane if (info->force_grayscale && 9045ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane srcinfo->jpeg_color_space == JCS_YCbCr && 905989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding srcinfo->num_components == 3) 9065ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane /* We'll only process the first component */ 9075ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane info->num_components = 1; 908989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding else 9095ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane /* Process all the components */ 9105ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane info->num_components = srcinfo->num_components; 911989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding 912989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding /* Compute output image dimensions and related values. */ 913c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#if JPEG_LIB_VERSION >= 80 914989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding jpeg_core_output_dimensions(srcinfo); 915c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#else 916c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC srcinfo->output_width = srcinfo->image_width; 917c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC srcinfo->output_height = srcinfo->image_height; 918c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#endif 919989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding 920989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding /* Return right away if -perfect is given and transformation is not perfect. 921989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding */ 922989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding if (info->perfect) { 923989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding if (info->num_components == 1) { 924989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding if (!jtransform_perfect_transform(srcinfo->output_width, 925e5eaf37440b8e337ab150c017df7c03faf846c51DRC srcinfo->output_height, 926e5eaf37440b8e337ab150c017df7c03faf846c51DRC srcinfo->_min_DCT_h_scaled_size, 927e5eaf37440b8e337ab150c017df7c03faf846c51DRC srcinfo->_min_DCT_v_scaled_size, 928e5eaf37440b8e337ab150c017df7c03faf846c51DRC info->transform)) 929e5eaf37440b8e337ab150c017df7c03faf846c51DRC return FALSE; 930989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding } else { 931989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding if (!jtransform_perfect_transform(srcinfo->output_width, 932e5eaf37440b8e337ab150c017df7c03faf846c51DRC srcinfo->output_height, 933e5eaf37440b8e337ab150c017df7c03faf846c51DRC srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size, 934e5eaf37440b8e337ab150c017df7c03faf846c51DRC srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size, 935e5eaf37440b8e337ab150c017df7c03faf846c51DRC info->transform)) 936e5eaf37440b8e337ab150c017df7c03faf846c51DRC return FALSE; 937989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding } 9385ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 9395ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 9405996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* If there is only one output component, force the iMCU size to be 1; 9415996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * else use the source iMCU size. (This allows us to do the right thing 9425996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * when reducing color to grayscale, and also provides a handy way of 9435996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * cleaning up "funny" grayscale images whose sampling factors are not 1x1.) 9445996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding */ 9455ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane switch (info->transform) { 9465996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding case JXFORM_TRANSPOSE: 9475996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding case JXFORM_TRANSVERSE: 9485996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding case JXFORM_ROT_90: 9495996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding case JXFORM_ROT_270: 950989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding info->output_width = srcinfo->output_height; 951989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding info->output_height = srcinfo->output_width; 9525996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (info->num_components == 1) { 953c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC info->iMCU_sample_width = srcinfo->_min_DCT_v_scaled_size; 954c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC info->iMCU_sample_height = srcinfo->_min_DCT_h_scaled_size; 9555996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } else { 956989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding info->iMCU_sample_width = 957e5eaf37440b8e337ab150c017df7c03faf846c51DRC srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size; 958989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding info->iMCU_sample_height = 959e5eaf37440b8e337ab150c017df7c03faf846c51DRC srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size; 9605996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 9615996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding break; 9625996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding default: 963989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding info->output_width = srcinfo->output_width; 964989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding info->output_height = srcinfo->output_height; 9655996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (info->num_components == 1) { 966c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC info->iMCU_sample_width = srcinfo->_min_DCT_h_scaled_size; 967c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC info->iMCU_sample_height = srcinfo->_min_DCT_v_scaled_size; 9685996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } else { 969989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding info->iMCU_sample_width = 970e5eaf37440b8e337ab150c017df7c03faf846c51DRC srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size; 971989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding info->iMCU_sample_height = 972e5eaf37440b8e337ab150c017df7c03faf846c51DRC srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size; 9735996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 9745996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding break; 9755996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 9765996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 9775996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* If cropping has been requested, compute the crop area's position and 9785996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * dimensions, ensuring that its upper left corner falls at an iMCU boundary. 9795996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding */ 9805996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (info->crop) { 9815996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Insert default values for unset crop parameters */ 9825996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (info->crop_xoffset_set == JCROP_UNSET) 983e5eaf37440b8e337ab150c017df7c03faf846c51DRC info->crop_xoffset = 0; /* default to +0 */ 9845996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (info->crop_yoffset_set == JCROP_UNSET) 985e5eaf37440b8e337ab150c017df7c03faf846c51DRC info->crop_yoffset = 0; /* default to +0 */ 9865996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (info->crop_xoffset >= info->output_width || 987e5eaf37440b8e337ab150c017df7c03faf846c51DRC info->crop_yoffset >= info->output_height) 9885996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); 9895996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (info->crop_width_set == JCROP_UNSET) 9905996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding info->crop_width = info->output_width - info->crop_xoffset; 9915996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (info->crop_height_set == JCROP_UNSET) 9925996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding info->crop_height = info->output_height - info->crop_yoffset; 9935996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Ensure parameters are valid */ 9945996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (info->crop_width <= 0 || info->crop_width > info->output_width || 995e5eaf37440b8e337ab150c017df7c03faf846c51DRC info->crop_height <= 0 || info->crop_height > info->output_height || 996e5eaf37440b8e337ab150c017df7c03faf846c51DRC info->crop_xoffset > info->output_width - info->crop_width || 997e5eaf37440b8e337ab150c017df7c03faf846c51DRC info->crop_yoffset > info->output_height - info->crop_height) 9985996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); 9995996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Convert negative crop offsets into regular offsets */ 10005996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (info->crop_xoffset_set == JCROP_NEG) 10015996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding xoffset = info->output_width - info->crop_width - info->crop_xoffset; 10025996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding else 10035996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding xoffset = info->crop_xoffset; 10045996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (info->crop_yoffset_set == JCROP_NEG) 10055996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding yoffset = info->output_height - info->crop_height - info->crop_yoffset; 10065996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding else 10075996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding yoffset = info->crop_yoffset; 10085996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Now adjust so that upper left corner falls at an iMCU boundary */ 10095829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding if (info->crop_width_set == JCROP_FORCE) 10105829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding info->output_width = info->crop_width; 10115829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding else 10125829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding info->output_width = 10135829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding info->crop_width + (xoffset % info->iMCU_sample_width); 10145829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding if (info->crop_height_set == JCROP_FORCE) 10155829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding info->output_height = info->crop_height; 10165829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding else 10175829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding info->output_height = 10185829cb23983cd241c48abd8ed70ff3627560c453Guido Vollbeding info->crop_height + (yoffset % info->iMCU_sample_height); 10195996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Save x/y offsets measured in iMCUs */ 1020989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding info->x_crop_offset = xoffset / info->iMCU_sample_width; 1021989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding info->y_crop_offset = yoffset / info->iMCU_sample_height; 10225996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } else { 10235996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding info->x_crop_offset = 0; 10245996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding info->y_crop_offset = 0; 10255996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 10265996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 10275996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Figure out whether we need workspace arrays, 10285996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * and if so whether they are transposed relative to the source. 10295996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding */ 10305996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding need_workspace = FALSE; 10315996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding transpose_it = FALSE; 10325ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane switch (info->transform) { 10335ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane case JXFORM_NONE: 10345996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (info->x_crop_offset != 0 || info->y_crop_offset != 0) 10355996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding need_workspace = TRUE; 10365996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* No workspace needed if neither cropping nor transforming */ 10375996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding break; 10385ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane case JXFORM_FLIP_H: 10395996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (info->trim) 1040989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding trim_right_edge(info, srcinfo->output_width); 1041ba5ea5143e48b71234414139e3b4cb244599e875DRC if (info->y_crop_offset != 0 || info->slow_hflip) 10425996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding need_workspace = TRUE; 10435996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* do_flip_h_no_crop doesn't need a workspace array */ 10445ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane break; 10455ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane case JXFORM_FLIP_V: 10465996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (info->trim) 1047989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding trim_bottom_edge(info, srcinfo->output_height); 10485996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Need workspace arrays having same dimensions as source image. */ 10495996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding need_workspace = TRUE; 10505ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane break; 10515ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane case JXFORM_TRANSPOSE: 10525996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* transpose does NOT have to trim anything */ 10535996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Need workspace arrays having transposed dimensions. */ 10545996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding need_workspace = TRUE; 10555996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding transpose_it = TRUE; 10565996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding break; 10575ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane case JXFORM_TRANSVERSE: 10585996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (info->trim) { 1059989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding trim_right_edge(info, srcinfo->output_height); 1060989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding trim_bottom_edge(info, srcinfo->output_width); 10615996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 10625996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Need workspace arrays having transposed dimensions. */ 10635996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding need_workspace = TRUE; 10645996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding transpose_it = TRUE; 10655996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding break; 10665ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane case JXFORM_ROT_90: 10675996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (info->trim) 1068989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding trim_right_edge(info, srcinfo->output_height); 10695996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Need workspace arrays having transposed dimensions. */ 10705996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding need_workspace = TRUE; 10715996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding transpose_it = TRUE; 10725996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding break; 10735996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding case JXFORM_ROT_180: 10745996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (info->trim) { 1075989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding trim_right_edge(info, srcinfo->output_width); 1076989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding trim_bottom_edge(info, srcinfo->output_height); 10775996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 10785996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Need workspace arrays having same dimensions as source image. */ 10795996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding need_workspace = TRUE; 10805996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding break; 10815ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane case JXFORM_ROT_270: 10825996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (info->trim) 1083989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding trim_bottom_edge(info, srcinfo->output_width); 10845996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Need workspace arrays having transposed dimensions. */ 10855996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding need_workspace = TRUE; 10865996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding transpose_it = TRUE; 10875996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding break; 10885996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 10895996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 10905996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Allocate workspace if needed. 10915996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * Note that we allocate arrays padded out to the next iMCU boundary, 10925996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * so that transform routines need not worry about missing edge blocks. 10935996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding */ 10945996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (need_workspace) { 10955ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane coef_arrays = (jvirt_barray_ptr *) 10965ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE, 10975de454b291f48382648a5d1dc2aa0fca8b5786d4DRC sizeof(jvirt_barray_ptr) * info->num_components); 10985996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding width_in_iMCUs = (JDIMENSION) 10995996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding jdiv_round_up((long) info->output_width, 1100e5eaf37440b8e337ab150c017df7c03faf846c51DRC (long) info->iMCU_sample_width); 11015996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding height_in_iMCUs = (JDIMENSION) 11025996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding jdiv_round_up((long) info->output_height, 1103e5eaf37440b8e337ab150c017df7c03faf846c51DRC (long) info->iMCU_sample_height); 11045ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (ci = 0; ci < info->num_components; ci++) { 11055ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane compptr = srcinfo->comp_info + ci; 11065996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (info->num_components == 1) { 1107e5eaf37440b8e337ab150c017df7c03faf846c51DRC /* we're going to force samp factors to 1x1 in this case */ 1108e5eaf37440b8e337ab150c017df7c03faf846c51DRC h_samp_factor = v_samp_factor = 1; 11095996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } else if (transpose_it) { 1110e5eaf37440b8e337ab150c017df7c03faf846c51DRC h_samp_factor = compptr->v_samp_factor; 1111e5eaf37440b8e337ab150c017df7c03faf846c51DRC v_samp_factor = compptr->h_samp_factor; 11125996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } else { 1113e5eaf37440b8e337ab150c017df7c03faf846c51DRC h_samp_factor = compptr->h_samp_factor; 1114e5eaf37440b8e337ab150c017df7c03faf846c51DRC v_samp_factor = compptr->v_samp_factor; 11155996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 11165996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding width_in_blocks = width_in_iMCUs * h_samp_factor; 11175996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding height_in_blocks = height_in_iMCUs * v_samp_factor; 11185ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane coef_arrays[ci] = (*srcinfo->mem->request_virt_barray) 1119e5eaf37440b8e337ab150c017df7c03faf846c51DRC ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE, 1120e5eaf37440b8e337ab150c017df7c03faf846c51DRC width_in_blocks, height_in_blocks, (JDIMENSION) v_samp_factor); 11215ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 1122989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding info->workspace_coef_arrays = coef_arrays; 1123989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding } else 1124989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding info->workspace_coef_arrays = NULL; 11255996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 1126989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding return TRUE; 11275ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane} 11285ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 11295ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 11305ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* Transpose destination image parameters */ 11315ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 11325ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneLOCAL(void) 11335ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lanetranspose_critical_parameters (j_compress_ptr dstinfo) 11345ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{ 11355ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane int tblno, i, j, ci, itemp; 11365ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane jpeg_component_info *compptr; 11375ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane JQUANT_TBL *qtblptr; 1138989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding JDIMENSION jtemp; 11395ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane UINT16 qtemp; 11405ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 1141989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding /* Transpose image dimensions */ 1142989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding jtemp = dstinfo->image_width; 11435ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane dstinfo->image_width = dstinfo->image_height; 1144989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding dstinfo->image_height = jtemp; 114536a6eec93250e390d1028b3372078810b4428eafDRC#if JPEG_LIB_VERSION >= 70 1146989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding itemp = dstinfo->min_DCT_h_scaled_size; 1147989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding dstinfo->min_DCT_h_scaled_size = dstinfo->min_DCT_v_scaled_size; 1148989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding dstinfo->min_DCT_v_scaled_size = itemp; 114936a6eec93250e390d1028b3372078810b4428eafDRC#endif 11505ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 11515ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane /* Transpose sampling factors */ 11525ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (ci = 0; ci < dstinfo->num_components; ci++) { 11535ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane compptr = dstinfo->comp_info + ci; 11545ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane itemp = compptr->h_samp_factor; 11555ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane compptr->h_samp_factor = compptr->v_samp_factor; 11565ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane compptr->v_samp_factor = itemp; 11575ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 11585ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 11595ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane /* Transpose quantization tables */ 11605ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { 11615ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane qtblptr = dstinfo->quant_tbl_ptrs[tblno]; 11625ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane if (qtblptr != NULL) { 11635ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (i = 0; i < DCTSIZE; i++) { 1164e5eaf37440b8e337ab150c017df7c03faf846c51DRC for (j = 0; j < i; j++) { 1165e5eaf37440b8e337ab150c017df7c03faf846c51DRC qtemp = qtblptr->quantval[i*DCTSIZE+j]; 1166e5eaf37440b8e337ab150c017df7c03faf846c51DRC qtblptr->quantval[i*DCTSIZE+j] = qtblptr->quantval[j*DCTSIZE+i]; 1167e5eaf37440b8e337ab150c017df7c03faf846c51DRC qtblptr->quantval[j*DCTSIZE+i] = qtemp; 1168e5eaf37440b8e337ab150c017df7c03faf846c51DRC } 11695ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 11705ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 11715ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 11725ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane} 11735ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 11745ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 11755996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding/* Adjust Exif image parameters. 11765996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * 11775996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible. 11785996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding */ 11795ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 1180506a742193ed5549074f40c3e0d2f0fd2eefb22bDRC#if JPEG_LIB_VERSION >= 70 11815ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneLOCAL(void) 11826eb7d3798b5a79347c62825fc4c16f7ce673bdd0Alex Naidisadjust_exif_parameters (JOCTET *data, unsigned int length, 1183e5eaf37440b8e337ab150c017df7c03faf846c51DRC JDIMENSION new_width, JDIMENSION new_height) 11845ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{ 11855996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding boolean is_motorola; /* Flag for byte order */ 11865996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding unsigned int number_of_tags, tagnum; 11875996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding unsigned int firstoffset, offset; 11885996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding JDIMENSION new_value; 11895ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 11905996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (length < 12) return; /* Length of an IFD entry */ 11915996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 11925996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Discover byte order */ 11935996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (GETJOCTET(data[0]) == 0x49 && GETJOCTET(data[1]) == 0x49) 11945996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding is_motorola = FALSE; 11955996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding else if (GETJOCTET(data[0]) == 0x4D && GETJOCTET(data[1]) == 0x4D) 11965996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding is_motorola = TRUE; 11975996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding else 11985996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding return; 11995996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 12005996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Check Tag Mark */ 12015996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (is_motorola) { 12025996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (GETJOCTET(data[2]) != 0) return; 12035996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (GETJOCTET(data[3]) != 0x2A) return; 12045996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } else { 12055996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (GETJOCTET(data[3]) != 0) return; 12065996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (GETJOCTET(data[2]) != 0x2A) return; 12075ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 12085ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 12095996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Get first IFD offset (offset to IFD0) */ 12105996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (is_motorola) { 12115996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (GETJOCTET(data[4]) != 0) return; 12125996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (GETJOCTET(data[5]) != 0) return; 12135996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding firstoffset = GETJOCTET(data[6]); 12145996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding firstoffset <<= 8; 12155996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding firstoffset += GETJOCTET(data[7]); 12165996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } else { 12175996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (GETJOCTET(data[7]) != 0) return; 12185996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (GETJOCTET(data[6]) != 0) return; 12195996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding firstoffset = GETJOCTET(data[5]); 12205996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding firstoffset <<= 8; 12215996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding firstoffset += GETJOCTET(data[4]); 12225996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 12235996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (firstoffset > length - 2) return; /* check end of data segment */ 12245ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 12255996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Get the number of directory entries contained in this IFD */ 12265996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (is_motorola) { 12275996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding number_of_tags = GETJOCTET(data[firstoffset]); 12285996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding number_of_tags <<= 8; 12295996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding number_of_tags += GETJOCTET(data[firstoffset+1]); 12305996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } else { 12315996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding number_of_tags = GETJOCTET(data[firstoffset+1]); 12325996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding number_of_tags <<= 8; 12335996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding number_of_tags += GETJOCTET(data[firstoffset]); 12345ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 12355996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (number_of_tags == 0) return; 12365996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding firstoffset += 2; 12375996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 12385996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Search for ExifSubIFD offset Tag in IFD0 */ 12395996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding for (;;) { 12405996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (firstoffset > length - 12) return; /* check end of data segment */ 12415996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Get Tag number */ 12425996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (is_motorola) { 12435996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding tagnum = GETJOCTET(data[firstoffset]); 12445996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding tagnum <<= 8; 12455996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding tagnum += GETJOCTET(data[firstoffset+1]); 12465996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } else { 12475996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding tagnum = GETJOCTET(data[firstoffset+1]); 12485996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding tagnum <<= 8; 12495996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding tagnum += GETJOCTET(data[firstoffset]); 12505996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 12515996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */ 12525996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (--number_of_tags == 0) return; 12535996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding firstoffset += 12; 12545996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 12555996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 12565996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Get the ExifSubIFD offset */ 12575996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (is_motorola) { 12585996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (GETJOCTET(data[firstoffset+8]) != 0) return; 12595996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (GETJOCTET(data[firstoffset+9]) != 0) return; 12605996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding offset = GETJOCTET(data[firstoffset+10]); 12615996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding offset <<= 8; 12625996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding offset += GETJOCTET(data[firstoffset+11]); 12635996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } else { 12645996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (GETJOCTET(data[firstoffset+11]) != 0) return; 12655996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (GETJOCTET(data[firstoffset+10]) != 0) return; 12665996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding offset = GETJOCTET(data[firstoffset+9]); 12675996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding offset <<= 8; 12685996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding offset += GETJOCTET(data[firstoffset+8]); 12695996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 12705996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (offset > length - 2) return; /* check end of data segment */ 12715996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 12725996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Get the number of directory entries contained in this SubIFD */ 12735996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (is_motorola) { 12745996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding number_of_tags = GETJOCTET(data[offset]); 12755996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding number_of_tags <<= 8; 12765996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding number_of_tags += GETJOCTET(data[offset+1]); 12775996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } else { 12785996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding number_of_tags = GETJOCTET(data[offset+1]); 12795996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding number_of_tags <<= 8; 12805996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding number_of_tags += GETJOCTET(data[offset]); 12815996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 12825996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (number_of_tags < 2) return; 12835996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding offset += 2; 12845996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 12855996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */ 12865996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding do { 12875996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (offset > length - 12) return; /* check end of data segment */ 12885996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Get Tag number */ 12895996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (is_motorola) { 12905996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding tagnum = GETJOCTET(data[offset]); 12915996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding tagnum <<= 8; 12925996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding tagnum += GETJOCTET(data[offset+1]); 12935996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } else { 12945996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding tagnum = GETJOCTET(data[offset+1]); 12955996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding tagnum <<= 8; 12965996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding tagnum += GETJOCTET(data[offset]); 12975996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 12985996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (tagnum == 0xA002 || tagnum == 0xA003) { 12995996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (tagnum == 0xA002) 1300e5eaf37440b8e337ab150c017df7c03faf846c51DRC new_value = new_width; /* ExifImageWidth Tag */ 13015996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding else 1302e5eaf37440b8e337ab150c017df7c03faf846c51DRC new_value = new_height; /* ExifImageHeight Tag */ 13035996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (is_motorola) { 1304e5eaf37440b8e337ab150c017df7c03faf846c51DRC data[offset+2] = 0; /* Format = unsigned long (4 octets) */ 1305e5eaf37440b8e337ab150c017df7c03faf846c51DRC data[offset+3] = 4; 1306e5eaf37440b8e337ab150c017df7c03faf846c51DRC data[offset+4] = 0; /* Number Of Components = 1 */ 1307e5eaf37440b8e337ab150c017df7c03faf846c51DRC data[offset+5] = 0; 1308e5eaf37440b8e337ab150c017df7c03faf846c51DRC data[offset+6] = 0; 1309e5eaf37440b8e337ab150c017df7c03faf846c51DRC data[offset+7] = 1; 1310e5eaf37440b8e337ab150c017df7c03faf846c51DRC data[offset+8] = 0; 1311e5eaf37440b8e337ab150c017df7c03faf846c51DRC data[offset+9] = 0; 1312e5eaf37440b8e337ab150c017df7c03faf846c51DRC data[offset+10] = (JOCTET)((new_value >> 8) & 0xFF); 1313e5eaf37440b8e337ab150c017df7c03faf846c51DRC data[offset+11] = (JOCTET)(new_value & 0xFF); 13145996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } else { 1315e5eaf37440b8e337ab150c017df7c03faf846c51DRC data[offset+2] = 4; /* Format = unsigned long (4 octets) */ 1316e5eaf37440b8e337ab150c017df7c03faf846c51DRC data[offset+3] = 0; 1317e5eaf37440b8e337ab150c017df7c03faf846c51DRC data[offset+4] = 1; /* Number Of Components = 1 */ 1318e5eaf37440b8e337ab150c017df7c03faf846c51DRC data[offset+5] = 0; 1319e5eaf37440b8e337ab150c017df7c03faf846c51DRC data[offset+6] = 0; 1320e5eaf37440b8e337ab150c017df7c03faf846c51DRC data[offset+7] = 0; 1321e5eaf37440b8e337ab150c017df7c03faf846c51DRC data[offset+8] = (JOCTET)(new_value & 0xFF); 1322e5eaf37440b8e337ab150c017df7c03faf846c51DRC data[offset+9] = (JOCTET)((new_value >> 8) & 0xFF); 1323e5eaf37440b8e337ab150c017df7c03faf846c51DRC data[offset+10] = 0; 1324e5eaf37440b8e337ab150c017df7c03faf846c51DRC data[offset+11] = 0; 13255996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 13265996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 13275996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding offset += 12; 13285996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } while (--number_of_tags); 13295ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane} 1330506a742193ed5549074f40c3e0d2f0fd2eefb22bDRC#endif 13315ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 13325ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 13335ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* Adjust output image parameters as needed. 13345ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 13355ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * This must be called after jpeg_copy_critical_parameters() 13365ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * and before jpeg_write_coefficients(). 13375ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 13385ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * The return value is the set of virtual coefficient arrays to be written 13395ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * (either the ones allocated by jtransform_request_workspace, or the 13405ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * original source data arrays). The caller will need to pass this value 13415ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * to jpeg_write_coefficients(). 13425ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */ 13435ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 13445ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneGLOBAL(jvirt_barray_ptr *) 13455ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lanejtransform_adjust_parameters (j_decompress_ptr srcinfo, 1346e5eaf37440b8e337ab150c017df7c03faf846c51DRC j_compress_ptr dstinfo, 1347e5eaf37440b8e337ab150c017df7c03faf846c51DRC jvirt_barray_ptr *src_coef_arrays, 1348e5eaf37440b8e337ab150c017df7c03faf846c51DRC jpeg_transform_info *info) 13495ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{ 13505ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane /* If force-to-grayscale is requested, adjust destination parameters */ 13515ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane if (info->force_grayscale) { 13525996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* First, ensure we have YCbCr or grayscale data, and that the source's 13535996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * Y channel is full resolution. (No reasonable person would make Y 13545996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * be less than full resolution, so actually coping with that case 13555996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * isn't worth extra code space. But we check it to avoid crashing.) 13565ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */ 13575996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (((dstinfo->jpeg_color_space == JCS_YCbCr && 1358e5eaf37440b8e337ab150c017df7c03faf846c51DRC dstinfo->num_components == 3) || 1359e5eaf37440b8e337ab150c017df7c03faf846c51DRC (dstinfo->jpeg_color_space == JCS_GRAYSCALE && 1360e5eaf37440b8e337ab150c017df7c03faf846c51DRC dstinfo->num_components == 1)) && 1361e5eaf37440b8e337ab150c017df7c03faf846c51DRC srcinfo->comp_info[0].h_samp_factor == srcinfo->max_h_samp_factor && 1362e5eaf37440b8e337ab150c017df7c03faf846c51DRC srcinfo->comp_info[0].v_samp_factor == srcinfo->max_v_samp_factor) { 13635996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed 13645996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * properly. Among other things, it sets the target h_samp_factor & 13655996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * v_samp_factor to 1, which typically won't match the source. 13665996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * We have to preserve the source's quantization table number, however. 13675996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding */ 13685ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no; 13695ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE); 13705ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no; 13715ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } else { 13725ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane /* Sorry, can't do it */ 13735ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL); 13745ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 13755996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } else if (info->num_components == 1) { 13765996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* For a single-component source, we force the destination sampling factors 13775996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * to 1x1, with or without force_grayscale. This is useful because some 13785996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * decoders choke on grayscale images with other sampling factors. 13795996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding */ 13805996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding dstinfo->comp_info[0].h_samp_factor = 1; 13815996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding dstinfo->comp_info[0].v_samp_factor = 1; 13825ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 13835ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 13845996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Correct the destination's image dimensions as necessary 1385989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding * for rotate/flip, resize, and crop operations. 13865996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding */ 1387c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#if JPEG_LIB_VERSION >= 70 1388989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding dstinfo->jpeg_width = info->output_width; 1389989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding dstinfo->jpeg_height = info->output_height; 1390c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#endif 13915996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 13925996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Transpose destination image parameters */ 13935ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane switch (info->transform) { 13945ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane case JXFORM_TRANSPOSE: 13955ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane case JXFORM_TRANSVERSE: 13965ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane case JXFORM_ROT_90: 13975ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane case JXFORM_ROT_270: 13989a648cc90b77216060193466f86a3621c0bbb965DRC#if JPEG_LIB_VERSION < 70 13999a648cc90b77216060193466f86a3621c0bbb965DRC dstinfo->image_width = info->output_height; 14009a648cc90b77216060193466f86a3621c0bbb965DRC dstinfo->image_height = info->output_width; 14019a648cc90b77216060193466f86a3621c0bbb965DRC#endif 14025ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane transpose_critical_parameters(dstinfo); 14035ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane break; 14045996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding default: 14059a648cc90b77216060193466f86a3621c0bbb965DRC#if JPEG_LIB_VERSION < 70 14069a648cc90b77216060193466f86a3621c0bbb965DRC dstinfo->image_width = info->output_width; 14079a648cc90b77216060193466f86a3621c0bbb965DRC dstinfo->image_height = info->output_height; 14089a648cc90b77216060193466f86a3621c0bbb965DRC#endif 14095ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane break; 14105ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 14115ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 14125996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Adjust Exif properties */ 14135996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (srcinfo->marker_list != NULL && 14145996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding srcinfo->marker_list->marker == JPEG_APP0+1 && 14155996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding srcinfo->marker_list->data_length >= 6 && 14165996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding GETJOCTET(srcinfo->marker_list->data[0]) == 0x45 && 14175996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding GETJOCTET(srcinfo->marker_list->data[1]) == 0x78 && 14185996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding GETJOCTET(srcinfo->marker_list->data[2]) == 0x69 && 14195996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding GETJOCTET(srcinfo->marker_list->data[3]) == 0x66 && 14205996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding GETJOCTET(srcinfo->marker_list->data[4]) == 0 && 14215996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding GETJOCTET(srcinfo->marker_list->data[5]) == 0) { 14225996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Suppress output of JFIF marker */ 14235996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding dstinfo->write_JFIF_header = FALSE; 1424c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#if JPEG_LIB_VERSION >= 70 14255996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Adjust Exif image parameters */ 1426989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding if (dstinfo->jpeg_width != srcinfo->image_width || 1427e5eaf37440b8e337ab150c017df7c03faf846c51DRC dstinfo->jpeg_height != srcinfo->image_height) 14285996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Align data segment to start of TIFF structure for parsing */ 14295996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding adjust_exif_parameters(srcinfo->marker_list->data + 6, 1430e5eaf37440b8e337ab150c017df7c03faf846c51DRC srcinfo->marker_list->data_length - 6, 1431e5eaf37440b8e337ab150c017df7c03faf846c51DRC dstinfo->jpeg_width, dstinfo->jpeg_height); 1432c04bd3cc97f44fd9030de1e141754c8775d4e5a5DRC#endif 14335ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 14345ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 14355ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane /* Return the appropriate output data set */ 14365ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane if (info->workspace_coef_arrays != NULL) 14375ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane return info->workspace_coef_arrays; 14385ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane return src_coef_arrays; 14395ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane} 14405ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 14415ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 14425ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* Execute the actual transformation, if any. 14435ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 14445ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * This must be called *after* jpeg_write_coefficients, because it depends 14455ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * on jpeg_write_coefficients to have computed subsidiary values such as 14465ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * the per-component width and height fields in the destination object. 14475ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * 14485ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * Note that some transformations will modify the source data arrays! 14495ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */ 14505ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 14515ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneGLOBAL(void) 14525996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbedingjtransform_execute_transform (j_decompress_ptr srcinfo, 1453e5eaf37440b8e337ab150c017df7c03faf846c51DRC j_compress_ptr dstinfo, 1454e5eaf37440b8e337ab150c017df7c03faf846c51DRC jvirt_barray_ptr *src_coef_arrays, 1455e5eaf37440b8e337ab150c017df7c03faf846c51DRC jpeg_transform_info *info) 14565ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{ 14575ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays; 14585ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 14595996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding /* Note: conditions tested here should match those in switch statement 14605996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * in jtransform_request_workspace() 14615996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding */ 14625ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane switch (info->transform) { 14635ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane case JXFORM_NONE: 14645996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (info->x_crop_offset != 0 || info->y_crop_offset != 0) 14655996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding do_crop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1466e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_coef_arrays, dst_coef_arrays); 14675ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane break; 14685ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane case JXFORM_FLIP_H: 1469ba5ea5143e48b71234414139e3b4cb244599e875DRC if (info->y_crop_offset != 0 || info->slow_hflip) 14705996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding do_flip_h(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1471e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_coef_arrays, dst_coef_arrays); 14725996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding else 14735996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding do_flip_h_no_crop(srcinfo, dstinfo, info->x_crop_offset, 1474e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_coef_arrays); 14755ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane break; 14765ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane case JXFORM_FLIP_V: 14775996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding do_flip_v(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1478e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_coef_arrays, dst_coef_arrays); 14795ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane break; 14805ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane case JXFORM_TRANSPOSE: 14815996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding do_transpose(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1482e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_coef_arrays, dst_coef_arrays); 14835ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane break; 14845ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane case JXFORM_TRANSVERSE: 14855996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding do_transverse(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1486e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_coef_arrays, dst_coef_arrays); 14875ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane break; 14885ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane case JXFORM_ROT_90: 14895996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding do_rot_90(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1490e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_coef_arrays, dst_coef_arrays); 14915ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane break; 14925ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane case JXFORM_ROT_180: 14935996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding do_rot_180(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1494e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_coef_arrays, dst_coef_arrays); 14955996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding break; 14965996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding case JXFORM_ROT_270: 14975996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, 1498e5eaf37440b8e337ab150c017df7c03faf846c51DRC src_coef_arrays, dst_coef_arrays); 14995ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane break; 15005996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding } 15015996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding} 15025996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 15035996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding/* jtransform_perfect_transform 15045996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * 15055996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * Determine whether lossless transformation is perfectly 15065996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * possible for a specified image and transformation. 15075996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * 15085996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * Inputs: 15095996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * image_width, image_height: source image dimensions. 15105996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * MCU_width, MCU_height: pixel dimensions of MCU. 15115996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * transform: transformation identifier. 15125996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * Parameter sources from initialized jpeg_struct 15135996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * (after reading source header): 15145996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * image_width = cinfo.image_width 15155996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * image_height = cinfo.image_height 1516989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding * MCU_width = cinfo.max_h_samp_factor * cinfo.block_size 1517989630f70cf1af69ebfefca8910d1647bf189712Guido Vollbeding * MCU_height = cinfo.max_v_samp_factor * cinfo.block_size 15185996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * Result: 15195996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * TRUE = perfect transformation possible 15205996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * FALSE = perfect transformation not possible 15215996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding * (may use custom action then) 15225996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding */ 15235996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 15245996a25e2f50d20d6a8f09830724035b49c3927bGuido VollbedingGLOBAL(boolean) 15255996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbedingjtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height, 1526e5eaf37440b8e337ab150c017df7c03faf846c51DRC int MCU_width, int MCU_height, 1527e5eaf37440b8e337ab150c017df7c03faf846c51DRC JXFORM_CODE transform) 15285996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding{ 15295996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding boolean result = TRUE; /* initialize TRUE */ 15305996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 15315996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding switch (transform) { 15325996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding case JXFORM_FLIP_H: 15335ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane case JXFORM_ROT_270: 15345996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (image_width % (JDIMENSION) MCU_width) 15355996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding result = FALSE; 15365996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding break; 15375996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding case JXFORM_FLIP_V: 15385996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding case JXFORM_ROT_90: 15395996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (image_height % (JDIMENSION) MCU_height) 15405996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding result = FALSE; 15415996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding break; 15425996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding case JXFORM_TRANSVERSE: 15435996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding case JXFORM_ROT_180: 15445996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (image_width % (JDIMENSION) MCU_width) 15455996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding result = FALSE; 15465996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding if (image_height % (JDIMENSION) MCU_height) 15475996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding result = FALSE; 15485996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding break; 15495996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding default: 15505ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane break; 15515ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 15525996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding 15535996a25e2f50d20d6a8f09830724035b49c3927bGuido Vollbeding return result; 15545ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane} 15555ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 15565ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane#endif /* TRANSFORMS_SUPPORTED */ 15575ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 15585ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 15595ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* Setup decompression object to save desired markers in memory. 15605ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * This must be called before jpeg_read_header() to have the desired effect. 15615ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */ 15625ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 15635ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneGLOBAL(void) 15645ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lanejcopy_markers_setup (j_decompress_ptr srcinfo, JCOPY_OPTION option) 15655ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{ 15665ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane#ifdef SAVE_MARKERS_SUPPORTED 15675ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane int m; 15685ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 15695ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane /* Save comments except under NONE option */ 15705ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane if (option != JCOPYOPT_NONE) { 15715ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF); 15725ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 15735ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane /* Save all types of APPn markers iff ALL option */ 15745ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane if (option == JCOPYOPT_ALL) { 15755ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (m = 0; m < 16; m++) 15765ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF); 15775ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 15785ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane#endif /* SAVE_MARKERS_SUPPORTED */ 15795ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane} 15805ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 15815ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane/* Copy markers saved in the given source object to the destination object. 15825ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * This should be called just after jpeg_start_compress() or 15835ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * jpeg_write_coefficients(). 15845ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * Note that those routines will have written the SOI, and also the 15855ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * JFIF APP0 or Adobe APP14 markers if selected. 15865ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */ 15875ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 15885ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. LaneGLOBAL(void) 15895ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lanejcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, 1590e5eaf37440b8e337ab150c017df7c03faf846c51DRC JCOPY_OPTION option) 15915ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane{ 15925ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane jpeg_saved_marker_ptr marker; 15935ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane 15945ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane /* In the current implementation, we don't actually need to examine the 15955ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * option flag here; we just copy everything that got saved. 15965ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * But to avoid confusion, we do not output JFIF and Adobe APP14 markers 15975ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * if the encoder library already wrote one. 15985ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane */ 15995ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) { 16005ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane if (dstinfo->write_JFIF_header && 1601e5eaf37440b8e337ab150c017df7c03faf846c51DRC marker->marker == JPEG_APP0 && 1602e5eaf37440b8e337ab150c017df7c03faf846c51DRC marker->data_length >= 5 && 1603e5eaf37440b8e337ab150c017df7c03faf846c51DRC GETJOCTET(marker->data[0]) == 0x4A && 1604e5eaf37440b8e337ab150c017df7c03faf846c51DRC GETJOCTET(marker->data[1]) == 0x46 && 1605e5eaf37440b8e337ab150c017df7c03faf846c51DRC GETJOCTET(marker->data[2]) == 0x49 && 1606e5eaf37440b8e337ab150c017df7c03faf846c51DRC GETJOCTET(marker->data[3]) == 0x46 && 1607e5eaf37440b8e337ab150c017df7c03faf846c51DRC GETJOCTET(marker->data[4]) == 0) 1608e5eaf37440b8e337ab150c017df7c03faf846c51DRC continue; /* reject duplicate JFIF */ 16095ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane if (dstinfo->write_Adobe_marker && 1610e5eaf37440b8e337ab150c017df7c03faf846c51DRC marker->marker == JPEG_APP0+14 && 1611e5eaf37440b8e337ab150c017df7c03faf846c51DRC marker->data_length >= 5 && 1612e5eaf37440b8e337ab150c017df7c03faf846c51DRC GETJOCTET(marker->data[0]) == 0x41 && 1613e5eaf37440b8e337ab150c017df7c03faf846c51DRC GETJOCTET(marker->data[1]) == 0x64 && 1614e5eaf37440b8e337ab150c017df7c03faf846c51DRC GETJOCTET(marker->data[2]) == 0x6F && 1615e5eaf37440b8e337ab150c017df7c03faf846c51DRC GETJOCTET(marker->data[3]) == 0x62 && 1616e5eaf37440b8e337ab150c017df7c03faf846c51DRC GETJOCTET(marker->data[4]) == 0x65) 1617e5eaf37440b8e337ab150c017df7c03faf846c51DRC continue; /* reject duplicate Adobe */ 16185ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane jpeg_write_marker(dstinfo, marker->marker, 1619e5eaf37440b8e337ab150c017df7c03faf846c51DRC marker->data, marker->data_length); 16205ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane } 16215ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane} 1622