4 * Copyright (C) 1997-2017, Thomas G. Lane, Guido Vollbeding.
5 * This file is part of the Independent JPEG Group's software.
6 * For conditions of distribution and use, see the accompanying README file.
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
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().
18 #define JPEG_INTERNALS
22 #include "transupp.h" /* My own external interface */
23 #include <ctype.h> /* to declare isdigit() */
26 #if TRANSFORMS_SUPPORTED
29 * Lossless image transformation routines. These routines work on DCT
30 * coefficient arrays and thus do not require any lossy decompression
31 * or recompression of the image.
32 * Thanks to Guido Vollbeding for the initial design and code of this feature,
33 * and to Ben Jackson for introducing the cropping feature.
35 * Horizontal flipping is done in-place, using a single top-to-bottom
36 * pass through the virtual source array. It will thus be much the
37 * fastest option for images larger than main memory.
39 * The other routines require a set of destination virtual arrays, so they
40 * need twice as much memory as jpegtran normally does. The destination
41 * arrays are always written in normal scan order (top to bottom) because
42 * the virtual array manager expects this. The source arrays will be scanned
43 * in the corresponding order, which means multiple passes through the source
44 * arrays for most of the transforms. That could result in much thrashing
45 * if the image is larger than main memory.
47 * If cropping or trimming is involved, the destination arrays may be smaller
48 * than the source arrays. Note it is not possible to do horizontal flip
49 * in-place when a nonzero Y crop offset is specified, since we'd have to move
50 * data from one block row to another but the virtual array manager doesn't
51 * guarantee we can touch more than one row at a time. So in that case,
52 * we have to use a separate destination array.
54 * Some notes about the operating environment of the individual transform
56 * 1. Both the source and destination virtual arrays are allocated from the
57 * source JPEG object, and therefore should be manipulated by calling the
58 * source's memory manager.
59 * 2. The destination's component count should be used. It may be smaller
60 * than the source's when forcing to grayscale.
61 * 3. Likewise the destination's sampling factors should be used. When
62 * forcing to grayscale the destination's sampling factors will be all 1,
63 * and we may as well take that as the effective iMCU size.
64 * 4. When "trim" is in effect, the destination's dimensions will be the
65 * trimmed values but the source's will be untrimmed.
66 * 5. When "crop" is in effect, the destination's dimensions will be the
67 * cropped values but the source's will be uncropped. Each transform
68 * routine is responsible for picking up source data starting at the
69 * correct X and Y offset for the crop region. (The X and Y offsets
70 * passed to the transform routines are measured in iMCU blocks of the
72 * 6. All the routines assume that the source and destination buffers are
73 * padded out to a full iMCU boundary. This is true, although for the
74 * source buffer it is an undocumented property of jdcoefct.c.
79 do_crop (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
80 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
81 jvirt_barray_ptr
*src_coef_arrays
,
82 jvirt_barray_ptr
*dst_coef_arrays
)
83 /* Crop. This is only used when no rotate/flip is requested with the crop. */
85 JDIMENSION dst_blk_y
, x_crop_blocks
, y_crop_blocks
;
87 JBLOCKARRAY src_buffer
, dst_buffer
;
88 jpeg_component_info
*compptr
;
90 /* We simply have to copy the right amount of data (the destination's
91 * image size) starting at the given X and Y offsets in the source.
93 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
94 compptr
= dstinfo
->comp_info
+ ci
;
95 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
96 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
97 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
98 dst_blk_y
+= compptr
->v_samp_factor
) {
99 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
100 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
101 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
102 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
103 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
104 dst_blk_y
+ y_crop_blocks
,
105 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
106 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
107 jcopy_block_row(src_buffer
[offset_y
] + x_crop_blocks
,
108 dst_buffer
[offset_y
],
109 compptr
->width_in_blocks
);
117 do_crop_ext (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
118 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
119 jvirt_barray_ptr
*src_coef_arrays
,
120 jvirt_barray_ptr
*dst_coef_arrays
)
121 /* Crop. This is only used when no rotate/flip is requested with the crop.
122 * Extension: If the destination size is larger than the source, we fill in
123 * the extra area with zero (neutral gray). Note we also have to zero partial
124 * iMCUs at the right and bottom edge of the source image area in this case.
127 JDIMENSION MCU_cols
, MCU_rows
, comp_width
, comp_height
;
128 JDIMENSION dst_blk_y
, x_crop_blocks
, y_crop_blocks
;
130 JBLOCKARRAY src_buffer
, dst_buffer
;
131 jpeg_component_info
*compptr
;
133 MCU_cols
= srcinfo
->output_width
/
134 (dstinfo
->max_h_samp_factor
* dstinfo
->min_DCT_h_scaled_size
);
135 MCU_rows
= srcinfo
->output_height
/
136 (dstinfo
->max_v_samp_factor
* dstinfo
->min_DCT_v_scaled_size
);
138 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
139 compptr
= dstinfo
->comp_info
+ ci
;
140 comp_width
= MCU_cols
* compptr
->h_samp_factor
;
141 comp_height
= MCU_rows
* compptr
->v_samp_factor
;
142 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
143 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
144 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
145 dst_blk_y
+= compptr
->v_samp_factor
) {
146 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
147 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
148 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
149 if (dstinfo
->jpeg_height
> srcinfo
->output_height
) {
150 if (dst_blk_y
< y_crop_blocks
||
151 dst_blk_y
>= comp_height
+ y_crop_blocks
) {
152 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
153 FMEMZERO(dst_buffer
[offset_y
],
154 compptr
->width_in_blocks
* SIZEOF(JBLOCK
));
158 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
159 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
160 dst_blk_y
- y_crop_blocks
,
161 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
163 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
164 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
165 dst_blk_y
+ y_crop_blocks
,
166 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
168 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
169 if (dstinfo
->jpeg_width
> srcinfo
->output_width
) {
170 if (x_crop_blocks
> 0) {
171 FMEMZERO(dst_buffer
[offset_y
],
172 x_crop_blocks
* SIZEOF(JBLOCK
));
174 jcopy_block_row(src_buffer
[offset_y
],
175 dst_buffer
[offset_y
] + x_crop_blocks
,
177 if (compptr
->width_in_blocks
> comp_width
+ x_crop_blocks
) {
178 FMEMZERO(dst_buffer
[offset_y
] +
179 comp_width
+ x_crop_blocks
,
180 (compptr
->width_in_blocks
-
181 comp_width
- x_crop_blocks
) * SIZEOF(JBLOCK
));
184 jcopy_block_row(src_buffer
[offset_y
] + x_crop_blocks
,
185 dst_buffer
[offset_y
],
186 compptr
->width_in_blocks
);
195 do_wipe (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
196 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
197 jvirt_barray_ptr
*src_coef_arrays
,
198 JDIMENSION drop_width
, JDIMENSION drop_height
)
199 /* Wipe - drop content of specified area, fill with zero (neutral gray) */
201 JDIMENSION x_wipe_blocks
, wipe_width
;
202 JDIMENSION y_wipe_blocks
, wipe_bottom
;
205 jpeg_component_info
*compptr
;
207 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
208 compptr
= dstinfo
->comp_info
+ ci
;
209 x_wipe_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
210 wipe_width
= drop_width
* compptr
->h_samp_factor
;
211 y_wipe_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
212 wipe_bottom
= drop_height
* compptr
->v_samp_factor
+ y_wipe_blocks
;
213 for (; y_wipe_blocks
< wipe_bottom
;
214 y_wipe_blocks
+= compptr
->v_samp_factor
) {
215 buffer
= (*srcinfo
->mem
->access_virt_barray
)
216 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
], y_wipe_blocks
,
217 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
218 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
219 FMEMZERO(buffer
[offset_y
] + x_wipe_blocks
,
220 wipe_width
* SIZEOF(JBLOCK
));
228 do_flatten (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
229 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
230 jvirt_barray_ptr
*src_coef_arrays
,
231 JDIMENSION drop_width
, JDIMENSION drop_height
)
232 /* Flatten - drop content of specified area, similar to wipe,
233 * but fill with average of adjacent blocks, instead of zero.
236 JDIMENSION x_wipe_blocks
, wipe_width
, wipe_right
;
237 JDIMENSION y_wipe_blocks
, wipe_bottom
, blk_x
;
238 int ci
, offset_y
, dc_left_value
, dc_right_value
, average
;
240 jpeg_component_info
*compptr
;
242 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
243 compptr
= dstinfo
->comp_info
+ ci
;
244 x_wipe_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
245 wipe_width
= drop_width
* compptr
->h_samp_factor
;
246 wipe_right
= wipe_width
+ x_wipe_blocks
;
247 y_wipe_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
248 wipe_bottom
= drop_height
* compptr
->v_samp_factor
+ y_wipe_blocks
;
249 for (; y_wipe_blocks
< wipe_bottom
;
250 y_wipe_blocks
+= compptr
->v_samp_factor
) {
251 buffer
= (*srcinfo
->mem
->access_virt_barray
)
252 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
], y_wipe_blocks
,
253 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
254 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
255 FMEMZERO(buffer
[offset_y
] + x_wipe_blocks
,
256 wipe_width
* SIZEOF(JBLOCK
));
257 if (x_wipe_blocks
> 0) {
258 dc_left_value
= buffer
[offset_y
][x_wipe_blocks
- 1][0];
259 if (wipe_right
< compptr
->width_in_blocks
) {
260 dc_right_value
= buffer
[offset_y
][wipe_right
][0];
261 average
= (dc_left_value
+ dc_right_value
) >> 1;
263 average
= dc_left_value
;
265 } else if (wipe_right
< compptr
->width_in_blocks
) {
266 average
= buffer
[offset_y
][wipe_right
][0];
268 for (blk_x
= x_wipe_blocks
; blk_x
< wipe_right
; blk_x
++) {
269 buffer
[offset_y
][blk_x
][0] = (JCOEF
) average
;
278 do_flip_h_no_crop (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
279 JDIMENSION x_crop_offset
,
280 jvirt_barray_ptr
*src_coef_arrays
)
281 /* Horizontal flip; done in-place, so no separate dest array is required.
282 * NB: this only works when y_crop_offset is zero.
285 JDIMENSION MCU_cols
, comp_width
, blk_x
, blk_y
, x_crop_blocks
;
290 jpeg_component_info
*compptr
;
292 /* Horizontal mirroring of DCT blocks is accomplished by swapping
293 * pairs of blocks in-place. Within a DCT block, we perform horizontal
294 * mirroring by changing the signs of odd-numbered columns.
295 * Partial iMCUs at the right edge are left untouched.
297 MCU_cols
= srcinfo
->output_width
/
298 (dstinfo
->max_h_samp_factor
* dstinfo
->min_DCT_h_scaled_size
);
300 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
301 compptr
= dstinfo
->comp_info
+ ci
;
302 comp_width
= MCU_cols
* compptr
->h_samp_factor
;
303 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
304 for (blk_y
= 0; blk_y
< compptr
->height_in_blocks
;
305 blk_y
+= compptr
->v_samp_factor
) {
306 buffer
= (*srcinfo
->mem
->access_virt_barray
)
307 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
], blk_y
,
308 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
309 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
310 /* Do the mirroring */
311 for (blk_x
= 0; blk_x
* 2 < comp_width
; blk_x
++) {
312 ptr1
= buffer
[offset_y
][blk_x
];
313 ptr2
= buffer
[offset_y
][comp_width
- blk_x
- 1];
314 /* this unrolled loop doesn't need to know which row it's on... */
315 for (k
= 0; k
< DCTSIZE2
; k
+= 2) {
316 temp1
= *ptr1
; /* swap even column */
320 temp1
= *ptr1
; /* swap odd column with sign change */
326 if (x_crop_blocks
> 0) {
327 /* Now left-justify the portion of the data to be kept.
328 * We can't use a single jcopy_block_row() call because that routine
329 * depends on memcpy(), whose behavior is unspecified for overlapping
330 * source and destination areas. Sigh.
332 for (blk_x
= 0; blk_x
< compptr
->width_in_blocks
; blk_x
++) {
333 jcopy_block_row(buffer
[offset_y
] + blk_x
+ x_crop_blocks
,
334 buffer
[offset_y
] + blk_x
,
345 do_flip_h (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
346 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
347 jvirt_barray_ptr
*src_coef_arrays
,
348 jvirt_barray_ptr
*dst_coef_arrays
)
349 /* Horizontal flip in general cropping case */
351 JDIMENSION MCU_cols
, comp_width
, dst_blk_x
, dst_blk_y
;
352 JDIMENSION x_crop_blocks
, y_crop_blocks
;
354 JBLOCKARRAY src_buffer
, dst_buffer
;
355 JBLOCKROW src_row_ptr
, dst_row_ptr
;
356 JCOEFPTR src_ptr
, dst_ptr
;
357 jpeg_component_info
*compptr
;
359 /* Here we must output into a separate array because we can't touch
360 * different rows of a single virtual array simultaneously. Otherwise,
361 * this is essentially the same as the routine above.
363 MCU_cols
= srcinfo
->output_width
/
364 (dstinfo
->max_h_samp_factor
* dstinfo
->min_DCT_h_scaled_size
);
366 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
367 compptr
= dstinfo
->comp_info
+ ci
;
368 comp_width
= MCU_cols
* compptr
->h_samp_factor
;
369 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
370 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
371 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
372 dst_blk_y
+= compptr
->v_samp_factor
) {
373 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
374 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
375 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
376 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
377 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
378 dst_blk_y
+ y_crop_blocks
,
379 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
380 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
381 dst_row_ptr
= dst_buffer
[offset_y
];
382 src_row_ptr
= src_buffer
[offset_y
];
383 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
; dst_blk_x
++) {
384 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
385 /* Do the mirrorable blocks */
386 dst_ptr
= dst_row_ptr
[dst_blk_x
];
387 src_ptr
= src_row_ptr
[comp_width
- x_crop_blocks
- dst_blk_x
- 1];
388 /* this unrolled loop doesn't need to know which row it's on... */
389 for (k
= 0; k
< DCTSIZE2
; k
+= 2) {
390 *dst_ptr
++ = *src_ptr
++; /* copy even column */
391 *dst_ptr
++ = - *src_ptr
++; /* copy odd column with sign change */
394 /* Copy last partial block(s) verbatim */
395 jcopy_block_row(src_row_ptr
+ dst_blk_x
+ x_crop_blocks
,
396 dst_row_ptr
+ dst_blk_x
,
407 do_flip_v (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
408 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
409 jvirt_barray_ptr
*src_coef_arrays
,
410 jvirt_barray_ptr
*dst_coef_arrays
)
413 JDIMENSION MCU_rows
, comp_height
, dst_blk_x
, dst_blk_y
;
414 JDIMENSION x_crop_blocks
, y_crop_blocks
;
415 int ci
, i
, j
, offset_y
;
416 JBLOCKARRAY src_buffer
, dst_buffer
;
417 JBLOCKROW src_row_ptr
, dst_row_ptr
;
418 JCOEFPTR src_ptr
, dst_ptr
;
419 jpeg_component_info
*compptr
;
421 /* We output into a separate array because we can't touch different
422 * rows of the source virtual array simultaneously. Otherwise, this
423 * is a pretty straightforward analog of horizontal flip.
424 * Within a DCT block, vertical mirroring is done by changing the signs
425 * of odd-numbered rows.
426 * Partial iMCUs at the bottom edge are copied verbatim.
428 MCU_rows
= srcinfo
->output_height
/
429 (dstinfo
->max_v_samp_factor
* dstinfo
->min_DCT_v_scaled_size
);
431 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
432 compptr
= dstinfo
->comp_info
+ ci
;
433 comp_height
= MCU_rows
* compptr
->v_samp_factor
;
434 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
435 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
436 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
437 dst_blk_y
+= compptr
->v_samp_factor
) {
438 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
439 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
440 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
441 if (y_crop_blocks
+ dst_blk_y
< comp_height
) {
442 /* Row is within the mirrorable area. */
443 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
444 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
445 comp_height
- y_crop_blocks
- dst_blk_y
-
446 (JDIMENSION
) compptr
->v_samp_factor
,
447 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
449 /* Bottom-edge blocks will be copied verbatim. */
450 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
451 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
452 dst_blk_y
+ y_crop_blocks
,
453 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
455 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
456 if (y_crop_blocks
+ dst_blk_y
< comp_height
) {
457 /* Row is within the mirrorable area. */
458 dst_row_ptr
= dst_buffer
[offset_y
];
459 src_row_ptr
= src_buffer
[compptr
->v_samp_factor
- offset_y
- 1];
460 src_row_ptr
+= x_crop_blocks
;
461 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
;
463 dst_ptr
= dst_row_ptr
[dst_blk_x
];
464 src_ptr
= src_row_ptr
[dst_blk_x
];
465 for (i
= 0; i
< DCTSIZE
; i
+= 2) {
467 for (j
= 0; j
< DCTSIZE
; j
++)
468 *dst_ptr
++ = *src_ptr
++;
469 /* copy odd row with sign change */
470 for (j
= 0; j
< DCTSIZE
; j
++)
471 *dst_ptr
++ = - *src_ptr
++;
475 /* Just copy row verbatim. */
476 jcopy_block_row(src_buffer
[offset_y
] + x_crop_blocks
,
477 dst_buffer
[offset_y
],
478 compptr
->width_in_blocks
);
487 do_transpose (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
488 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
489 jvirt_barray_ptr
*src_coef_arrays
,
490 jvirt_barray_ptr
*dst_coef_arrays
)
491 /* Transpose source into destination */
493 JDIMENSION dst_blk_x
, dst_blk_y
, x_crop_blocks
, y_crop_blocks
;
494 int ci
, i
, j
, offset_x
, offset_y
;
495 JBLOCKARRAY src_buffer
, dst_buffer
;
496 JCOEFPTR src_ptr
, dst_ptr
;
497 jpeg_component_info
*compptr
;
499 /* Transposing pixels within a block just requires transposing the
501 * Partial iMCUs at the edges require no special treatment; we simply
502 * process all the available DCT blocks for every component.
504 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
505 compptr
= dstinfo
->comp_info
+ ci
;
506 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
507 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
508 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
509 dst_blk_y
+= compptr
->v_samp_factor
) {
510 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
511 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
512 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
513 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
514 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
;
515 dst_blk_x
+= compptr
->h_samp_factor
) {
516 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
517 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
518 dst_blk_x
+ x_crop_blocks
,
519 (JDIMENSION
) compptr
->h_samp_factor
, FALSE
);
520 for (offset_x
= 0; offset_x
< compptr
->h_samp_factor
; offset_x
++) {
521 dst_ptr
= dst_buffer
[offset_y
][dst_blk_x
+ offset_x
];
522 src_ptr
= src_buffer
[offset_x
][dst_blk_y
+ offset_y
+ y_crop_blocks
];
523 for (i
= 0; i
< DCTSIZE
; i
++)
524 for (j
= 0; j
< DCTSIZE
; j
++)
525 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
535 do_rot_90 (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
536 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
537 jvirt_barray_ptr
*src_coef_arrays
,
538 jvirt_barray_ptr
*dst_coef_arrays
)
539 /* 90 degree rotation is equivalent to
540 * 1. Transposing the image;
541 * 2. Horizontal mirroring.
542 * These two steps are merged into a single processing routine.
545 JDIMENSION MCU_cols
, comp_width
, dst_blk_x
, dst_blk_y
;
546 JDIMENSION x_crop_blocks
, y_crop_blocks
;
547 int ci
, i
, j
, offset_x
, offset_y
;
548 JBLOCKARRAY src_buffer
, dst_buffer
;
549 JCOEFPTR src_ptr
, dst_ptr
;
550 jpeg_component_info
*compptr
;
552 /* Because of the horizontal mirror step, we can't process partial iMCUs
553 * at the (output) right edge properly. They just get transposed and
556 MCU_cols
= srcinfo
->output_height
/
557 (dstinfo
->max_h_samp_factor
* dstinfo
->min_DCT_h_scaled_size
);
559 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
560 compptr
= dstinfo
->comp_info
+ ci
;
561 comp_width
= MCU_cols
* compptr
->h_samp_factor
;
562 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
563 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
564 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
565 dst_blk_y
+= compptr
->v_samp_factor
) {
566 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
567 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
568 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
569 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
570 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
;
571 dst_blk_x
+= compptr
->h_samp_factor
) {
572 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
573 /* Block is within the mirrorable area. */
574 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
575 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
576 comp_width
- x_crop_blocks
- dst_blk_x
-
577 (JDIMENSION
) compptr
->h_samp_factor
,
578 (JDIMENSION
) compptr
->h_samp_factor
, FALSE
);
580 /* Edge blocks are transposed but not mirrored. */
581 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
582 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
583 dst_blk_x
+ x_crop_blocks
,
584 (JDIMENSION
) compptr
->h_samp_factor
, FALSE
);
586 for (offset_x
= 0; offset_x
< compptr
->h_samp_factor
; offset_x
++) {
587 dst_ptr
= dst_buffer
[offset_y
][dst_blk_x
+ offset_x
];
588 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
589 /* Block is within the mirrorable area. */
590 src_ptr
= src_buffer
[compptr
->h_samp_factor
- offset_x
- 1]
591 [dst_blk_y
+ offset_y
+ y_crop_blocks
];
592 for (i
= 0; i
< DCTSIZE
; i
++) {
593 for (j
= 0; j
< DCTSIZE
; j
++)
594 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
596 for (j
= 0; j
< DCTSIZE
; j
++)
597 dst_ptr
[j
*DCTSIZE
+i
] = -src_ptr
[i
*DCTSIZE
+j
];
600 /* Edge blocks are transposed but not mirrored. */
601 src_ptr
= src_buffer
[offset_x
]
602 [dst_blk_y
+ offset_y
+ y_crop_blocks
];
603 for (i
= 0; i
< DCTSIZE
; i
++)
604 for (j
= 0; j
< DCTSIZE
; j
++)
605 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
616 do_rot_270 (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
617 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
618 jvirt_barray_ptr
*src_coef_arrays
,
619 jvirt_barray_ptr
*dst_coef_arrays
)
620 /* 270 degree rotation is equivalent to
621 * 1. Horizontal mirroring;
622 * 2. Transposing the image.
623 * These two steps are merged into a single processing routine.
626 JDIMENSION MCU_rows
, comp_height
, dst_blk_x
, dst_blk_y
;
627 JDIMENSION x_crop_blocks
, y_crop_blocks
;
628 int ci
, i
, j
, offset_x
, offset_y
;
629 JBLOCKARRAY src_buffer
, dst_buffer
;
630 JCOEFPTR src_ptr
, dst_ptr
;
631 jpeg_component_info
*compptr
;
633 /* Because of the horizontal mirror step, we can't process partial iMCUs
634 * at the (output) bottom edge properly. They just get transposed and
637 MCU_rows
= srcinfo
->output_width
/
638 (dstinfo
->max_v_samp_factor
* dstinfo
->min_DCT_v_scaled_size
);
640 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
641 compptr
= dstinfo
->comp_info
+ ci
;
642 comp_height
= MCU_rows
* compptr
->v_samp_factor
;
643 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
644 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
645 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
646 dst_blk_y
+= compptr
->v_samp_factor
) {
647 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
648 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
649 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
650 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
651 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
;
652 dst_blk_x
+= compptr
->h_samp_factor
) {
653 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
654 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
655 dst_blk_x
+ x_crop_blocks
,
656 (JDIMENSION
) compptr
->h_samp_factor
, FALSE
);
657 for (offset_x
= 0; offset_x
< compptr
->h_samp_factor
; offset_x
++) {
658 dst_ptr
= dst_buffer
[offset_y
][dst_blk_x
+ offset_x
];
659 if (y_crop_blocks
+ dst_blk_y
< comp_height
) {
660 /* Block is within the mirrorable area. */
661 src_ptr
= src_buffer
[offset_x
]
662 [comp_height
- y_crop_blocks
- dst_blk_y
- offset_y
- 1];
663 for (i
= 0; i
< DCTSIZE
; i
++) {
664 for (j
= 0; j
< DCTSIZE
; j
++) {
665 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
667 dst_ptr
[j
*DCTSIZE
+i
] = -src_ptr
[i
*DCTSIZE
+j
];
671 /* Edge blocks are transposed but not mirrored. */
672 src_ptr
= src_buffer
[offset_x
]
673 [dst_blk_y
+ offset_y
+ y_crop_blocks
];
674 for (i
= 0; i
< DCTSIZE
; i
++)
675 for (j
= 0; j
< DCTSIZE
; j
++)
676 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
687 do_rot_180 (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
688 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
689 jvirt_barray_ptr
*src_coef_arrays
,
690 jvirt_barray_ptr
*dst_coef_arrays
)
691 /* 180 degree rotation is equivalent to
692 * 1. Vertical mirroring;
693 * 2. Horizontal mirroring.
694 * These two steps are merged into a single processing routine.
697 JDIMENSION MCU_cols
, MCU_rows
, comp_width
, comp_height
, dst_blk_x
, dst_blk_y
;
698 JDIMENSION x_crop_blocks
, y_crop_blocks
;
699 int ci
, i
, j
, offset_y
;
700 JBLOCKARRAY src_buffer
, dst_buffer
;
701 JBLOCKROW src_row_ptr
, dst_row_ptr
;
702 JCOEFPTR src_ptr
, dst_ptr
;
703 jpeg_component_info
*compptr
;
705 MCU_cols
= srcinfo
->output_width
/
706 (dstinfo
->max_h_samp_factor
* dstinfo
->min_DCT_h_scaled_size
);
707 MCU_rows
= srcinfo
->output_height
/
708 (dstinfo
->max_v_samp_factor
* dstinfo
->min_DCT_v_scaled_size
);
710 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
711 compptr
= dstinfo
->comp_info
+ ci
;
712 comp_width
= MCU_cols
* compptr
->h_samp_factor
;
713 comp_height
= MCU_rows
* compptr
->v_samp_factor
;
714 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
715 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
716 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
717 dst_blk_y
+= compptr
->v_samp_factor
) {
718 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
719 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
720 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
721 if (y_crop_blocks
+ dst_blk_y
< comp_height
) {
722 /* Row is within the vertically mirrorable area. */
723 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
724 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
725 comp_height
- y_crop_blocks
- dst_blk_y
-
726 (JDIMENSION
) compptr
->v_samp_factor
,
727 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
729 /* Bottom-edge rows are only mirrored horizontally. */
730 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
731 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
732 dst_blk_y
+ y_crop_blocks
,
733 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
735 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
736 dst_row_ptr
= dst_buffer
[offset_y
];
737 if (y_crop_blocks
+ dst_blk_y
< comp_height
) {
738 /* Row is within the mirrorable area. */
739 src_row_ptr
= src_buffer
[compptr
->v_samp_factor
- offset_y
- 1];
740 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
; dst_blk_x
++) {
741 dst_ptr
= dst_row_ptr
[dst_blk_x
];
742 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
743 /* Process the blocks that can be mirrored both ways. */
744 src_ptr
= src_row_ptr
[comp_width
- x_crop_blocks
- dst_blk_x
- 1];
745 for (i
= 0; i
< DCTSIZE
; i
+= 2) {
746 /* For even row, negate every odd column. */
747 for (j
= 0; j
< DCTSIZE
; j
+= 2) {
748 *dst_ptr
++ = *src_ptr
++;
749 *dst_ptr
++ = - *src_ptr
++;
751 /* For odd row, negate every even column. */
752 for (j
= 0; j
< DCTSIZE
; j
+= 2) {
753 *dst_ptr
++ = - *src_ptr
++;
754 *dst_ptr
++ = *src_ptr
++;
758 /* Any remaining right-edge blocks are only mirrored vertically. */
759 src_ptr
= src_row_ptr
[x_crop_blocks
+ dst_blk_x
];
760 for (i
= 0; i
< DCTSIZE
; i
+= 2) {
761 for (j
= 0; j
< DCTSIZE
; j
++)
762 *dst_ptr
++ = *src_ptr
++;
763 for (j
= 0; j
< DCTSIZE
; j
++)
764 *dst_ptr
++ = - *src_ptr
++;
769 /* Remaining rows are just mirrored horizontally. */
770 src_row_ptr
= src_buffer
[offset_y
];
771 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
; dst_blk_x
++) {
772 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
773 /* Process the blocks that can be mirrored. */
774 dst_ptr
= dst_row_ptr
[dst_blk_x
];
775 src_ptr
= src_row_ptr
[comp_width
- x_crop_blocks
- dst_blk_x
- 1];
776 for (i
= 0; i
< DCTSIZE2
; i
+= 2) {
777 *dst_ptr
++ = *src_ptr
++;
778 *dst_ptr
++ = - *src_ptr
++;
781 /* Any remaining right-edge blocks are only copied. */
782 jcopy_block_row(src_row_ptr
+ dst_blk_x
+ x_crop_blocks
,
783 dst_row_ptr
+ dst_blk_x
,
795 do_transverse (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
796 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
797 jvirt_barray_ptr
*src_coef_arrays
,
798 jvirt_barray_ptr
*dst_coef_arrays
)
799 /* Transverse transpose is equivalent to
800 * 1. 180 degree rotation;
803 * 1. Horizontal mirroring;
805 * 3. Horizontal mirroring.
806 * These steps are merged into a single processing routine.
809 JDIMENSION MCU_cols
, MCU_rows
, comp_width
, comp_height
, dst_blk_x
, dst_blk_y
;
810 JDIMENSION x_crop_blocks
, y_crop_blocks
;
811 int ci
, i
, j
, offset_x
, offset_y
;
812 JBLOCKARRAY src_buffer
, dst_buffer
;
813 JCOEFPTR src_ptr
, dst_ptr
;
814 jpeg_component_info
*compptr
;
816 MCU_cols
= srcinfo
->output_height
/
817 (dstinfo
->max_h_samp_factor
* dstinfo
->min_DCT_h_scaled_size
);
818 MCU_rows
= srcinfo
->output_width
/
819 (dstinfo
->max_v_samp_factor
* dstinfo
->min_DCT_v_scaled_size
);
821 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
822 compptr
= dstinfo
->comp_info
+ ci
;
823 comp_width
= MCU_cols
* compptr
->h_samp_factor
;
824 comp_height
= MCU_rows
* compptr
->v_samp_factor
;
825 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
826 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
827 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
828 dst_blk_y
+= compptr
->v_samp_factor
) {
829 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
830 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
831 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
832 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
833 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
;
834 dst_blk_x
+= compptr
->h_samp_factor
) {
835 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
836 /* Block is within the mirrorable area. */
837 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
838 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
839 comp_width
- x_crop_blocks
- dst_blk_x
-
840 (JDIMENSION
) compptr
->h_samp_factor
,
841 (JDIMENSION
) compptr
->h_samp_factor
, FALSE
);
843 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
844 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
845 dst_blk_x
+ x_crop_blocks
,
846 (JDIMENSION
) compptr
->h_samp_factor
, FALSE
);
848 for (offset_x
= 0; offset_x
< compptr
->h_samp_factor
; offset_x
++) {
849 dst_ptr
= dst_buffer
[offset_y
][dst_blk_x
+ offset_x
];
850 if (y_crop_blocks
+ dst_blk_y
< comp_height
) {
851 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
852 /* Block is within the mirrorable area. */
853 src_ptr
= src_buffer
[compptr
->h_samp_factor
- offset_x
- 1]
854 [comp_height
- y_crop_blocks
- dst_blk_y
- offset_y
- 1];
855 for (i
= 0; i
< DCTSIZE
; i
++) {
856 for (j
= 0; j
< DCTSIZE
; j
++) {
857 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
859 dst_ptr
[j
*DCTSIZE
+i
] = -src_ptr
[i
*DCTSIZE
+j
];
862 for (j
= 0; j
< DCTSIZE
; j
++) {
863 dst_ptr
[j
*DCTSIZE
+i
] = -src_ptr
[i
*DCTSIZE
+j
];
865 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
869 /* Right-edge blocks are mirrored in y only */
870 src_ptr
= src_buffer
[offset_x
]
871 [comp_height
- y_crop_blocks
- dst_blk_y
- offset_y
- 1];
872 for (i
= 0; i
< DCTSIZE
; i
++) {
873 for (j
= 0; j
< DCTSIZE
; j
++) {
874 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
876 dst_ptr
[j
*DCTSIZE
+i
] = -src_ptr
[i
*DCTSIZE
+j
];
881 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
882 /* Bottom-edge blocks are mirrored in x only */
883 src_ptr
= src_buffer
[compptr
->h_samp_factor
- offset_x
- 1]
884 [dst_blk_y
+ offset_y
+ y_crop_blocks
];
885 for (i
= 0; i
< DCTSIZE
; i
++) {
886 for (j
= 0; j
< DCTSIZE
; j
++)
887 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
889 for (j
= 0; j
< DCTSIZE
; j
++)
890 dst_ptr
[j
*DCTSIZE
+i
] = -src_ptr
[i
*DCTSIZE
+j
];
893 /* At lower right corner, just transpose, no mirroring */
894 src_ptr
= src_buffer
[offset_x
]
895 [dst_blk_y
+ offset_y
+ y_crop_blocks
];
896 for (i
= 0; i
< DCTSIZE
; i
++)
897 for (j
= 0; j
< DCTSIZE
; j
++)
898 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
909 /* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec.
910 * Returns TRUE if valid integer found, FALSE if not.
911 * *strptr is advanced over the digit string, and *result is set to its value.
915 jt_read_integer (const char ** strptr
, JDIMENSION
* result
)
917 const char * ptr
= *strptr
;
920 for (; isdigit(*ptr
); ptr
++) {
921 val
= val
* 10 + (JDIMENSION
) (*ptr
- '0');
925 return FALSE
; /* oops, no digits */
931 /* Parse a crop specification (written in X11 geometry style).
932 * The routine returns TRUE if the spec string is valid, FALSE if not.
934 * The crop spec string should have the format
935 * <width>[f]x<height>[f]{+-}<xoffset>{+-}<yoffset>
936 * where width, height, xoffset, and yoffset are unsigned integers.
937 * Each of the elements can be omitted to indicate a default value.
938 * (A weakness of this style is that it is not possible to omit xoffset
939 * while specifying yoffset, since they look alike.)
941 * This code is loosely based on XParseGeometry from the X11 distribution.
945 jtransform_parse_crop_spec (jpeg_transform_info
*info
, const char *spec
)
948 info
->crop_width_set
= JCROP_UNSET
;
949 info
->crop_height_set
= JCROP_UNSET
;
950 info
->crop_xoffset_set
= JCROP_UNSET
;
951 info
->crop_yoffset_set
= JCROP_UNSET
;
953 if (isdigit(*spec
)) {
955 if (! jt_read_integer(&spec
, &info
->crop_width
))
957 if (*spec
== 'f' || *spec
== 'F') {
959 info
->crop_width_set
= JCROP_FORCE
;
961 info
->crop_width_set
= JCROP_POS
;
963 if (*spec
== 'x' || *spec
== 'X') {
966 if (! jt_read_integer(&spec
, &info
->crop_height
))
968 if (*spec
== 'f' || *spec
== 'F') {
970 info
->crop_height_set
= JCROP_FORCE
;
972 info
->crop_height_set
= JCROP_POS
;
974 if (*spec
== '+' || *spec
== '-') {
976 info
->crop_xoffset_set
= (*spec
== '-') ? JCROP_NEG
: JCROP_POS
;
978 if (! jt_read_integer(&spec
, &info
->crop_xoffset
))
981 if (*spec
== '+' || *spec
== '-') {
983 info
->crop_yoffset_set
= (*spec
== '-') ? JCROP_NEG
: JCROP_POS
;
985 if (! jt_read_integer(&spec
, &info
->crop_yoffset
))
988 /* We had better have gotten to the end of the string. */
996 /* Trim off any partial iMCUs on the indicated destination edge */
999 trim_right_edge (jpeg_transform_info
*info
, JDIMENSION full_width
)
1001 JDIMENSION MCU_cols
;
1003 MCU_cols
= info
->output_width
/ info
->iMCU_sample_width
;
1004 if (MCU_cols
> 0 && info
->x_crop_offset
+ MCU_cols
==
1005 full_width
/ info
->iMCU_sample_width
)
1006 info
->output_width
= MCU_cols
* info
->iMCU_sample_width
;
1010 trim_bottom_edge (jpeg_transform_info
*info
, JDIMENSION full_height
)
1012 JDIMENSION MCU_rows
;
1014 MCU_rows
= info
->output_height
/ info
->iMCU_sample_height
;
1015 if (MCU_rows
> 0 && info
->y_crop_offset
+ MCU_rows
==
1016 full_height
/ info
->iMCU_sample_height
)
1017 info
->output_height
= MCU_rows
* info
->iMCU_sample_height
;
1021 /* Request any required workspace.
1023 * This routine figures out the size that the output image will be
1024 * (which implies that all the transform parameters must be set before
1027 * We allocate the workspace virtual arrays from the source decompression
1028 * object, so that all the arrays (both the original data and the workspace)
1029 * will be taken into account while making memory management decisions.
1030 * Hence, this routine must be called after jpeg_read_header (which reads
1031 * the image dimensions) and before jpeg_read_coefficients (which realizes
1032 * the source's virtual arrays).
1034 * This function returns FALSE right away if -perfect is given
1035 * and transformation is not perfect. Otherwise returns TRUE.
1039 jtransform_request_workspace (j_decompress_ptr srcinfo
,
1040 jpeg_transform_info
*info
)
1042 jvirt_barray_ptr
*coef_arrays
;
1043 boolean need_workspace
, transpose_it
;
1044 jpeg_component_info
*compptr
;
1045 JDIMENSION xoffset
, yoffset
;
1046 JDIMENSION width_in_iMCUs
, height_in_iMCUs
;
1047 JDIMENSION width_in_blocks
, height_in_blocks
;
1048 int ci
, h_samp_factor
, v_samp_factor
;
1050 /* Determine number of components in output image */
1051 if (info
->force_grayscale
&&
1052 (srcinfo
->jpeg_color_space
== JCS_YCbCr
||
1053 srcinfo
->jpeg_color_space
== JCS_BG_YCC
) &&
1054 srcinfo
->num_components
== 3)
1055 /* We'll only process the first component */
1056 info
->num_components
= 1;
1058 /* Process all the components */
1059 info
->num_components
= srcinfo
->num_components
;
1061 /* Compute output image dimensions and related values. */
1062 jpeg_core_output_dimensions(srcinfo
);
1064 /* Return right away if -perfect is given and transformation is not perfect.
1066 if (info
->perfect
) {
1067 if (info
->num_components
== 1) {
1068 if (!jtransform_perfect_transform(srcinfo
->output_width
,
1069 srcinfo
->output_height
,
1070 srcinfo
->min_DCT_h_scaled_size
,
1071 srcinfo
->min_DCT_v_scaled_size
,
1075 if (!jtransform_perfect_transform(srcinfo
->output_width
,
1076 srcinfo
->output_height
,
1077 srcinfo
->max_h_samp_factor
* srcinfo
->min_DCT_h_scaled_size
,
1078 srcinfo
->max_v_samp_factor
* srcinfo
->min_DCT_v_scaled_size
,
1084 /* If there is only one output component, force the iMCU size to be 1;
1085 * else use the source iMCU size. (This allows us to do the right thing
1086 * when reducing color to grayscale, and also provides a handy way of
1087 * cleaning up "funny" grayscale images whose sampling factors are not 1x1.)
1089 switch (info
->transform
) {
1090 case JXFORM_TRANSPOSE
:
1091 case JXFORM_TRANSVERSE
:
1093 case JXFORM_ROT_270
:
1094 info
->output_width
= srcinfo
->output_height
;
1095 info
->output_height
= srcinfo
->output_width
;
1096 if (info
->num_components
== 1) {
1097 info
->iMCU_sample_width
= srcinfo
->min_DCT_v_scaled_size
;
1098 info
->iMCU_sample_height
= srcinfo
->min_DCT_h_scaled_size
;
1100 info
->iMCU_sample_width
=
1101 srcinfo
->max_v_samp_factor
* srcinfo
->min_DCT_v_scaled_size
;
1102 info
->iMCU_sample_height
=
1103 srcinfo
->max_h_samp_factor
* srcinfo
->min_DCT_h_scaled_size
;
1107 info
->output_width
= srcinfo
->output_width
;
1108 info
->output_height
= srcinfo
->output_height
;
1109 if (info
->num_components
== 1) {
1110 info
->iMCU_sample_width
= srcinfo
->min_DCT_h_scaled_size
;
1111 info
->iMCU_sample_height
= srcinfo
->min_DCT_v_scaled_size
;
1113 info
->iMCU_sample_width
=
1114 srcinfo
->max_h_samp_factor
* srcinfo
->min_DCT_h_scaled_size
;
1115 info
->iMCU_sample_height
=
1116 srcinfo
->max_v_samp_factor
* srcinfo
->min_DCT_v_scaled_size
;
1121 /* If cropping has been requested, compute the crop area's position and
1122 * dimensions, ensuring that its upper left corner falls at an iMCU boundary.
1125 /* Insert default values for unset crop parameters */
1126 if (info
->crop_xoffset_set
== JCROP_UNSET
)
1127 info
->crop_xoffset
= 0; /* default to +0 */
1128 if (info
->crop_yoffset_set
== JCROP_UNSET
)
1129 info
->crop_yoffset
= 0; /* default to +0 */
1130 if (info
->crop_width_set
== JCROP_UNSET
) {
1131 if (info
->crop_xoffset
>= info
->output_width
)
1132 ERREXIT(srcinfo
, JERR_BAD_CROP_SPEC
);
1133 info
->crop_width
= info
->output_width
- info
->crop_xoffset
;
1135 /* Check for crop extension */
1136 if (info
->crop_width
> info
->output_width
) {
1137 /* Crop extension does not work when transforming! */
1138 if (info
->transform
!= JXFORM_NONE
||
1139 info
->crop_xoffset
>= info
->crop_width
||
1140 info
->crop_xoffset
> info
->crop_width
- info
->output_width
)
1141 ERREXIT(srcinfo
, JERR_BAD_CROP_SPEC
);
1143 if (info
->crop_xoffset
>= info
->output_width
||
1144 info
->crop_width
<= 0 ||
1145 info
->crop_xoffset
> info
->output_width
- info
->crop_width
)
1146 ERREXIT(srcinfo
, JERR_BAD_CROP_SPEC
);
1149 if (info
->crop_height_set
== JCROP_UNSET
) {
1150 if (info
->crop_yoffset
>= info
->output_height
)
1151 ERREXIT(srcinfo
, JERR_BAD_CROP_SPEC
);
1152 info
->crop_height
= info
->output_height
- info
->crop_yoffset
;
1154 /* Check for crop extension */
1155 if (info
->crop_height
> info
->output_height
) {
1156 /* Crop extension does not work when transforming! */
1157 if (info
->transform
!= JXFORM_NONE
||
1158 info
->crop_yoffset
>= info
->crop_height
||
1159 info
->crop_yoffset
> info
->crop_height
- info
->output_height
)
1160 ERREXIT(srcinfo
, JERR_BAD_CROP_SPEC
);
1162 if (info
->crop_yoffset
>= info
->output_height
||
1163 info
->crop_height
<= 0 ||
1164 info
->crop_yoffset
> info
->output_height
- info
->crop_height
)
1165 ERREXIT(srcinfo
, JERR_BAD_CROP_SPEC
);
1168 /* Convert negative crop offsets into regular offsets */
1169 if (info
->crop_xoffset_set
!= JCROP_NEG
)
1170 xoffset
= info
->crop_xoffset
;
1171 else if (info
->crop_width
> info
->output_width
) /* crop extension */
1172 xoffset
= info
->crop_width
- info
->output_width
- info
->crop_xoffset
;
1174 xoffset
= info
->output_width
- info
->crop_width
- info
->crop_xoffset
;
1175 if (info
->crop_yoffset_set
!= JCROP_NEG
)
1176 yoffset
= info
->crop_yoffset
;
1177 else if (info
->crop_height
> info
->output_height
) /* crop extension */
1178 yoffset
= info
->crop_height
- info
->output_height
- info
->crop_yoffset
;
1180 yoffset
= info
->output_height
- info
->crop_height
- info
->crop_yoffset
;
1181 /* Now adjust so that upper left corner falls at an iMCU boundary */
1182 if (info
->transform
== JXFORM_WIPE
) {
1183 /* Ensure the effective wipe region will cover the requested */
1184 info
->drop_width
= (JDIMENSION
) jdiv_round_up
1185 ((long) (info
->crop_width
+ (xoffset
% info
->iMCU_sample_width
)),
1186 (long) info
->iMCU_sample_width
);
1187 info
->drop_height
= (JDIMENSION
) jdiv_round_up
1188 ((long) (info
->crop_height
+ (yoffset
% info
->iMCU_sample_height
)),
1189 (long) info
->iMCU_sample_height
);
1191 /* Ensure the effective crop region will cover the requested */
1192 if (info
->crop_width_set
== JCROP_FORCE
||
1193 info
->crop_width
> info
->output_width
)
1194 info
->output_width
= info
->crop_width
;
1196 info
->output_width
=
1197 info
->crop_width
+ (xoffset
% info
->iMCU_sample_width
);
1198 if (info
->crop_height_set
== JCROP_FORCE
||
1199 info
->crop_height
> info
->output_height
)
1200 info
->output_height
= info
->crop_height
;
1202 info
->output_height
=
1203 info
->crop_height
+ (yoffset
% info
->iMCU_sample_height
);
1205 /* Save x/y offsets measured in iMCUs */
1206 info
->x_crop_offset
= xoffset
/ info
->iMCU_sample_width
;
1207 info
->y_crop_offset
= yoffset
/ info
->iMCU_sample_height
;
1209 info
->x_crop_offset
= 0;
1210 info
->y_crop_offset
= 0;
1213 /* Figure out whether we need workspace arrays,
1214 * and if so whether they are transposed relative to the source.
1216 need_workspace
= FALSE
;
1217 transpose_it
= FALSE
;
1218 switch (info
->transform
) {
1220 if (info
->x_crop_offset
!= 0 || info
->y_crop_offset
!= 0 ||
1221 info
->output_width
> srcinfo
->output_width
||
1222 info
->output_height
> srcinfo
->output_height
)
1223 need_workspace
= TRUE
;
1224 /* No workspace needed if neither cropping nor transforming */
1228 trim_right_edge(info
, srcinfo
->output_width
);
1229 if (info
->y_crop_offset
!= 0)
1230 need_workspace
= TRUE
;
1231 /* do_flip_h_no_crop doesn't need a workspace array */
1235 trim_bottom_edge(info
, srcinfo
->output_height
);
1236 /* Need workspace arrays having same dimensions as source image. */
1237 need_workspace
= TRUE
;
1239 case JXFORM_TRANSPOSE
:
1240 /* transpose does NOT have to trim anything */
1241 /* Need workspace arrays having transposed dimensions. */
1242 need_workspace
= TRUE
;
1243 transpose_it
= TRUE
;
1245 case JXFORM_TRANSVERSE
:
1247 trim_right_edge(info
, srcinfo
->output_height
);
1248 trim_bottom_edge(info
, srcinfo
->output_width
);
1250 /* Need workspace arrays having transposed dimensions. */
1251 need_workspace
= TRUE
;
1252 transpose_it
= TRUE
;
1256 trim_right_edge(info
, srcinfo
->output_height
);
1257 /* Need workspace arrays having transposed dimensions. */
1258 need_workspace
= TRUE
;
1259 transpose_it
= TRUE
;
1261 case JXFORM_ROT_180
:
1263 trim_right_edge(info
, srcinfo
->output_width
);
1264 trim_bottom_edge(info
, srcinfo
->output_height
);
1266 /* Need workspace arrays having same dimensions as source image. */
1267 need_workspace
= TRUE
;
1269 case JXFORM_ROT_270
:
1271 trim_bottom_edge(info
, srcinfo
->output_width
);
1272 /* Need workspace arrays having transposed dimensions. */
1273 need_workspace
= TRUE
;
1274 transpose_it
= TRUE
;
1280 /* Allocate workspace if needed.
1281 * Note that we allocate arrays padded out to the next iMCU boundary,
1282 * so that transform routines need not worry about missing edge blocks.
1284 if (need_workspace
) {
1285 coef_arrays
= (jvirt_barray_ptr
*)
1286 (*srcinfo
->mem
->alloc_small
) ((j_common_ptr
) srcinfo
, JPOOL_IMAGE
,
1287 SIZEOF(jvirt_barray_ptr
) * info
->num_components
);
1288 width_in_iMCUs
= (JDIMENSION
)
1289 jdiv_round_up((long) info
->output_width
,
1290 (long) info
->iMCU_sample_width
);
1291 height_in_iMCUs
= (JDIMENSION
)
1292 jdiv_round_up((long) info
->output_height
,
1293 (long) info
->iMCU_sample_height
);
1294 for (ci
= 0; ci
< info
->num_components
; ci
++) {
1295 compptr
= srcinfo
->comp_info
+ ci
;
1296 if (info
->num_components
== 1) {
1297 /* we're going to force samp factors to 1x1 in this case */
1298 h_samp_factor
= v_samp_factor
= 1;
1299 } else if (transpose_it
) {
1300 h_samp_factor
= compptr
->v_samp_factor
;
1301 v_samp_factor
= compptr
->h_samp_factor
;
1303 h_samp_factor
= compptr
->h_samp_factor
;
1304 v_samp_factor
= compptr
->v_samp_factor
;
1306 width_in_blocks
= width_in_iMCUs
* h_samp_factor
;
1307 height_in_blocks
= height_in_iMCUs
* v_samp_factor
;
1308 coef_arrays
[ci
] = (*srcinfo
->mem
->request_virt_barray
)
1309 ((j_common_ptr
) srcinfo
, JPOOL_IMAGE
, FALSE
,
1310 width_in_blocks
, height_in_blocks
, (JDIMENSION
) v_samp_factor
);
1312 info
->workspace_coef_arrays
= coef_arrays
;
1314 info
->workspace_coef_arrays
= NULL
;
1320 /* Transpose destination image parameters */
1323 transpose_critical_parameters (j_compress_ptr dstinfo
)
1325 int tblno
, i
, j
, ci
, itemp
;
1326 jpeg_component_info
*compptr
;
1327 JQUANT_TBL
*qtblptr
;
1331 /* Transpose image dimensions */
1332 jtemp
= dstinfo
->image_width
;
1333 dstinfo
->image_width
= dstinfo
->image_height
;
1334 dstinfo
->image_height
= jtemp
;
1335 itemp
= dstinfo
->min_DCT_h_scaled_size
;
1336 dstinfo
->min_DCT_h_scaled_size
= dstinfo
->min_DCT_v_scaled_size
;
1337 dstinfo
->min_DCT_v_scaled_size
= itemp
;
1339 /* Transpose sampling factors */
1340 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
1341 compptr
= dstinfo
->comp_info
+ ci
;
1342 itemp
= compptr
->h_samp_factor
;
1343 compptr
->h_samp_factor
= compptr
->v_samp_factor
;
1344 compptr
->v_samp_factor
= itemp
;
1347 /* Transpose quantization tables */
1348 for (tblno
= 0; tblno
< NUM_QUANT_TBLS
; tblno
++) {
1349 qtblptr
= dstinfo
->quant_tbl_ptrs
[tblno
];
1350 if (qtblptr
!= NULL
) {
1351 for (i
= 0; i
< DCTSIZE
; i
++) {
1352 for (j
= 0; j
< i
; j
++) {
1353 qtemp
= qtblptr
->quantval
[i
*DCTSIZE
+j
];
1354 qtblptr
->quantval
[i
*DCTSIZE
+j
] = qtblptr
->quantval
[j
*DCTSIZE
+i
];
1355 qtblptr
->quantval
[j
*DCTSIZE
+i
] = qtemp
;
1363 /* Adjust Exif image parameters.
1365 * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible.
1369 adjust_exif_parameters (JOCTET FAR
* data
, unsigned int length
,
1370 JDIMENSION new_width
, JDIMENSION new_height
)
1372 boolean is_motorola
; /* Flag for byte order */
1373 unsigned int number_of_tags
, tagnum
;
1374 unsigned int firstoffset
, offset
;
1375 JDIMENSION new_value
;
1377 if (length
< 12) return; /* Length of an IFD entry */
1379 /* Discover byte order */
1380 if (GETJOCTET(data
[0]) == 0x49 && GETJOCTET(data
[1]) == 0x49)
1381 is_motorola
= FALSE
;
1382 else if (GETJOCTET(data
[0]) == 0x4D && GETJOCTET(data
[1]) == 0x4D)
1387 /* Check Tag Mark */
1389 if (GETJOCTET(data
[2]) != 0) return;
1390 if (GETJOCTET(data
[3]) != 0x2A) return;
1392 if (GETJOCTET(data
[3]) != 0) return;
1393 if (GETJOCTET(data
[2]) != 0x2A) return;
1396 /* Get first IFD offset (offset to IFD0) */
1398 if (GETJOCTET(data
[4]) != 0) return;
1399 if (GETJOCTET(data
[5]) != 0) return;
1400 firstoffset
= GETJOCTET(data
[6]);
1402 firstoffset
+= GETJOCTET(data
[7]);
1404 if (GETJOCTET(data
[7]) != 0) return;
1405 if (GETJOCTET(data
[6]) != 0) return;
1406 firstoffset
= GETJOCTET(data
[5]);
1408 firstoffset
+= GETJOCTET(data
[4]);
1410 if (firstoffset
> length
- 2) return; /* check end of data segment */
1412 /* Get the number of directory entries contained in this IFD */
1414 number_of_tags
= GETJOCTET(data
[firstoffset
]);
1415 number_of_tags
<<= 8;
1416 number_of_tags
+= GETJOCTET(data
[firstoffset
+1]);
1418 number_of_tags
= GETJOCTET(data
[firstoffset
+1]);
1419 number_of_tags
<<= 8;
1420 number_of_tags
+= GETJOCTET(data
[firstoffset
]);
1422 if (number_of_tags
== 0) return;
1425 /* Search for ExifSubIFD offset Tag in IFD0 */
1427 if (firstoffset
> length
- 12) return; /* check end of data segment */
1428 /* Get Tag number */
1430 tagnum
= GETJOCTET(data
[firstoffset
]);
1432 tagnum
+= GETJOCTET(data
[firstoffset
+1]);
1434 tagnum
= GETJOCTET(data
[firstoffset
+1]);
1436 tagnum
+= GETJOCTET(data
[firstoffset
]);
1438 if (tagnum
== 0x8769) break; /* found ExifSubIFD offset Tag */
1439 if (--number_of_tags
== 0) return;
1443 /* Get the ExifSubIFD offset */
1445 if (GETJOCTET(data
[firstoffset
+8]) != 0) return;
1446 if (GETJOCTET(data
[firstoffset
+9]) != 0) return;
1447 offset
= GETJOCTET(data
[firstoffset
+10]);
1449 offset
+= GETJOCTET(data
[firstoffset
+11]);
1451 if (GETJOCTET(data
[firstoffset
+11]) != 0) return;
1452 if (GETJOCTET(data
[firstoffset
+10]) != 0) return;
1453 offset
= GETJOCTET(data
[firstoffset
+9]);
1455 offset
+= GETJOCTET(data
[firstoffset
+8]);
1457 if (offset
> length
- 2) return; /* check end of data segment */
1459 /* Get the number of directory entries contained in this SubIFD */
1461 number_of_tags
= GETJOCTET(data
[offset
]);
1462 number_of_tags
<<= 8;
1463 number_of_tags
+= GETJOCTET(data
[offset
+1]);
1465 number_of_tags
= GETJOCTET(data
[offset
+1]);
1466 number_of_tags
<<= 8;
1467 number_of_tags
+= GETJOCTET(data
[offset
]);
1469 if (number_of_tags
< 2) return;
1472 /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */
1474 if (offset
> length
- 12) return; /* check end of data segment */
1475 /* Get Tag number */
1477 tagnum
= GETJOCTET(data
[offset
]);
1479 tagnum
+= GETJOCTET(data
[offset
+1]);
1481 tagnum
= GETJOCTET(data
[offset
+1]);
1483 tagnum
+= GETJOCTET(data
[offset
]);
1485 if (tagnum
== 0xA002 || tagnum
== 0xA003) {
1486 if (tagnum
== 0xA002)
1487 new_value
= new_width
; /* ExifImageWidth Tag */
1489 new_value
= new_height
; /* ExifImageHeight Tag */
1491 data
[offset
+2] = 0; /* Format = unsigned long (4 octets) */
1493 data
[offset
+4] = 0; /* Number Of Components = 1 */
1499 data
[offset
+10] = (JOCTET
)((new_value
>> 8) & 0xFF);
1500 data
[offset
+11] = (JOCTET
)(new_value
& 0xFF);
1502 data
[offset
+2] = 4; /* Format = unsigned long (4 octets) */
1504 data
[offset
+4] = 1; /* Number Of Components = 1 */
1508 data
[offset
+8] = (JOCTET
)(new_value
& 0xFF);
1509 data
[offset
+9] = (JOCTET
)((new_value
>> 8) & 0xFF);
1510 data
[offset
+10] = 0;
1511 data
[offset
+11] = 0;
1515 } while (--number_of_tags
);
1519 /* Adjust output image parameters as needed.
1521 * This must be called after jpeg_copy_critical_parameters()
1522 * and before jpeg_write_coefficients().
1524 * The return value is the set of virtual coefficient arrays to be written
1525 * (either the ones allocated by jtransform_request_workspace, or the
1526 * original source data arrays). The caller will need to pass this value
1527 * to jpeg_write_coefficients().
1530 GLOBAL(jvirt_barray_ptr
*)
1531 jtransform_adjust_parameters (j_decompress_ptr srcinfo
,
1532 j_compress_ptr dstinfo
,
1533 jvirt_barray_ptr
*src_coef_arrays
,
1534 jpeg_transform_info
*info
)
1536 /* If force-to-grayscale is requested, adjust destination parameters */
1537 if (info
->force_grayscale
) {
1538 /* First, ensure we have YCC or grayscale data, and that the source's
1539 * Y channel is full resolution. (No reasonable person would make Y
1540 * be less than full resolution, so actually coping with that case
1541 * isn't worth extra code space. But we check it to avoid crashing.)
1543 if ((((dstinfo
->jpeg_color_space
== JCS_YCbCr
||
1544 dstinfo
->jpeg_color_space
== JCS_BG_YCC
) &&
1545 dstinfo
->num_components
== 3) ||
1546 (dstinfo
->jpeg_color_space
== JCS_GRAYSCALE
&&
1547 dstinfo
->num_components
== 1)) &&
1548 srcinfo
->comp_info
[0].h_samp_factor
== srcinfo
->max_h_samp_factor
&&
1549 srcinfo
->comp_info
[0].v_samp_factor
== srcinfo
->max_v_samp_factor
) {
1550 /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
1551 * properly. Among other things, it sets the target h_samp_factor &
1552 * v_samp_factor to 1, which typically won't match the source.
1553 * We have to preserve the source's quantization table number, however.
1555 int sv_quant_tbl_no
= dstinfo
->comp_info
[0].quant_tbl_no
;
1556 jpeg_set_colorspace(dstinfo
, JCS_GRAYSCALE
);
1557 dstinfo
->comp_info
[0].quant_tbl_no
= sv_quant_tbl_no
;
1559 /* Sorry, can't do it */
1560 ERREXIT(dstinfo
, JERR_CONVERSION_NOTIMPL
);
1562 } else if (info
->num_components
== 1) {
1563 /* For a single-component source, we force the destination sampling factors
1564 * to 1x1, with or without force_grayscale. This is useful because some
1565 * decoders choke on grayscale images with other sampling factors.
1567 dstinfo
->comp_info
[0].h_samp_factor
= 1;
1568 dstinfo
->comp_info
[0].v_samp_factor
= 1;
1571 /* Correct the destination's image dimensions as necessary
1572 * for rotate/flip, resize, and crop operations.
1574 dstinfo
->jpeg_width
= info
->output_width
;
1575 dstinfo
->jpeg_height
= info
->output_height
;
1577 /* Transpose destination image parameters */
1578 switch (info
->transform
) {
1579 case JXFORM_TRANSPOSE
:
1580 case JXFORM_TRANSVERSE
:
1582 case JXFORM_ROT_270
:
1583 transpose_critical_parameters(dstinfo
);
1589 /* Adjust Exif properties */
1590 if (srcinfo
->marker_list
!= NULL
&&
1591 srcinfo
->marker_list
->marker
== JPEG_APP0
+1 &&
1592 srcinfo
->marker_list
->data_length
>= 6 &&
1593 GETJOCTET(srcinfo
->marker_list
->data
[0]) == 0x45 &&
1594 GETJOCTET(srcinfo
->marker_list
->data
[1]) == 0x78 &&
1595 GETJOCTET(srcinfo
->marker_list
->data
[2]) == 0x69 &&
1596 GETJOCTET(srcinfo
->marker_list
->data
[3]) == 0x66 &&
1597 GETJOCTET(srcinfo
->marker_list
->data
[4]) == 0 &&
1598 GETJOCTET(srcinfo
->marker_list
->data
[5]) == 0) {
1599 /* Suppress output of JFIF marker */
1600 dstinfo
->write_JFIF_header
= FALSE
;
1601 /* Adjust Exif image parameters */
1602 if (dstinfo
->jpeg_width
!= srcinfo
->image_width
||
1603 dstinfo
->jpeg_height
!= srcinfo
->image_height
)
1604 /* Align data segment to start of TIFF structure for parsing */
1605 adjust_exif_parameters(srcinfo
->marker_list
->data
+ 6,
1606 srcinfo
->marker_list
->data_length
- 6,
1607 dstinfo
->jpeg_width
, dstinfo
->jpeg_height
);
1610 /* Return the appropriate output data set */
1611 if (info
->workspace_coef_arrays
!= NULL
)
1612 return info
->workspace_coef_arrays
;
1613 return src_coef_arrays
;
1617 /* Execute the actual transformation, if any.
1619 * This must be called *after* jpeg_write_coefficients, because it depends
1620 * on jpeg_write_coefficients to have computed subsidiary values such as
1621 * the per-component width and height fields in the destination object.
1623 * Note that some transformations will modify the source data arrays!
1627 jtransform_execute_transform (j_decompress_ptr srcinfo
,
1628 j_compress_ptr dstinfo
,
1629 jvirt_barray_ptr
*src_coef_arrays
,
1630 jpeg_transform_info
*info
)
1632 jvirt_barray_ptr
*dst_coef_arrays
= info
->workspace_coef_arrays
;
1634 /* Note: conditions tested here should match those in switch statement
1635 * in jtransform_request_workspace()
1637 switch (info
->transform
) {
1639 if (info
->output_width
> srcinfo
->output_width
||
1640 info
->output_height
> srcinfo
->output_height
)
1641 do_crop_ext(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1642 src_coef_arrays
, dst_coef_arrays
);
1643 else if (info
->x_crop_offset
!= 0 || info
->y_crop_offset
!= 0)
1644 do_crop(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1645 src_coef_arrays
, dst_coef_arrays
);
1648 if (info
->y_crop_offset
!= 0)
1649 do_flip_h(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1650 src_coef_arrays
, dst_coef_arrays
);
1652 do_flip_h_no_crop(srcinfo
, dstinfo
, info
->x_crop_offset
,
1656 do_flip_v(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1657 src_coef_arrays
, dst_coef_arrays
);
1659 case JXFORM_TRANSPOSE
:
1660 do_transpose(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1661 src_coef_arrays
, dst_coef_arrays
);
1663 case JXFORM_TRANSVERSE
:
1664 do_transverse(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1665 src_coef_arrays
, dst_coef_arrays
);
1668 do_rot_90(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1669 src_coef_arrays
, dst_coef_arrays
);
1671 case JXFORM_ROT_180
:
1672 do_rot_180(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1673 src_coef_arrays
, dst_coef_arrays
);
1675 case JXFORM_ROT_270
:
1676 do_rot_270(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1677 src_coef_arrays
, dst_coef_arrays
);
1680 if (info
->crop_width_set
!= JCROP_FORCE
)
1681 do_wipe(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1682 src_coef_arrays
, info
->drop_width
, info
->drop_height
);
1684 do_flatten(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1685 src_coef_arrays
, info
->drop_width
, info
->drop_height
);
1690 /* jtransform_perfect_transform
1692 * Determine whether lossless transformation is perfectly
1693 * possible for a specified image and transformation.
1696 * image_width, image_height: source image dimensions.
1697 * MCU_width, MCU_height: pixel dimensions of MCU.
1698 * transform: transformation identifier.
1699 * Parameter sources from initialized jpeg_struct
1700 * (after reading source header):
1701 * image_width = cinfo.image_width
1702 * image_height = cinfo.image_height
1703 * MCU_width = cinfo.max_h_samp_factor * cinfo.block_size
1704 * MCU_height = cinfo.max_v_samp_factor * cinfo.block_size
1706 * TRUE = perfect transformation possible
1707 * FALSE = perfect transformation not possible
1708 * (may use custom action then)
1712 jtransform_perfect_transform(JDIMENSION image_width
, JDIMENSION image_height
,
1713 int MCU_width
, int MCU_height
,
1714 JXFORM_CODE transform
)
1716 boolean result
= TRUE
; /* initialize TRUE */
1718 switch (transform
) {
1720 case JXFORM_ROT_270
:
1721 if (image_width
% (JDIMENSION
) MCU_width
)
1726 if (image_height
% (JDIMENSION
) MCU_height
)
1729 case JXFORM_TRANSVERSE
:
1730 case JXFORM_ROT_180
:
1731 if (image_width
% (JDIMENSION
) MCU_width
)
1733 if (image_height
% (JDIMENSION
) MCU_height
)
1743 #endif /* TRANSFORMS_SUPPORTED */
1746 /* Setup decompression object to save desired markers in memory.
1747 * This must be called before jpeg_read_header() to have the desired effect.
1751 jcopy_markers_setup (j_decompress_ptr srcinfo
, JCOPY_OPTION option
)
1753 #ifdef SAVE_MARKERS_SUPPORTED
1756 /* Save comments except under NONE option */
1757 if (option
!= JCOPYOPT_NONE
) {
1758 jpeg_save_markers(srcinfo
, JPEG_COM
, 0xFFFF);
1760 /* Save all types of APPn markers iff ALL option */
1761 if (option
== JCOPYOPT_ALL
) {
1762 for (m
= 0; m
< 16; m
++)
1763 jpeg_save_markers(srcinfo
, JPEG_APP0
+ m
, 0xFFFF);
1765 #endif /* SAVE_MARKERS_SUPPORTED */
1768 /* Copy markers saved in the given source object to the destination object.
1769 * This should be called just after jpeg_start_compress() or
1770 * jpeg_write_coefficients().
1771 * Note that those routines will have written the SOI, and also the
1772 * JFIF APP0 or Adobe APP14 markers if selected.
1776 jcopy_markers_execute (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
1777 JCOPY_OPTION option
)
1779 jpeg_saved_marker_ptr marker
;
1781 /* In the current implementation, we don't actually need to examine the
1782 * option flag here; we just copy everything that got saved.
1783 * But to avoid confusion, we do not output JFIF and Adobe APP14 markers
1784 * if the encoder library already wrote one.
1786 for (marker
= srcinfo
->marker_list
; marker
!= NULL
; marker
= marker
->next
) {
1787 if (dstinfo
->write_JFIF_header
&&
1788 marker
->marker
== JPEG_APP0
&&
1789 marker
->data_length
>= 5 &&
1790 GETJOCTET(marker
->data
[0]) == 0x4A &&
1791 GETJOCTET(marker
->data
[1]) == 0x46 &&
1792 GETJOCTET(marker
->data
[2]) == 0x49 &&
1793 GETJOCTET(marker
->data
[3]) == 0x46 &&
1794 GETJOCTET(marker
->data
[4]) == 0)
1795 continue; /* reject duplicate JFIF */
1796 if (dstinfo
->write_Adobe_marker
&&
1797 marker
->marker
== JPEG_APP0
+14 &&
1798 marker
->data_length
>= 5 &&
1799 GETJOCTET(marker
->data
[0]) == 0x41 &&
1800 GETJOCTET(marker
->data
[1]) == 0x64 &&
1801 GETJOCTET(marker
->data
[2]) == 0x6F &&
1802 GETJOCTET(marker
->data
[3]) == 0x62 &&
1803 GETJOCTET(marker
->data
[4]) == 0x65)
1804 continue; /* reject duplicate Adobe */
1805 #ifdef NEED_FAR_POINTERS
1806 /* We could use jpeg_write_marker if the data weren't FAR... */
1809 jpeg_write_m_header(dstinfo
, marker
->marker
, marker
->data_length
);
1810 for (i
= 0; i
< marker
->data_length
; i
++)
1811 jpeg_write_m_byte(dstinfo
, marker
->data
[i
]);
1814 jpeg_write_marker(dstinfo
, marker
->marker
,
1815 marker
->data
, marker
->data_length
);