ReactOS  0.4.14-dev-831-gef8c9239
transupp.c
Go to the documentation of this file.
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)
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;
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,
102  src_buffer = (*srcinfo->mem->access_virt_barray)
103  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
104  dst_blk_y + y_crop_blocks,
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],
110  }
111  }
112  }
113 }
114 
115 
116 LOCAL(void)
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;
132 
133  MCU_cols = srcinfo->output_width /
135  MCU_rows = srcinfo->output_height /
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,
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],
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,
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,
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,
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],
187  }
188  }
189  }
190  }
191 }
192 
193 
194 LOCAL(void)
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;
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,
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)
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;
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,
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)
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;
288  JCOEFPTR ptr1, ptr2;
289  JCOEF temp1, temp2;
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 /
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,
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)
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;
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 /
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,
376  src_buffer = (*srcinfo->mem->access_virt_barray)
377  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
378  dst_blk_y + y_crop_blocks,
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)
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;
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 /
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,
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 -
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,
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],
479  }
480  }
481  }
482  }
483 }
484 
485 
486 LOCAL(void)
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;
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,
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,
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)
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;
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 /
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,
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 -
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,
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)
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;
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 /
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,
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,
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)
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;
704 
705  MCU_cols = srcinfo->output_width /
707  MCU_rows = srcinfo->output_height /
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,
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 -
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,
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)
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;
815 
816  MCU_cols = srcinfo->output_height /
818  MCU_rows = srcinfo->output_width /
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,
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 -
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,
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)
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)
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)
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)
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)
1039 jtransform_request_workspace (j_decompress_ptr srcinfo,
1041 {
1043  boolean need_workspace, transpose_it;
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) {
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)
1323 transpose_critical_parameters (j_compress_ptr dstinfo)
1324 {
1325  int tblno, i, j, ci, itemp;
1327  JQUANT_TBL *qtblptr;
1328  JDIMENSION jtemp;
1329  UINT16 qtemp;
1330 
1331  /* Transpose image dimensions */
1332  jtemp = dstinfo->image_width;
1334  dstinfo->image_height = jtemp;
1335  itemp = dstinfo->min_DCT_h_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;
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)
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 
1531 jtransform_adjust_parameters (j_decompress_ptr srcinfo,
1533  jvirt_barray_ptr *src_coef_arrays,
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 ||
1545  dstinfo->num_components == 3) ||
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;
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  */
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 */
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,
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)
1627 jtransform_execute_transform (j_decompress_ptr srcinfo,
1629  jvirt_barray_ptr *src_coef_arrays,
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)
1712 jtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height,
1713  int MCU_width, int MCU_height,
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)
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)
1778 {
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 }
boolean write_Adobe_marker
Definition: jpeglib.h:385
#define TRUE
Definition: types.h:120
JDIMENSION output_height
Definition: jpeglib.h:508
#define ERREXIT(msg)
Definition: rdjpgcom.c:72
#define NUM_QUANT_TBLS
Definition: jpeglib.h:52
J_COLOR_SPACE jpeg_color_space
Definition: jpeglib.h:331
#define GETJOCTET(value)
Definition: jmorecfg.h:171
jpeg_component_info * comp_info
Definition: jpeglib.h:583
GLintptr offset
Definition: glext.h:5920
struct jpeg_common_struct * j_common_ptr
Definition: jpeglib.h:284
UINT16 quantval[DCTSIZE2]
Definition: jpeglib.h:97
JCOEF JBLOCK[DCTSIZE2]
Definition: jpeglib.h:79
JDIMENSION image_height
Definition: jpeglib.h:303
JBLOCKROW * JBLOCKARRAY
Definition: jpeglib.h:81
GLuint buffer
Definition: glext.h:5915
JDIMENSION image_width
Definition: jpeglib.h:468
JDIMENSION output_width
Definition: jpeglib.h:507
struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr
Definition: jpeglib.h:207
JDIMENSION image_height
Definition: jpeglib.h:469
int image_height
GLint GLint GLint yoffset
Definition: gl.h:1547
jvirt_barray_ptr * coef_arrays
Definition: jpeglib.h:1095
short JCOEF
Definition: jmorecfg.h:151
const GLfloat * m
Definition: glext.h:10848
boolean write_JFIF_header
Definition: jpeglib.h:375
jpeg_component_info * compptr
Definition: jdct.h:238
JDIMENSION width_in_blocks
Definition: jpeglib.h:148
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
JDIMENSION jpeg_height
Definition: jpeglib.h:320
jpeg_saved_marker_ptr marker_list
Definition: jpeglib.h:618
#define SIZEOF(_ar)
Definition: calc.h:97
#define JPOOL_IMAGE
Definition: jpeglib.h:808
GLint GLint xoffset
Definition: gl.h:1547
jcopy_markers_execute(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, JCOPY_OPTION option)
Definition: transupp.c:1776
#define FAR
Definition: guiddef.h:36
static PVOID ptr
Definition: dispmode.c:27
int image_width
#define JPEG_APP0
Definition: jpeglib.h:1125
smooth NULL
Definition: ftsmooth.c:416
Definition: getopt.h:108
JDIMENSION height_in_blocks
Definition: jpeglib.h:149
JDIMENSION jpeg_width
Definition: jpeglib.h:319
int marker
Definition: jpeglib.h:1027
jpeg_write_marker(j_compress_ptr cinfo, int marker, const JOCTET *dataptr, unsigned int datalen)
Definition: jcapimin.c:200
#define DCTSIZE2
Definition: jpeglib.h:51
#define isdigit(c)
Definition: acclib.h:68
#define LOCAL(type)
Definition: jmorecfg.h:289
GLuint GLfloat * val
Definition: glext.h:7180
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
jdiv_round_up(long a, long b)
Definition: jutils.c:124
JBLOCK FAR * JBLOCKROW
Definition: jpeglib.h:80
JCOEF FAR * JCOEFPTR
Definition: jpeglib.h:84
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
j_compress_ptr dstinfo
Definition: jpeglib.h:1097
#define GLOBAL(type)
Definition: jmorecfg.h:291
JXFORM_CODE
Definition: transupp.h:100
JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]
Definition: jpeglib.h:336
jpeg_set_colorspace(j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
Definition: jcparam.c:425
jcopy_markers_setup(j_decompress_ptr srcinfo, JCOPY_OPTION option)
Definition: transupp.c:1751
#define long
Definition: qsort.c:33
jpeg_write_m_byte(j_compress_ptr cinfo, int val)
Definition: jcapimin.c:234
unsigned short UINT16
#define DCTSIZE
Definition: jpeglib.h:50
jcopy_block_row(JBLOCKROW input_row, JBLOCKROW output_row, JDIMENSION num_blocks)
Definition: jutils.c:211
jpeg_write_m_header(j_compress_ptr cinfo, int marker, unsigned int datalen)
Definition: jcapimin.c:222
unsigned int JDIMENSION
Definition: jmorecfg.h:229
char JOCTET
Definition: jmorecfg.h:167
GLuint GLenum GLenum transform
Definition: glext.h:9407
JCOPY_OPTION
Definition: transupp.h:205
GLuint64EXT * result
Definition: glext.h:11304
int k
Definition: mpi.c:3369
jpeg_component_info * comp_info
Definition: jpeglib.h:333
J_COLOR_SPACE jpeg_color_space
Definition: jpeglib.h:471
#define JPEG_COM
Definition: jpeglib.h:1126
#define FMEMZERO(target, size)
Definition: jpegint.h:361
JDIMENSION image_width
Definition: jpeglib.h:302