ReactOS  0.4.15-dev-492-ga1108f6
transupp.c
Go to the documentation of this file.
1 /*
2  * transupp.c
3  *
4  * Copyright (C) 1997-2019, 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  * Also, the (switchable) virtual memory adaptation code for
18  * the drop feature has dependencies on library internals.
19  */
20 #define JPEG_INTERNALS
21 
22 #include "jinclude.h"
23 #include "jpeglib.h"
24 #include "transupp.h" /* My own external interface */
25 #include <ctype.h> /* to declare isdigit() */
26 
27 
28 #if TRANSFORMS_SUPPORTED
29 
30 /*
31  * Lossless image transformation routines. These routines work on DCT
32  * coefficient arrays and thus do not require any lossy decompression
33  * or recompression of the image.
34  * Thanks to Guido Vollbeding for the initial design and code of this feature,
35  * and to Ben Jackson for introducing the cropping feature.
36  *
37  * Horizontal flipping is done in-place, using a single top-to-bottom
38  * pass through the virtual source array. It will thus be much the
39  * fastest option for images larger than main memory.
40  *
41  * The other routines require a set of destination virtual arrays, so they
42  * need twice as much memory as jpegtran normally does. The destination
43  * arrays are always written in normal scan order (top to bottom) because
44  * the virtual array manager expects this. The source arrays will be scanned
45  * in the corresponding order, which means multiple passes through the source
46  * arrays for most of the transforms. That could result in much thrashing
47  * if the image is larger than main memory.
48  *
49  * If cropping or trimming is involved, the destination arrays may be smaller
50  * than the source arrays. Note it is not possible to do horizontal flip
51  * in-place when a nonzero Y crop offset is specified, since we'd have to move
52  * data from one block row to another but the virtual array manager doesn't
53  * guarantee we can touch more than one row at a time. So in that case,
54  * we have to use a separate destination array.
55  *
56  * Some notes about the operating environment of the individual transform
57  * routines:
58  * 1. Both the source and destination virtual arrays are allocated from the
59  * source JPEG object, and therefore should be manipulated by calling the
60  * source's memory manager.
61  * 2. The destination's component count should be used. It may be smaller
62  * than the source's when forcing to grayscale.
63  * 3. Likewise the destination's sampling factors should be used. When
64  * forcing to grayscale the destination's sampling factors will be all 1,
65  * and we may as well take that as the effective iMCU size.
66  * 4. When "trim" is in effect, the destination's dimensions will be the
67  * trimmed values but the source's will be untrimmed.
68  * 5. When "crop" is in effect, the destination's dimensions will be the
69  * cropped values but the source's will be uncropped. Each transform
70  * routine is responsible for picking up source data starting at the
71  * correct X and Y offset for the crop region. (The X and Y offsets
72  * passed to the transform routines are measured in iMCU blocks of the
73  * destination.)
74  * 6. All the routines assume that the source and destination buffers are
75  * padded out to a full iMCU boundary. This is true, although for the
76  * source buffer it is an undocumented property of jdcoefct.c.
77  */
78 
79 
80 /* Drop code may be used with or without virtual memory adaptation code.
81  * This code has some dependencies on internal library behavior, so you
82  * may choose to disable it. For example, it doesn't make a difference
83  * if you only use jmemnobs anyway.
84  */
85 #ifndef DROP_REQUEST_FROM_SRC
86 #define DROP_REQUEST_FROM_SRC 1 /* 0 disables adaptation */
87 #endif
88 
89 
90 #if DROP_REQUEST_FROM_SRC
91 /* Force jpeg_read_coefficients to request
92  * the virtual coefficient arrays from
93  * the source decompression object.
94  */
96 drop_request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
97  JDIMENSION blocksperrow, JDIMENSION numrows,
98  JDIMENSION maxaccess)
99 {
100  j_common_ptr srcinfo = (j_common_ptr) cinfo->client_data;
101 
102  return (*srcinfo->mem->request_virt_barray)
103  (srcinfo, pool_id, pre_zero,
104  blocksperrow, numrows, maxaccess);
105 }
106 
107 
108 /* Force jpeg_read_coefficients to return
109  * after requesting and before accessing
110  * the virtual coefficient arrays.
111  */
112 METHODDEF(int)
113 drop_consume_input (j_decompress_ptr cinfo)
114 {
115  return JPEG_SUSPENDED;
116 }
117 
118 
119 METHODDEF(void)
120 drop_start_input_pass (j_decompress_ptr cinfo)
121 {
122  cinfo->inputctl->consume_input = drop_consume_input;
123 }
124 
125 
126 LOCAL(void)
127 drop_request_from_src (j_decompress_ptr dropinfo, j_decompress_ptr srcinfo)
128 {
129  void *save_client_data;
130  JMETHOD(jvirt_barray_ptr, save_request_virt_barray,
131  (j_common_ptr cinfo, int pool_id, boolean pre_zero,
132  JDIMENSION blocksperrow, JDIMENSION numrows, JDIMENSION maxaccess));
133  JMETHOD(void, save_start_input_pass, (j_decompress_ptr cinfo));
134 
135  /* Set custom method pointers, save original pointers */
136  save_client_data = dropinfo->client_data;
137  dropinfo->client_data = (void *) srcinfo;
138  save_request_virt_barray = dropinfo->mem->request_virt_barray;
139  dropinfo->mem->request_virt_barray = drop_request_virt_barray;
140  save_start_input_pass = dropinfo->inputctl->start_input_pass;
141  dropinfo->inputctl->start_input_pass = drop_start_input_pass;
142 
143  /* Execute only initialization part.
144  * Requested coefficient arrays will be realized later by the srcinfo object.
145  * Next call to the same function will then do the actual data reading.
146  * NB: since we request the coefficient arrays from another object,
147  * the inherent realization call is effectively a no-op.
148  */
149  (void) jpeg_read_coefficients(dropinfo);
150 
151  /* Reset method pointers */
152  dropinfo->client_data = save_client_data;
153  dropinfo->mem->request_virt_barray = save_request_virt_barray;
154  dropinfo->inputctl->start_input_pass = save_start_input_pass;
155  /* Do input initialization for first scan now,
156  * which also resets the consume_input method.
157  */
158  (*save_start_input_pass)(dropinfo);
159 }
160 #endif /* DROP_REQUEST_FROM_SRC */
161 
162 
163 LOCAL(void)
164 dequant_comp (j_decompress_ptr cinfo, jpeg_component_info *compptr,
165  jvirt_barray_ptr coef_array, JQUANT_TBL *qtblptr1)
166 {
167  JDIMENSION blk_x, blk_y;
168  int offset_y, k;
169  JQUANT_TBL *qtblptr;
172  JCOEFPTR ptr;
173 
174  qtblptr = compptr->quant_table;
175  for (blk_y = 0; blk_y < compptr->height_in_blocks;
176  blk_y += compptr->v_samp_factor) {
177  buffer = (*cinfo->mem->access_virt_barray)
178  ((j_common_ptr) cinfo, coef_array, blk_y,
180  for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
181  block = buffer[offset_y];
182  for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
183  ptr = block[blk_x];
184  for (k = 0; k < DCTSIZE2; k++)
185  if (qtblptr->quantval[k] != qtblptr1->quantval[k])
186  ptr[k] *= qtblptr->quantval[k] / qtblptr1->quantval[k];
187  }
188  }
189  }
190 }
191 
192 
193 LOCAL(void)
194 requant_comp (j_decompress_ptr cinfo, jpeg_component_info *compptr,
195  jvirt_barray_ptr coef_array, JQUANT_TBL *qtblptr1)
196 {
197  JDIMENSION blk_x, blk_y;
198  int offset_y, k;
199  JQUANT_TBL *qtblptr;
202  JCOEFPTR ptr;
203  JCOEF temp, qval;
204 
205  qtblptr = compptr->quant_table;
206  for (blk_y = 0; blk_y < compptr->height_in_blocks;
207  blk_y += compptr->v_samp_factor) {
208  buffer = (*cinfo->mem->access_virt_barray)
209  ((j_common_ptr) cinfo, coef_array, blk_y,
211  for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
212  block = buffer[offset_y];
213  for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
214  ptr = block[blk_x];
215  for (k = 0; k < DCTSIZE2; k++) {
216  temp = qtblptr->quantval[k];
217  qval = qtblptr1->quantval[k];
218  if (temp != qval) {
219  temp *= ptr[k];
220  /* The following quantization code is a copy from jcdctmgr.c */
221 #ifdef FAST_DIVIDE
222 #define DIVIDE_BY(a,b) a /= b
223 #else
224 #define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0
225 #endif
226  if (temp < 0) {
227  temp = -temp;
228  temp += qval>>1; /* for rounding */
229  DIVIDE_BY(temp, qval);
230  temp = -temp;
231  } else {
232  temp += qval>>1; /* for rounding */
233  DIVIDE_BY(temp, qval);
234  }
235  ptr[k] = temp;
236  }
237  }
238  }
239  }
240  }
241 }
242 
243 
244 /* Calculate largest common denominator with Euclid's algorithm.
245  */
246 LOCAL(JCOEF)
247 largest_common_denominator(JCOEF a, JCOEF b)
248 {
249  JCOEF c;
250 
251  do {
252  c = a % b;
253  a = b;
254  b = c;
255  } while (c);
256 
257  return a;
258 }
259 
260 
261 LOCAL(void)
262 adjust_quant(j_decompress_ptr srcinfo, jvirt_barray_ptr *src_coef_arrays,
263  j_decompress_ptr dropinfo, jvirt_barray_ptr *drop_coef_arrays,
264  boolean trim, j_compress_ptr dstinfo)
265 {
266  jpeg_component_info *compptr1, *compptr2;
267  JQUANT_TBL *qtblptr1, *qtblptr2, *qtblptr3;
268  int ci, k;
269 
270  for (ci = 0; ci < dstinfo->num_components &&
271  ci < dropinfo->num_components; ci++) {
272  compptr1 = srcinfo->comp_info + ci;
273  compptr2 = dropinfo->comp_info + ci;
274  qtblptr1 = compptr1->quant_table;
275  qtblptr2 = compptr2->quant_table;
276  for (k = 0; k < DCTSIZE2; k++) {
277  if (qtblptr1->quantval[k] != qtblptr2->quantval[k]) {
278  if (trim)
279  requant_comp(dropinfo, compptr2, drop_coef_arrays[ci], qtblptr1);
280  else {
281  qtblptr3 = dstinfo->quant_tbl_ptrs[compptr1->quant_tbl_no];
282  for (k = 0; k < DCTSIZE2; k++)
283  if (qtblptr1->quantval[k] != qtblptr2->quantval[k])
284  qtblptr3->quantval[k] = largest_common_denominator
285  (qtblptr1->quantval[k], qtblptr2->quantval[k]);
286  dequant_comp(srcinfo, compptr1, src_coef_arrays[ci], qtblptr3);
287  dequant_comp(dropinfo, compptr2, drop_coef_arrays[ci], qtblptr3);
288  }
289  break;
290  }
291  }
292  }
293 }
294 
295 
296 LOCAL(void)
297 do_drop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
298  JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
299  jvirt_barray_ptr *src_coef_arrays,
300  j_decompress_ptr dropinfo, jvirt_barray_ptr *drop_coef_arrays,
301  JDIMENSION drop_width, JDIMENSION drop_height)
302 /* Drop. If the dropinfo component number is smaller than the destination's,
303  * we fill in the remaining components with zero. This provides the feature
304  * of dropping grayscale into (arbitrarily sampled) color images.
305  */
306 {
307  JDIMENSION comp_width, comp_height;
308  JDIMENSION blk_y, x_drop_blocks, y_drop_blocks;
309  int ci, offset_y;
310  JBLOCKARRAY src_buffer, dst_buffer;
312 
313  for (ci = 0; ci < dstinfo->num_components; ci++) {
314  compptr = dstinfo->comp_info + ci;
315  comp_width = drop_width * compptr->h_samp_factor;
316  comp_height = drop_height * compptr->v_samp_factor;
317  x_drop_blocks = x_crop_offset * compptr->h_samp_factor;
318  y_drop_blocks = y_crop_offset * compptr->v_samp_factor;
319  for (blk_y = 0; blk_y < comp_height; blk_y += compptr->v_samp_factor) {
320  dst_buffer = (*srcinfo->mem->access_virt_barray)
321  ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y + y_drop_blocks,
323  if (ci < dropinfo->num_components) {
324 #if DROP_REQUEST_FROM_SRC
325  src_buffer = (*srcinfo->mem->access_virt_barray)
326  ((j_common_ptr) srcinfo, drop_coef_arrays[ci], blk_y,
327 #else
328  src_buffer = (*dropinfo->mem->access_virt_barray)
329  ((j_common_ptr) dropinfo, drop_coef_arrays[ci], blk_y,
330 #endif
332  for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
333  jcopy_block_row(src_buffer[offset_y],
334  dst_buffer[offset_y] + x_drop_blocks,
335  comp_width);
336  }
337  } else {
338  for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
339  FMEMZERO(dst_buffer[offset_y] + x_drop_blocks,
340  comp_width * SIZEOF(JBLOCK));
341  }
342  }
343  }
344  }
345 }
346 
347 
348 LOCAL(void)
349 do_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
350  JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
351  jvirt_barray_ptr *src_coef_arrays,
352  jvirt_barray_ptr *dst_coef_arrays)
353 /* Crop. This is only used when no rotate/flip is requested with the crop. */
354 {
355  JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks;
356  int ci, offset_y;
357  JBLOCKARRAY src_buffer, dst_buffer;
359 
360  /* We simply have to copy the right amount of data (the destination's
361  * image size) starting at the given X and Y offsets in the source.
362  */
363  for (ci = 0; ci < dstinfo->num_components; ci++) {
364  compptr = dstinfo->comp_info + ci;
365  x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
366  y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
367  for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
368  dst_blk_y += compptr->v_samp_factor) {
369  dst_buffer = (*srcinfo->mem->access_virt_barray)
370  ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
372  src_buffer = (*srcinfo->mem->access_virt_barray)
373  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
374  dst_blk_y + y_crop_blocks,
376  for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
377  jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
378  dst_buffer[offset_y],
380  }
381  }
382  }
383 }
384 
385 
386 LOCAL(void)
387 do_crop_ext_zero (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
388  JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
389  jvirt_barray_ptr *src_coef_arrays,
390  jvirt_barray_ptr *dst_coef_arrays)
391 /* Crop. This is only used when no rotate/flip is requested with the crop.
392  * Extension: If the destination size is larger than the source, we fill in
393  * the extra area with zero (neutral gray). Note we also have to zero partial
394  * iMCUs at the right and bottom edge of the source image area in this case.
395  */
396 {
397  JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height;
398  JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks;
399  int ci, offset_y;
400  JBLOCKARRAY src_buffer, dst_buffer;
402 
403  MCU_cols = srcinfo->output_width /
405  MCU_rows = srcinfo->output_height /
407 
408  for (ci = 0; ci < dstinfo->num_components; ci++) {
409  compptr = dstinfo->comp_info + ci;
410  comp_width = MCU_cols * compptr->h_samp_factor;
411  comp_height = MCU_rows * compptr->v_samp_factor;
412  x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
413  y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
414  for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
415  dst_blk_y += compptr->v_samp_factor) {
416  dst_buffer = (*srcinfo->mem->access_virt_barray)
417  ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
419  if (dstinfo->jpeg_height > srcinfo->output_height) {
420  if (dst_blk_y < y_crop_blocks ||
421  dst_blk_y >= y_crop_blocks + comp_height) {
422  for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
423  FMEMZERO(dst_buffer[offset_y],
425  }
426  continue;
427  }
428  src_buffer = (*srcinfo->mem->access_virt_barray)
429  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
430  dst_blk_y - y_crop_blocks,
432  } else {
433  src_buffer = (*srcinfo->mem->access_virt_barray)
434  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
435  dst_blk_y + y_crop_blocks,
437  }
438  for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
439  if (dstinfo->jpeg_width > srcinfo->output_width) {
440  if (x_crop_blocks > 0) {
441  FMEMZERO(dst_buffer[offset_y],
442  x_crop_blocks * SIZEOF(JBLOCK));
443  }
444  jcopy_block_row(src_buffer[offset_y],
445  dst_buffer[offset_y] + x_crop_blocks,
446  comp_width);
447  if (compptr->width_in_blocks > x_crop_blocks + comp_width) {
448  FMEMZERO(dst_buffer[offset_y] +
449  x_crop_blocks + comp_width,
451  x_crop_blocks - comp_width) * SIZEOF(JBLOCK));
452  }
453  } else {
454  jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
455  dst_buffer[offset_y],
457  }
458  }
459  }
460  }
461 }
462 
463 
464 LOCAL(void)
465 do_crop_ext_flat (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
466  JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
467  jvirt_barray_ptr *src_coef_arrays,
468  jvirt_barray_ptr *dst_coef_arrays)
469 /* Crop. This is only used when no rotate/flip is requested with the crop.
470  * Extension: The destination width is larger than the source and we fill in
471  * the extra area with the DC of the adjacent block. Note we also have to
472  * fill partial iMCUs at the right and bottom edge of the source image area
473  * in this case.
474  */
475 {
476  JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height;
477  JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks;
478  int ci, offset_y;
479  JCOEF dc;
480  JBLOCKARRAY src_buffer, dst_buffer;
482 
483  MCU_cols = srcinfo->output_width /
485  MCU_rows = srcinfo->output_height /
487 
488  for (ci = 0; ci < dstinfo->num_components; ci++) {
489  compptr = dstinfo->comp_info + ci;
490  comp_width = MCU_cols * compptr->h_samp_factor;
491  comp_height = MCU_rows * compptr->v_samp_factor;
492  x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
493  y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
494  for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
495  dst_blk_y += compptr->v_samp_factor) {
496  dst_buffer = (*srcinfo->mem->access_virt_barray)
497  ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
499  if (dstinfo->jpeg_height > srcinfo->output_height) {
500  if (dst_blk_y < y_crop_blocks ||
501  dst_blk_y >= y_crop_blocks + comp_height) {
502  for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
503  FMEMZERO(dst_buffer[offset_y],
505  }
506  continue;
507  }
508  src_buffer = (*srcinfo->mem->access_virt_barray)
509  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
510  dst_blk_y - y_crop_blocks,
512  } else {
513  src_buffer = (*srcinfo->mem->access_virt_barray)
514  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
515  dst_blk_y + y_crop_blocks,
517  }
518  for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
519  if (x_crop_blocks > 0) {
520  FMEMZERO(dst_buffer[offset_y],
521  x_crop_blocks * SIZEOF(JBLOCK));
522  dc = src_buffer[offset_y][0][0];
523  for (dst_blk_x = 0; dst_blk_x < x_crop_blocks; dst_blk_x++) {
524  dst_buffer[offset_y][dst_blk_x][0] = dc;
525  }
526  }
527  jcopy_block_row(src_buffer[offset_y],
528  dst_buffer[offset_y] + x_crop_blocks,
529  comp_width);
530  if (compptr->width_in_blocks > x_crop_blocks + comp_width) {
531  FMEMZERO(dst_buffer[offset_y] +
532  x_crop_blocks + comp_width,
534  x_crop_blocks - comp_width) * SIZEOF(JBLOCK));
535  dc = src_buffer[offset_y][comp_width - 1][0];
536  for (dst_blk_x = x_crop_blocks + comp_width;
537  dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
538  dst_buffer[offset_y][dst_blk_x][0] = dc;
539  }
540  }
541  }
542  }
543  }
544 }
545 
546 
547 LOCAL(void)
548 do_crop_ext_reflect (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
549  JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
550  jvirt_barray_ptr *src_coef_arrays,
551  jvirt_barray_ptr *dst_coef_arrays)
552 /* Crop. This is only used when no rotate/flip is requested with the crop.
553  * Extension: The destination width is larger than the source and we fill in
554  * the extra area with repeated reflections of the source region. Note we
555  * also have to fill partial iMCUs at the right and bottom edge of the source
556  * image area in this case.
557  */
558 {
559  JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, src_blk_x;
560  JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks;
561  int ci, k, offset_y;
562  JBLOCKARRAY src_buffer, dst_buffer;
563  JBLOCKROW src_row_ptr, dst_row_ptr;
564  JCOEFPTR src_ptr, dst_ptr;
566 
567  MCU_cols = srcinfo->output_width /
569  MCU_rows = srcinfo->output_height /
571 
572  for (ci = 0; ci < dstinfo->num_components; ci++) {
573  compptr = dstinfo->comp_info + ci;
574  comp_width = MCU_cols * compptr->h_samp_factor;
575  comp_height = MCU_rows * compptr->v_samp_factor;
576  x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
577  y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
578  for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
579  dst_blk_y += compptr->v_samp_factor) {
580  dst_buffer = (*srcinfo->mem->access_virt_barray)
581  ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
583  if (dstinfo->jpeg_height > srcinfo->output_height) {
584  if (dst_blk_y < y_crop_blocks ||
585  dst_blk_y >= y_crop_blocks + comp_height) {
586  for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
587  FMEMZERO(dst_buffer[offset_y],
589  }
590  continue;
591  }
592  src_buffer = (*srcinfo->mem->access_virt_barray)
593  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
594  dst_blk_y - y_crop_blocks,
596  } else {
597  src_buffer = (*srcinfo->mem->access_virt_barray)
598  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
599  dst_blk_y + y_crop_blocks,
601  }
602  for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
603  /* Copy source region */
604  jcopy_block_row(src_buffer[offset_y],
605  dst_buffer[offset_y] + x_crop_blocks,
606  comp_width);
607  if (x_crop_blocks > 0) {
608  /* Reflect to left */
609  dst_row_ptr = dst_buffer[offset_y] + x_crop_blocks;
610  for (dst_blk_x = x_crop_blocks; dst_blk_x > 0;) {
611  src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */
612  for (src_blk_x = comp_width; src_blk_x > 0 && dst_blk_x > 0;
613  src_blk_x--, dst_blk_x--) {
614  dst_ptr = *--dst_row_ptr; /* destination goes left */
615  src_ptr = *src_row_ptr++; /* source goes right */
616  /* this unrolled loop doesn't need to know which row it's on... */
617  for (k = 0; k < DCTSIZE2; k += 2) {
618  *dst_ptr++ = *src_ptr++; /* copy even column */
619  *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */
620  }
621  }
622  }
623  }
624  if (compptr->width_in_blocks > x_crop_blocks + comp_width) {
625  /* Reflect to right */
626  dst_row_ptr = dst_buffer[offset_y] + x_crop_blocks + comp_width;
627  for (dst_blk_x = compptr->width_in_blocks - x_crop_blocks - comp_width;
628  dst_blk_x > 0;) {
629  src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */
630  for (src_blk_x = comp_width; src_blk_x > 0 && dst_blk_x > 0;
631  src_blk_x--, dst_blk_x--) {
632  dst_ptr = *dst_row_ptr++; /* destination goes right */
633  src_ptr = *--src_row_ptr; /* source goes left */
634  /* this unrolled loop doesn't need to know which row it's on... */
635  for (k = 0; k < DCTSIZE2; k += 2) {
636  *dst_ptr++ = *src_ptr++; /* copy even column */
637  *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */
638  }
639  }
640  }
641  }
642  }
643  }
644  }
645 }
646 
647 
648 LOCAL(void)
649 do_wipe (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
650  JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
651  jvirt_barray_ptr *src_coef_arrays,
652  JDIMENSION drop_width, JDIMENSION drop_height)
653 /* Wipe - drop content of specified area, fill with zero (neutral gray) */
654 {
655  JDIMENSION x_wipe_blocks, wipe_width;
656  JDIMENSION y_wipe_blocks, wipe_bottom;
657  int ci, offset_y;
660 
661  for (ci = 0; ci < dstinfo->num_components; ci++) {
662  compptr = dstinfo->comp_info + ci;
663  x_wipe_blocks = x_crop_offset * compptr->h_samp_factor;
664  wipe_width = drop_width * compptr->h_samp_factor;
665  y_wipe_blocks = y_crop_offset * compptr->v_samp_factor;
666  wipe_bottom = drop_height * compptr->v_samp_factor + y_wipe_blocks;
667  for (; y_wipe_blocks < wipe_bottom;
668  y_wipe_blocks += compptr->v_samp_factor) {
669  buffer = (*srcinfo->mem->access_virt_barray)
670  ((j_common_ptr) srcinfo, src_coef_arrays[ci], y_wipe_blocks,
672  for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
673  FMEMZERO(buffer[offset_y] + x_wipe_blocks,
674  wipe_width * SIZEOF(JBLOCK));
675  }
676  }
677  }
678 }
679 
680 
681 LOCAL(void)
682 do_flatten (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
683  JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
684  jvirt_barray_ptr *src_coef_arrays,
685  JDIMENSION drop_width, JDIMENSION drop_height)
686 /* Flatten - drop content of specified area, similar to wipe,
687  * but fill with average of adjacent blocks, instead of zero.
688  */
689 {
690  JDIMENSION x_wipe_blocks, wipe_width, wipe_right;
691  JDIMENSION y_wipe_blocks, wipe_bottom, blk_x;
692  int ci, offset_y, dc_left_value, dc_right_value, average;
695 
696  for (ci = 0; ci < dstinfo->num_components; ci++) {
697  compptr = dstinfo->comp_info + ci;
698  x_wipe_blocks = x_crop_offset * compptr->h_samp_factor;
699  wipe_width = drop_width * compptr->h_samp_factor;
700  wipe_right = wipe_width + x_wipe_blocks;
701  y_wipe_blocks = y_crop_offset * compptr->v_samp_factor;
702  wipe_bottom = drop_height * compptr->v_samp_factor + y_wipe_blocks;
703  for (; y_wipe_blocks < wipe_bottom;
704  y_wipe_blocks += compptr->v_samp_factor) {
705  buffer = (*srcinfo->mem->access_virt_barray)
706  ((j_common_ptr) srcinfo, src_coef_arrays[ci], y_wipe_blocks,
708  for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
709  FMEMZERO(buffer[offset_y] + x_wipe_blocks,
710  wipe_width * SIZEOF(JBLOCK));
711  if (x_wipe_blocks > 0) {
712  dc_left_value = buffer[offset_y][x_wipe_blocks - 1][0];
713  if (wipe_right < compptr->width_in_blocks) {
714  dc_right_value = buffer[offset_y][wipe_right][0];
715  average = (dc_left_value + dc_right_value) >> 1;
716  } else {
717  average = dc_left_value;
718  }
719  } else if (wipe_right < compptr->width_in_blocks) {
720  average = buffer[offset_y][wipe_right][0];
721  } else continue;
722  for (blk_x = x_wipe_blocks; blk_x < wipe_right; blk_x++) {
723  buffer[offset_y][blk_x][0] = (JCOEF) average;
724  }
725  }
726  }
727  }
728 }
729 
730 
731 LOCAL(void)
732 do_reflect (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
733  JDIMENSION x_crop_offset,
734  jvirt_barray_ptr *src_coef_arrays,
735  JDIMENSION drop_width, JDIMENSION drop_height)
736 /* Reflect - drop content of specified area, similar to wipe, but
737  * fill with repeated reflections of the outside area, instead of zero.
738  * NB: y_crop_offset is assumed to be zero.
739  */
740 {
741  JDIMENSION x_wipe_blocks, wipe_width;
742  JDIMENSION y_wipe_blocks, wipe_bottom;
743  JDIMENSION src_blk_x, dst_blk_x;
744  int ci, k, offset_y;
746  JBLOCKROW src_row_ptr, dst_row_ptr;
747  JCOEFPTR src_ptr, dst_ptr;
749 
750  for (ci = 0; ci < dstinfo->num_components; ci++) {
751  compptr = dstinfo->comp_info + ci;
752  x_wipe_blocks = x_crop_offset * compptr->h_samp_factor;
753  wipe_width = drop_width * compptr->h_samp_factor;
754  wipe_bottom = drop_height * compptr->v_samp_factor;
755  for (y_wipe_blocks = 0; y_wipe_blocks < wipe_bottom;
756  y_wipe_blocks += compptr->v_samp_factor) {
757  buffer = (*srcinfo->mem->access_virt_barray)
758  ((j_common_ptr) srcinfo, src_coef_arrays[ci], y_wipe_blocks,
760  for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
761  if (x_wipe_blocks > 0) {
762  /* Reflect from left */
763  dst_row_ptr = buffer[offset_y] + x_wipe_blocks;
764  for (dst_blk_x = wipe_width; dst_blk_x > 0;) {
765  src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */
766  for (src_blk_x = x_wipe_blocks;
767  src_blk_x > 0 && dst_blk_x > 0; src_blk_x--, dst_blk_x--) {
768  dst_ptr = *dst_row_ptr++; /* destination goes right */
769  src_ptr = *--src_row_ptr; /* source goes left */
770  /* this unrolled loop doesn't need to know which row it's on... */
771  for (k = 0; k < DCTSIZE2; k += 2) {
772  *dst_ptr++ = *src_ptr++; /* copy even column */
773  *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */
774  }
775  }
776  }
777  } else if (compptr->width_in_blocks > x_wipe_blocks + wipe_width) {
778  /* Reflect from right */
779  dst_row_ptr = buffer[offset_y] + x_wipe_blocks + wipe_width;
780  for (dst_blk_x = wipe_width; dst_blk_x > 0;) {
781  src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */
782  src_blk_x = compptr->width_in_blocks - x_wipe_blocks - wipe_width;
783  for (; src_blk_x > 0 && dst_blk_x > 0; src_blk_x--, dst_blk_x--) {
784  dst_ptr = *--dst_row_ptr; /* destination goes left */
785  src_ptr = *src_row_ptr++; /* source goes right */
786  /* this unrolled loop doesn't need to know which row it's on... */
787  for (k = 0; k < DCTSIZE2; k += 2) {
788  *dst_ptr++ = *src_ptr++; /* copy even column */
789  *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */
790  }
791  }
792  }
793  } else {
794  FMEMZERO(buffer[offset_y] + x_wipe_blocks,
795  wipe_width * SIZEOF(JBLOCK));
796  }
797  }
798  }
799  }
800 }
801 
802 
803 LOCAL(void)
804 do_flip_h_no_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
805  JDIMENSION x_crop_offset,
806  jvirt_barray_ptr *src_coef_arrays)
807 /* Horizontal flip; done in-place, so no separate dest array is required.
808  * NB: this only works when y_crop_offset is zero.
809  */
810 {
811  JDIMENSION MCU_cols, comp_width, blk_x, blk_y, x_crop_blocks;
812  int ci, k, offset_y;
814  JCOEFPTR ptr1, ptr2;
815  JCOEF temp1, temp2;
817 
818  /* Horizontal mirroring of DCT blocks is accomplished by swapping
819  * pairs of blocks in-place. Within a DCT block, we perform horizontal
820  * mirroring by changing the signs of odd-numbered columns.
821  * Partial iMCUs at the right edge are left untouched.
822  */
823  MCU_cols = srcinfo->output_width /
825 
826  for (ci = 0; ci < dstinfo->num_components; ci++) {
827  compptr = dstinfo->comp_info + ci;
828  comp_width = MCU_cols * compptr->h_samp_factor;
829  x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
830  for (blk_y = 0; blk_y < compptr->height_in_blocks;
831  blk_y += compptr->v_samp_factor) {
832  buffer = (*srcinfo->mem->access_virt_barray)
833  ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y,
835  for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
836  /* Do the mirroring */
837  for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) {
838  ptr1 = buffer[offset_y][blk_x];
839  ptr2 = buffer[offset_y][comp_width - blk_x - 1];
840  /* this unrolled loop doesn't need to know which row it's on... */
841  for (k = 0; k < DCTSIZE2; k += 2) {
842  temp1 = *ptr1; /* swap even column */
843  temp2 = *ptr2;
844  *ptr1++ = temp2;
845  *ptr2++ = temp1;
846  temp1 = *ptr1; /* swap odd column with sign change */
847  temp2 = *ptr2;
848  *ptr1++ = -temp2;
849  *ptr2++ = -temp1;
850  }
851  }
852  if (x_crop_blocks > 0) {
853  /* Now left-justify the portion of the data to be kept.
854  * We can't use a single jcopy_block_row() call because that routine
855  * depends on memcpy(), whose behavior is unspecified for overlapping
856  * source and destination areas. Sigh.
857  */
858  for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
859  jcopy_block_row(buffer[offset_y] + blk_x + x_crop_blocks,
860  buffer[offset_y] + blk_x,
861  (JDIMENSION) 1);
862  }
863  }
864  }
865  }
866  }
867 }
868 
869 
870 LOCAL(void)
871 do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
872  JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
873  jvirt_barray_ptr *src_coef_arrays,
874  jvirt_barray_ptr *dst_coef_arrays)
875 /* Horizontal flip in general cropping case */
876 {
877  JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
878  JDIMENSION x_crop_blocks, y_crop_blocks;
879  int ci, k, offset_y;
880  JBLOCKARRAY src_buffer, dst_buffer;
881  JBLOCKROW src_row_ptr, dst_row_ptr;
882  JCOEFPTR src_ptr, dst_ptr;
884 
885  /* Here we must output into a separate array because we can't touch
886  * different rows of a single virtual array simultaneously. Otherwise,
887  * this is essentially the same as the routine above.
888  */
889  MCU_cols = srcinfo->output_width /
891 
892  for (ci = 0; ci < dstinfo->num_components; ci++) {
893  compptr = dstinfo->comp_info + ci;
894  comp_width = MCU_cols * compptr->h_samp_factor;
895  x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
896  y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
897  for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
898  dst_blk_y += compptr->v_samp_factor) {
899  dst_buffer = (*srcinfo->mem->access_virt_barray)
900  ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
902  src_buffer = (*srcinfo->mem->access_virt_barray)
903  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
904  dst_blk_y + y_crop_blocks,
906  for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
907  dst_row_ptr = dst_buffer[offset_y];
908  src_row_ptr = src_buffer[offset_y];
909  for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
910  if (x_crop_blocks + dst_blk_x < comp_width) {
911  /* Do the mirrorable blocks */
912  dst_ptr = dst_row_ptr[dst_blk_x];
913  src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
914  /* this unrolled loop doesn't need to know which row it's on... */
915  for (k = 0; k < DCTSIZE2; k += 2) {
916  *dst_ptr++ = *src_ptr++; /* copy even column */
917  *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */
918  }
919  } else {
920  /* Copy last partial block(s) verbatim */
921  jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
922  dst_row_ptr + dst_blk_x,
923  (JDIMENSION) 1);
924  }
925  }
926  }
927  }
928  }
929 }
930 
931 
932 LOCAL(void)
933 do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
934  JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
935  jvirt_barray_ptr *src_coef_arrays,
936  jvirt_barray_ptr *dst_coef_arrays)
937 /* Vertical flip */
938 {
939  JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
940  JDIMENSION x_crop_blocks, y_crop_blocks;
941  int ci, i, j, offset_y;
942  JBLOCKARRAY src_buffer, dst_buffer;
943  JBLOCKROW src_row_ptr, dst_row_ptr;
944  JCOEFPTR src_ptr, dst_ptr;
946 
947  /* We output into a separate array because we can't touch different
948  * rows of the source virtual array simultaneously. Otherwise, this
949  * is a pretty straightforward analog of horizontal flip.
950  * Within a DCT block, vertical mirroring is done by changing the signs
951  * of odd-numbered rows.
952  * Partial iMCUs at the bottom edge are copied verbatim.
953  */
954  MCU_rows = srcinfo->output_height /
956 
957  for (ci = 0; ci < dstinfo->num_components; ci++) {
958  compptr = dstinfo->comp_info + ci;
959  comp_height = MCU_rows * compptr->v_samp_factor;
960  x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
961  y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
962  for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
963  dst_blk_y += compptr->v_samp_factor) {
964  dst_buffer = (*srcinfo->mem->access_virt_barray)
965  ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
967  if (y_crop_blocks + dst_blk_y < comp_height) {
968  /* Row is within the mirrorable area. */
969  src_buffer = (*srcinfo->mem->access_virt_barray)
970  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
971  comp_height - y_crop_blocks - dst_blk_y -
974  } else {
975  /* Bottom-edge blocks will be copied verbatim. */
976  src_buffer = (*srcinfo->mem->access_virt_barray)
977  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
978  dst_blk_y + y_crop_blocks,
980  }
981  for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
982  if (y_crop_blocks + dst_blk_y < comp_height) {
983  /* Row is within the mirrorable area. */
984  dst_row_ptr = dst_buffer[offset_y];
985  src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
986  src_row_ptr += x_crop_blocks;
987  for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
988  dst_blk_x++) {
989  dst_ptr = dst_row_ptr[dst_blk_x];
990  src_ptr = src_row_ptr[dst_blk_x];
991  for (i = 0; i < DCTSIZE; i += 2) {
992  /* copy even row */
993  for (j = 0; j < DCTSIZE; j++)
994  *dst_ptr++ = *src_ptr++;
995  /* copy odd row with sign change */
996  for (j = 0; j < DCTSIZE; j++)
997  *dst_ptr++ = - *src_ptr++;
998  }
999  }
1000  } else {
1001  /* Just copy row verbatim. */
1002  jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
1003  dst_buffer[offset_y],
1005  }
1006  }
1007  }
1008  }
1009 }
1010 
1011 
1012 LOCAL(void)
1013 do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
1014  JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
1015  jvirt_barray_ptr *src_coef_arrays,
1016  jvirt_barray_ptr *dst_coef_arrays)
1017 /* Transpose source into destination */
1018 {
1019  JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks;
1020  int ci, i, j, offset_x, offset_y;
1021  JBLOCKARRAY src_buffer, dst_buffer;
1022  JCOEFPTR src_ptr, dst_ptr;
1024 
1025  /* Transposing pixels within a block just requires transposing the
1026  * DCT coefficients.
1027  * Partial iMCUs at the edges require no special treatment; we simply
1028  * process all the available DCT blocks for every component.
1029  */
1030  for (ci = 0; ci < dstinfo->num_components; ci++) {
1031  compptr = dstinfo->comp_info + ci;
1032  x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
1033  y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
1034  for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
1035  dst_blk_y += compptr->v_samp_factor) {
1036  dst_buffer = (*srcinfo->mem->access_virt_barray)
1037  ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
1039  for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
1040  for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
1041  dst_blk_x += compptr->h_samp_factor) {
1042  src_buffer = (*srcinfo->mem->access_virt_barray)
1043  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
1044  dst_blk_x + x_crop_blocks,
1046  for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
1047  dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
1048  src_ptr = src_buffer[offset_x][dst_blk_y + offset_y + y_crop_blocks];
1049  for (i = 0; i < DCTSIZE; i++)
1050  for (j = 0; j < DCTSIZE; j++)
1051  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
1052  }
1053  }
1054  }
1055  }
1056  }
1057 }
1058 
1059 
1060 LOCAL(void)
1061 do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
1062  JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
1063  jvirt_barray_ptr *src_coef_arrays,
1064  jvirt_barray_ptr *dst_coef_arrays)
1065 /* 90 degree rotation is equivalent to
1066  * 1. Transposing the image;
1067  * 2. Horizontal mirroring.
1068  * These two steps are merged into a single processing routine.
1069  */
1070 {
1071  JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
1072  JDIMENSION x_crop_blocks, y_crop_blocks;
1073  int ci, i, j, offset_x, offset_y;
1074  JBLOCKARRAY src_buffer, dst_buffer;
1075  JCOEFPTR src_ptr, dst_ptr;
1077 
1078  /* Because of the horizontal mirror step, we can't process partial iMCUs
1079  * at the (output) right edge properly. They just get transposed and
1080  * not mirrored.
1081  */
1082  MCU_cols = srcinfo->output_height /
1084 
1085  for (ci = 0; ci < dstinfo->num_components; ci++) {
1086  compptr = dstinfo->comp_info + ci;
1087  comp_width = MCU_cols * compptr->h_samp_factor;
1088  x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
1089  y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
1090  for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
1091  dst_blk_y += compptr->v_samp_factor) {
1092  dst_buffer = (*srcinfo->mem->access_virt_barray)
1093  ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
1095  for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
1096  for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
1097  dst_blk_x += compptr->h_samp_factor) {
1098  if (x_crop_blocks + dst_blk_x < comp_width) {
1099  /* Block is within the mirrorable area. */
1100  src_buffer = (*srcinfo->mem->access_virt_barray)
1101  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
1102  comp_width - x_crop_blocks - dst_blk_x -
1105  } else {
1106  /* Edge blocks are transposed but not mirrored. */
1107  src_buffer = (*srcinfo->mem->access_virt_barray)
1108  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
1109  dst_blk_x + x_crop_blocks,
1111  }
1112  for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
1113  dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
1114  if (x_crop_blocks + dst_blk_x < comp_width) {
1115  /* Block is within the mirrorable area. */
1116  src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
1117  [dst_blk_y + offset_y + y_crop_blocks];
1118  for (i = 0; i < DCTSIZE; i++) {
1119  for (j = 0; j < DCTSIZE; j++)
1120  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
1121  i++;
1122  for (j = 0; j < DCTSIZE; j++)
1123  dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
1124  }
1125  } else {
1126  /* Edge blocks are transposed but not mirrored. */
1127  src_ptr = src_buffer[offset_x]
1128  [dst_blk_y + offset_y + y_crop_blocks];
1129  for (i = 0; i < DCTSIZE; i++)
1130  for (j = 0; j < DCTSIZE; j++)
1131  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
1132  }
1133  }
1134  }
1135  }
1136  }
1137  }
1138 }
1139 
1140 
1141 LOCAL(void)
1142 do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
1143  JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
1144  jvirt_barray_ptr *src_coef_arrays,
1145  jvirt_barray_ptr *dst_coef_arrays)
1146 /* 270 degree rotation is equivalent to
1147  * 1. Horizontal mirroring;
1148  * 2. Transposing the image.
1149  * These two steps are merged into a single processing routine.
1150  */
1151 {
1152  JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
1153  JDIMENSION x_crop_blocks, y_crop_blocks;
1154  int ci, i, j, offset_x, offset_y;
1155  JBLOCKARRAY src_buffer, dst_buffer;
1156  JCOEFPTR src_ptr, dst_ptr;
1158 
1159  /* Because of the horizontal mirror step, we can't process partial iMCUs
1160  * at the (output) bottom edge properly. They just get transposed and
1161  * not mirrored.
1162  */
1163  MCU_rows = srcinfo->output_width /
1165 
1166  for (ci = 0; ci < dstinfo->num_components; ci++) {
1167  compptr = dstinfo->comp_info + ci;
1168  comp_height = MCU_rows * compptr->v_samp_factor;
1169  x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
1170  y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
1171  for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
1172  dst_blk_y += compptr->v_samp_factor) {
1173  dst_buffer = (*srcinfo->mem->access_virt_barray)
1174  ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
1176  for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
1177  for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
1178  dst_blk_x += compptr->h_samp_factor) {
1179  src_buffer = (*srcinfo->mem->access_virt_barray)
1180  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
1181  dst_blk_x + x_crop_blocks,
1183  for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
1184  dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
1185  if (y_crop_blocks + dst_blk_y < comp_height) {
1186  /* Block is within the mirrorable area. */
1187  src_ptr = src_buffer[offset_x]
1188  [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
1189  for (i = 0; i < DCTSIZE; i++) {
1190  for (j = 0; j < DCTSIZE; j++) {
1191  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
1192  j++;
1193  dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
1194  }
1195  }
1196  } else {
1197  /* Edge blocks are transposed but not mirrored. */
1198  src_ptr = src_buffer[offset_x]
1199  [dst_blk_y + offset_y + y_crop_blocks];
1200  for (i = 0; i < DCTSIZE; i++)
1201  for (j = 0; j < DCTSIZE; j++)
1202  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
1203  }
1204  }
1205  }
1206  }
1207  }
1208  }
1209 }
1210 
1211 
1212 LOCAL(void)
1213 do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
1214  JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
1215  jvirt_barray_ptr *src_coef_arrays,
1216  jvirt_barray_ptr *dst_coef_arrays)
1217 /* 180 degree rotation is equivalent to
1218  * 1. Vertical mirroring;
1219  * 2. Horizontal mirroring.
1220  * These two steps are merged into a single processing routine.
1221  */
1222 {
1223  JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
1224  JDIMENSION x_crop_blocks, y_crop_blocks;
1225  int ci, i, j, offset_y;
1226  JBLOCKARRAY src_buffer, dst_buffer;
1227  JBLOCKROW src_row_ptr, dst_row_ptr;
1228  JCOEFPTR src_ptr, dst_ptr;
1230 
1231  MCU_cols = srcinfo->output_width /
1233  MCU_rows = srcinfo->output_height /
1235 
1236  for (ci = 0; ci < dstinfo->num_components; ci++) {
1237  compptr = dstinfo->comp_info + ci;
1238  comp_width = MCU_cols * compptr->h_samp_factor;
1239  comp_height = MCU_rows * compptr->v_samp_factor;
1240  x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
1241  y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
1242  for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
1243  dst_blk_y += compptr->v_samp_factor) {
1244  dst_buffer = (*srcinfo->mem->access_virt_barray)
1245  ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
1247  if (y_crop_blocks + dst_blk_y < comp_height) {
1248  /* Row is within the vertically mirrorable area. */
1249  src_buffer = (*srcinfo->mem->access_virt_barray)
1250  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
1251  comp_height - y_crop_blocks - dst_blk_y -
1254  } else {
1255  /* Bottom-edge rows are only mirrored horizontally. */
1256  src_buffer = (*srcinfo->mem->access_virt_barray)
1257  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
1258  dst_blk_y + y_crop_blocks,
1260  }
1261  for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
1262  dst_row_ptr = dst_buffer[offset_y];
1263  if (y_crop_blocks + dst_blk_y < comp_height) {
1264  /* Row is within the mirrorable area. */
1265  src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
1266  for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
1267  dst_ptr = dst_row_ptr[dst_blk_x];
1268  if (x_crop_blocks + dst_blk_x < comp_width) {
1269  /* Process the blocks that can be mirrored both ways. */
1270  src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
1271  for (i = 0; i < DCTSIZE; i += 2) {
1272  /* For even row, negate every odd column. */
1273  for (j = 0; j < DCTSIZE; j += 2) {
1274  *dst_ptr++ = *src_ptr++;
1275  *dst_ptr++ = - *src_ptr++;
1276  }
1277  /* For odd row, negate every even column. */
1278  for (j = 0; j < DCTSIZE; j += 2) {
1279  *dst_ptr++ = - *src_ptr++;
1280  *dst_ptr++ = *src_ptr++;
1281  }
1282  }
1283  } else {
1284  /* Any remaining right-edge blocks are only mirrored vertically. */
1285  src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x];
1286  for (i = 0; i < DCTSIZE; i += 2) {
1287  for (j = 0; j < DCTSIZE; j++)
1288  *dst_ptr++ = *src_ptr++;
1289  for (j = 0; j < DCTSIZE; j++)
1290  *dst_ptr++ = - *src_ptr++;
1291  }
1292  }
1293  }
1294  } else {
1295  /* Remaining rows are just mirrored horizontally. */
1296  src_row_ptr = src_buffer[offset_y];
1297  for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
1298  if (x_crop_blocks + dst_blk_x < comp_width) {
1299  /* Process the blocks that can be mirrored. */
1300  dst_ptr = dst_row_ptr[dst_blk_x];
1301  src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
1302  for (i = 0; i < DCTSIZE2; i += 2) {
1303  *dst_ptr++ = *src_ptr++;
1304  *dst_ptr++ = - *src_ptr++;
1305  }
1306  } else {
1307  /* Any remaining right-edge blocks are only copied. */
1308  jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
1309  dst_row_ptr + dst_blk_x,
1310  (JDIMENSION) 1);
1311  }
1312  }
1313  }
1314  }
1315  }
1316  }
1317 }
1318 
1319 
1320 LOCAL(void)
1321 do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
1322  JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
1323  jvirt_barray_ptr *src_coef_arrays,
1324  jvirt_barray_ptr *dst_coef_arrays)
1325 /* Transverse transpose is equivalent to
1326  * 1. 180 degree rotation;
1327  * 2. Transposition;
1328  * or
1329  * 1. Horizontal mirroring;
1330  * 2. Transposition;
1331  * 3. Horizontal mirroring.
1332  * These steps are merged into a single processing routine.
1333  */
1334 {
1335  JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
1336  JDIMENSION x_crop_blocks, y_crop_blocks;
1337  int ci, i, j, offset_x, offset_y;
1338  JBLOCKARRAY src_buffer, dst_buffer;
1339  JCOEFPTR src_ptr, dst_ptr;
1341 
1342  MCU_cols = srcinfo->output_height /
1344  MCU_rows = srcinfo->output_width /
1346 
1347  for (ci = 0; ci < dstinfo->num_components; ci++) {
1348  compptr = dstinfo->comp_info + ci;
1349  comp_width = MCU_cols * compptr->h_samp_factor;
1350  comp_height = MCU_rows * compptr->v_samp_factor;
1351  x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
1352  y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
1353  for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
1354  dst_blk_y += compptr->v_samp_factor) {
1355  dst_buffer = (*srcinfo->mem->access_virt_barray)
1356  ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
1358  for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
1359  for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
1360  dst_blk_x += compptr->h_samp_factor) {
1361  if (x_crop_blocks + dst_blk_x < comp_width) {
1362  /* Block is within the mirrorable area. */
1363  src_buffer = (*srcinfo->mem->access_virt_barray)
1364  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
1365  comp_width - x_crop_blocks - dst_blk_x -
1368  } else {
1369  src_buffer = (*srcinfo->mem->access_virt_barray)
1370  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
1371  dst_blk_x + x_crop_blocks,
1373  }
1374  for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
1375  dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
1376  if (y_crop_blocks + dst_blk_y < comp_height) {
1377  if (x_crop_blocks + dst_blk_x < comp_width) {
1378  /* Block is within the mirrorable area. */
1379  src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
1380  [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
1381  for (i = 0; i < DCTSIZE; i++) {
1382  for (j = 0; j < DCTSIZE; j++) {
1383  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
1384  j++;
1385  dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
1386  }
1387  i++;
1388  for (j = 0; j < DCTSIZE; j++) {
1389  dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
1390  j++;
1391  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
1392  }
1393  }
1394  } else {
1395  /* Right-edge blocks are mirrored in y only */
1396  src_ptr = src_buffer[offset_x]
1397  [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
1398  for (i = 0; i < DCTSIZE; i++) {
1399  for (j = 0; j < DCTSIZE; j++) {
1400  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
1401  j++;
1402  dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
1403  }
1404  }
1405  }
1406  } else {
1407  if (x_crop_blocks + dst_blk_x < comp_width) {
1408  /* Bottom-edge blocks are mirrored in x only */
1409  src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
1410  [dst_blk_y + offset_y + y_crop_blocks];
1411  for (i = 0; i < DCTSIZE; i++) {
1412  for (j = 0; j < DCTSIZE; j++)
1413  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
1414  i++;
1415  for (j = 0; j < DCTSIZE; j++)
1416  dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
1417  }
1418  } else {
1419  /* At lower right corner, just transpose, no mirroring */
1420  src_ptr = src_buffer[offset_x]
1421  [dst_blk_y + offset_y + y_crop_blocks];
1422  for (i = 0; i < DCTSIZE; i++)
1423  for (j = 0; j < DCTSIZE; j++)
1424  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
1425  }
1426  }
1427  }
1428  }
1429  }
1430  }
1431  }
1432 }
1433 
1434 
1435 /* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec.
1436  * Returns TRUE if valid integer found, FALSE if not.
1437  * *strptr is advanced over the digit string, and *result is set to its value.
1438  */
1439 
1440 LOCAL(boolean)
1441 jt_read_integer (const char ** strptr, JDIMENSION * result)
1442 {
1443  const char * ptr = *strptr;
1444  JDIMENSION val = 0;
1445 
1446  for (; isdigit(*ptr); ptr++) {
1447  val = val * 10 + (JDIMENSION) (*ptr - '0');
1448  }
1449  *result = val;
1450  if (ptr == *strptr)
1451  return FALSE; /* oops, no digits */
1452  *strptr = ptr;
1453  return TRUE;
1454 }
1455 
1456 
1457 /* Parse a crop specification (written in X11 geometry style).
1458  * The routine returns TRUE if the spec string is valid, FALSE if not.
1459  *
1460  * The crop spec string should have the format
1461  * <width>[{fr}]x<height>[{fr}]{+-}<xoffset>{+-}<yoffset>
1462  * where width, height, xoffset, and yoffset are unsigned integers.
1463  * Each of the elements can be omitted to indicate a default value.
1464  * (A weakness of this style is that it is not possible to omit xoffset
1465  * while specifying yoffset, since they look alike.)
1466  *
1467  * This code is loosely based on XParseGeometry from the X11 distribution.
1468  */
1469 
1470 GLOBAL(boolean)
1471 jtransform_parse_crop_spec (jpeg_transform_info *info, const char *spec)
1472 {
1473  info->crop = FALSE;
1474  info->crop_width_set = JCROP_UNSET;
1475  info->crop_height_set = JCROP_UNSET;
1476  info->crop_xoffset_set = JCROP_UNSET;
1477  info->crop_yoffset_set = JCROP_UNSET;
1478 
1479  if (isdigit(*spec)) {
1480  /* fetch width */
1481  if (! jt_read_integer(&spec, &info->crop_width))
1482  return FALSE;
1483  if (*spec == 'f' || *spec == 'F') {
1484  spec++;
1485  info->crop_width_set = JCROP_FORCE;
1486  } else if (*spec == 'r' || *spec == 'R') {
1487  spec++;
1488  info->crop_width_set = JCROP_REFLECT;
1489  } else
1490  info->crop_width_set = JCROP_POS;
1491  }
1492  if (*spec == 'x' || *spec == 'X') {
1493  /* fetch height */
1494  spec++;
1495  if (! jt_read_integer(&spec, &info->crop_height))
1496  return FALSE;
1497  if (*spec == 'f' || *spec == 'F') {
1498  spec++;
1499  info->crop_height_set = JCROP_FORCE;
1500  } else if (*spec == 'r' || *spec == 'R') {
1501  spec++;
1502  info->crop_height_set = JCROP_REFLECT;
1503  } else
1504  info->crop_height_set = JCROP_POS;
1505  }
1506  if (*spec == '+' || *spec == '-') {
1507  /* fetch xoffset */
1508  info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
1509  spec++;
1510  if (! jt_read_integer(&spec, &info->crop_xoffset))
1511  return FALSE;
1512  }
1513  if (*spec == '+' || *spec == '-') {
1514  /* fetch yoffset */
1515  info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
1516  spec++;
1517  if (! jt_read_integer(&spec, &info->crop_yoffset))
1518  return FALSE;
1519  }
1520  /* We had better have gotten to the end of the string. */
1521  if (*spec != '\0')
1522  return FALSE;
1523  info->crop = TRUE;
1524  return TRUE;
1525 }
1526 
1527 
1528 /* Trim off any partial iMCUs on the indicated destination edge */
1529 
1530 LOCAL(void)
1531 trim_right_edge (jpeg_transform_info *info, JDIMENSION full_width)
1532 {
1533  JDIMENSION MCU_cols;
1534 
1535  MCU_cols = info->output_width / info->iMCU_sample_width;
1536  if (MCU_cols > 0 && info->x_crop_offset + MCU_cols ==
1537  full_width / info->iMCU_sample_width)
1538  info->output_width = MCU_cols * info->iMCU_sample_width;
1539 }
1540 
1541 LOCAL(void)
1542 trim_bottom_edge (jpeg_transform_info *info, JDIMENSION full_height)
1543 {
1544  JDIMENSION MCU_rows;
1545 
1546  MCU_rows = info->output_height / info->iMCU_sample_height;
1547  if (MCU_rows > 0 && info->y_crop_offset + MCU_rows ==
1548  full_height / info->iMCU_sample_height)
1549  info->output_height = MCU_rows * info->iMCU_sample_height;
1550 }
1551 
1552 
1553 /* Request any required workspace.
1554  *
1555  * This routine figures out the size that the output image will be
1556  * (which implies that all the transform parameters must be set before
1557  * it is called).
1558  *
1559  * We allocate the workspace virtual arrays from the source decompression
1560  * object, so that all the arrays (both the original data and the workspace)
1561  * will be taken into account while making memory management decisions.
1562  * Hence, this routine must be called after jpeg_read_header (which reads
1563  * the image dimensions) and before jpeg_read_coefficients (which realizes
1564  * the source's virtual arrays).
1565  *
1566  * This function returns FALSE right away if -perfect is given
1567  * and transformation is not perfect. Otherwise returns TRUE.
1568  */
1569 
1570 GLOBAL(boolean)
1571 jtransform_request_workspace (j_decompress_ptr srcinfo,
1573 {
1575  boolean need_workspace, transpose_it;
1577  JDIMENSION xoffset, yoffset, dtemp;
1578  JDIMENSION width_in_iMCUs, height_in_iMCUs;
1579  JDIMENSION width_in_blocks, height_in_blocks;
1580  int itemp, ci, h_samp_factor, v_samp_factor;
1581 
1582  /* Determine number of components in output image */
1583  if (info->force_grayscale &&
1584  (srcinfo->jpeg_color_space == JCS_YCbCr ||
1585  srcinfo->jpeg_color_space == JCS_BG_YCC) &&
1586  srcinfo->num_components == 3)
1587  /* We'll only process the first component */
1588  info->num_components = 1;
1589  else
1590  /* Process all the components */
1591  info->num_components = srcinfo->num_components;
1592 
1593  /* Compute output image dimensions and related values. */
1594  jpeg_core_output_dimensions(srcinfo);
1595 
1596  /* Return right away if -perfect is given and transformation is not perfect.
1597  */
1598  if (info->perfect) {
1599  if (info->num_components == 1) {
1600  if (!jtransform_perfect_transform(srcinfo->output_width,
1601  srcinfo->output_height,
1602  srcinfo->min_DCT_h_scaled_size,
1603  srcinfo->min_DCT_v_scaled_size,
1604  info->transform))
1605  return FALSE;
1606  } else {
1607  if (!jtransform_perfect_transform(srcinfo->output_width,
1608  srcinfo->output_height,
1609  srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size,
1610  srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size,
1611  info->transform))
1612  return FALSE;
1613  }
1614  }
1615 
1616  /* If there is only one output component, force the iMCU size to be 1;
1617  * else use the source iMCU size. (This allows us to do the right thing
1618  * when reducing color to grayscale, and also provides a handy way of
1619  * cleaning up "funny" grayscale images whose sampling factors are not 1x1.)
1620  */
1621  switch (info->transform) {
1622  case JXFORM_TRANSPOSE:
1623  case JXFORM_TRANSVERSE:
1624  case JXFORM_ROT_90:
1625  case JXFORM_ROT_270:
1626  info->output_width = srcinfo->output_height;
1627  info->output_height = srcinfo->output_width;
1628  if (info->num_components == 1) {
1629  info->iMCU_sample_width = srcinfo->min_DCT_v_scaled_size;
1630  info->iMCU_sample_height = srcinfo->min_DCT_h_scaled_size;
1631  } else {
1632  info->iMCU_sample_width =
1633  srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size;
1634  info->iMCU_sample_height =
1635  srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size;
1636  }
1637  break;
1638  default:
1639  info->output_width = srcinfo->output_width;
1640  info->output_height = srcinfo->output_height;
1641  if (info->num_components == 1) {
1642  info->iMCU_sample_width = srcinfo->min_DCT_h_scaled_size;
1643  info->iMCU_sample_height = srcinfo->min_DCT_v_scaled_size;
1644  } else {
1645  info->iMCU_sample_width =
1646  srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size;
1647  info->iMCU_sample_height =
1648  srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size;
1649  }
1650  }
1651 
1652  /* If cropping has been requested, compute the crop area's position and
1653  * dimensions, ensuring that its upper left corner falls at an iMCU boundary.
1654  */
1655  if (info->crop) {
1656  /* Insert default values for unset crop parameters */
1657  if (info->crop_xoffset_set == JCROP_UNSET)
1658  info->crop_xoffset = 0; /* default to +0 */
1659  if (info->crop_yoffset_set == JCROP_UNSET)
1660  info->crop_yoffset = 0; /* default to +0 */
1661  if (info->crop_width_set == JCROP_UNSET) {
1662  if (info->crop_xoffset >= info->output_width)
1663  ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1664  info->crop_width = info->output_width - info->crop_xoffset;
1665  } else {
1666  /* Check for crop extension */
1667  if (info->crop_width > info->output_width) {
1668  /* Crop extension does not work when transforming! */
1669  if (info->transform != JXFORM_NONE ||
1670  info->crop_xoffset >= info->crop_width ||
1671  info->crop_xoffset > info->crop_width - info->output_width)
1672  ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1673  } else {
1674  if (info->crop_xoffset >= info->output_width ||
1675  info->crop_width <= 0 ||
1676  info->crop_xoffset > info->output_width - info->crop_width)
1677  ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1678  }
1679  }
1680  if (info->crop_height_set == JCROP_UNSET) {
1681  if (info->crop_yoffset >= info->output_height)
1682  ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1683  info->crop_height = info->output_height - info->crop_yoffset;
1684  } else {
1685  /* Check for crop extension */
1686  if (info->crop_height > info->output_height) {
1687  /* Crop extension does not work when transforming! */
1688  if (info->transform != JXFORM_NONE ||
1689  info->crop_yoffset >= info->crop_height ||
1690  info->crop_yoffset > info->crop_height - info->output_height)
1691  ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1692  } else {
1693  if (info->crop_yoffset >= info->output_height ||
1694  info->crop_height <= 0 ||
1695  info->crop_yoffset > info->output_height - info->crop_height)
1696  ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1697  }
1698  }
1699  /* Convert negative crop offsets into regular offsets */
1700  if (info->crop_xoffset_set != JCROP_NEG)
1701  xoffset = info->crop_xoffset;
1702  else if (info->crop_width > info->output_width) /* crop extension */
1703  xoffset = info->crop_width - info->output_width - info->crop_xoffset;
1704  else
1705  xoffset = info->output_width - info->crop_width - info->crop_xoffset;
1706  if (info->crop_yoffset_set != JCROP_NEG)
1707  yoffset = info->crop_yoffset;
1708  else if (info->crop_height > info->output_height) /* crop extension */
1709  yoffset = info->crop_height - info->output_height - info->crop_yoffset;
1710  else
1711  yoffset = info->output_height - info->crop_height - info->crop_yoffset;
1712  /* Now adjust so that upper left corner falls at an iMCU boundary */
1713  switch (info->transform) {
1714  case JXFORM_DROP:
1715  /* Ensure the effective drop region will not exceed the requested */
1716  itemp = info->iMCU_sample_width;
1717  dtemp = itemp - 1 - ((xoffset + itemp - 1) % itemp);
1718  xoffset += dtemp;
1719  if (info->crop_width <= dtemp)
1720  info->drop_width = 0;
1721  else if (xoffset + info->crop_width - dtemp == info->output_width)
1722  /* Matching right edge: include partial iMCU */
1723  info->drop_width = (info->crop_width - dtemp + itemp - 1) / itemp;
1724  else
1725  info->drop_width = (info->crop_width - dtemp) / itemp;
1726  itemp = info->iMCU_sample_height;
1727  dtemp = itemp - 1 - ((yoffset + itemp - 1) % itemp);
1728  yoffset += dtemp;
1729  if (info->crop_height <= dtemp)
1730  info->drop_height = 0;
1731  else if (yoffset + info->crop_height - dtemp == info->output_height)
1732  /* Matching bottom edge: include partial iMCU */
1733  info->drop_height = (info->crop_height - dtemp + itemp - 1) / itemp;
1734  else
1735  info->drop_height = (info->crop_height - dtemp) / itemp;
1736  /* Check if sampling factors match for dropping */
1737  if (info->drop_width != 0 && info->drop_height != 0)
1738  for (ci = 0; ci < info->num_components &&
1739  ci < info->drop_ptr->num_components; ci++) {
1740  if (info->drop_ptr->comp_info[ci].h_samp_factor *
1741  srcinfo->max_h_samp_factor !=
1742  srcinfo->comp_info[ci].h_samp_factor *
1743  info->drop_ptr->max_h_samp_factor)
1744  ERREXIT6(srcinfo, JERR_BAD_DROP_SAMPLING, ci,
1745  info->drop_ptr->comp_info[ci].h_samp_factor,
1746  info->drop_ptr->max_h_samp_factor,
1747  srcinfo->comp_info[ci].h_samp_factor,
1748  srcinfo->max_h_samp_factor, 'h');
1749  if (info->drop_ptr->comp_info[ci].v_samp_factor *
1750  srcinfo->max_v_samp_factor !=
1751  srcinfo->comp_info[ci].v_samp_factor *
1752  info->drop_ptr->max_v_samp_factor)
1753  ERREXIT6(srcinfo, JERR_BAD_DROP_SAMPLING, ci,
1754  info->drop_ptr->comp_info[ci].v_samp_factor,
1755  info->drop_ptr->max_v_samp_factor,
1756  srcinfo->comp_info[ci].v_samp_factor,
1757  srcinfo->max_v_samp_factor, 'v');
1758  }
1759  break;
1760  case JXFORM_WIPE:
1761  /* Ensure the effective wipe region will cover the requested */
1762  info->drop_width = (JDIMENSION) jdiv_round_up
1763  ((long) (info->crop_width + (xoffset % info->iMCU_sample_width)),
1764  (long) info->iMCU_sample_width);
1765  info->drop_height = (JDIMENSION) jdiv_round_up
1766  ((long) (info->crop_height + (yoffset % info->iMCU_sample_height)),
1767  (long) info->iMCU_sample_height);
1768  break;
1769  default:
1770  /* Ensure the effective crop region will cover the requested */
1771  if (info->crop_width_set == JCROP_FORCE ||
1772  info->crop_width > info->output_width)
1773  info->output_width = info->crop_width;
1774  else
1775  info->output_width =
1776  info->crop_width + (xoffset % info->iMCU_sample_width);
1777  if (info->crop_height_set == JCROP_FORCE ||
1778  info->crop_height > info->output_height)
1779  info->output_height = info->crop_height;
1780  else
1781  info->output_height =
1782  info->crop_height + (yoffset % info->iMCU_sample_height);
1783  }
1784  /* Save x/y offsets measured in iMCUs */
1785  info->x_crop_offset = xoffset / info->iMCU_sample_width;
1786  info->y_crop_offset = yoffset / info->iMCU_sample_height;
1787  } else {
1788  info->x_crop_offset = 0;
1789  info->y_crop_offset = 0;
1790  }
1791 
1792  /* Figure out whether we need workspace arrays,
1793  * and if so whether they are transposed relative to the source.
1794  */
1795  need_workspace = FALSE;
1796  transpose_it = FALSE;
1797  switch (info->transform) {
1798  case JXFORM_NONE:
1799  if (info->x_crop_offset != 0 || info->y_crop_offset != 0 ||
1800  info->output_width > srcinfo->output_width ||
1801  info->output_height > srcinfo->output_height)
1802  need_workspace = TRUE;
1803  /* No workspace needed if neither cropping nor transforming */
1804  break;
1805  case JXFORM_FLIP_H:
1806  if (info->trim)
1807  trim_right_edge(info, srcinfo->output_width);
1808  if (info->y_crop_offset != 0)
1809  need_workspace = TRUE;
1810  /* do_flip_h_no_crop doesn't need a workspace array */
1811  break;
1812  case JXFORM_FLIP_V:
1813  if (info->trim)
1814  trim_bottom_edge(info, srcinfo->output_height);
1815  /* Need workspace arrays having same dimensions as source image. */
1816  need_workspace = TRUE;
1817  break;
1818  case JXFORM_TRANSPOSE:
1819  /* transpose does NOT have to trim anything */
1820  /* Need workspace arrays having transposed dimensions. */
1821  need_workspace = TRUE;
1822  transpose_it = TRUE;
1823  break;
1824  case JXFORM_TRANSVERSE:
1825  if (info->trim) {
1826  trim_right_edge(info, srcinfo->output_height);
1827  trim_bottom_edge(info, srcinfo->output_width);
1828  }
1829  /* Need workspace arrays having transposed dimensions. */
1830  need_workspace = TRUE;
1831  transpose_it = TRUE;
1832  break;
1833  case JXFORM_ROT_90:
1834  if (info->trim)
1835  trim_right_edge(info, srcinfo->output_height);
1836  /* Need workspace arrays having transposed dimensions. */
1837  need_workspace = TRUE;
1838  transpose_it = TRUE;
1839  break;
1840  case JXFORM_ROT_180:
1841  if (info->trim) {
1842  trim_right_edge(info, srcinfo->output_width);
1843  trim_bottom_edge(info, srcinfo->output_height);
1844  }
1845  /* Need workspace arrays having same dimensions as source image. */
1846  need_workspace = TRUE;
1847  break;
1848  case JXFORM_ROT_270:
1849  if (info->trim)
1850  trim_bottom_edge(info, srcinfo->output_width);
1851  /* Need workspace arrays having transposed dimensions. */
1852  need_workspace = TRUE;
1853  transpose_it = TRUE;
1854  break;
1855  case JXFORM_WIPE:
1856  break;
1857  case JXFORM_DROP:
1858 #if DROP_REQUEST_FROM_SRC
1859  drop_request_from_src(info->drop_ptr, srcinfo);
1860 #endif
1861  break;
1862  }
1863 
1864  /* Allocate workspace if needed.
1865  * Note that we allocate arrays padded out to the next iMCU boundary,
1866  * so that transform routines need not worry about missing edge blocks.
1867  */
1868  if (need_workspace) {
1869  coef_arrays = (jvirt_barray_ptr *) (*srcinfo->mem->alloc_small)
1870  ((j_common_ptr) srcinfo, JPOOL_IMAGE,
1871  SIZEOF(jvirt_barray_ptr) * info->num_components);
1872  width_in_iMCUs = (JDIMENSION) jdiv_round_up
1873  ((long) info->output_width, (long) info->iMCU_sample_width);
1874  height_in_iMCUs = (JDIMENSION) jdiv_round_up
1875  ((long) info->output_height, (long) info->iMCU_sample_height);
1876  for (ci = 0; ci < info->num_components; ci++) {
1877  compptr = srcinfo->comp_info + ci;
1878  if (info->num_components == 1) {
1879  /* we're going to force samp factors to 1x1 in this case */
1880  h_samp_factor = v_samp_factor = 1;
1881  } else if (transpose_it) {
1882  h_samp_factor = compptr->v_samp_factor;
1883  v_samp_factor = compptr->h_samp_factor;
1884  } else {
1885  h_samp_factor = compptr->h_samp_factor;
1886  v_samp_factor = compptr->v_samp_factor;
1887  }
1888  width_in_blocks = width_in_iMCUs * h_samp_factor;
1889  height_in_blocks = height_in_iMCUs * v_samp_factor;
1890  coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
1891  ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
1892  width_in_blocks, height_in_blocks, (JDIMENSION) v_samp_factor);
1893  }
1894  info->workspace_coef_arrays = coef_arrays;
1895  } else
1896  info->workspace_coef_arrays = NULL;
1897 
1898  return TRUE;
1899 }
1900 
1901 
1902 /* Transpose destination image parameters */
1903 
1904 LOCAL(void)
1905 transpose_critical_parameters (j_compress_ptr dstinfo)
1906 {
1907  int tblno, i, j, ci, itemp;
1909  JQUANT_TBL *qtblptr;
1910  JDIMENSION jtemp;
1911  UINT16 qtemp;
1912 
1913  /* Transpose image dimensions */
1914  jtemp = dstinfo->image_width;
1916  dstinfo->image_height = jtemp;
1917  itemp = dstinfo->min_DCT_h_scaled_size;
1919  dstinfo->min_DCT_v_scaled_size = itemp;
1920 
1921  /* Transpose sampling factors */
1922  for (ci = 0; ci < dstinfo->num_components; ci++) {
1923  compptr = dstinfo->comp_info + ci;
1924  itemp = compptr->h_samp_factor;
1926  compptr->v_samp_factor = itemp;
1927  }
1928 
1929  /* Transpose quantization tables */
1930  for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
1931  qtblptr = dstinfo->quant_tbl_ptrs[tblno];
1932  if (qtblptr != NULL) {
1933  for (i = 0; i < DCTSIZE; i++) {
1934  for (j = 0; j < i; j++) {
1935  qtemp = qtblptr->quantval[i*DCTSIZE+j];
1936  qtblptr->quantval[i*DCTSIZE+j] = qtblptr->quantval[j*DCTSIZE+i];
1937  qtblptr->quantval[j*DCTSIZE+i] = qtemp;
1938  }
1939  }
1940  }
1941  }
1942 }
1943 
1944 
1945 /* Adjust Exif image parameters.
1946  *
1947  * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible.
1948  */
1949 
1950 LOCAL(void)
1951 adjust_exif_parameters (JOCTET FAR * data, unsigned int length,
1952  JDIMENSION new_width, JDIMENSION new_height)
1953 {
1954  boolean is_motorola; /* Flag for byte order */
1955  unsigned int number_of_tags, tagnum;
1956  unsigned int firstoffset, offset;
1957  JDIMENSION new_value;
1958 
1959  if (length < 12) return; /* Length of an IFD entry */
1960 
1961  /* Discover byte order */
1962  if (GETJOCTET(data[0]) == 0x49 && GETJOCTET(data[1]) == 0x49)
1963  is_motorola = FALSE;
1964  else if (GETJOCTET(data[0]) == 0x4D && GETJOCTET(data[1]) == 0x4D)
1965  is_motorola = TRUE;
1966  else
1967  return;
1968 
1969  /* Check Tag Mark */
1970  if (is_motorola) {
1971  if (GETJOCTET(data[2]) != 0) return;
1972  if (GETJOCTET(data[3]) != 0x2A) return;
1973  } else {
1974  if (GETJOCTET(data[3]) != 0) return;
1975  if (GETJOCTET(data[2]) != 0x2A) return;
1976  }
1977 
1978  /* Get first IFD offset (offset to IFD0) */
1979  if (is_motorola) {
1980  if (GETJOCTET(data[4]) != 0) return;
1981  if (GETJOCTET(data[5]) != 0) return;
1982  firstoffset = GETJOCTET(data[6]);
1983  firstoffset <<= 8;
1984  firstoffset += GETJOCTET(data[7]);
1985  } else {
1986  if (GETJOCTET(data[7]) != 0) return;
1987  if (GETJOCTET(data[6]) != 0) return;
1988  firstoffset = GETJOCTET(data[5]);
1989  firstoffset <<= 8;
1990  firstoffset += GETJOCTET(data[4]);
1991  }
1992  if (firstoffset > length - 2) return; /* check end of data segment */
1993 
1994  /* Get the number of directory entries contained in this IFD */
1995  if (is_motorola) {
1996  number_of_tags = GETJOCTET(data[firstoffset]);
1997  number_of_tags <<= 8;
1998  number_of_tags += GETJOCTET(data[firstoffset+1]);
1999  } else {
2000  number_of_tags = GETJOCTET(data[firstoffset+1]);
2001  number_of_tags <<= 8;
2002  number_of_tags += GETJOCTET(data[firstoffset]);
2003  }
2004  if (number_of_tags == 0) return;
2005  firstoffset += 2;
2006 
2007  /* Search for ExifSubIFD offset Tag in IFD0 */
2008  for (;;) {
2009  if (firstoffset > length - 12) return; /* check end of data segment */
2010  /* Get Tag number */
2011  if (is_motorola) {
2012  tagnum = GETJOCTET(data[firstoffset]);
2013  tagnum <<= 8;
2014  tagnum += GETJOCTET(data[firstoffset+1]);
2015  } else {
2016  tagnum = GETJOCTET(data[firstoffset+1]);
2017  tagnum <<= 8;
2018  tagnum += GETJOCTET(data[firstoffset]);
2019  }
2020  if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */
2021  if (--number_of_tags == 0) return;
2022  firstoffset += 12;
2023  }
2024 
2025  /* Get the ExifSubIFD offset */
2026  if (is_motorola) {
2027  if (GETJOCTET(data[firstoffset+8]) != 0) return;
2028  if (GETJOCTET(data[firstoffset+9]) != 0) return;
2029  offset = GETJOCTET(data[firstoffset+10]);
2030  offset <<= 8;
2031  offset += GETJOCTET(data[firstoffset+11]);
2032  } else {
2033  if (GETJOCTET(data[firstoffset+11]) != 0) return;
2034  if (GETJOCTET(data[firstoffset+10]) != 0) return;
2035  offset = GETJOCTET(data[firstoffset+9]);
2036  offset <<= 8;
2037  offset += GETJOCTET(data[firstoffset+8]);
2038  }
2039  if (offset > length - 2) return; /* check end of data segment */
2040 
2041  /* Get the number of directory entries contained in this SubIFD */
2042  if (is_motorola) {
2043  number_of_tags = GETJOCTET(data[offset]);
2044  number_of_tags <<= 8;
2045  number_of_tags += GETJOCTET(data[offset+1]);
2046  } else {
2047  number_of_tags = GETJOCTET(data[offset+1]);
2048  number_of_tags <<= 8;
2049  number_of_tags += GETJOCTET(data[offset]);
2050  }
2051  if (number_of_tags < 2) return;
2052  offset += 2;
2053 
2054  /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */
2055  do {
2056  if (offset > length - 12) return; /* check end of data segment */
2057  /* Get Tag number */
2058  if (is_motorola) {
2059  tagnum = GETJOCTET(data[offset]);
2060  tagnum <<= 8;
2061  tagnum += GETJOCTET(data[offset+1]);
2062  } else {
2063  tagnum = GETJOCTET(data[offset+1]);
2064  tagnum <<= 8;
2065  tagnum += GETJOCTET(data[offset]);
2066  }
2067  if (tagnum == 0xA002 || tagnum == 0xA003) {
2068  if (tagnum == 0xA002)
2069  new_value = new_width; /* ExifImageWidth Tag */
2070  else
2071  new_value = new_height; /* ExifImageHeight Tag */
2072  if (is_motorola) {
2073  data[offset+2] = 0; /* Format = unsigned long (4 octets) */
2074  data[offset+3] = 4;
2075  data[offset+4] = 0; /* Number Of Components = 1 */
2076  data[offset+5] = 0;
2077  data[offset+6] = 0;
2078  data[offset+7] = 1;
2079  data[offset+8] = 0;
2080  data[offset+9] = 0;
2081  data[offset+10] = (JOCTET)((new_value >> 8) & 0xFF);
2082  data[offset+11] = (JOCTET)(new_value & 0xFF);
2083  } else {
2084  data[offset+2] = 4; /* Format = unsigned long (4 octets) */
2085  data[offset+3] = 0;
2086  data[offset+4] = 1; /* Number Of Components = 1 */
2087  data[offset+5] = 0;
2088  data[offset+6] = 0;
2089  data[offset+7] = 0;
2090  data[offset+8] = (JOCTET)(new_value & 0xFF);
2091  data[offset+9] = (JOCTET)((new_value >> 8) & 0xFF);
2092  data[offset+10] = 0;
2093  data[offset+11] = 0;
2094  }
2095  }
2096  offset += 12;
2097  } while (--number_of_tags);
2098 }
2099 
2100 
2101 /* Adjust output image parameters as needed.
2102  *
2103  * This must be called after jpeg_copy_critical_parameters()
2104  * and before jpeg_write_coefficients().
2105  *
2106  * The return value is the set of virtual coefficient arrays to be written
2107  * (either the ones allocated by jtransform_request_workspace, or the
2108  * original source data arrays). The caller will need to pass this value
2109  * to jpeg_write_coefficients().
2110  */
2111 
2113 jtransform_adjust_parameters (j_decompress_ptr srcinfo,
2115  jvirt_barray_ptr *src_coef_arrays,
2117 {
2118  /* If force-to-grayscale is requested, adjust destination parameters */
2119  if (info->force_grayscale) {
2120  /* First, ensure we have YCC or grayscale data, and that the source's
2121  * Y channel is full resolution. (No reasonable person would make Y
2122  * be less than full resolution, so actually coping with that case
2123  * isn't worth extra code space. But we check it to avoid crashing.)
2124  */
2125  if ((((dstinfo->jpeg_color_space == JCS_YCbCr ||
2127  dstinfo->num_components == 3) ||
2129  dstinfo->num_components == 1)) &&
2130  srcinfo->comp_info[0].h_samp_factor == srcinfo->max_h_samp_factor &&
2131  srcinfo->comp_info[0].v_samp_factor == srcinfo->max_v_samp_factor) {
2132  /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
2133  * properly. Among other things, it sets the target h_samp_factor &
2134  * v_samp_factor to 1, which typically won't match the source.
2135  * We have to preserve the source's quantization table number, however.
2136  */
2137  int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no;
2139  dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no;
2140  } else {
2141  /* Sorry, can't do it */
2142  ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL);
2143  }
2144  } else if (info->num_components == 1) {
2145  /* For a single-component source, we force the destination sampling factors
2146  * to 1x1, with or without force_grayscale. This is useful because some
2147  * decoders choke on grayscale images with other sampling factors.
2148  */
2151  }
2152 
2153  /* Correct the destination's image dimensions as necessary
2154  * for rotate/flip, resize, and crop operations.
2155  */
2156  dstinfo->jpeg_width = info->output_width;
2157  dstinfo->jpeg_height = info->output_height;
2158 
2159  /* Transpose destination image parameters, adjust quantization */
2160  switch (info->transform) {
2161  case JXFORM_TRANSPOSE:
2162  case JXFORM_TRANSVERSE:
2163  case JXFORM_ROT_90:
2164  case JXFORM_ROT_270:
2165  transpose_critical_parameters(dstinfo);
2166  break;
2167  case JXFORM_DROP:
2168  if (info->drop_width != 0 && info->drop_height != 0)
2169  adjust_quant(srcinfo, src_coef_arrays,
2170  info->drop_ptr, info->drop_coef_arrays,
2171  info->trim, dstinfo);
2172  break;
2173  default:
2174  break;
2175  }
2176 
2177  /* Adjust Exif properties */
2178  if (srcinfo->marker_list != NULL &&
2179  srcinfo->marker_list->marker == JPEG_APP0+1 &&
2180  srcinfo->marker_list->data_length >= 6 &&
2181  GETJOCTET(srcinfo->marker_list->data[0]) == 0x45 &&
2182  GETJOCTET(srcinfo->marker_list->data[1]) == 0x78 &&
2183  GETJOCTET(srcinfo->marker_list->data[2]) == 0x69 &&
2184  GETJOCTET(srcinfo->marker_list->data[3]) == 0x66 &&
2185  GETJOCTET(srcinfo->marker_list->data[4]) == 0 &&
2186  GETJOCTET(srcinfo->marker_list->data[5]) == 0) {
2187  /* Suppress output of JFIF marker */
2189  /* Adjust Exif image parameters */
2190  if (dstinfo->jpeg_width != srcinfo->image_width ||
2191  dstinfo->jpeg_height != srcinfo->image_height)
2192  /* Align data segment to start of TIFF structure for parsing */
2193  adjust_exif_parameters(srcinfo->marker_list->data + 6,
2194  srcinfo->marker_list->data_length - 6,
2196  }
2197 
2198  /* Return the appropriate output data set */
2199  if (info->workspace_coef_arrays != NULL)
2200  return info->workspace_coef_arrays;
2201  return src_coef_arrays;
2202 }
2203 
2204 
2205 /* Execute the actual transformation, if any.
2206  *
2207  * This must be called *after* jpeg_write_coefficients, because it depends
2208  * on jpeg_write_coefficients to have computed subsidiary values such as
2209  * the per-component width and height fields in the destination object.
2210  *
2211  * Note that some transformations will modify the source data arrays!
2212  */
2213 
2214 GLOBAL(void)
2215 jtransform_execute_transform (j_decompress_ptr srcinfo,
2217  jvirt_barray_ptr *src_coef_arrays,
2219 {
2220  jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays;
2221 
2222  /* Note: conditions tested here should match those in switch statement
2223  * in jtransform_request_workspace()
2224  */
2225  switch (info->transform) {
2226  case JXFORM_NONE:
2227  if (info->output_width > srcinfo->output_width ||
2228  info->output_height > srcinfo->output_height) {
2229  if (info->output_width > srcinfo->output_width &&
2230  info->crop_width_set == JCROP_REFLECT)
2231  do_crop_ext_reflect(srcinfo, dstinfo,
2232  info->x_crop_offset, info->y_crop_offset,
2233  src_coef_arrays, dst_coef_arrays);
2234  else if (info->output_width > srcinfo->output_width &&
2235  info->crop_width_set == JCROP_FORCE)
2236  do_crop_ext_flat(srcinfo, dstinfo,
2237  info->x_crop_offset, info->y_crop_offset,
2238  src_coef_arrays, dst_coef_arrays);
2239  else
2240  do_crop_ext_zero(srcinfo, dstinfo,
2241  info->x_crop_offset, info->y_crop_offset,
2242  src_coef_arrays, dst_coef_arrays);
2243  } else if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
2244  do_crop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2245  src_coef_arrays, dst_coef_arrays);
2246  break;
2247  case JXFORM_FLIP_H:
2248  if (info->y_crop_offset != 0)
2249  do_flip_h(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2250  src_coef_arrays, dst_coef_arrays);
2251  else
2252  do_flip_h_no_crop(srcinfo, dstinfo, info->x_crop_offset,
2253  src_coef_arrays);
2254  break;
2255  case JXFORM_FLIP_V:
2256  do_flip_v(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2257  src_coef_arrays, dst_coef_arrays);
2258  break;
2259  case JXFORM_TRANSPOSE:
2260  do_transpose(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2261  src_coef_arrays, dst_coef_arrays);
2262  break;
2263  case JXFORM_TRANSVERSE:
2264  do_transverse(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2265  src_coef_arrays, dst_coef_arrays);
2266  break;
2267  case JXFORM_ROT_90:
2268  do_rot_90(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2269  src_coef_arrays, dst_coef_arrays);
2270  break;
2271  case JXFORM_ROT_180:
2272  do_rot_180(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2273  src_coef_arrays, dst_coef_arrays);
2274  break;
2275  case JXFORM_ROT_270:
2276  do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2277  src_coef_arrays, dst_coef_arrays);
2278  break;
2279  case JXFORM_WIPE:
2280  if (info->crop_width_set == JCROP_REFLECT &&
2281  info->y_crop_offset == 0 && info->drop_height ==
2283  ((long) info->output_height, (long) info->iMCU_sample_height) &&
2284  (info->x_crop_offset == 0 ||
2285  info->x_crop_offset + info->drop_width ==
2287  ((long) info->output_width, (long) info->iMCU_sample_width)))
2288  do_reflect(srcinfo, dstinfo, info->x_crop_offset,
2289  src_coef_arrays, info->drop_width, info->drop_height);
2290  else if (info->crop_width_set == JCROP_FORCE)
2291  do_flatten(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2292  src_coef_arrays, info->drop_width, info->drop_height);
2293  else
2294  do_wipe(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2295  src_coef_arrays, info->drop_width, info->drop_height);
2296  break;
2297  case JXFORM_DROP:
2298  if (info->drop_width != 0 && info->drop_height != 0)
2299  do_drop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2300  src_coef_arrays, info->drop_ptr, info->drop_coef_arrays,
2301  info->drop_width, info->drop_height);
2302  break;
2303  }
2304 }
2305 
2306 /* jtransform_perfect_transform
2307  *
2308  * Determine whether lossless transformation is perfectly
2309  * possible for a specified image and transformation.
2310  *
2311  * Inputs:
2312  * image_width, image_height: source image dimensions.
2313  * MCU_width, MCU_height: pixel dimensions of MCU.
2314  * transform: transformation identifier.
2315  * Parameter sources from initialized jpeg_struct
2316  * (after reading source header):
2317  * image_width = cinfo.image_width
2318  * image_height = cinfo.image_height
2319  * MCU_width = cinfo.max_h_samp_factor * cinfo.block_size
2320  * MCU_height = cinfo.max_v_samp_factor * cinfo.block_size
2321  * Result:
2322  * TRUE = perfect transformation possible
2323  * FALSE = perfect transformation not possible
2324  * (may use custom action then)
2325  */
2326 
2327 GLOBAL(boolean)
2328 jtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height,
2329  int MCU_width, int MCU_height,
2331 {
2332  boolean result = TRUE; /* initialize TRUE */
2333 
2334  switch (transform) {
2335  case JXFORM_FLIP_H:
2336  case JXFORM_ROT_270:
2337  if (image_width % (JDIMENSION) MCU_width)
2338  result = FALSE;
2339  break;
2340  case JXFORM_FLIP_V:
2341  case JXFORM_ROT_90:
2342  if (image_height % (JDIMENSION) MCU_height)
2343  result = FALSE;
2344  break;
2345  case JXFORM_TRANSVERSE:
2346  case JXFORM_ROT_180:
2347  if (image_width % (JDIMENSION) MCU_width)
2348  result = FALSE;
2349  if (image_height % (JDIMENSION) MCU_height)
2350  result = FALSE;
2351  break;
2352  default:
2353  break;
2354  }
2355 
2356  return result;
2357 }
2358 
2359 #endif /* TRANSFORMS_SUPPORTED */
2360 
2361 
2362 /* Setup decompression object to save desired markers in memory.
2363  * This must be called before jpeg_read_header() to have the desired effect.
2364  */
2365 
2366 GLOBAL(void)
2368 {
2369 #ifdef SAVE_MARKERS_SUPPORTED
2370  int m;
2371 
2372  /* Save comments except under NONE option */
2373  if (option != JCOPYOPT_NONE) {
2374  jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF);
2375  }
2376  /* Save all types of APPn markers iff ALL option */
2377  if (option == JCOPYOPT_ALL) {
2378  for (m = 0; m < 16; m++)
2379  jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF);
2380  }
2381 #endif /* SAVE_MARKERS_SUPPORTED */
2382 }
2383 
2384 /* Copy markers saved in the given source object to the destination object.
2385  * This should be called just after jpeg_start_compress() or
2386  * jpeg_write_coefficients().
2387  * Note that those routines will have written the SOI, and also the
2388  * JFIF APP0 or Adobe APP14 markers if selected.
2389  */
2390 
2391 GLOBAL(void)
2394 {
2396 
2397  /* In the current implementation, we don't actually need to examine the
2398  * option flag here; we just copy everything that got saved.
2399  * But to avoid confusion, we do not output JFIF and Adobe APP14 markers
2400  * if the encoder library already wrote one.
2401  */
2402  for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) {
2403  if (dstinfo->write_JFIF_header &&
2404  marker->marker == JPEG_APP0 &&
2405  marker->data_length >= 5 &&
2406  GETJOCTET(marker->data[0]) == 0x4A &&
2407  GETJOCTET(marker->data[1]) == 0x46 &&
2408  GETJOCTET(marker->data[2]) == 0x49 &&
2409  GETJOCTET(marker->data[3]) == 0x46 &&
2410  GETJOCTET(marker->data[4]) == 0)
2411  continue; /* reject duplicate JFIF */
2412  if (dstinfo->write_Adobe_marker &&
2413  marker->marker == JPEG_APP0+14 &&
2414  marker->data_length >= 5 &&
2415  GETJOCTET(marker->data[0]) == 0x41 &&
2416  GETJOCTET(marker->data[1]) == 0x64 &&
2417  GETJOCTET(marker->data[2]) == 0x6F &&
2418  GETJOCTET(marker->data[3]) == 0x62 &&
2419  GETJOCTET(marker->data[4]) == 0x65)
2420  continue; /* reject duplicate Adobe */
2421 #ifdef NEED_FAR_POINTERS
2422  /* We could use jpeg_write_marker if the data weren't FAR... */
2423  {
2424  unsigned int i;
2425  jpeg_write_m_header(dstinfo, marker->marker, marker->data_length);
2426  for (i = 0; i < marker->data_length; i++)
2427  jpeg_write_m_byte(dstinfo, marker->data[i]);
2428  }
2429 #else
2430  jpeg_write_marker(dstinfo, marker->marker,
2431  marker->data, marker->data_length);
2432 #endif
2433  }
2434 }
boolean write_Adobe_marker
Definition: jpeglib.h:385
static unsigned int block
Definition: xmlmemory.c:118
#define DIVIDE_BY(a, b)
return
Definition: dirsup.c:529
#define TRUE
Definition: types.h:120
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
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
struct jpeg_input_controller * inputctl
Definition: jpeglib.h:682
jpeg_component_info * comp_info
Definition: jpeglib.h:583
boolean int tblno
Definition: jpeglib.h:1010
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:1098
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
#define a
Definition: ke_i.h:78
GLint GLint xoffset
Definition: gl.h:1547
jcopy_markers_execute(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, JCOPY_OPTION option)
Definition: transupp.c:2392
#define FAR
Definition: guiddef.h:36
static PVOID ptr
Definition: dispmode.c:27
int image_width
#define JPEG_APP0
Definition: jpeglib.h:1128
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:1030
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 b
Definition: ke_i.h:79
#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
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define JMETHOD(type, methodname, arglist)
Definition: jmorecfg.h:308
jdiv_round_up(long a, long b)
Definition: jutils.c:124
JBLOCK FAR * JBLOCKROW
Definition: jpeglib.h:80
const GLubyte * c
Definition: glext.h:8905
JCOEF FAR * JCOEFPTR
Definition: jpeglib.h:84
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
JQUANT_TBL * quant_table
Definition: jpeglib.h:189
j_compress_ptr dstinfo
Definition: jpeglib.h:1100
#define GLOBAL(type)
Definition: jmorecfg.h:291
JXFORM_CODE
Definition: transupp.h:105
JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]
Definition: jpeglib.h:336
#define METHODDEF(type)
Definition: jmorecfg.h:287
jpeg_set_colorspace(j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
Definition: jcparam.c:336
jcopy_markers_setup(j_decompress_ptr srcinfo, JCOPY_OPTION option)
Definition: transupp.c:2367
static calc_node_t temp
Definition: rpn_ieee.c:38
#define long
Definition: qsort.c:33
jpeg_write_m_byte(j_compress_ptr cinfo, int val)
Definition: jcapimin.c:234
#define JPEG_SUSPENDED
Definition: jpeglib.h:1045
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
#define c
Definition: ke_i.h:80
char JOCTET
Definition: jmorecfg.h:167
GLuint GLenum GLenum transform
Definition: glext.h:9407
static const WCHAR dc[]
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
char * trim(char *str, char **last_chr, BOOL strip_quotes)
Definition: inf.c:258
JCOPY_OPTION
Definition: transupp.h:216
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:1129
#define ERREXIT6(cinfo, code, p1, p2, p3, p4, p5, p6)
Definition: jerror.h:234
#define FMEMZERO(target, size)
Definition: jpegint.h:368
JDIMENSION image_width
Definition: jpeglib.h:302