diff options
| author | Daniel Friesel <derf@derf.homelinux.org> | 2010-02-21 15:30:43 +0100 | 
|---|---|---|
| committer | Daniel Friesel <derf@derf.homelinux.org> | 2010-02-21 15:30:43 +0100 | 
| commit | ac0d19cd4804e3114494c4f6ef6954a0e63fd7a7 (patch) | |
| tree | e0a7cffe0c15cf41cfb6468ddef548c0fa3e7bb0 /src | |
| parent | 8b53d170885a9bdf3e0ddfd7362b9caeef0528cf (diff) | |
Revert "Fix lossless image rotation"
This reverts commit 15ede2653b45a1fe73bc8c7c9151e3e8dc1c32dc.
Diffstat (limited to 'src')
| -rw-r--r-- | src/jpegint.h | 114 | ||||
| -rw-r--r-- | src/transupp.c | 1069 | ||||
| -rw-r--r-- | src/transupp.h | 129 | 
3 files changed, 535 insertions, 777 deletions
| diff --git a/src/jpegint.h b/src/jpegint.h index eb6ec8b..e55a2be 100644 --- a/src/jpegint.h +++ b/src/jpegint.h @@ -2,7 +2,6 @@   * jpegint.h   *   * Copyright (C) 1991-1997, Thomas G. Lane. - * Modified 1997-2009 by Guido Vollbeding.   * This file is part of the Independent JPEG Group's software.   * For conditions of distribution and use, see the accompanying README file.   * @@ -11,7 +10,6 @@   * applications using the library shouldn't need to include this file.   */ -  /* Declarations for both compression & decompression */  typedef enum {			/* Operating modes for buffer controllers */ @@ -39,7 +37,6 @@ typedef enum {			/* Operating modes for buffer controllers */  #define DSTATE_RDCOEFS	209	/* reading file in jpeg_read_coefficients */  #define DSTATE_STOPPING	210	/* looking for EOI in jpeg_finish_decompress */ -  /* Declarations for compression modules */  /* Master control module */ @@ -56,19 +53,17 @@ struct jpeg_comp_master {  /* Main buffer control (downsampled-data buffer) */  struct jpeg_c_main_controller {  	JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); -	 JMETHOD(void, process_data, (j_compress_ptr cinfo, -				      JSAMPARRAY input_buf, JDIMENSION * in_row_ctr, JDIMENSION in_rows_avail)); +	 JMETHOD(void, process_data, +		 (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION * in_row_ctr, JDIMENSION in_rows_avail));  };  /* Compression preprocessing (downsampling input buffer control) */  struct jpeg_c_prep_controller {  	JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); -	 JMETHOD(void, pre_process_data, (j_compress_ptr cinfo, -					  JSAMPARRAY input_buf, -					  JDIMENSION * in_row_ctr, -					  JDIMENSION in_rows_avail, -					  JSAMPIMAGE output_buf, -					  JDIMENSION * out_row_group_ctr, JDIMENSION out_row_groups_avail)); +	 JMETHOD(void, pre_process_data, +		 (j_compress_ptr cinfo, JSAMPARRAY input_buf, +		  JDIMENSION * in_row_ctr, JDIMENSION in_rows_avail, +		  JSAMPIMAGE output_buf, JDIMENSION * out_row_group_ctr, JDIMENSION out_row_groups_avail));  };  /* Coefficient buffer control */ @@ -81,30 +76,29 @@ struct jpeg_c_coef_controller {  struct jpeg_color_converter {  	JMETHOD(void, start_pass, (j_compress_ptr cinfo));  	 JMETHOD(void, color_convert, (j_compress_ptr cinfo, -				       JSAMPARRAY input_buf, JSAMPIMAGE output_buf, -				       JDIMENSION output_row, int num_rows)); +				       JSAMPARRAY input_buf, +				       JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows));  };  /* Downsampling */  struct jpeg_downsampler {  	JMETHOD(void, start_pass, (j_compress_ptr cinfo));  	 JMETHOD(void, downsample, (j_compress_ptr cinfo, -				    JSAMPIMAGE input_buf, JDIMENSION in_row_index, -				    JSAMPIMAGE output_buf, JDIMENSION out_row_group_index)); +				    JSAMPIMAGE input_buf, +				    JDIMENSION in_row_index, JSAMPIMAGE output_buf, JDIMENSION out_row_group_index));  	boolean need_context_rows;	/* TRUE if need rows above & below */  };  /* Forward DCT (also controls coefficient quantization) */ -typedef JMETHOD(void, forward_DCT_ptr, -		(j_compress_ptr cinfo, jpeg_component_info * compptr, -		 JSAMPARRAY sample_data, JBLOCKROW coef_blocks, -		 JDIMENSION start_row, JDIMENSION start_col, JDIMENSION num_blocks)); -  struct jpeg_forward_dct {  	JMETHOD(void, start_pass, (j_compress_ptr cinfo)); -	/* It is useful to allow each component to have a separate FDCT method. */ -	forward_DCT_ptr forward_DCT[MAX_COMPONENTS]; +	/* perhaps this should be an array??? */ +	 JMETHOD(void, forward_DCT, (j_compress_ptr cinfo, +				     jpeg_component_info * compptr, +				     JSAMPARRAY sample_data, +				     JBLOCKROW coef_blocks, +				     JDIMENSION start_row, JDIMENSION start_col, JDIMENSION num_blocks));  };  /* Entropy encoding */ @@ -127,7 +121,6 @@ struct jpeg_marker_writer {  	 JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val));  }; -  /* Declarations for decompression modules */  /* Master control module */ @@ -154,8 +147,8 @@ struct jpeg_input_controller {  /* Main buffer control (downsampled-data buffer) */  struct jpeg_d_main_controller {  	JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); -	 JMETHOD(void, process_data, (j_decompress_ptr cinfo, -				      JSAMPARRAY output_buf, JDIMENSION * out_row_ctr, JDIMENSION out_rows_avail)); +	 JMETHOD(void, process_data, +		 (j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION * out_row_ctr, JDIMENSION out_rows_avail));  };  /* Coefficient buffer control */ @@ -171,11 +164,11 @@ struct jpeg_d_coef_controller {  /* Decompression postprocessing (color quantization buffer control) */  struct jpeg_d_post_controller {  	JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); -	 JMETHOD(void, post_process_data, (j_decompress_ptr cinfo, -					   JSAMPIMAGE input_buf, -					   JDIMENSION * in_row_group_ctr, -					   JDIMENSION in_row_groups_avail, -					   JSAMPARRAY output_buf, JDIMENSION * out_row_ctr, JDIMENSION out_rows_avail)); +	 JMETHOD(void, post_process_data, +		 (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, +		  JDIMENSION * in_row_group_ctr, +		  JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, +		  JDIMENSION * out_row_ctr, JDIMENSION out_rows_avail));  };  /* Marker reading & parsing */ @@ -202,6 +195,10 @@ struct jpeg_marker_reader {  struct jpeg_entropy_decoder {  	JMETHOD(void, start_pass, (j_decompress_ptr cinfo));  	 JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo, JBLOCKROW * MCU_data)); + +	/* This is here to share code between baseline and progressive decoders; */ +	/* other modules probably should not use it */ +	boolean insufficient_data;	/* set TRUE after emitting warning */  };  /* Inverse DCT (also performs dequantization) */ @@ -231,20 +228,19 @@ struct jpeg_upsampler {  struct jpeg_color_deconverter {  	JMETHOD(void, start_pass, (j_decompress_ptr cinfo));  	 JMETHOD(void, color_convert, (j_decompress_ptr cinfo, -				       JSAMPIMAGE input_buf, JDIMENSION input_row, -				       JSAMPARRAY output_buf, int num_rows)); +				       JSAMPIMAGE input_buf, +				       JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows));  };  /* Color quantization or color precision reduction */  struct jpeg_color_quantizer {  	JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan)); -	 JMETHOD(void, color_quantize, (j_decompress_ptr cinfo, -					JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows)); +	 JMETHOD(void, color_quantize, +		 (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows));  	 JMETHOD(void, finish_pass, (j_decompress_ptr cinfo));  	 JMETHOD(void, new_color_map, (j_decompress_ptr cinfo));  }; -  /* Miscellaneous useful macros */  #undef MAX @@ -252,7 +248,6 @@ struct jpeg_color_quantizer {  #undef MIN  #define MIN(a,b)	((a) < (b) ? (a) : (b)) -  /* We assume that right shift corresponds to signed division by 2 with   * rounding towards minus infinity.  This is correct for typical "arithmetic   * shift" instructions that shift in copies of the sign bit.  But some @@ -274,7 +269,6 @@ struct jpeg_color_quantizer {  #define RIGHT_SHIFT(x,shft)	((x) >> (shft))  #endif -  /* Short forms of external names for systems with brain-damaged linkers. */  #ifdef NEED_SHORT_EXTERNAL_NAMES @@ -287,7 +281,7 @@ struct jpeg_color_quantizer {  #define jinit_downsampler	jIDownsampler  #define jinit_forward_dct	jIFDCT  #define jinit_huff_encoder	jIHEncoder -#define jinit_arith_encoder	jIAEncoder +#define jinit_phuff_encoder	jIPHEncoder  #define jinit_marker_writer	jIMWriter  #define jinit_master_decompress	jIDMaster  #define jinit_d_main_controller	jIDMainC @@ -296,7 +290,7 @@ struct jpeg_color_quantizer {  #define jinit_input_controller	jIInCtlr  #define jinit_marker_reader	jIMReader  #define jinit_huff_decoder	jIHDecoder -#define jinit_arith_decoder	jIADecoder +#define jinit_phuff_decoder	jIPHDecoder  #define jinit_inverse_dct	jIIDCT  #define jinit_upsampler		jIUpsampler  #define jinit_color_deconverter	jIDColor @@ -311,27 +305,16 @@ struct jpeg_color_quantizer {  #define jzero_far		jZeroFar  #define jpeg_zigzag_order	jZIGTable  #define jpeg_natural_order	jZAGTable -#define jpeg_natural_order7	jZAGTable7 -#define jpeg_natural_order6	jZAGTable6 -#define jpeg_natural_order5	jZAGTable5 -#define jpeg_natural_order4	jZAGTable4 -#define jpeg_natural_order3	jZAGTable3 -#define jpeg_natural_order2	jZAGTable2 -#define jpeg_aritab		jAriTab  #endif				/* NEED_SHORT_EXTERNAL_NAMES */ -  /* Compression module initialization routines */  EXTERN(void)  jinit_compress_master JPP((j_compress_ptr cinfo));  EXTERN(void)  jinit_c_master_control JPP((j_compress_ptr cinfo, boolean transcode_only)); -EXTERN(void) -jinit_c_main_controller JPP((j_compress_ptr cinfo, boolean need_full_buffer)); -EXTERN(void) -jinit_c_prep_controller JPP((j_compress_ptr cinfo, boolean need_full_buffer)); -EXTERN(void) -jinit_c_coef_controller JPP((j_compress_ptr cinfo, boolean need_full_buffer)); +EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo, boolean need_full_buffer)); +EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo, boolean need_full_buffer)); +EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo, boolean need_full_buffer));  EXTERN(void)  jinit_color_converter JPP((j_compress_ptr cinfo));  EXTERN(void) @@ -341,18 +324,15 @@ jinit_forward_dct JPP((j_compress_ptr cinfo));  EXTERN(void)  jinit_huff_encoder JPP((j_compress_ptr cinfo));  EXTERN(void) -jinit_arith_encoder JPP((j_compress_ptr cinfo)); +jinit_phuff_encoder JPP((j_compress_ptr cinfo));  EXTERN(void)  jinit_marker_writer JPP((j_compress_ptr cinfo));  /* Decompression module initialization routines */  EXTERN(void)  jinit_master_decompress JPP((j_decompress_ptr cinfo)); -EXTERN(void) -jinit_d_main_controller JPP((j_decompress_ptr cinfo, boolean need_full_buffer)); -EXTERN(void) -jinit_d_coef_controller JPP((j_decompress_ptr cinfo, boolean need_full_buffer)); -EXTERN(void) -jinit_d_post_controller JPP((j_decompress_ptr cinfo, boolean need_full_buffer)); +EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo, boolean need_full_buffer)); +EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo, boolean need_full_buffer)); +EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo, boolean need_full_buffer));  EXTERN(void)  jinit_input_controller JPP((j_decompress_ptr cinfo));  EXTERN(void) @@ -360,7 +340,7 @@ jinit_marker_reader JPP((j_decompress_ptr cinfo));  EXTERN(void)  jinit_huff_decoder JPP((j_decompress_ptr cinfo));  EXTERN(void) -jinit_arith_decoder JPP((j_decompress_ptr cinfo)); +jinit_phuff_decoder JPP((j_decompress_ptr cinfo));  EXTERN(void)  jinit_inverse_dct JPP((j_decompress_ptr cinfo));  EXTERN(void) @@ -385,8 +365,7 @@ jround_up JPP((long a, long b));  EXTERN(void)  jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row,  		       JSAMPARRAY output_array, int dest_row, int num_rows, JDIMENSION num_cols)); -EXTERN(void) -jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row, JDIMENSION num_blocks)); +EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row, JDIMENSION num_blocks));  EXTERN(void)  jzero_far JPP((void FAR * target, size_t bytestozero));  /* Constant tables in jutils.c */ @@ -394,15 +373,6 @@ jzero_far JPP((void FAR * target, size_t bytestozero));  extern const int jpeg_zigzag_order[];	/* natural coef order to zigzag order */  #endif  extern const int jpeg_natural_order[];	/* zigzag coef order to natural order */ -extern const int jpeg_natural_order7[];	/* zz to natural order for 7x7 block */ -extern const int jpeg_natural_order6[];	/* zz to natural order for 6x6 block */ -extern const int jpeg_natural_order5[];	/* zz to natural order for 5x5 block */ -extern const int jpeg_natural_order4[];	/* zz to natural order for 4x4 block */ -extern const int jpeg_natural_order3[];	/* zz to natural order for 3x3 block */ -extern const int jpeg_natural_order2[];	/* zz to natural order for 2x2 block */ - -/* Arithmetic coding probability estimation tables in jaricom.c */ -extern const INT32 jpeg_aritab[];  /* Suppress undefined-structure complaints if necessary. */ diff --git a/src/transupp.c b/src/transupp.c index 7a114be..162cc3f 100644 --- a/src/transupp.c +++ b/src/transupp.c @@ -1,7 +1,7 @@  /*   * transupp.c   * - * Copyright (C) 1997-2009, Thomas G. Lane, Guido Vollbeding. + * Copyright (C) 1997, Thomas G. Lane.   * This file is part of the Independent JPEG Group's software.   * For conditions of distribution and use, see the accompanying README file.   * @@ -27,13 +27,12 @@  #define MEMCOPY(dest,src,size)  memcpy((void *)(dest), (const void *)(src), (size_t)(size))  #define SIZEOF(object)  ((size_t) sizeof(object))  #define JFREAD(file,buf,sizeofbuf)  \ -	((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) +  ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))  #define JFWRITE(file,buf,sizeofbuf)  \ -	((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) +    ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) +  #include "jpeglib.h"  #include "transupp.h"		/* My own external interface */ -#include <ctype.h>		/* to declare isdigit() */ -  #if TRANSFORMS_SUPPORTED @@ -41,8 +40,7 @@   * Lossless image transformation routines.  These routines work on DCT   * coefficient arrays and thus do not require any lossy decompression   * or recompression of the image. - * Thanks to Guido Vollbeding for the initial design and code of this feature, - * and to Ben Jackson for introducing the cropping feature. + * Thanks to Guido Vollbeding for the initial design and code of this feature.   *   * Horizontal flipping is done in-place, using a single top-to-bottom   * pass through the virtual source array.  It will thus be much the @@ -56,13 +54,6 @@   * arrays for most of the transforms.  That could result in much thrashing   * if the image is larger than main memory.   * - * If cropping or trimming is involved, the destination arrays may be smaller - * than the source arrays.  Note it is not possible to do horizontal flip - * in-place when a nonzero Y crop offset is specified, since we'd have to move - * data from one block row to another but the virtual array manager doesn't - * guarantee we can touch more than one row at a time.  So in that case, - * we have to use a separate destination array. - *   * Some notes about the operating environment of the individual transform   * routines:   * 1. Both the source and destination virtual arrays are allocated from the @@ -75,25 +66,17 @@   *    and we may as well take that as the effective iMCU size.   * 4. When "trim" is in effect, the destination's dimensions will be the   *    trimmed values but the source's will be untrimmed. - * 5. When "crop" is in effect, the destination's dimensions will be the - *    cropped values but the source's will be uncropped.  Each transform - *    routine is responsible for picking up source data starting at the - *    correct X and Y offset for the crop region.  (The X and Y offsets - *    passed to the transform routines are measured in iMCU blocks of the - *    destination.) - * 6. All the routines assume that the source and destination buffers are + * 5. All the routines assume that the source and destination buffers are   *    padded out to a full iMCU boundary.  This is true, although for the   *    source buffer it is an undocumented property of jdcoefct.c. + * Notes 2,3,4 boil down to this: generally we should use the destination's + * dimensions and ignore the source's.   */ -LOCAL(void) -do_flip_h_no_crop(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, -		  JDIMENSION x_crop_offset, jvirt_barray_ptr * src_coef_arrays) -/* Horizontal flip; done in-place, so no separate dest array is required. - * NB: this only works when y_crop_offset is zero. - */ +LOCAL(void) do_flip_h(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, jvirt_barray_ptr * src_coef_arrays) +/* Horizontal flip; done in-place, so no separate dest array is required */  { -	JDIMENSION MCU_cols, comp_width, blk_x, blk_y, x_crop_blocks; +	JDIMENSION MCU_cols, comp_width, blk_x, blk_y;  	int ci, k, offset_y;  	JBLOCKARRAY buffer;  	JCOEFPTR ptr1, ptr2; @@ -105,18 +88,16 @@ do_flip_h_no_crop(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,  	 * mirroring by changing the signs of odd-numbered columns.  	 * Partial iMCUs at the right edge are left untouched.  	 */ -	MCU_cols = srcinfo->output_width / (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); +	MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);  	for (ci = 0; ci < dstinfo->num_components; ci++) {  		compptr = dstinfo->comp_info + ci;  		comp_width = MCU_cols * compptr->h_samp_factor; -		x_crop_blocks = x_crop_offset * compptr->h_samp_factor;  		for (blk_y = 0; blk_y < compptr->height_in_blocks; blk_y += compptr->v_samp_factor) {  			buffer = (*srcinfo->mem->access_virt_barray) -			    ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y, -			     (JDIMENSION) compptr->v_samp_factor, TRUE); +			    ((j_common_ptr) srcinfo, src_coef_arrays[ci], +			     blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE);  			for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { -				/* Do the mirroring */  				for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) {  					ptr1 = buffer[offset_y][blk_x];  					ptr2 = buffer[offset_y][comp_width - blk_x - 1]; @@ -132,31 +113,17 @@ do_flip_h_no_crop(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,  						*ptr2++ = -temp1;  					}  				} -				if (x_crop_blocks > 0) { -					/* Now left-justify the portion of the data to be kept. -					 * We can't use a single jcopy_block_row() call because that routine -					 * depends on memcpy(), whose behavior is unspecified for overlapping -					 * source and destination areas.  Sigh. -					 */ -					for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) { -						jcopy_block_row(buffer[offset_y] + blk_x + x_crop_blocks, -								buffer[offset_y] + blk_x, (JDIMENSION) 1); -					} -				}  			}  		}  	}  } -  LOCAL(void)  do_flip_v(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, -	  JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,  	  jvirt_barray_ptr * src_coef_arrays, jvirt_barray_ptr * dst_coef_arrays)  /* Vertical flip */  {  	JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; -	JDIMENSION x_crop_blocks, y_crop_blocks;  	int ci, i, j, offset_y;  	JBLOCKARRAY src_buffer, dst_buffer;  	JBLOCKROW src_row_ptr, dst_row_ptr; @@ -170,35 +137,33 @@ do_flip_v(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,  	 * of odd-numbered rows.  	 * Partial iMCUs at the bottom edge are copied verbatim.  	 */ -	MCU_rows = srcinfo->output_height / (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); +	MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);  	for (ci = 0; ci < dstinfo->num_components; ci++) {  		compptr = dstinfo->comp_info + ci;  		comp_height = MCU_rows * compptr->v_samp_factor; -		x_crop_blocks = x_crop_offset * compptr->h_samp_factor; -		y_crop_blocks = y_crop_offset * compptr->v_samp_factor;  		for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; dst_blk_y += compptr->v_samp_factor) {  			dst_buffer = (*srcinfo->mem->access_virt_barray) -			    ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, -			     (JDIMENSION) compptr->v_samp_factor, TRUE); -			if (y_crop_blocks + dst_blk_y < comp_height) { +			    ((j_common_ptr) srcinfo, dst_coef_arrays[ci], +			     dst_blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE); +			if (dst_blk_y < comp_height) {  				/* Row is within the mirrorable area. */  				src_buffer = (*srcinfo->mem->access_virt_barray) -				    ((j_common_ptr) srcinfo, src_coef_arrays[ci], -				     comp_height - y_crop_blocks - dst_blk_y - +				    ((j_common_ptr) srcinfo, +				     src_coef_arrays[ci], +				     comp_height - dst_blk_y -  				     (JDIMENSION) compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, FALSE);  			} else {  				/* Bottom-edge blocks will be copied verbatim. */  				src_buffer = (*srcinfo->mem->access_virt_barray) -				    ((j_common_ptr) srcinfo, src_coef_arrays[ci], -				     dst_blk_y + y_crop_blocks, (JDIMENSION) compptr->v_samp_factor, FALSE); +				    ((j_common_ptr) srcinfo, +				     src_coef_arrays[ci], dst_blk_y, (JDIMENSION) compptr->v_samp_factor, FALSE);  			}  			for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { -				if (y_crop_blocks + dst_blk_y < comp_height) { +				if (dst_blk_y < comp_height) {  					/* Row is within the mirrorable area. */  					dst_row_ptr = dst_buffer[offset_y];  					src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; -					src_row_ptr += x_crop_blocks;  					for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {  						dst_ptr = dst_row_ptr[dst_blk_x];  						src_ptr = src_row_ptr[dst_blk_x]; @@ -213,22 +178,20 @@ do_flip_v(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,  					}  				} else {  					/* Just copy row verbatim. */ -					jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, -							dst_buffer[offset_y], compptr->width_in_blocks); +					jcopy_block_row(src_buffer +							[offset_y], dst_buffer[offset_y], compptr->width_in_blocks);  				}  			}  		}  	}  } -  LOCAL(void)  do_transpose(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, -	     JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,  	     jvirt_barray_ptr * src_coef_arrays, jvirt_barray_ptr * dst_coef_arrays)  /* Transpose source into destination */  { -	JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks; +	JDIMENSION dst_blk_x, dst_blk_y;  	int ci, i, j, offset_x, offset_y;  	JBLOCKARRAY src_buffer, dst_buffer;  	JCOEFPTR src_ptr, dst_ptr; @@ -241,24 +204,25 @@ do_transpose(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,  	 */  	for (ci = 0; ci < dstinfo->num_components; ci++) {  		compptr = dstinfo->comp_info + ci; -		x_crop_blocks = x_crop_offset * compptr->h_samp_factor; -		y_crop_blocks = y_crop_offset * compptr->v_samp_factor;  		for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; dst_blk_y += compptr->v_samp_factor) {  			dst_buffer = (*srcinfo->mem->access_virt_barray) -			    ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, -			     (JDIMENSION) compptr->v_samp_factor, TRUE); +			    ((j_common_ptr) srcinfo, dst_coef_arrays[ci], +			     dst_blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE);  			for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { -				for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; -				     dst_blk_x += compptr->h_samp_factor) { +				for (dst_blk_x = 0; +				     dst_blk_x < compptr->width_in_blocks; dst_blk_x += compptr->h_samp_factor) {  					src_buffer = (*srcinfo->mem->access_virt_barray) -					    ((j_common_ptr) srcinfo, src_coef_arrays[ci], -					     dst_blk_x + x_crop_blocks, (JDIMENSION) compptr->h_samp_factor, FALSE); +					    ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, (JDIMENSION) +					     compptr->h_samp_factor, FALSE);  					for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { -						dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; -						src_ptr = src_buffer[offset_x][dst_blk_y + offset_y + y_crop_blocks]; +						src_ptr = src_buffer[offset_x] +						    [dst_blk_y + offset_y]; +						dst_ptr = dst_buffer[offset_y] +						    [dst_blk_x + offset_x];  						for (i = 0; i < DCTSIZE; i++)  							for (j = 0; j < DCTSIZE; j++) -								dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j]; +								dst_ptr[j * DCTSIZE + i] +								    = src_ptr[i * DCTSIZE + j];  					}  				}  			} @@ -266,10 +230,8 @@ do_transpose(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,  	}  } -  LOCAL(void)  do_rot_90(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, -	  JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,  	  jvirt_barray_ptr * src_coef_arrays, jvirt_barray_ptr * dst_coef_arrays)  /* 90 degree rotation is equivalent to   *   1. Transposing the image; @@ -278,7 +240,6 @@ do_rot_90(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,   */  {  	JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y; -	JDIMENSION x_crop_blocks, y_crop_blocks;  	int ci, i, j, offset_x, offset_y;  	JBLOCKARRAY src_buffer, dst_buffer;  	JCOEFPTR src_ptr, dst_ptr; @@ -288,57 +249,45 @@ do_rot_90(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,  	 * at the (output) right edge properly.  They just get transposed and  	 * not mirrored.  	 */ -	MCU_cols = srcinfo->output_height / (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); +	MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);  	for (ci = 0; ci < dstinfo->num_components; ci++) {  		compptr = dstinfo->comp_info + ci;  		comp_width = MCU_cols * compptr->h_samp_factor; -		x_crop_blocks = x_crop_offset * compptr->h_samp_factor; -		y_crop_blocks = y_crop_offset * compptr->v_samp_factor;  		for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; dst_blk_y += compptr->v_samp_factor) {  			dst_buffer = (*srcinfo->mem->access_virt_barray) -			    ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, -			     (JDIMENSION) compptr->v_samp_factor, TRUE); +			    ((j_common_ptr) srcinfo, dst_coef_arrays[ci], +			     dst_blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE);  			for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { -				for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; -				     dst_blk_x += compptr->h_samp_factor) { -					if (x_crop_blocks + dst_blk_x < comp_width) { -						/* Block is within the mirrorable area. */ -						src_buffer = (*srcinfo->mem->access_virt_barray) -						    ((j_common_ptr) srcinfo, src_coef_arrays[ci], -						     comp_width - x_crop_blocks - dst_blk_x - -						     (JDIMENSION) compptr->h_samp_factor, -						     (JDIMENSION) compptr->h_samp_factor, FALSE); -					} else { -						/* Edge blocks are transposed but not mirrored. */ -						src_buffer = (*srcinfo->mem->access_virt_barray) -						    ((j_common_ptr) srcinfo, src_coef_arrays[ci], -						     dst_blk_x + x_crop_blocks, -						     (JDIMENSION) compptr->h_samp_factor, FALSE); -					} +				for (dst_blk_x = 0; +				     dst_blk_x < compptr->width_in_blocks; dst_blk_x += compptr->h_samp_factor) { +					src_buffer = (*srcinfo->mem->access_virt_barray) +					    ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, (JDIMENSION) +					     compptr->h_samp_factor, FALSE);  					for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { -						dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; -						if (x_crop_blocks + dst_blk_x < comp_width) { +						src_ptr = src_buffer[offset_x] +						    [dst_blk_y + offset_y]; +						if (dst_blk_x < comp_width) {  							/* Block is within the mirrorable area. */ -							src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] -							    [dst_blk_y + offset_y + y_crop_blocks]; +							dst_ptr = dst_buffer[offset_y] +							    [comp_width - dst_blk_x - offset_x - 1];  							for (i = 0; i < DCTSIZE; i++) {  								for (j = 0; j < DCTSIZE; j++) -									dst_ptr[j * DCTSIZE + i] = -									    src_ptr[i * DCTSIZE + j]; +									dst_ptr[j * DCTSIZE + i] +									    = src_ptr[i * DCTSIZE + j];  								i++;  								for (j = 0; j < DCTSIZE; j++) -									dst_ptr[j * DCTSIZE + i] = -									    -src_ptr[i * DCTSIZE + j]; +									dst_ptr[j * DCTSIZE + i] +									    = -src_ptr[i * DCTSIZE + j];  							}  						} else {  							/* Edge blocks are transposed but not mirrored. */ -							src_ptr = src_buffer[offset_x] -							    [dst_blk_y + offset_y + y_crop_blocks]; +							dst_ptr = dst_buffer[offset_y] +							    [dst_blk_x + offset_x];  							for (i = 0; i < DCTSIZE; i++)  								for (j = 0; j < DCTSIZE; j++) -									dst_ptr[j * DCTSIZE + i] = -									    src_ptr[i * DCTSIZE + j]; +									dst_ptr[j * DCTSIZE + i] +									    = src_ptr[i * DCTSIZE + j];  						}  					}  				} @@ -347,10 +296,8 @@ do_rot_90(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,  	}  } -  LOCAL(void)  do_rot_270(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, -	   JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,  	   jvirt_barray_ptr * src_coef_arrays, jvirt_barray_ptr * dst_coef_arrays)  /* 270 degree rotation is equivalent to   *   1. Horizontal mirroring; @@ -359,7 +306,6 @@ do_rot_270(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,   */  {  	JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; -	JDIMENSION x_crop_blocks, y_crop_blocks;  	int ci, i, j, offset_x, offset_y;  	JBLOCKARRAY src_buffer, dst_buffer;  	JCOEFPTR src_ptr, dst_ptr; @@ -369,46 +315,45 @@ do_rot_270(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,  	 * at the (output) bottom edge properly.  They just get transposed and  	 * not mirrored.  	 */ -	MCU_rows = srcinfo->output_width / (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); +	MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);  	for (ci = 0; ci < dstinfo->num_components; ci++) {  		compptr = dstinfo->comp_info + ci;  		comp_height = MCU_rows * compptr->v_samp_factor; -		x_crop_blocks = x_crop_offset * compptr->h_samp_factor; -		y_crop_blocks = y_crop_offset * compptr->v_samp_factor;  		for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; dst_blk_y += compptr->v_samp_factor) {  			dst_buffer = (*srcinfo->mem->access_virt_barray) -			    ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, -			     (JDIMENSION) compptr->v_samp_factor, TRUE); +			    ((j_common_ptr) srcinfo, dst_coef_arrays[ci], +			     dst_blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE);  			for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { -				for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; -				     dst_blk_x += compptr->h_samp_factor) { +				for (dst_blk_x = 0; +				     dst_blk_x < compptr->width_in_blocks; dst_blk_x += compptr->h_samp_factor) {  					src_buffer = (*srcinfo->mem->access_virt_barray) -					    ((j_common_ptr) srcinfo, src_coef_arrays[ci], -					     dst_blk_x + x_crop_blocks, (JDIMENSION) compptr->h_samp_factor, FALSE); +					    ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, (JDIMENSION) +					     compptr->h_samp_factor, FALSE);  					for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { -						dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; -						if (y_crop_blocks + dst_blk_y < comp_height) { +						dst_ptr = dst_buffer[offset_y] +						    [dst_blk_x + offset_x]; +						if (dst_blk_y < comp_height) {  							/* Block is within the mirrorable area. */  							src_ptr = src_buffer[offset_x] -							    [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; +							    [comp_height - dst_blk_y - offset_y - 1];  							for (i = 0; i < DCTSIZE; i++) {  								for (j = 0; j < DCTSIZE; j++) { -									dst_ptr[j * DCTSIZE + i] = -									    src_ptr[i * DCTSIZE + j]; +									dst_ptr[j * DCTSIZE + i] +									    = src_ptr[i * DCTSIZE + j];  									j++; -									dst_ptr[j * DCTSIZE + i] = -									    -src_ptr[i * DCTSIZE + j]; +									dst_ptr[j * DCTSIZE + i] +									    = -src_ptr[i * DCTSIZE + j];  								}  							}  						} else {  							/* Edge blocks are transposed but not mirrored. */  							src_ptr = src_buffer[offset_x] -							    [dst_blk_y + offset_y + y_crop_blocks]; +							    [dst_blk_y + offset_y];  							for (i = 0; i < DCTSIZE; i++)  								for (j = 0; j < DCTSIZE; j++) -									dst_ptr[j * DCTSIZE + i] = -									    src_ptr[i * DCTSIZE + j]; +									dst_ptr[j * DCTSIZE + i] +									    = src_ptr[i * DCTSIZE + j];  						}  					}  				} @@ -417,10 +362,8 @@ do_rot_270(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,  	}  } -  LOCAL(void)  do_rot_180(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, -	   JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,  	   jvirt_barray_ptr * src_coef_arrays, jvirt_barray_ptr * dst_coef_arrays)  /* 180 degree rotation is equivalent to   *   1. Vertical mirroring; @@ -429,101 +372,97 @@ do_rot_180(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,   */  {  	JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; -	JDIMENSION x_crop_blocks, y_crop_blocks;  	int ci, i, j, offset_y;  	JBLOCKARRAY src_buffer, dst_buffer;  	JBLOCKROW src_row_ptr, dst_row_ptr;  	JCOEFPTR src_ptr, dst_ptr;  	jpeg_component_info *compptr; -	MCU_cols = srcinfo->output_width / (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); -	MCU_rows = srcinfo->output_height / (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); +	MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); +	MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);  	for (ci = 0; ci < dstinfo->num_components; ci++) {  		compptr = dstinfo->comp_info + ci;  		comp_width = MCU_cols * compptr->h_samp_factor;  		comp_height = MCU_rows * compptr->v_samp_factor; -		x_crop_blocks = x_crop_offset * compptr->h_samp_factor; -		y_crop_blocks = y_crop_offset * compptr->v_samp_factor;  		for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; dst_blk_y += compptr->v_samp_factor) {  			dst_buffer = (*srcinfo->mem->access_virt_barray) -			    ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, -			     (JDIMENSION) compptr->v_samp_factor, TRUE); -			if (y_crop_blocks + dst_blk_y < comp_height) { +			    ((j_common_ptr) srcinfo, dst_coef_arrays[ci], +			     dst_blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE); +			if (dst_blk_y < comp_height) {  				/* Row is within the vertically mirrorable area. */  				src_buffer = (*srcinfo->mem->access_virt_barray) -				    ((j_common_ptr) srcinfo, src_coef_arrays[ci], -				     comp_height - y_crop_blocks - dst_blk_y - +				    ((j_common_ptr) srcinfo, +				     src_coef_arrays[ci], +				     comp_height - dst_blk_y -  				     (JDIMENSION) compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, FALSE);  			} else {  				/* Bottom-edge rows are only mirrored horizontally. */  				src_buffer = (*srcinfo->mem->access_virt_barray) -				    ((j_common_ptr) srcinfo, src_coef_arrays[ci], -				     dst_blk_y + y_crop_blocks, (JDIMENSION) compptr->v_samp_factor, FALSE); +				    ((j_common_ptr) srcinfo, +				     src_coef_arrays[ci], dst_blk_y, (JDIMENSION) compptr->v_samp_factor, FALSE);  			}  			for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { -				dst_row_ptr = dst_buffer[offset_y]; -				if (y_crop_blocks + dst_blk_y < comp_height) { +				if (dst_blk_y < comp_height) {  					/* Row is within the mirrorable area. */ +					dst_row_ptr = dst_buffer[offset_y];  					src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; -					for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { +					/* Process the blocks that can be mirrored both ways. */ +					for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) {  						dst_ptr = dst_row_ptr[dst_blk_x]; -						if (x_crop_blocks + dst_blk_x < comp_width) { -							/* Process the blocks that can be mirrored both ways. */ -							src_ptr = -							    src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; -							for (i = 0; i < DCTSIZE; i += 2) { -								/* For even row, negate every odd column. */ -								for (j = 0; j < DCTSIZE; j += 2) { -									*dst_ptr++ = *src_ptr++; -									*dst_ptr++ = -*src_ptr++; -								} -								/* For odd row, negate every even column. */ -								for (j = 0; j < DCTSIZE; j += 2) { -									*dst_ptr++ = -*src_ptr++; -									*dst_ptr++ = *src_ptr++; -								} +						src_ptr = src_row_ptr[comp_width - dst_blk_x - 1]; +						for (i = 0; i < DCTSIZE; i += 2) { +							/* For even row, negate every odd column. */ +							for (j = 0; j < DCTSIZE; j += 2) { +								*dst_ptr++ = *src_ptr++; +								*dst_ptr++ = -*src_ptr++;  							} -						} else { -							/* Any remaining right-edge blocks are only mirrored vertically. */ -							src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x]; -							for (i = 0; i < DCTSIZE; i += 2) { -								for (j = 0; j < DCTSIZE; j++) -									*dst_ptr++ = *src_ptr++; -								for (j = 0; j < DCTSIZE; j++) -									*dst_ptr++ = -*src_ptr++; +							/* For odd row, negate every even column. */ +							for (j = 0; j < DCTSIZE; j += 2) { +								*dst_ptr++ = -*src_ptr++; +								*dst_ptr++ = *src_ptr++;  							}  						}  					} +					/* Any remaining right-edge blocks are only mirrored vertically. */ +					for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { +						dst_ptr = dst_row_ptr[dst_blk_x]; +						src_ptr = src_row_ptr[dst_blk_x]; +						for (i = 0; i < DCTSIZE; i += 2) { +							for (j = 0; j < DCTSIZE; j++) +								*dst_ptr++ = *src_ptr++; +							for (j = 0; j < DCTSIZE; j++) +								*dst_ptr++ = -*src_ptr++; +						} +					}  				} else {  					/* Remaining rows are just mirrored horizontally. */ +					dst_row_ptr = dst_buffer[offset_y];  					src_row_ptr = src_buffer[offset_y]; -					for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { -						if (x_crop_blocks + dst_blk_x < comp_width) { -							/* Process the blocks that can be mirrored. */ -							dst_ptr = dst_row_ptr[dst_blk_x]; -							src_ptr = -							    src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; -							for (i = 0; i < DCTSIZE2; i += 2) { -								*dst_ptr++ = *src_ptr++; -								*dst_ptr++ = -*src_ptr++; -							} -						} else { -							/* Any remaining right-edge blocks are only copied. */ -							jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks, -									dst_row_ptr + dst_blk_x, (JDIMENSION) 1); +					/* Process the blocks that can be mirrored. */ +					for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) { +						dst_ptr = dst_row_ptr[dst_blk_x]; +						src_ptr = src_row_ptr[comp_width - dst_blk_x - 1]; +						for (i = 0; i < DCTSIZE2; i += 2) { +							*dst_ptr++ = *src_ptr++; +							*dst_ptr++ = -*src_ptr++;  						}  					} +					/* Any remaining right-edge blocks are only copied. */ +					for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { +						dst_ptr = dst_row_ptr[dst_blk_x]; +						src_ptr = src_row_ptr[dst_blk_x]; +						for (i = 0; i < DCTSIZE2; i++) +							*dst_ptr++ = *src_ptr++; +					}  				}  			}  		}  	}  } -  LOCAL(void)  do_transverse(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, -	      JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,  	      jvirt_barray_ptr * src_coef_arrays, jvirt_barray_ptr * dst_coef_arrays)  /* Transverse transpose is equivalent to   *   1. 180 degree rotation; @@ -536,105 +475,91 @@ do_transverse(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,   */  {  	JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; -	JDIMENSION x_crop_blocks, y_crop_blocks;  	int ci, i, j, offset_x, offset_y;  	JBLOCKARRAY src_buffer, dst_buffer;  	JCOEFPTR src_ptr, dst_ptr;  	jpeg_component_info *compptr; -	MCU_cols = srcinfo->output_height / (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); -	MCU_rows = srcinfo->output_width / (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); +	MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); +	MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);  	for (ci = 0; ci < dstinfo->num_components; ci++) {  		compptr = dstinfo->comp_info + ci;  		comp_width = MCU_cols * compptr->h_samp_factor;  		comp_height = MCU_rows * compptr->v_samp_factor; -		x_crop_blocks = x_crop_offset * compptr->h_samp_factor; -		y_crop_blocks = y_crop_offset * compptr->v_samp_factor;  		for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; dst_blk_y += compptr->v_samp_factor) {  			dst_buffer = (*srcinfo->mem->access_virt_barray) -			    ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, -			     (JDIMENSION) compptr->v_samp_factor, TRUE); +			    ((j_common_ptr) srcinfo, dst_coef_arrays[ci], +			     dst_blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE);  			for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { -				for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; -				     dst_blk_x += compptr->h_samp_factor) { -					if (x_crop_blocks + dst_blk_x < comp_width) { -						/* Block is within the mirrorable area. */ -						src_buffer = (*srcinfo->mem->access_virt_barray) -						    ((j_common_ptr) srcinfo, src_coef_arrays[ci], -						     comp_width - x_crop_blocks - dst_blk_x - -						     (JDIMENSION) compptr->h_samp_factor, -						     (JDIMENSION) compptr->h_samp_factor, FALSE); -					} else { -						src_buffer = (*srcinfo->mem->access_virt_barray) -						    ((j_common_ptr) srcinfo, src_coef_arrays[ci], -						     dst_blk_x + x_crop_blocks, -						     (JDIMENSION) compptr->h_samp_factor, FALSE); -					} +				for (dst_blk_x = 0; +				     dst_blk_x < compptr->width_in_blocks; dst_blk_x += compptr->h_samp_factor) { +					src_buffer = (*srcinfo->mem->access_virt_barray) +					    ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, (JDIMENSION) +					     compptr->h_samp_factor, FALSE);  					for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { -						dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; -						if (y_crop_blocks + dst_blk_y < comp_height) { -							if (x_crop_blocks + dst_blk_x < comp_width) { +						if (dst_blk_y < comp_height) { +							src_ptr = src_buffer[offset_x] +							    [comp_height - dst_blk_y - offset_y - 1]; +							if (dst_blk_x < comp_width) {  								/* Block is within the mirrorable area. */ -								src_ptr = -								    src_buffer[compptr->h_samp_factor - offset_x - 1] -								    [comp_height - y_crop_blocks - dst_blk_y - -								     offset_y - 1]; +								dst_ptr = dst_buffer[offset_y] +								    [comp_width - dst_blk_x - offset_x - 1];  								for (i = 0; i < DCTSIZE; i++) {  									for (j = 0; j < DCTSIZE; j++) { -										dst_ptr[j * DCTSIZE + i] = -										    src_ptr[i * DCTSIZE + j]; +										dst_ptr[j * DCTSIZE + i] +										    = src_ptr[i * DCTSIZE + j];  										j++; -										dst_ptr[j * DCTSIZE + i] = -										    -src_ptr[i * DCTSIZE + j]; +										dst_ptr[j * DCTSIZE + i] +										    = -src_ptr[i * DCTSIZE + j];  									}  									i++;  									for (j = 0; j < DCTSIZE; j++) { -										dst_ptr[j * DCTSIZE + i] = -										    -src_ptr[i * DCTSIZE + j]; +										dst_ptr[j * DCTSIZE + i] +										    = -src_ptr[i * DCTSIZE + j];  										j++; -										dst_ptr[j * DCTSIZE + i] = -										    src_ptr[i * DCTSIZE + j]; +										dst_ptr[j * DCTSIZE + i] +										    = src_ptr[i * DCTSIZE + j];  									}  								}  							} else {  								/* Right-edge blocks are mirrored in y only */ -								src_ptr = src_buffer[offset_x] -								    [comp_height - y_crop_blocks - dst_blk_y - -								     offset_y - 1]; +								dst_ptr = dst_buffer[offset_y] +								    [dst_blk_x + offset_x];  								for (i = 0; i < DCTSIZE; i++) {  									for (j = 0; j < DCTSIZE; j++) { -										dst_ptr[j * DCTSIZE + i] = -										    src_ptr[i * DCTSIZE + j]; +										dst_ptr[j * DCTSIZE + i] +										    = src_ptr[i * DCTSIZE + j];  										j++; -										dst_ptr[j * DCTSIZE + i] = -										    -src_ptr[i * DCTSIZE + j]; +										dst_ptr[j * DCTSIZE + i] +										    = -src_ptr[i * DCTSIZE + j];  									}  								}  							}  						} else { -							if (x_crop_blocks + dst_blk_x < comp_width) { +							src_ptr = src_buffer[offset_x] +							    [dst_blk_y + offset_y]; +							if (dst_blk_x < comp_width) {  								/* Bottom-edge blocks are mirrored in x only */ -								src_ptr = -								    src_buffer[compptr->h_samp_factor - offset_x - 1] -								    [dst_blk_y + offset_y + y_crop_blocks]; +								dst_ptr = dst_buffer[offset_y] +								    [comp_width - dst_blk_x - offset_x - 1];  								for (i = 0; i < DCTSIZE; i++) {  									for (j = 0; j < DCTSIZE; j++) -										dst_ptr[j * DCTSIZE + i] = -										    src_ptr[i * DCTSIZE + j]; +										dst_ptr[j * DCTSIZE + i] +										    = src_ptr[i * DCTSIZE + j];  									i++;  									for (j = 0; j < DCTSIZE; j++) -										dst_ptr[j * DCTSIZE + i] = -										    -src_ptr[i * DCTSIZE + j]; +										dst_ptr[j * DCTSIZE + i] +										    = -src_ptr[i * DCTSIZE + j];  								}  							} else {  								/* At lower right corner, just transpose, no mirroring */ -								src_ptr = src_buffer[offset_x] -								    [dst_blk_y + offset_y + y_crop_blocks]; +								dst_ptr = dst_buffer[offset_y] +								    [dst_blk_x + offset_x];  								for (i = 0; i < DCTSIZE; i++)  									for (j = 0; j < DCTSIZE; j++) -										dst_ptr[j * DCTSIZE + i] = -										    src_ptr[i * DCTSIZE + j]; +										dst_ptr[j * DCTSIZE + i] +										    = src_ptr[i * DCTSIZE + j];  							}  						}  					} @@ -644,114 +569,8 @@ do_transverse(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,  	}  } - -/* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec. - * Returns TRUE if valid integer found, FALSE if not. - * *strptr is advanced over the digit string, and *result is set to its value. - */ - -LOCAL(boolean) -    jt_read_integer(const char **strptr, JDIMENSION * result) -{ -	const char *ptr = *strptr; -	JDIMENSION val = 0; - -	for (; isdigit(*ptr); ptr++) { -		val = val * 10 + (JDIMENSION) (*ptr - '0'); -	} -	*result = val; -	if (ptr == *strptr) -		return FALSE;	/* oops, no digits */ -	*strptr = ptr; -	return TRUE; -} - - -/* Parse a crop specification (written in X11 geometry style). - * The routine returns TRUE if the spec string is valid, FALSE if not. - * - * The crop spec string should have the format - *	<width>x<height>{+-}<xoffset>{+-}<yoffset> - * where width, height, xoffset, and yoffset are unsigned integers. - * Each of the elements can be omitted to indicate a default value. - * (A weakness of this style is that it is not possible to omit xoffset - * while specifying yoffset, since they look alike.) - * - * This code is loosely based on XParseGeometry from the X11 distribution. - */ - -GLOBAL(boolean) -    jtransform_parse_crop_spec(jpeg_transform_info * info, const char *spec) -{ -	info->crop = FALSE; -	info->crop_width_set = JCROP_UNSET; -	info->crop_height_set = JCROP_UNSET; -	info->crop_xoffset_set = JCROP_UNSET; -	info->crop_yoffset_set = JCROP_UNSET; - -	if (isdigit(*spec)) { -		/* fetch width */ -		if (!jt_read_integer(&spec, &info->crop_width)) -			return FALSE; -		info->crop_width_set = JCROP_POS; -	} -	if (*spec == 'x' || *spec == 'X') { -		/* fetch height */ -		spec++; -		if (!jt_read_integer(&spec, &info->crop_height)) -			return FALSE; -		info->crop_height_set = JCROP_POS; -	} -	if (*spec == '+' || *spec == '-') { -		/* fetch xoffset */ -		info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS; -		spec++; -		if (!jt_read_integer(&spec, &info->crop_xoffset)) -			return FALSE; -	} -	if (*spec == '+' || *spec == '-') { -		/* fetch yoffset */ -		info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS; -		spec++; -		if (!jt_read_integer(&spec, &info->crop_yoffset)) -			return FALSE; -	} -	/* We had better have gotten to the end of the string. */ -	if (*spec != '\0') -		return FALSE; -	info->crop = TRUE; -	return TRUE; -} - - -/* Trim off any partial iMCUs on the indicated destination edge */ - -LOCAL(void) -    trim_right_edge(jpeg_transform_info * info, JDIMENSION full_width) -{ -	JDIMENSION MCU_cols; - -	MCU_cols = info->output_width / info->iMCU_sample_width; -	if (MCU_cols > 0 && info->x_crop_offset + MCU_cols == full_width / info->iMCU_sample_width) -		info->output_width = MCU_cols * info->iMCU_sample_width; -} - -LOCAL(void) trim_bottom_edge(jpeg_transform_info * info, JDIMENSION full_height) -{ -	JDIMENSION MCU_rows; - -	MCU_rows = info->output_height / info->iMCU_sample_height; -	if (MCU_rows > 0 && info->y_crop_offset + MCU_rows == full_height / info->iMCU_sample_height) -		info->output_height = MCU_rows * info->iMCU_sample_height; -} - -  /* Request any required workspace.   * - * This routine figures out the size that the output image will be - * (which implies that all the transform parameters must be set before - * it is called). - *   * We allocate the workspace virtual arrays from the source decompression   * object, so that all the arrays (both the original data and the workspace)   * will be taken into account while making memory management decisions. @@ -760,221 +579,87 @@ LOCAL(void) trim_bottom_edge(jpeg_transform_info * info, JDIMENSION full_height)   * the source's virtual arrays).   */ -GLOBAL(boolean) -    jtransform_request_workspace(j_decompress_ptr srcinfo, jpeg_transform_info * info) +GLOBAL(void) jtransform_request_workspace(j_decompress_ptr srcinfo, jpeg_transform_info * info)  { -	jvirt_barray_ptr *coef_arrays; -	boolean need_workspace, transpose_it; +	jvirt_barray_ptr *coef_arrays = NULL;  	jpeg_component_info *compptr; -	JDIMENSION xoffset, yoffset; -	JDIMENSION width_in_iMCUs, height_in_iMCUs; -	JDIMENSION width_in_blocks, height_in_blocks; -	int ci, h_samp_factor, v_samp_factor; +	int ci; -	/* Determine number of components in output image */ -	if (info->force_grayscale && srcinfo->jpeg_color_space == JCS_YCbCr && srcinfo->num_components == 3) +	if (info->force_grayscale && srcinfo->jpeg_color_space == JCS_YCbCr && srcinfo->num_components == 3) {  		/* We'll only process the first component */  		info->num_components = 1; -	else +	} else {  		/* Process all the components */  		info->num_components = srcinfo->num_components; - -	/* Compute output image dimensions and related values. */ -	jpeg_core_output_dimensions(srcinfo); - -	/* If there is only one output component, force the iMCU size to be 1; -	 * else use the source iMCU size.  (This allows us to do the right thing -	 * when reducing color to grayscale, and also provides a handy way of -	 * cleaning up "funny" grayscale images whose sampling factors are not 1x1.) -	 */ -	switch (info->transform) { -	case JXFORM_TRANSPOSE: -	case JXFORM_TRANSVERSE: -	case JXFORM_ROT_90: -	case JXFORM_ROT_270: -		info->output_width = srcinfo->output_height; -		info->output_height = srcinfo->output_width; -		if (info->num_components == 1) { -			info->iMCU_sample_width = srcinfo->min_DCT_v_scaled_size; -			info->iMCU_sample_height = srcinfo->min_DCT_h_scaled_size; -		} else { -			info->iMCU_sample_width = srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size; -			info->iMCU_sample_height = srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size; -		} -		break; -	default: -		info->output_width = srcinfo->output_width; -		info->output_height = srcinfo->output_height; -		if (info->num_components == 1) { -			info->iMCU_sample_width = srcinfo->min_DCT_h_scaled_size; -			info->iMCU_sample_height = srcinfo->min_DCT_v_scaled_size; -		} else { -			info->iMCU_sample_width = srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size; -			info->iMCU_sample_height = srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size; -		} -		break;  	} -	/* If cropping has been requested, compute the crop area's position and -	 * dimensions, ensuring that its upper left corner falls at an iMCU boundary. -	 */ -	if (info->crop) { -		/* Insert default values for unset crop parameters */ -		if (info->crop_xoffset_set == JCROP_UNSET) -			info->crop_xoffset = 0;	/* default to +0 */ -		if (info->crop_yoffset_set == JCROP_UNSET) -			info->crop_yoffset = 0;	/* default to +0 */ -		if (info->crop_xoffset >= info->output_width || info->crop_yoffset >= info->output_height) -			ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); -		if (info->crop_width_set == JCROP_UNSET) -			info->crop_width = info->output_width - info->crop_xoffset; -		if (info->crop_height_set == JCROP_UNSET) -			info->crop_height = info->output_height - info->crop_yoffset; -		/* Ensure parameters are valid */ -		if (info->crop_width <= 0 || info->crop_width > info->output_width || -		    info->crop_height <= 0 || info->crop_height > info->output_height || -		    info->crop_xoffset > info->output_width - info->crop_width || -		    info->crop_yoffset > info->output_height - info->crop_height) -			ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); -		/* Convert negative crop offsets into regular offsets */ -		if (info->crop_xoffset_set == JCROP_NEG) -			xoffset = info->output_width - info->crop_width - info->crop_xoffset; -		else -			xoffset = info->crop_xoffset; -		if (info->crop_yoffset_set == JCROP_NEG) -			yoffset = info->output_height - info->crop_height - info->crop_yoffset; -		else -			yoffset = info->crop_yoffset; -		/* Now adjust so that upper left corner falls at an iMCU boundary */ -		info->output_width = info->crop_width + (xoffset % info->iMCU_sample_width); -		info->output_height = info->crop_height + (yoffset % info->iMCU_sample_height); -		/* Save x/y offsets measured in iMCUs */ -		info->x_crop_offset = xoffset / info->iMCU_sample_width; -		info->y_crop_offset = yoffset / info->iMCU_sample_height; -	} else { -		info->x_crop_offset = 0; -		info->y_crop_offset = 0; -	} - -	/* Figure out whether we need workspace arrays, -	 * and if so whether they are transposed relative to the source. -	 */ -	need_workspace = FALSE; -	transpose_it = FALSE;  	switch (info->transform) {  	case JXFORM_NONE: -		if (info->x_crop_offset != 0 || info->y_crop_offset != 0) -			need_workspace = TRUE; -		/* No workspace needed if neither cropping nor transforming */ -		break;  	case JXFORM_FLIP_H: -		if (info->trim) -			trim_right_edge(info, srcinfo->output_width); -		if (info->y_crop_offset != 0) -			need_workspace = TRUE; -		/* do_flip_h_no_crop doesn't need a workspace array */ +		/* Don't need a workspace array */  		break;  	case JXFORM_FLIP_V: -		if (info->trim) -			trim_bottom_edge(info, srcinfo->output_height); -		/* Need workspace arrays having same dimensions as source image. */ -		need_workspace = TRUE; +	case JXFORM_ROT_180: +		/* Need workspace arrays having same dimensions as source image. +		 * Note that we allocate arrays padded out to the next iMCU boundary, +		 * so that transform routines need not worry about missing edge blocks. +		 */ +		coef_arrays = (jvirt_barray_ptr *) +		    (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE, SIZEOF(jvirt_barray_ptr) +						  * info->num_components); +		for (ci = 0; ci < info->num_components; ci++) { +			compptr = srcinfo->comp_info + ci; +			coef_arrays[ci] = (*srcinfo->mem->request_virt_barray) +			    ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE, (JDIMENSION) jround_up((long) +												compptr->width_in_blocks, +												(long) +												compptr->h_samp_factor), +			     (JDIMENSION) jround_up((long) +						    compptr->height_in_blocks, (long) +						    compptr->v_samp_factor), (JDIMENSION) compptr->v_samp_factor); +		}  		break;  	case JXFORM_TRANSPOSE: -		/* transpose does NOT have to trim anything */ -		/* Need workspace arrays having transposed dimensions. */ -		need_workspace = TRUE; -		transpose_it = TRUE; -		break;  	case JXFORM_TRANSVERSE: -		if (info->trim) { -			trim_right_edge(info, srcinfo->output_height); -			trim_bottom_edge(info, srcinfo->output_width); -		} -		/* Need workspace arrays having transposed dimensions. */ -		need_workspace = TRUE; -		transpose_it = TRUE; -		break;  	case JXFORM_ROT_90: -		if (info->trim) -			trim_right_edge(info, srcinfo->output_height); -		/* Need workspace arrays having transposed dimensions. */ -		need_workspace = TRUE; -		transpose_it = TRUE; -		break; -	case JXFORM_ROT_180: -		if (info->trim) { -			trim_right_edge(info, srcinfo->output_width); -			trim_bottom_edge(info, srcinfo->output_height); -		} -		/* Need workspace arrays having same dimensions as source image. */ -		need_workspace = TRUE; -		break;  	case JXFORM_ROT_270: -		if (info->trim) -			trim_bottom_edge(info, srcinfo->output_width); -		/* Need workspace arrays having transposed dimensions. */ -		need_workspace = TRUE; -		transpose_it = TRUE; -		break; -	} - -	/* Allocate workspace if needed. -	 * Note that we allocate arrays padded out to the next iMCU boundary, -	 * so that transform routines need not worry about missing edge blocks. -	 */ -	if (need_workspace) { +		/* Need workspace arrays having transposed dimensions. +		 * Note that we allocate arrays padded out to the next iMCU boundary, +		 * so that transform routines need not worry about missing edge blocks. +		 */  		coef_arrays = (jvirt_barray_ptr *) -		    (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE, -						  SIZEOF(jvirt_barray_ptr) * info->num_components); -		width_in_iMCUs = (JDIMENSION) -		    jdiv_round_up((long) info->output_width, (long) info->iMCU_sample_width); -		height_in_iMCUs = (JDIMENSION) -		    jdiv_round_up((long) info->output_height, (long) info->iMCU_sample_height); +		    (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE, SIZEOF(jvirt_barray_ptr) +						  * info->num_components);  		for (ci = 0; ci < info->num_components; ci++) {  			compptr = srcinfo->comp_info + ci; -			if (info->num_components == 1) { -				/* we're going to force samp factors to 1x1 in this case */ -				h_samp_factor = v_samp_factor = 1; -			} else if (transpose_it) { -				h_samp_factor = compptr->v_samp_factor; -				v_samp_factor = compptr->h_samp_factor; -			} else { -				h_samp_factor = compptr->h_samp_factor; -				v_samp_factor = compptr->v_samp_factor; -			} -			width_in_blocks = width_in_iMCUs * h_samp_factor; -			height_in_blocks = height_in_iMCUs * v_samp_factor;  			coef_arrays[ci] = (*srcinfo->mem->request_virt_barray) -			    ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE, -			     width_in_blocks, height_in_blocks, (JDIMENSION) v_samp_factor); +			    ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE, (JDIMENSION) jround_up((long) +												compptr->height_in_blocks, +												(long) +												compptr->v_samp_factor), +			     (JDIMENSION) jround_up((long) +						    compptr->width_in_blocks, (long) +						    compptr->h_samp_factor), (JDIMENSION) compptr->h_samp_factor);  		} -		info->workspace_coef_arrays = coef_arrays; -	} else -		info->workspace_coef_arrays = NULL; - -	return TRUE; +		break; +	} +	info->workspace_coef_arrays = coef_arrays;  } -  /* Transpose destination image parameters */ -LOCAL(void) -    transpose_critical_parameters(j_compress_ptr dstinfo) +LOCAL(void) transpose_critical_parameters(j_compress_ptr dstinfo)  {  	int tblno, i, j, ci, itemp;  	jpeg_component_info *compptr;  	JQUANT_TBL *qtblptr; -	JDIMENSION jtemp; +	JDIMENSION dtemp;  	UINT16 qtemp; -	/* Transpose image dimensions */ -	jtemp = dstinfo->image_width; +	/* Transpose basic image dimensions */ +	dtemp = dstinfo->image_width;  	dstinfo->image_width = dstinfo->image_height; -	dstinfo->image_height = jtemp; -	itemp = dstinfo->min_DCT_h_scaled_size; -	dstinfo->min_DCT_h_scaled_size = dstinfo->min_DCT_v_scaled_size; -	dstinfo->min_DCT_v_scaled_size = itemp; +	dstinfo->image_height = dtemp;  	/* Transpose sampling factors */  	for (ci = 0; ci < dstinfo->num_components; ci++) { @@ -999,6 +684,156 @@ LOCAL(void)  	}  } +/* Trim off any partial iMCUs on the indicated destination edge */ + +LOCAL(void) trim_right_edge(j_compress_ptr dstinfo) +{ +	int ci, max_h_samp_factor; +	JDIMENSION MCU_cols; + +	/* We have to compute max_h_samp_factor ourselves, +	 * because it hasn't been set yet in the destination +	 * (and we don't want to use the source's value). +	 */ +	max_h_samp_factor = 1; +	for (ci = 0; ci < dstinfo->num_components; ci++) { +		int h_samp_factor = dstinfo->comp_info[ci].h_samp_factor; +		max_h_samp_factor = MAX(max_h_samp_factor, h_samp_factor); +	} +	MCU_cols = dstinfo->image_width / (max_h_samp_factor * DCTSIZE); +	if (MCU_cols > 0)	/* can't trim to 0 pixels */ +		dstinfo->image_width = MCU_cols * (max_h_samp_factor * DCTSIZE); +} + +LOCAL(void) trim_bottom_edge(j_compress_ptr dstinfo) +{ +	int ci, max_v_samp_factor; +	JDIMENSION MCU_rows; + +	/* We have to compute max_v_samp_factor ourselves, +	 * because it hasn't been set yet in the destination +	 * (and we don't want to use the source's value). +	 */ +	max_v_samp_factor = 1; +	for (ci = 0; ci < dstinfo->num_components; ci++) { +		int v_samp_factor = dstinfo->comp_info[ci].v_samp_factor; +		max_v_samp_factor = MAX(max_v_samp_factor, v_samp_factor); +	} +	MCU_rows = dstinfo->image_height / (max_v_samp_factor * DCTSIZE); +	if (MCU_rows > 0)	/* can't trim to 0 pixels */ +		dstinfo->image_height = MCU_rows * (max_v_samp_factor * DCTSIZE); +} + +LOCAL(void) set_exif_orientation(JOCTET FAR * data, unsigned int length, unsigned char new_orient) +{ +	boolean is_motorola;	/* Flag for byte order */ +	unsigned int number_of_tags, tagnum; +	unsigned int firstoffset, offset; + +	if (length < 12) +		return;		/* Length of an IFD entry */ + +	/* Discover byte order */ +	if (GETJOCTET(data[0]) == 0x49 && GETJOCTET(data[1]) == 0x49) +		is_motorola = FALSE; +	else if (GETJOCTET(data[0]) == 0x4D && GETJOCTET(data[1]) == 0x4D) +		is_motorola = TRUE; +	else +		return; + +	/* Check Tag Mark */ +	if (is_motorola) { +		if (GETJOCTET(data[2]) != 0) +			return; +		if (GETJOCTET(data[3]) != 0x2A) +			return; +	} else { +		if (GETJOCTET(data[3]) != 0) +			return; +		if (GETJOCTET(data[2]) != 0x2A) +			return; +	} + +	/* Get first IFD offset (offset to IFD0) */ +	if (is_motorola) { +		if (GETJOCTET(data[4]) != 0) +			return; +		if (GETJOCTET(data[5]) != 0) +			return; +		firstoffset = GETJOCTET(data[6]); +		firstoffset <<= 8; +		firstoffset += GETJOCTET(data[7]); +	} else { +		if (GETJOCTET(data[7]) != 0) +			return; +		if (GETJOCTET(data[6]) != 0) +			return; +		firstoffset = GETJOCTET(data[5]); +		firstoffset <<= 8; +		firstoffset += GETJOCTET(data[4]); +	} +	if (firstoffset > length - 2) +		return;		/* check end of data segment */ + +	/* Get the number of directory entries contained in this IFD */ +	if (is_motorola) { +		number_of_tags = GETJOCTET(data[firstoffset]); +		number_of_tags <<= 8; +		number_of_tags += GETJOCTET(data[firstoffset + 1]); +	} else { +		number_of_tags = GETJOCTET(data[firstoffset + 1]); +		number_of_tags <<= 8; +		number_of_tags += GETJOCTET(data[firstoffset]); +	} +	if (number_of_tags == 0) +		return; +	firstoffset += 2; + +	/* Search for Orientation offset Tag in IFD0 */ +	for (;;) { +		if (firstoffset > length - 12) +			return;	/* check end of data segment */ +		/* Get Tag number */ +		if (is_motorola) { +			tagnum = GETJOCTET(data[firstoffset]); +			tagnum <<= 8; +			tagnum += GETJOCTET(data[firstoffset + 1]); +		} else { +			tagnum = GETJOCTET(data[firstoffset + 1]); +			tagnum <<= 8; +			tagnum += GETJOCTET(data[firstoffset]); +		} +		if (tagnum == 0x0112) +			break;	/* found Orientation Tag */ +		if (--number_of_tags == 0) +			return; +		firstoffset += 12; +	} + +	if (is_motorola) { +		data[firstoffset + 2] = 0;	/* Format = unsigned short (2 octets) */ +		data[firstoffset + 3] = 3; +		data[firstoffset + 4] = 0;	/* Number Of Components = 1 */ +		data[firstoffset + 5] = 0; +		data[firstoffset + 6] = 0; +		data[firstoffset + 7] = 1; +		data[firstoffset + 8] = 0; +		data[firstoffset + 9] = (unsigned char) new_orient; +		data[firstoffset + 10] = 0; +		data[firstoffset + 11] = 0; +	} else { +		data[firstoffset + 2] = 3;	/* Format = unsigned short (2 octets) */ +		data[firstoffset + 3] = 0; +		data[firstoffset + 4] = 1;	/* Number Of Components = 1 */ +		data[firstoffset + 5] = 0; +		data[firstoffset + 6] = 0; +		data[firstoffset + 7] = 0; +		data[firstoffset + 8] = (unsigned char) new_orient; +		data[firstoffset + 9] = 0; +		data[firstoffset + 10] = 0; +		data[firstoffset + 11] = 0; +	} +}  /* Adjust Exif image parameters.   * @@ -1010,6 +845,7 @@ LOCAL(void) adjust_exif_parameters(JOCTET FAR * data, unsigned int length, JDIME  	boolean is_motorola;	/* Flag for byte order */  	unsigned int number_of_tags, tagnum;  	unsigned int firstoffset, offset; +	unsigned int new_orient;  	JDIMENSION new_value;  	if (length < 12) @@ -1142,10 +978,11 @@ LOCAL(void) adjust_exif_parameters(JOCTET FAR * data, unsigned int length, JDIME  			tagnum += GETJOCTET(data[offset]);  		}  		if (tagnum == 0xA002 || tagnum == 0xA003) { -			if (tagnum == 0xA002) +			if (tagnum == 0xA002) {  				new_value = new_width;	/* ExifImageWidth Tag */ -			else +			} else {  				new_value = new_height;	/* ExifImageHeight Tag */ +			}  			if (is_motorola) {  				data[offset + 2] = 0;	/* Format = unsigned long (4 octets) */  				data[offset + 3] = 4; @@ -1174,7 +1011,6 @@ LOCAL(void) adjust_exif_parameters(JOCTET FAR * data, unsigned int length, JDIME  	} while (--number_of_tags);  } -  /* Adjust output image parameters as needed.   *   * This must be called after jpeg_copy_critical_parameters() @@ -1190,24 +1026,20 @@ GLOBAL(jvirt_barray_ptr *)      jtransform_adjust_parameters(j_decompress_ptr srcinfo,  			     j_compress_ptr dstinfo, jvirt_barray_ptr * src_coef_arrays, jpeg_transform_info * info)  { +	jpeg_saved_marker_ptr marker;  	/* If force-to-grayscale is requested, adjust destination parameters */  	if (info->force_grayscale) { -		/* First, ensure we have YCbCr or grayscale data, and that the source's -		 * Y channel is full resolution.  (No reasonable person would make Y -		 * be less than full resolution, so actually coping with that case -		 * isn't worth extra code space.  But we check it to avoid crashing.) +		/* We use jpeg_set_colorspace to make sure subsidiary settings get fixed +		 * properly.  Among other things, the target h_samp_factor & v_samp_factor +		 * will get set to 1, which typically won't match the source. +		 * In fact we do this even if the source is already grayscale; that +		 * provides an easy way of coercing a grayscale JPEG with funny sampling +		 * factors to the customary 1,1.  (Some decoders fail on other factors.)  		 */ -		if (((dstinfo->jpeg_color_space == JCS_YCbCr && -		      dstinfo->num_components == 3) || -		     (dstinfo->jpeg_color_space == JCS_GRAYSCALE && -		      dstinfo->num_components == 1)) && -		    srcinfo->comp_info[0].h_samp_factor == srcinfo->max_h_samp_factor && -		    srcinfo->comp_info[0].v_samp_factor == srcinfo->max_v_samp_factor) { -			/* We use jpeg_set_colorspace to make sure subsidiary settings get fixed -			 * properly.  Among other things, it sets the target h_samp_factor & -			 * v_samp_factor to 1, which typically won't match the source. -			 * We have to preserve the source's quantization table number, however. -			 */ +		if ((dstinfo->jpeg_color_space == JCS_YCbCr && +		     dstinfo->num_components == 3) || +		    (dstinfo->jpeg_color_space == JCS_GRAYSCALE && dstinfo->num_components == 1)) { +			/* We have to preserve the source's quantization table number. */  			int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no;  			jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE);  			dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no; @@ -1215,50 +1047,79 @@ GLOBAL(jvirt_barray_ptr *)  			/* Sorry, can't do it */  			ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL);  		} -	} else if (info->num_components == 1) { -		/* For a single-component source, we force the destination sampling factors -		 * to 1x1, with or without force_grayscale.  This is useful because some -		 * decoders choke on grayscale images with other sampling factors. -		 */ -		dstinfo->comp_info[0].h_samp_factor = 1; -		dstinfo->comp_info[0].v_samp_factor = 1;  	} -	/* Correct the destination's image dimensions as necessary -	 * for rotate/flip, resize, and crop operations. -	 */ -	dstinfo->jpeg_width = info->output_width; -	dstinfo->jpeg_height = info->output_height; - -	/* Transpose destination image parameters */ +	/* Correct the destination's image dimensions etc if necessary */  	switch (info->transform) { +	case JXFORM_NONE: +		/* Nothing to do */ +		break; +	case JXFORM_FLIP_H: +		if (info->trim) +			trim_right_edge(dstinfo); +		break; +	case JXFORM_FLIP_V: +		if (info->trim) +			trim_bottom_edge(dstinfo); +		break;  	case JXFORM_TRANSPOSE: +		transpose_critical_parameters(dstinfo); +		/* transpose does NOT have to trim anything */ +		break;  	case JXFORM_TRANSVERSE: +		transpose_critical_parameters(dstinfo); +		if (info->trim) { +			trim_right_edge(dstinfo); +			trim_bottom_edge(dstinfo); +		} +		break;  	case JXFORM_ROT_90: -	case JXFORM_ROT_270:  		transpose_critical_parameters(dstinfo); +		if (info->trim) +			trim_right_edge(dstinfo);  		break; -	default: +	case JXFORM_ROT_180: +		if (info->trim) { +			trim_right_edge(dstinfo); +			trim_bottom_edge(dstinfo); +		} +		break; +	case JXFORM_ROT_270: +		transpose_critical_parameters(dstinfo); +		if (info->trim) +			trim_bottom_edge(dstinfo);  		break;  	} -	/* Adjust Exif properties */ -	if (srcinfo->marker_list != NULL && -	    srcinfo->marker_list->marker == JPEG_APP0 + 1 && -	    srcinfo->marker_list->data_length >= 6 && -	    GETJOCTET(srcinfo->marker_list->data[0]) == 0x45 && -	    GETJOCTET(srcinfo->marker_list->data[1]) == 0x78 && -	    GETJOCTET(srcinfo->marker_list->data[2]) == 0x69 && -	    GETJOCTET(srcinfo->marker_list->data[3]) == 0x66 && -	    GETJOCTET(srcinfo->marker_list->data[4]) == 0 && GETJOCTET(srcinfo->marker_list->data[5]) == 0) { -		/* Suppress output of JFIF marker */ -		dstinfo->write_JFIF_header = FALSE; -		/* Adjust Exif image parameters */ -		if (dstinfo->jpeg_width != srcinfo->image_width || dstinfo->jpeg_height != srcinfo->image_height) -			/* Align data segment to start of TIFF structure for parsing */ -			adjust_exif_parameters(srcinfo->marker_list->data + 6, -					       srcinfo->marker_list->data_length - 6, -					       dstinfo->jpeg_width, dstinfo->jpeg_height); +	for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) { +		if (marker->marker != JPEG_APP0 + 1) +			continue; +		/* Adjust Exif properties */ +		if (marker->marker == JPEG_APP0 + 1 && +		    marker->data_length >= 6 && +		    GETJOCTET(marker->data[0]) == 0x45 && +		    GETJOCTET(marker->data[1]) == 0x78 && +		    GETJOCTET(marker->data[2]) == 0x69 && +		    GETJOCTET(marker->data[3]) == 0x66 && +		    GETJOCTET(marker->data[4]) == 0 && GETJOCTET(marker->data[5]) == 0) { +			/* Suppress output of JFIF marker */ +			dstinfo->write_JFIF_header = FALSE; +			/* Adjust Exif image parameters */ +			if (dstinfo->image_width != srcinfo->image_width || +			    dstinfo->image_height != srcinfo->image_height) +				/* Align data segment to start of TIFF structure for parsing */ +				adjust_exif_parameters(marker->data + 6, +						       marker->data_length - 6, +						       dstinfo->image_width, dstinfo->image_height); +			/* I'm honestly not sure what the right thing to do is here.. The +			 * existing orientation tag may be incorrect, so making a change based +			 * on the previous value seems like the wrong thing to do. For now, I'm +			 * going to assume that the user is always "fixing" the orientation, +			 * i.e. putting the image the "right way up". In this case, we want to +			 * set the orientation to "top left". +			 */ +			set_exif_orientation(marker->data + 6, marker->data_length - 6, 1); +		}  	}  	/* Return the appropriate output data set */ @@ -1267,7 +1128,6 @@ GLOBAL(jvirt_barray_ptr *)  	return src_coef_arrays;  } -  /* Execute the actual transformation, if any.   *   * This must be called *after* jpeg_write_coefficients, because it depends @@ -1278,51 +1138,48 @@ GLOBAL(jvirt_barray_ptr *)   */  GLOBAL(void) -    jtransform_execute_transform(j_decompress_ptr srcinfo, -			     j_compress_ptr dstinfo, jvirt_barray_ptr * src_coef_arrays, jpeg_transform_info * info) + + +    jtransform_execute_transformation(j_decompress_ptr srcinfo, +				  j_compress_ptr dstinfo, +				  jvirt_barray_ptr * src_coef_arrays, jpeg_transform_info * info)  {  	jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays; -	/* Note: conditions tested here should match those in switch statement -	 * in jtransform_request_workspace() -	 */  	switch (info->transform) {  	case JXFORM_NONE:  		break;  	case JXFORM_FLIP_H: -		do_flip_h_no_crop(srcinfo, dstinfo, 0, src_coef_arrays); +		do_flip_h(srcinfo, dstinfo, src_coef_arrays);  		break;  	case JXFORM_FLIP_V: -		do_flip_v(srcinfo, dstinfo, 0, 0, src_coef_arrays, dst_coef_arrays); +		do_flip_v(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);  		break;  	case JXFORM_TRANSPOSE: -		do_transpose(srcinfo, dstinfo, 0, 0, -			     src_coef_arrays, dst_coef_arrays); +		do_transpose(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);  		break;  	case JXFORM_TRANSVERSE: -		do_transverse(srcinfo, dstinfo, 0, 0, src_coef_arrays, dst_coef_arrays); +		do_transverse(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);  		break;  	case JXFORM_ROT_90: -		do_rot_90(srcinfo, dstinfo, 0, 0, src_coef_arrays, dst_coef_arrays); +		do_rot_90(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);  		break;  	case JXFORM_ROT_180: -		do_rot_180(srcinfo, dstinfo, 0, 0, src_coef_arrays, dst_coef_arrays); +		do_rot_180(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);  		break;  	case JXFORM_ROT_270: -		do_rot_270(srcinfo, dstinfo, 0, 0, src_coef_arrays, dst_coef_arrays); +		do_rot_270(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);  		break;  	}  }  #endif				/* TRANSFORMS_SUPPORTED */ -  /* Setup decompression object to save desired markers in memory.   * This must be called before jpeg_read_header() to have the desired effect.   */ -GLOBAL(void) -    jcopy_markers_setup(j_decompress_ptr srcinfo, JCOPY_OPTION option) +GLOBAL(void) jcopy_markers_setup(j_decompress_ptr srcinfo, JCOPY_OPTION option)  {  #ifdef SAVE_MARKERS_SUPPORTED  	int m; @@ -1356,13 +1213,13 @@ GLOBAL(void) jcopy_markers_execute(j_decompress_ptr srcinfo, j_compress_ptr dsti  	 * if the encoder library already wrote one.  	 */  	for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) { -		if (dstinfo->write_JFIF_header && -		    marker->marker == JPEG_APP0 && -		    marker->data_length >= 5 && -		    GETJOCTET(marker->data[0]) == 0x4A && -		    GETJOCTET(marker->data[1]) == 0x46 && -		    GETJOCTET(marker->data[2]) == 0x49 && -		    GETJOCTET(marker->data[3]) == 0x46 && GETJOCTET(marker->data[4]) == 0) +		if (dstinfo->write_JFIF_header +		    && marker->marker == JPEG_APP0 +		    && marker->data_length >= 5 +		    && GETJOCTET(marker->data[0]) == 0x4A +		    && GETJOCTET(marker->data[1]) == 0x46 +		    && GETJOCTET(marker->data[2]) == 0x49 +		    && GETJOCTET(marker->data[3]) == 0x46 && GETJOCTET(marker->data[4]) == 0)  			continue;	/* reject duplicate JFIF */  		if (dstinfo->write_Adobe_marker &&  		    marker->marker == JPEG_APP0 + 14 && diff --git a/src/transupp.h b/src/transupp.h index 4f01d29..056a282 100644 --- a/src/transupp.h +++ b/src/transupp.h @@ -1,7 +1,7 @@  /*   * transupp.h   * - * Copyright (C) 1997-2009, Thomas G. Lane, Guido Vollbeding. + * Copyright (C) 1997, Thomas G. Lane.   * This file is part of the Independent JPEG Group's software.   * For conditions of distribution and use, see the accompanying README file.   * @@ -22,6 +22,31 @@  #define TRANSFORMS_SUPPORTED 1	/* 0 disables transform code */  #endif +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jtransform_request_workspace		jTrRequest +#define jtransform_adjust_parameters		jTrAdjust +#define jtransform_execute_transformation	jTrExec +#define jcopy_markers_setup			jCMrkSetup +#define jcopy_markers_execute			jCMrkExec +#endif				/* NEED_SHORT_EXTERNAL_NAMES */ + +/* + * Codes for supported types of image transformations. + */ + +typedef enum { +	JXFORM_NONE,		/* no transformation */ +	JXFORM_FLIP_H,		/* horizontal flip */ +	JXFORM_FLIP_V,		/* vertical flip */ +	JXFORM_TRANSPOSE,	/* transpose across UL-to-LR axis */ +	JXFORM_TRANSVERSE,	/* transpose across UR-to-LL axis */ +	JXFORM_ROT_90,		/* 90-degree clockwise rotation */ +	JXFORM_ROT_180,		/* 180-degree rotation */ +	JXFORM_ROT_270		/* 270-degree clockwise (or 90 ccw) */ +} JXFORM_CODE; +  /*   * Although rotating and flipping data expressed as DCT coefficients is not   * hard, there is an asymmetry in the JPEG format specification for images @@ -49,24 +74,6 @@   * (For example, -rot 270 -trim trims only the bottom edge, but -rot 90 -trim   * followed by -rot 180 -trim trims both edges.)   * - * We also offer a lossless-crop option, which discards data outside a given - * image region but losslessly preserves what is inside.  Like the rotate and - * flip transforms, lossless crop is restricted by the JPEG format: the upper - * left corner of the selected region must fall on an iMCU boundary.  If this - * does not hold for the given crop parameters, we silently move the upper left - * corner up and/or left to make it so, simultaneously increasing the region - * dimensions to keep the lower right crop corner unchanged.  (Thus, the - * output image covers at least the requested region, but may cover more.) - * - * We also provide a lossless-resize option, which is kind of a lossless-crop - * operation in the DCT coefficient block domain - it discards higher-order - * coefficients and losslessly preserves lower-order coefficients of a - * sub-block. - * - * Rotate/flip transform, resize, and crop can be requested together in a - * single invocation.  The crop is applied last --- that is, the crop region - * is specified in terms of the destination image after transform/resize. - *   * We also offer a "force to grayscale" option, which simply discards the   * chrominance channels of a YCbCr image.  This is lossless in the sense that   * the luminance channel is preserved exactly.  It's not the same kind of @@ -75,107 +82,30 @@   * be aware of the option to know how many components to work on.   */ - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jtransform_parse_crop_spec	jTrParCrop -#define jtransform_request_workspace	jTrRequest -#define jtransform_adjust_parameters	jTrAdjust -#define jtransform_execute_transform	jTrExec -#define jtransform_perfect_transform	jTrPerfect -#define jcopy_markers_setup		jCMrkSetup -#define jcopy_markers_execute		jCMrkExec -#endif				/* NEED_SHORT_EXTERNAL_NAMES */ - - -/* - * Codes for supported types of image transformations. - */ - -typedef enum { -	JXFORM_NONE,		/* no transformation */ -	JXFORM_FLIP_H,		/* horizontal flip */ -	JXFORM_FLIP_V,		/* vertical flip */ -	JXFORM_TRANSPOSE,	/* transpose across UL-to-LR axis */ -	JXFORM_TRANSVERSE,	/* transpose across UR-to-LL axis */ -	JXFORM_ROT_90,		/* 90-degree clockwise rotation */ -	JXFORM_ROT_180,		/* 180-degree rotation */ -	JXFORM_ROT_270		/* 270-degree clockwise (or 90 ccw) */ -} JXFORM_CODE; - -/* - * Codes for crop parameters, which can individually be unspecified, - * positive, or negative.  (Negative width or height makes no sense, though.) - */ - -typedef enum { -	JCROP_UNSET, -	JCROP_POS, -	JCROP_NEG -} JCROP_CODE; - -/* - * Transform parameters struct. - * NB: application must not change any elements of this struct after - * calling jtransform_request_workspace. - */ -  typedef struct {  	/* Options: set by caller */  	JXFORM_CODE transform;	/* image transform operator */ -	boolean perfect;	/* if TRUE, fail if partial MCUs are requested */  	boolean trim;		/* if TRUE, trim partial MCUs as needed */  	boolean force_grayscale;	/* if TRUE, convert color image to grayscale */ -	boolean crop;		/* if TRUE, crop source image */ - -	/* Crop parameters: application need not set these unless crop is TRUE. -	 * These can be filled in by jtransform_parse_crop_spec(). -	 */ -	JDIMENSION crop_width;	/* Width of selected region */ -	JCROP_CODE crop_width_set; -	JDIMENSION crop_height;	/* Height of selected region */ -	JCROP_CODE crop_height_set; -	JDIMENSION crop_xoffset;	/* X offset of selected region */ -	JCROP_CODE crop_xoffset_set;	/* (negative measures from right edge) */ -	JDIMENSION crop_yoffset;	/* Y offset of selected region */ -	JCROP_CODE crop_yoffset_set;	/* (negative measures from bottom edge) */  	/* Internal workspace: caller should not touch these */  	int num_components;	/* # of components in workspace */  	jvirt_barray_ptr *workspace_coef_arrays;	/* workspace for transformations */ -	JDIMENSION output_width;	/* cropped destination dimensions */ -	JDIMENSION output_height; -	JDIMENSION x_crop_offset;	/* destination crop offsets measured in iMCUs */ -	JDIMENSION y_crop_offset; -	int iMCU_sample_width;	/* destination iMCU size */ -	int iMCU_sample_height;  } jpeg_transform_info; -  #if TRANSFORMS_SUPPORTED -/* Parse a crop specification (written in X11 geometry style) */ -EXTERN(boolean) jtransform_parse_crop_spec JPP((jpeg_transform_info * info, const char *spec));  /* Request any required workspace */ -EXTERN(boolean) jtransform_request_workspace JPP((j_decompress_ptr srcinfo, jpeg_transform_info * info)); +EXTERN(void) jtransform_request_workspace JPP((j_decompress_ptr srcinfo, jpeg_transform_info * info));  /* Adjust output image parameters */  EXTERN(jvirt_barray_ptr *) jtransform_adjust_parameters  JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, jvirt_barray_ptr * src_coef_arrays, jpeg_transform_info * info));  /* Execute the actual transformation, if any */ -EXTERN(void) jtransform_execute_transform +EXTERN(void) jtransform_execute_transformation  JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, jvirt_barray_ptr * src_coef_arrays, jpeg_transform_info * info)); -/* jtransform_execute_transform used to be called - * jtransform_execute_transformation, but some compilers complain about - * routine names that long.  This macro is here to avoid breaking any - * old source code that uses the original name... - */ -#define jtransform_execute_transformation	jtransform_execute_transform -  #endif				/* TRANSFORMS_SUPPORTED */ -  /*   * Support for copying optional markers from source to destination file.   */ @@ -189,6 +119,7 @@ typedef enum {  #define JCOPYOPT_DEFAULT  JCOPYOPT_COMMENTS	/* recommended default */  /* Setup decompression object to save desired markers in memory */ -EXTERN(void) jcopy_markers_setup JPP((j_decompress_ptr srcinfo, JCOPY_OPTION option)); +EXTERN(void) +jcopy_markers_setup JPP((j_decompress_ptr srcinfo, JCOPY_OPTION option));  /* Copy markers saved in the given source object to the destination object */  EXTERN(void) jcopy_markers_execute JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, JCOPY_OPTION option)); | 
