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