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