4 * Copyright (C) 1997-2012, 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_flip_h_no_crop (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
118 JDIMENSION x_crop_offset
,
119 jvirt_barray_ptr
*src_coef_arrays
)
120 /* Horizontal flip; done in-place, so no separate dest array is required.
121 * NB: this only works when y_crop_offset is zero.
124 JDIMENSION MCU_cols
, comp_width
, blk_x
, blk_y
, x_crop_blocks
;
129 jpeg_component_info
*compptr
;
131 /* Horizontal mirroring of DCT blocks is accomplished by swapping
132 * pairs of blocks in-place. Within a DCT block, we perform horizontal
133 * mirroring by changing the signs of odd-numbered columns.
134 * Partial iMCUs at the right edge are left untouched.
136 MCU_cols
= srcinfo
->output_width
/
137 (dstinfo
->max_h_samp_factor
* dstinfo
->min_DCT_h_scaled_size
);
139 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
140 compptr
= dstinfo
->comp_info
+ ci
;
141 comp_width
= MCU_cols
* compptr
->h_samp_factor
;
142 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
143 for (blk_y
= 0; blk_y
< compptr
->height_in_blocks
;
144 blk_y
+= compptr
->v_samp_factor
) {
145 buffer
= (*srcinfo
->mem
->access_virt_barray
)
146 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
], blk_y
,
147 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
148 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
149 /* Do the mirroring */
150 for (blk_x
= 0; blk_x
* 2 < comp_width
; blk_x
++) {
151 ptr1
= buffer
[offset_y
][blk_x
];
152 ptr2
= buffer
[offset_y
][comp_width
- blk_x
- 1];
153 /* this unrolled loop doesn't need to know which row it's on... */
154 for (k
= 0; k
< DCTSIZE2
; k
+= 2) {
155 temp1
= *ptr1
; /* swap even column */
159 temp1
= *ptr1
; /* swap odd column with sign change */
165 if (x_crop_blocks
> 0) {
166 /* Now left-justify the portion of the data to be kept.
167 * We can't use a single jcopy_block_row() call because that routine
168 * depends on memcpy(), whose behavior is unspecified for overlapping
169 * source and destination areas. Sigh.
171 for (blk_x
= 0; blk_x
< compptr
->width_in_blocks
; blk_x
++) {
172 jcopy_block_row(buffer
[offset_y
] + blk_x
+ x_crop_blocks
,
173 buffer
[offset_y
] + blk_x
,
184 do_flip_h (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
185 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
186 jvirt_barray_ptr
*src_coef_arrays
,
187 jvirt_barray_ptr
*dst_coef_arrays
)
188 /* Horizontal flip in general cropping case */
190 JDIMENSION MCU_cols
, comp_width
, dst_blk_x
, dst_blk_y
;
191 JDIMENSION x_crop_blocks
, y_crop_blocks
;
193 JBLOCKARRAY src_buffer
, dst_buffer
;
194 JBLOCKROW src_row_ptr
, dst_row_ptr
;
195 JCOEFPTR src_ptr
, dst_ptr
;
196 jpeg_component_info
*compptr
;
198 /* Here we must output into a separate array because we can't touch
199 * different rows of a single virtual array simultaneously. Otherwise,
200 * this is essentially the same as the routine above.
202 MCU_cols
= srcinfo
->output_width
/
203 (dstinfo
->max_h_samp_factor
* dstinfo
->min_DCT_h_scaled_size
);
205 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
206 compptr
= dstinfo
->comp_info
+ ci
;
207 comp_width
= MCU_cols
* compptr
->h_samp_factor
;
208 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
209 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
210 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
211 dst_blk_y
+= compptr
->v_samp_factor
) {
212 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
213 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
214 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
215 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
216 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
217 dst_blk_y
+ y_crop_blocks
,
218 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
219 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
220 dst_row_ptr
= dst_buffer
[offset_y
];
221 src_row_ptr
= src_buffer
[offset_y
];
222 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
; dst_blk_x
++) {
223 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
224 /* Do the mirrorable blocks */
225 dst_ptr
= dst_row_ptr
[dst_blk_x
];
226 src_ptr
= src_row_ptr
[comp_width
- x_crop_blocks
- dst_blk_x
- 1];
227 /* this unrolled loop doesn't need to know which row it's on... */
228 for (k
= 0; k
< DCTSIZE2
; k
+= 2) {
229 *dst_ptr
++ = *src_ptr
++; /* copy even column */
230 *dst_ptr
++ = - *src_ptr
++; /* copy odd column with sign change */
233 /* Copy last partial block(s) verbatim */
234 jcopy_block_row(src_row_ptr
+ dst_blk_x
+ x_crop_blocks
,
235 dst_row_ptr
+ dst_blk_x
,
246 do_flip_v (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
247 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
248 jvirt_barray_ptr
*src_coef_arrays
,
249 jvirt_barray_ptr
*dst_coef_arrays
)
252 JDIMENSION MCU_rows
, comp_height
, dst_blk_x
, dst_blk_y
;
253 JDIMENSION x_crop_blocks
, y_crop_blocks
;
254 int ci
, i
, j
, offset_y
;
255 JBLOCKARRAY src_buffer
, dst_buffer
;
256 JBLOCKROW src_row_ptr
, dst_row_ptr
;
257 JCOEFPTR src_ptr
, dst_ptr
;
258 jpeg_component_info
*compptr
;
260 /* We output into a separate array because we can't touch different
261 * rows of the source virtual array simultaneously. Otherwise, this
262 * is a pretty straightforward analog of horizontal flip.
263 * Within a DCT block, vertical mirroring is done by changing the signs
264 * of odd-numbered rows.
265 * Partial iMCUs at the bottom edge are copied verbatim.
267 MCU_rows
= srcinfo
->output_height
/
268 (dstinfo
->max_v_samp_factor
* dstinfo
->min_DCT_v_scaled_size
);
270 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
271 compptr
= dstinfo
->comp_info
+ ci
;
272 comp_height
= MCU_rows
* compptr
->v_samp_factor
;
273 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
274 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
275 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
276 dst_blk_y
+= compptr
->v_samp_factor
) {
277 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
278 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
279 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
280 if (y_crop_blocks
+ dst_blk_y
< comp_height
) {
281 /* Row is within the mirrorable area. */
282 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
283 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
284 comp_height
- y_crop_blocks
- dst_blk_y
-
285 (JDIMENSION
) compptr
->v_samp_factor
,
286 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
288 /* Bottom-edge blocks will be copied verbatim. */
289 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
290 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
291 dst_blk_y
+ y_crop_blocks
,
292 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
294 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
295 if (y_crop_blocks
+ dst_blk_y
< comp_height
) {
296 /* Row is within the mirrorable area. */
297 dst_row_ptr
= dst_buffer
[offset_y
];
298 src_row_ptr
= src_buffer
[compptr
->v_samp_factor
- offset_y
- 1];
299 src_row_ptr
+= x_crop_blocks
;
300 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
;
302 dst_ptr
= dst_row_ptr
[dst_blk_x
];
303 src_ptr
= src_row_ptr
[dst_blk_x
];
304 for (i
= 0; i
< DCTSIZE
; i
+= 2) {
306 for (j
= 0; j
< DCTSIZE
; j
++)
307 *dst_ptr
++ = *src_ptr
++;
308 /* copy odd row with sign change */
309 for (j
= 0; j
< DCTSIZE
; j
++)
310 *dst_ptr
++ = - *src_ptr
++;
314 /* Just copy row verbatim. */
315 jcopy_block_row(src_buffer
[offset_y
] + x_crop_blocks
,
316 dst_buffer
[offset_y
],
317 compptr
->width_in_blocks
);
326 do_transpose (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
327 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
328 jvirt_barray_ptr
*src_coef_arrays
,
329 jvirt_barray_ptr
*dst_coef_arrays
)
330 /* Transpose source into destination */
332 JDIMENSION dst_blk_x
, dst_blk_y
, x_crop_blocks
, y_crop_blocks
;
333 int ci
, i
, j
, offset_x
, offset_y
;
334 JBLOCKARRAY src_buffer
, dst_buffer
;
335 JCOEFPTR src_ptr
, dst_ptr
;
336 jpeg_component_info
*compptr
;
338 /* Transposing pixels within a block just requires transposing the
340 * Partial iMCUs at the edges require no special treatment; we simply
341 * process all the available DCT blocks for every component.
343 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
344 compptr
= dstinfo
->comp_info
+ ci
;
345 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
346 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
347 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
348 dst_blk_y
+= compptr
->v_samp_factor
) {
349 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
350 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
351 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
352 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
353 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
;
354 dst_blk_x
+= compptr
->h_samp_factor
) {
355 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
356 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
357 dst_blk_x
+ x_crop_blocks
,
358 (JDIMENSION
) compptr
->h_samp_factor
, FALSE
);
359 for (offset_x
= 0; offset_x
< compptr
->h_samp_factor
; offset_x
++) {
360 dst_ptr
= dst_buffer
[offset_y
][dst_blk_x
+ offset_x
];
361 src_ptr
= src_buffer
[offset_x
][dst_blk_y
+ offset_y
+ y_crop_blocks
];
362 for (i
= 0; i
< DCTSIZE
; i
++)
363 for (j
= 0; j
< DCTSIZE
; j
++)
364 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
374 do_rot_90 (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
375 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
376 jvirt_barray_ptr
*src_coef_arrays
,
377 jvirt_barray_ptr
*dst_coef_arrays
)
378 /* 90 degree rotation is equivalent to
379 * 1. Transposing the image;
380 * 2. Horizontal mirroring.
381 * These two steps are merged into a single processing routine.
384 JDIMENSION MCU_cols
, comp_width
, dst_blk_x
, dst_blk_y
;
385 JDIMENSION x_crop_blocks
, y_crop_blocks
;
386 int ci
, i
, j
, offset_x
, offset_y
;
387 JBLOCKARRAY src_buffer
, dst_buffer
;
388 JCOEFPTR src_ptr
, dst_ptr
;
389 jpeg_component_info
*compptr
;
391 /* Because of the horizontal mirror step, we can't process partial iMCUs
392 * at the (output) right edge properly. They just get transposed and
395 MCU_cols
= srcinfo
->output_height
/
396 (dstinfo
->max_h_samp_factor
* dstinfo
->min_DCT_h_scaled_size
);
398 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
399 compptr
= dstinfo
->comp_info
+ ci
;
400 comp_width
= MCU_cols
* compptr
->h_samp_factor
;
401 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
402 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
403 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
404 dst_blk_y
+= compptr
->v_samp_factor
) {
405 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
406 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
407 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
408 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
409 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
;
410 dst_blk_x
+= compptr
->h_samp_factor
) {
411 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
412 /* Block is within the mirrorable area. */
413 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
414 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
415 comp_width
- x_crop_blocks
- dst_blk_x
-
416 (JDIMENSION
) compptr
->h_samp_factor
,
417 (JDIMENSION
) compptr
->h_samp_factor
, FALSE
);
419 /* Edge blocks are transposed but not mirrored. */
420 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
421 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
422 dst_blk_x
+ x_crop_blocks
,
423 (JDIMENSION
) compptr
->h_samp_factor
, FALSE
);
425 for (offset_x
= 0; offset_x
< compptr
->h_samp_factor
; offset_x
++) {
426 dst_ptr
= dst_buffer
[offset_y
][dst_blk_x
+ offset_x
];
427 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
428 /* Block is within the mirrorable area. */
429 src_ptr
= src_buffer
[compptr
->h_samp_factor
- offset_x
- 1]
430 [dst_blk_y
+ offset_y
+ y_crop_blocks
];
431 for (i
= 0; i
< DCTSIZE
; i
++) {
432 for (j
= 0; j
< DCTSIZE
; j
++)
433 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
435 for (j
= 0; j
< DCTSIZE
; j
++)
436 dst_ptr
[j
*DCTSIZE
+i
] = -src_ptr
[i
*DCTSIZE
+j
];
439 /* Edge blocks are transposed but not mirrored. */
440 src_ptr
= src_buffer
[offset_x
]
441 [dst_blk_y
+ offset_y
+ y_crop_blocks
];
442 for (i
= 0; i
< DCTSIZE
; i
++)
443 for (j
= 0; j
< DCTSIZE
; j
++)
444 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
455 do_rot_270 (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
456 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
457 jvirt_barray_ptr
*src_coef_arrays
,
458 jvirt_barray_ptr
*dst_coef_arrays
)
459 /* 270 degree rotation is equivalent to
460 * 1. Horizontal mirroring;
461 * 2. Transposing the image.
462 * These two steps are merged into a single processing routine.
465 JDIMENSION MCU_rows
, comp_height
, dst_blk_x
, dst_blk_y
;
466 JDIMENSION x_crop_blocks
, y_crop_blocks
;
467 int ci
, i
, j
, offset_x
, offset_y
;
468 JBLOCKARRAY src_buffer
, dst_buffer
;
469 JCOEFPTR src_ptr
, dst_ptr
;
470 jpeg_component_info
*compptr
;
472 /* Because of the horizontal mirror step, we can't process partial iMCUs
473 * at the (output) bottom edge properly. They just get transposed and
476 MCU_rows
= srcinfo
->output_width
/
477 (dstinfo
->max_v_samp_factor
* dstinfo
->min_DCT_v_scaled_size
);
479 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
480 compptr
= dstinfo
->comp_info
+ ci
;
481 comp_height
= MCU_rows
* compptr
->v_samp_factor
;
482 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
483 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
484 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
485 dst_blk_y
+= compptr
->v_samp_factor
) {
486 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
487 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
488 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
489 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
490 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
;
491 dst_blk_x
+= compptr
->h_samp_factor
) {
492 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
493 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
494 dst_blk_x
+ x_crop_blocks
,
495 (JDIMENSION
) compptr
->h_samp_factor
, FALSE
);
496 for (offset_x
= 0; offset_x
< compptr
->h_samp_factor
; offset_x
++) {
497 dst_ptr
= dst_buffer
[offset_y
][dst_blk_x
+ offset_x
];
498 if (y_crop_blocks
+ dst_blk_y
< comp_height
) {
499 /* Block is within the mirrorable area. */
500 src_ptr
= src_buffer
[offset_x
]
501 [comp_height
- y_crop_blocks
- dst_blk_y
- offset_y
- 1];
502 for (i
= 0; i
< DCTSIZE
; i
++) {
503 for (j
= 0; j
< DCTSIZE
; j
++) {
504 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
506 dst_ptr
[j
*DCTSIZE
+i
] = -src_ptr
[i
*DCTSIZE
+j
];
510 /* Edge blocks are transposed but not mirrored. */
511 src_ptr
= src_buffer
[offset_x
]
512 [dst_blk_y
+ offset_y
+ y_crop_blocks
];
513 for (i
= 0; i
< DCTSIZE
; i
++)
514 for (j
= 0; j
< DCTSIZE
; j
++)
515 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
526 do_rot_180 (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
527 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
528 jvirt_barray_ptr
*src_coef_arrays
,
529 jvirt_barray_ptr
*dst_coef_arrays
)
530 /* 180 degree rotation is equivalent to
531 * 1. Vertical mirroring;
532 * 2. Horizontal mirroring.
533 * These two steps are merged into a single processing routine.
536 JDIMENSION MCU_cols
, MCU_rows
, comp_width
, comp_height
, dst_blk_x
, dst_blk_y
;
537 JDIMENSION x_crop_blocks
, y_crop_blocks
;
538 int ci
, i
, j
, offset_y
;
539 JBLOCKARRAY src_buffer
, dst_buffer
;
540 JBLOCKROW src_row_ptr
, dst_row_ptr
;
541 JCOEFPTR src_ptr
, dst_ptr
;
542 jpeg_component_info
*compptr
;
544 MCU_cols
= srcinfo
->output_width
/
545 (dstinfo
->max_h_samp_factor
* dstinfo
->min_DCT_h_scaled_size
);
546 MCU_rows
= srcinfo
->output_height
/
547 (dstinfo
->max_v_samp_factor
* dstinfo
->min_DCT_v_scaled_size
);
549 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
550 compptr
= dstinfo
->comp_info
+ ci
;
551 comp_width
= MCU_cols
* compptr
->h_samp_factor
;
552 comp_height
= MCU_rows
* compptr
->v_samp_factor
;
553 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
554 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
555 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
556 dst_blk_y
+= compptr
->v_samp_factor
) {
557 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
558 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
559 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
560 if (y_crop_blocks
+ dst_blk_y
< comp_height
) {
561 /* Row is within the vertically mirrorable area. */
562 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
563 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
564 comp_height
- y_crop_blocks
- dst_blk_y
-
565 (JDIMENSION
) compptr
->v_samp_factor
,
566 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
568 /* Bottom-edge rows are only mirrored horizontally. */
569 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
570 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
571 dst_blk_y
+ y_crop_blocks
,
572 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
574 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
575 dst_row_ptr
= dst_buffer
[offset_y
];
576 if (y_crop_blocks
+ dst_blk_y
< comp_height
) {
577 /* Row is within the mirrorable area. */
578 src_row_ptr
= src_buffer
[compptr
->v_samp_factor
- offset_y
- 1];
579 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
; dst_blk_x
++) {
580 dst_ptr
= dst_row_ptr
[dst_blk_x
];
581 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
582 /* Process the blocks that can be mirrored both ways. */
583 src_ptr
= src_row_ptr
[comp_width
- x_crop_blocks
- dst_blk_x
- 1];
584 for (i
= 0; i
< DCTSIZE
; i
+= 2) {
585 /* For even row, negate every odd column. */
586 for (j
= 0; j
< DCTSIZE
; j
+= 2) {
587 *dst_ptr
++ = *src_ptr
++;
588 *dst_ptr
++ = - *src_ptr
++;
590 /* For odd row, negate every even column. */
591 for (j
= 0; j
< DCTSIZE
; j
+= 2) {
592 *dst_ptr
++ = - *src_ptr
++;
593 *dst_ptr
++ = *src_ptr
++;
597 /* Any remaining right-edge blocks are only mirrored vertically. */
598 src_ptr
= src_row_ptr
[x_crop_blocks
+ dst_blk_x
];
599 for (i
= 0; i
< DCTSIZE
; i
+= 2) {
600 for (j
= 0; j
< DCTSIZE
; j
++)
601 *dst_ptr
++ = *src_ptr
++;
602 for (j
= 0; j
< DCTSIZE
; j
++)
603 *dst_ptr
++ = - *src_ptr
++;
608 /* Remaining rows are just mirrored horizontally. */
609 src_row_ptr
= src_buffer
[offset_y
];
610 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
; dst_blk_x
++) {
611 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
612 /* Process the blocks that can be mirrored. */
613 dst_ptr
= dst_row_ptr
[dst_blk_x
];
614 src_ptr
= src_row_ptr
[comp_width
- x_crop_blocks
- dst_blk_x
- 1];
615 for (i
= 0; i
< DCTSIZE2
; i
+= 2) {
616 *dst_ptr
++ = *src_ptr
++;
617 *dst_ptr
++ = - *src_ptr
++;
620 /* Any remaining right-edge blocks are only copied. */
621 jcopy_block_row(src_row_ptr
+ dst_blk_x
+ x_crop_blocks
,
622 dst_row_ptr
+ dst_blk_x
,
634 do_transverse (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
635 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
636 jvirt_barray_ptr
*src_coef_arrays
,
637 jvirt_barray_ptr
*dst_coef_arrays
)
638 /* Transverse transpose is equivalent to
639 * 1. 180 degree rotation;
642 * 1. Horizontal mirroring;
644 * 3. Horizontal mirroring.
645 * These steps are merged into a single processing routine.
648 JDIMENSION MCU_cols
, MCU_rows
, comp_width
, comp_height
, dst_blk_x
, dst_blk_y
;
649 JDIMENSION x_crop_blocks
, y_crop_blocks
;
650 int ci
, i
, j
, offset_x
, offset_y
;
651 JBLOCKARRAY src_buffer
, dst_buffer
;
652 JCOEFPTR src_ptr
, dst_ptr
;
653 jpeg_component_info
*compptr
;
655 MCU_cols
= srcinfo
->output_height
/
656 (dstinfo
->max_h_samp_factor
* dstinfo
->min_DCT_h_scaled_size
);
657 MCU_rows
= srcinfo
->output_width
/
658 (dstinfo
->max_v_samp_factor
* dstinfo
->min_DCT_v_scaled_size
);
660 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
661 compptr
= dstinfo
->comp_info
+ ci
;
662 comp_width
= MCU_cols
* compptr
->h_samp_factor
;
663 comp_height
= MCU_rows
* compptr
->v_samp_factor
;
664 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
665 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
666 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
667 dst_blk_y
+= compptr
->v_samp_factor
) {
668 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
669 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
670 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
671 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
672 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
;
673 dst_blk_x
+= compptr
->h_samp_factor
) {
674 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
675 /* Block is within the mirrorable area. */
676 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
677 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
678 comp_width
- x_crop_blocks
- dst_blk_x
-
679 (JDIMENSION
) compptr
->h_samp_factor
,
680 (JDIMENSION
) compptr
->h_samp_factor
, FALSE
);
682 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
683 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
684 dst_blk_x
+ x_crop_blocks
,
685 (JDIMENSION
) compptr
->h_samp_factor
, FALSE
);
687 for (offset_x
= 0; offset_x
< compptr
->h_samp_factor
; offset_x
++) {
688 dst_ptr
= dst_buffer
[offset_y
][dst_blk_x
+ offset_x
];
689 if (y_crop_blocks
+ dst_blk_y
< comp_height
) {
690 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
691 /* Block is within the mirrorable area. */
692 src_ptr
= src_buffer
[compptr
->h_samp_factor
- offset_x
- 1]
693 [comp_height
- y_crop_blocks
- dst_blk_y
- offset_y
- 1];
694 for (i
= 0; i
< DCTSIZE
; i
++) {
695 for (j
= 0; j
< DCTSIZE
; j
++) {
696 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
698 dst_ptr
[j
*DCTSIZE
+i
] = -src_ptr
[i
*DCTSIZE
+j
];
701 for (j
= 0; j
< DCTSIZE
; j
++) {
702 dst_ptr
[j
*DCTSIZE
+i
] = -src_ptr
[i
*DCTSIZE
+j
];
704 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
708 /* Right-edge blocks are mirrored in y only */
709 src_ptr
= src_buffer
[offset_x
]
710 [comp_height
- y_crop_blocks
- dst_blk_y
- offset_y
- 1];
711 for (i
= 0; i
< DCTSIZE
; i
++) {
712 for (j
= 0; j
< DCTSIZE
; j
++) {
713 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
715 dst_ptr
[j
*DCTSIZE
+i
] = -src_ptr
[i
*DCTSIZE
+j
];
720 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
721 /* Bottom-edge blocks are mirrored in x only */
722 src_ptr
= src_buffer
[compptr
->h_samp_factor
- offset_x
- 1]
723 [dst_blk_y
+ offset_y
+ y_crop_blocks
];
724 for (i
= 0; i
< DCTSIZE
; i
++) {
725 for (j
= 0; j
< DCTSIZE
; j
++)
726 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
728 for (j
= 0; j
< DCTSIZE
; j
++)
729 dst_ptr
[j
*DCTSIZE
+i
] = -src_ptr
[i
*DCTSIZE
+j
];
732 /* At lower right corner, just transpose, no mirroring */
733 src_ptr
= src_buffer
[offset_x
]
734 [dst_blk_y
+ offset_y
+ y_crop_blocks
];
735 for (i
= 0; i
< DCTSIZE
; i
++)
736 for (j
= 0; j
< DCTSIZE
; j
++)
737 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
748 /* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec.
749 * Returns TRUE if valid integer found, FALSE if not.
750 * *strptr is advanced over the digit string, and *result is set to its value.
754 jt_read_integer (const char ** strptr
, JDIMENSION
* result
)
756 const char * ptr
= *strptr
;
759 for (; isdigit(*ptr
); ptr
++) {
760 val
= val
* 10 + (JDIMENSION
) (*ptr
- '0');
764 return FALSE
; /* oops, no digits */
770 /* Parse a crop specification (written in X11 geometry style).
771 * The routine returns TRUE if the spec string is valid, FALSE if not.
773 * The crop spec string should have the format
774 * <width>[f]x<height>[f]{+-}<xoffset>{+-}<yoffset>
775 * where width, height, xoffset, and yoffset are unsigned integers.
776 * Each of the elements can be omitted to indicate a default value.
777 * (A weakness of this style is that it is not possible to omit xoffset
778 * while specifying yoffset, since they look alike.)
780 * This code is loosely based on XParseGeometry from the X11 distribution.
784 jtransform_parse_crop_spec (jpeg_transform_info
*info
, const char *spec
)
787 info
->crop_width_set
= JCROP_UNSET
;
788 info
->crop_height_set
= JCROP_UNSET
;
789 info
->crop_xoffset_set
= JCROP_UNSET
;
790 info
->crop_yoffset_set
= JCROP_UNSET
;
792 if (isdigit(*spec
)) {
794 if (! jt_read_integer(&spec
, &info
->crop_width
))
796 if (*spec
== 'f' || *spec
== 'F') {
798 info
->crop_width_set
= JCROP_FORCE
;
800 info
->crop_width_set
= JCROP_POS
;
802 if (*spec
== 'x' || *spec
== 'X') {
805 if (! jt_read_integer(&spec
, &info
->crop_height
))
807 if (*spec
== 'f' || *spec
== 'F') {
809 info
->crop_height_set
= JCROP_FORCE
;
811 info
->crop_height_set
= JCROP_POS
;
813 if (*spec
== '+' || *spec
== '-') {
815 info
->crop_xoffset_set
= (*spec
== '-') ? JCROP_NEG
: JCROP_POS
;
817 if (! jt_read_integer(&spec
, &info
->crop_xoffset
))
820 if (*spec
== '+' || *spec
== '-') {
822 info
->crop_yoffset_set
= (*spec
== '-') ? JCROP_NEG
: JCROP_POS
;
824 if (! jt_read_integer(&spec
, &info
->crop_yoffset
))
827 /* We had better have gotten to the end of the string. */
835 /* Trim off any partial iMCUs on the indicated destination edge */
838 trim_right_edge (jpeg_transform_info
*info
, JDIMENSION full_width
)
842 MCU_cols
= info
->output_width
/ info
->iMCU_sample_width
;
843 if (MCU_cols
> 0 && info
->x_crop_offset
+ MCU_cols
==
844 full_width
/ info
->iMCU_sample_width
)
845 info
->output_width
= MCU_cols
* info
->iMCU_sample_width
;
849 trim_bottom_edge (jpeg_transform_info
*info
, JDIMENSION full_height
)
853 MCU_rows
= info
->output_height
/ info
->iMCU_sample_height
;
854 if (MCU_rows
> 0 && info
->y_crop_offset
+ MCU_rows
==
855 full_height
/ info
->iMCU_sample_height
)
856 info
->output_height
= MCU_rows
* info
->iMCU_sample_height
;
860 /* Request any required workspace.
862 * This routine figures out the size that the output image will be
863 * (which implies that all the transform parameters must be set before
866 * We allocate the workspace virtual arrays from the source decompression
867 * object, so that all the arrays (both the original data and the workspace)
868 * will be taken into account while making memory management decisions.
869 * Hence, this routine must be called after jpeg_read_header (which reads
870 * the image dimensions) and before jpeg_read_coefficients (which realizes
871 * the source's virtual arrays).
873 * This function returns FALSE right away if -perfect is given
874 * and transformation is not perfect. Otherwise returns TRUE.
878 jtransform_request_workspace (j_decompress_ptr srcinfo
,
879 jpeg_transform_info
*info
)
881 jvirt_barray_ptr
*coef_arrays
;
882 boolean need_workspace
, transpose_it
;
883 jpeg_component_info
*compptr
;
884 JDIMENSION xoffset
, yoffset
;
885 JDIMENSION width_in_iMCUs
, height_in_iMCUs
;
886 JDIMENSION width_in_blocks
, height_in_blocks
;
887 int ci
, h_samp_factor
, v_samp_factor
;
889 /* Determine number of components in output image */
890 if (info
->force_grayscale
&&
891 srcinfo
->jpeg_color_space
== JCS_YCbCr
&&
892 srcinfo
->num_components
== 3)
893 /* We'll only process the first component */
894 info
->num_components
= 1;
896 /* Process all the components */
897 info
->num_components
= srcinfo
->num_components
;
899 /* Compute output image dimensions and related values. */
900 jpeg_core_output_dimensions(srcinfo
);
902 /* Return right away if -perfect is given and transformation is not perfect.
905 if (info
->num_components
== 1) {
906 if (!jtransform_perfect_transform(srcinfo
->output_width
,
907 srcinfo
->output_height
,
908 srcinfo
->min_DCT_h_scaled_size
,
909 srcinfo
->min_DCT_v_scaled_size
,
913 if (!jtransform_perfect_transform(srcinfo
->output_width
,
914 srcinfo
->output_height
,
915 srcinfo
->max_h_samp_factor
* srcinfo
->min_DCT_h_scaled_size
,
916 srcinfo
->max_v_samp_factor
* srcinfo
->min_DCT_v_scaled_size
,
922 /* If there is only one output component, force the iMCU size to be 1;
923 * else use the source iMCU size. (This allows us to do the right thing
924 * when reducing color to grayscale, and also provides a handy way of
925 * cleaning up "funny" grayscale images whose sampling factors are not 1x1.)
927 switch (info
->transform
) {
928 case JXFORM_TRANSPOSE
:
929 case JXFORM_TRANSVERSE
:
932 info
->output_width
= srcinfo
->output_height
;
933 info
->output_height
= srcinfo
->output_width
;
934 if (info
->num_components
== 1) {
935 info
->iMCU_sample_width
= srcinfo
->min_DCT_v_scaled_size
;
936 info
->iMCU_sample_height
= srcinfo
->min_DCT_h_scaled_size
;
938 info
->iMCU_sample_width
=
939 srcinfo
->max_v_samp_factor
* srcinfo
->min_DCT_v_scaled_size
;
940 info
->iMCU_sample_height
=
941 srcinfo
->max_h_samp_factor
* srcinfo
->min_DCT_h_scaled_size
;
945 info
->output_width
= srcinfo
->output_width
;
946 info
->output_height
= srcinfo
->output_height
;
947 if (info
->num_components
== 1) {
948 info
->iMCU_sample_width
= srcinfo
->min_DCT_h_scaled_size
;
949 info
->iMCU_sample_height
= srcinfo
->min_DCT_v_scaled_size
;
951 info
->iMCU_sample_width
=
952 srcinfo
->max_h_samp_factor
* srcinfo
->min_DCT_h_scaled_size
;
953 info
->iMCU_sample_height
=
954 srcinfo
->max_v_samp_factor
* srcinfo
->min_DCT_v_scaled_size
;
959 /* If cropping has been requested, compute the crop area's position and
960 * dimensions, ensuring that its upper left corner falls at an iMCU boundary.
963 /* Insert default values for unset crop parameters */
964 if (info
->crop_xoffset_set
== JCROP_UNSET
)
965 info
->crop_xoffset
= 0; /* default to +0 */
966 if (info
->crop_yoffset_set
== JCROP_UNSET
)
967 info
->crop_yoffset
= 0; /* default to +0 */
968 if (info
->crop_xoffset
>= info
->output_width
||
969 info
->crop_yoffset
>= info
->output_height
)
970 ERREXIT(srcinfo
, JERR_BAD_CROP_SPEC
);
971 if (info
->crop_width_set
== JCROP_UNSET
)
972 info
->crop_width
= info
->output_width
- info
->crop_xoffset
;
973 if (info
->crop_height_set
== JCROP_UNSET
)
974 info
->crop_height
= info
->output_height
- info
->crop_yoffset
;
975 /* Ensure parameters are valid */
976 if (info
->crop_width
<= 0 || info
->crop_width
> info
->output_width
||
977 info
->crop_height
<= 0 || info
->crop_height
> info
->output_height
||
978 info
->crop_xoffset
> info
->output_width
- info
->crop_width
||
979 info
->crop_yoffset
> info
->output_height
- info
->crop_height
)
980 ERREXIT(srcinfo
, JERR_BAD_CROP_SPEC
);
981 /* Convert negative crop offsets into regular offsets */
982 if (info
->crop_xoffset_set
== JCROP_NEG
)
983 xoffset
= info
->output_width
- info
->crop_width
- info
->crop_xoffset
;
985 xoffset
= info
->crop_xoffset
;
986 if (info
->crop_yoffset_set
== JCROP_NEG
)
987 yoffset
= info
->output_height
- info
->crop_height
- info
->crop_yoffset
;
989 yoffset
= info
->crop_yoffset
;
990 /* Now adjust so that upper left corner falls at an iMCU boundary */
991 if (info
->crop_width_set
== JCROP_FORCE
)
992 info
->output_width
= info
->crop_width
;
995 info
->crop_width
+ (xoffset
% info
->iMCU_sample_width
);
996 if (info
->crop_height_set
== JCROP_FORCE
)
997 info
->output_height
= info
->crop_height
;
999 info
->output_height
=
1000 info
->crop_height
+ (yoffset
% info
->iMCU_sample_height
);
1001 /* Save x/y offsets measured in iMCUs */
1002 info
->x_crop_offset
= xoffset
/ info
->iMCU_sample_width
;
1003 info
->y_crop_offset
= yoffset
/ info
->iMCU_sample_height
;
1005 info
->x_crop_offset
= 0;
1006 info
->y_crop_offset
= 0;
1009 /* Figure out whether we need workspace arrays,
1010 * and if so whether they are transposed relative to the source.
1012 need_workspace
= FALSE
;
1013 transpose_it
= FALSE
;
1014 switch (info
->transform
) {
1016 if (info
->x_crop_offset
!= 0 || info
->y_crop_offset
!= 0)
1017 need_workspace
= TRUE
;
1018 /* No workspace needed if neither cropping nor transforming */
1022 trim_right_edge(info
, srcinfo
->output_width
);
1023 if (info
->y_crop_offset
!= 0)
1024 need_workspace
= TRUE
;
1025 /* do_flip_h_no_crop doesn't need a workspace array */
1029 trim_bottom_edge(info
, srcinfo
->output_height
);
1030 /* Need workspace arrays having same dimensions as source image. */
1031 need_workspace
= TRUE
;
1033 case JXFORM_TRANSPOSE
:
1034 /* transpose does NOT have to trim anything */
1035 /* Need workspace arrays having transposed dimensions. */
1036 need_workspace
= TRUE
;
1037 transpose_it
= TRUE
;
1039 case JXFORM_TRANSVERSE
:
1041 trim_right_edge(info
, srcinfo
->output_height
);
1042 trim_bottom_edge(info
, srcinfo
->output_width
);
1044 /* Need workspace arrays having transposed dimensions. */
1045 need_workspace
= TRUE
;
1046 transpose_it
= TRUE
;
1050 trim_right_edge(info
, srcinfo
->output_height
);
1051 /* Need workspace arrays having transposed dimensions. */
1052 need_workspace
= TRUE
;
1053 transpose_it
= TRUE
;
1055 case JXFORM_ROT_180
:
1057 trim_right_edge(info
, srcinfo
->output_width
);
1058 trim_bottom_edge(info
, srcinfo
->output_height
);
1060 /* Need workspace arrays having same dimensions as source image. */
1061 need_workspace
= TRUE
;
1063 case JXFORM_ROT_270
:
1065 trim_bottom_edge(info
, srcinfo
->output_width
);
1066 /* Need workspace arrays having transposed dimensions. */
1067 need_workspace
= TRUE
;
1068 transpose_it
= TRUE
;
1072 /* Allocate workspace if needed.
1073 * Note that we allocate arrays padded out to the next iMCU boundary,
1074 * so that transform routines need not worry about missing edge blocks.
1076 if (need_workspace
) {
1077 coef_arrays
= (jvirt_barray_ptr
*)
1078 (*srcinfo
->mem
->alloc_small
) ((j_common_ptr
) srcinfo
, JPOOL_IMAGE
,
1079 SIZEOF(jvirt_barray_ptr
) * info
->num_components
);
1080 width_in_iMCUs
= (JDIMENSION
)
1081 jdiv_round_up((long) info
->output_width
,
1082 (long) info
->iMCU_sample_width
);
1083 height_in_iMCUs
= (JDIMENSION
)
1084 jdiv_round_up((long) info
->output_height
,
1085 (long) info
->iMCU_sample_height
);
1086 for (ci
= 0; ci
< info
->num_components
; ci
++) {
1087 compptr
= srcinfo
->comp_info
+ ci
;
1088 if (info
->num_components
== 1) {
1089 /* we're going to force samp factors to 1x1 in this case */
1090 h_samp_factor
= v_samp_factor
= 1;
1091 } else if (transpose_it
) {
1092 h_samp_factor
= compptr
->v_samp_factor
;
1093 v_samp_factor
= compptr
->h_samp_factor
;
1095 h_samp_factor
= compptr
->h_samp_factor
;
1096 v_samp_factor
= compptr
->v_samp_factor
;
1098 width_in_blocks
= width_in_iMCUs
* h_samp_factor
;
1099 height_in_blocks
= height_in_iMCUs
* v_samp_factor
;
1100 coef_arrays
[ci
] = (*srcinfo
->mem
->request_virt_barray
)
1101 ((j_common_ptr
) srcinfo
, JPOOL_IMAGE
, FALSE
,
1102 width_in_blocks
, height_in_blocks
, (JDIMENSION
) v_samp_factor
);
1104 info
->workspace_coef_arrays
= coef_arrays
;
1106 info
->workspace_coef_arrays
= NULL
;
1112 /* Transpose destination image parameters */
1115 transpose_critical_parameters (j_compress_ptr dstinfo
)
1117 int tblno
, i
, j
, ci
, itemp
;
1118 jpeg_component_info
*compptr
;
1119 JQUANT_TBL
*qtblptr
;
1123 /* Transpose image dimensions */
1124 jtemp
= dstinfo
->image_width
;
1125 dstinfo
->image_width
= dstinfo
->image_height
;
1126 dstinfo
->image_height
= jtemp
;
1127 itemp
= dstinfo
->min_DCT_h_scaled_size
;
1128 dstinfo
->min_DCT_h_scaled_size
= dstinfo
->min_DCT_v_scaled_size
;
1129 dstinfo
->min_DCT_v_scaled_size
= itemp
;
1131 /* Transpose sampling factors */
1132 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
1133 compptr
= dstinfo
->comp_info
+ ci
;
1134 itemp
= compptr
->h_samp_factor
;
1135 compptr
->h_samp_factor
= compptr
->v_samp_factor
;
1136 compptr
->v_samp_factor
= itemp
;
1139 /* Transpose quantization tables */
1140 for (tblno
= 0; tblno
< NUM_QUANT_TBLS
; tblno
++) {
1141 qtblptr
= dstinfo
->quant_tbl_ptrs
[tblno
];
1142 if (qtblptr
!= NULL
) {
1143 for (i
= 0; i
< DCTSIZE
; i
++) {
1144 for (j
= 0; j
< i
; j
++) {
1145 qtemp
= qtblptr
->quantval
[i
*DCTSIZE
+j
];
1146 qtblptr
->quantval
[i
*DCTSIZE
+j
] = qtblptr
->quantval
[j
*DCTSIZE
+i
];
1147 qtblptr
->quantval
[j
*DCTSIZE
+i
] = qtemp
;
1155 /* Adjust Exif image parameters.
1157 * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible.
1161 adjust_exif_parameters (JOCTET FAR
* data
, unsigned int length
,
1162 JDIMENSION new_width
, JDIMENSION new_height
)
1164 boolean is_motorola
; /* Flag for byte order */
1165 unsigned int number_of_tags
, tagnum
;
1166 unsigned int firstoffset
, offset
;
1167 JDIMENSION new_value
;
1169 if (length
< 12) return; /* Length of an IFD entry */
1171 /* Discover byte order */
1172 if (GETJOCTET(data
[0]) == 0x49 && GETJOCTET(data
[1]) == 0x49)
1173 is_motorola
= FALSE
;
1174 else if (GETJOCTET(data
[0]) == 0x4D && GETJOCTET(data
[1]) == 0x4D)
1179 /* Check Tag Mark */
1181 if (GETJOCTET(data
[2]) != 0) return;
1182 if (GETJOCTET(data
[3]) != 0x2A) return;
1184 if (GETJOCTET(data
[3]) != 0) return;
1185 if (GETJOCTET(data
[2]) != 0x2A) return;
1188 /* Get first IFD offset (offset to IFD0) */
1190 if (GETJOCTET(data
[4]) != 0) return;
1191 if (GETJOCTET(data
[5]) != 0) return;
1192 firstoffset
= GETJOCTET(data
[6]);
1194 firstoffset
+= GETJOCTET(data
[7]);
1196 if (GETJOCTET(data
[7]) != 0) return;
1197 if (GETJOCTET(data
[6]) != 0) return;
1198 firstoffset
= GETJOCTET(data
[5]);
1200 firstoffset
+= GETJOCTET(data
[4]);
1202 if (firstoffset
> length
- 2) return; /* check end of data segment */
1204 /* Get the number of directory entries contained in this IFD */
1206 number_of_tags
= GETJOCTET(data
[firstoffset
]);
1207 number_of_tags
<<= 8;
1208 number_of_tags
+= GETJOCTET(data
[firstoffset
+1]);
1210 number_of_tags
= GETJOCTET(data
[firstoffset
+1]);
1211 number_of_tags
<<= 8;
1212 number_of_tags
+= GETJOCTET(data
[firstoffset
]);
1214 if (number_of_tags
== 0) return;
1217 /* Search for ExifSubIFD offset Tag in IFD0 */
1219 if (firstoffset
> length
- 12) return; /* check end of data segment */
1220 /* Get Tag number */
1222 tagnum
= GETJOCTET(data
[firstoffset
]);
1224 tagnum
+= GETJOCTET(data
[firstoffset
+1]);
1226 tagnum
= GETJOCTET(data
[firstoffset
+1]);
1228 tagnum
+= GETJOCTET(data
[firstoffset
]);
1230 if (tagnum
== 0x8769) break; /* found ExifSubIFD offset Tag */
1231 if (--number_of_tags
== 0) return;
1235 /* Get the ExifSubIFD offset */
1237 if (GETJOCTET(data
[firstoffset
+8]) != 0) return;
1238 if (GETJOCTET(data
[firstoffset
+9]) != 0) return;
1239 offset
= GETJOCTET(data
[firstoffset
+10]);
1241 offset
+= GETJOCTET(data
[firstoffset
+11]);
1243 if (GETJOCTET(data
[firstoffset
+11]) != 0) return;
1244 if (GETJOCTET(data
[firstoffset
+10]) != 0) return;
1245 offset
= GETJOCTET(data
[firstoffset
+9]);
1247 offset
+= GETJOCTET(data
[firstoffset
+8]);
1249 if (offset
> length
- 2) return; /* check end of data segment */
1251 /* Get the number of directory entries contained in this SubIFD */
1253 number_of_tags
= GETJOCTET(data
[offset
]);
1254 number_of_tags
<<= 8;
1255 number_of_tags
+= GETJOCTET(data
[offset
+1]);
1257 number_of_tags
= GETJOCTET(data
[offset
+1]);
1258 number_of_tags
<<= 8;
1259 number_of_tags
+= GETJOCTET(data
[offset
]);
1261 if (number_of_tags
< 2) return;
1264 /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */
1266 if (offset
> length
- 12) return; /* check end of data segment */
1267 /* Get Tag number */
1269 tagnum
= GETJOCTET(data
[offset
]);
1271 tagnum
+= GETJOCTET(data
[offset
+1]);
1273 tagnum
= GETJOCTET(data
[offset
+1]);
1275 tagnum
+= GETJOCTET(data
[offset
]);
1277 if (tagnum
== 0xA002 || tagnum
== 0xA003) {
1278 if (tagnum
== 0xA002)
1279 new_value
= new_width
; /* ExifImageWidth Tag */
1281 new_value
= new_height
; /* ExifImageHeight Tag */
1283 data
[offset
+2] = 0; /* Format = unsigned long (4 octets) */
1285 data
[offset
+4] = 0; /* Number Of Components = 1 */
1291 data
[offset
+10] = (JOCTET
)((new_value
>> 8) & 0xFF);
1292 data
[offset
+11] = (JOCTET
)(new_value
& 0xFF);
1294 data
[offset
+2] = 4; /* Format = unsigned long (4 octets) */
1296 data
[offset
+4] = 1; /* Number Of Components = 1 */
1300 data
[offset
+8] = (JOCTET
)(new_value
& 0xFF);
1301 data
[offset
+9] = (JOCTET
)((new_value
>> 8) & 0xFF);
1302 data
[offset
+10] = 0;
1303 data
[offset
+11] = 0;
1307 } while (--number_of_tags
);
1311 /* Adjust output image parameters as needed.
1313 * This must be called after jpeg_copy_critical_parameters()
1314 * and before jpeg_write_coefficients().
1316 * The return value is the set of virtual coefficient arrays to be written
1317 * (either the ones allocated by jtransform_request_workspace, or the
1318 * original source data arrays). The caller will need to pass this value
1319 * to jpeg_write_coefficients().
1322 GLOBAL(jvirt_barray_ptr
*)
1323 jtransform_adjust_parameters (j_decompress_ptr srcinfo
,
1324 j_compress_ptr dstinfo
,
1325 jvirt_barray_ptr
*src_coef_arrays
,
1326 jpeg_transform_info
*info
)
1328 /* If force-to-grayscale is requested, adjust destination parameters */
1329 if (info
->force_grayscale
) {
1330 /* First, ensure we have YCbCr or grayscale data, and that the source's
1331 * Y channel is full resolution. (No reasonable person would make Y
1332 * be less than full resolution, so actually coping with that case
1333 * isn't worth extra code space. But we check it to avoid crashing.)
1335 if (((dstinfo
->jpeg_color_space
== JCS_YCbCr
&&
1336 dstinfo
->num_components
== 3) ||
1337 (dstinfo
->jpeg_color_space
== JCS_GRAYSCALE
&&
1338 dstinfo
->num_components
== 1)) &&
1339 srcinfo
->comp_info
[0].h_samp_factor
== srcinfo
->max_h_samp_factor
&&
1340 srcinfo
->comp_info
[0].v_samp_factor
== srcinfo
->max_v_samp_factor
) {
1341 /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
1342 * properly. Among other things, it sets the target h_samp_factor &
1343 * v_samp_factor to 1, which typically won't match the source.
1344 * We have to preserve the source's quantization table number, however.
1346 int sv_quant_tbl_no
= dstinfo
->comp_info
[0].quant_tbl_no
;
1347 jpeg_set_colorspace(dstinfo
, JCS_GRAYSCALE
);
1348 dstinfo
->comp_info
[0].quant_tbl_no
= sv_quant_tbl_no
;
1350 /* Sorry, can't do it */
1351 ERREXIT(dstinfo
, JERR_CONVERSION_NOTIMPL
);
1353 } else if (info
->num_components
== 1) {
1354 /* For a single-component source, we force the destination sampling factors
1355 * to 1x1, with or without force_grayscale. This is useful because some
1356 * decoders choke on grayscale images with other sampling factors.
1358 dstinfo
->comp_info
[0].h_samp_factor
= 1;
1359 dstinfo
->comp_info
[0].v_samp_factor
= 1;
1362 /* Correct the destination's image dimensions as necessary
1363 * for rotate/flip, resize, and crop operations.
1365 dstinfo
->jpeg_width
= info
->output_width
;
1366 dstinfo
->jpeg_height
= info
->output_height
;
1368 /* Transpose destination image parameters */
1369 switch (info
->transform
) {
1370 case JXFORM_TRANSPOSE
:
1371 case JXFORM_TRANSVERSE
:
1373 case JXFORM_ROT_270
:
1374 transpose_critical_parameters(dstinfo
);
1380 /* Adjust Exif properties */
1381 if (srcinfo
->marker_list
!= NULL
&&
1382 srcinfo
->marker_list
->marker
== JPEG_APP0
+1 &&
1383 srcinfo
->marker_list
->data_length
>= 6 &&
1384 GETJOCTET(srcinfo
->marker_list
->data
[0]) == 0x45 &&
1385 GETJOCTET(srcinfo
->marker_list
->data
[1]) == 0x78 &&
1386 GETJOCTET(srcinfo
->marker_list
->data
[2]) == 0x69 &&
1387 GETJOCTET(srcinfo
->marker_list
->data
[3]) == 0x66 &&
1388 GETJOCTET(srcinfo
->marker_list
->data
[4]) == 0 &&
1389 GETJOCTET(srcinfo
->marker_list
->data
[5]) == 0) {
1390 /* Suppress output of JFIF marker */
1391 dstinfo
->write_JFIF_header
= FALSE
;
1392 /* Adjust Exif image parameters */
1393 if (dstinfo
->jpeg_width
!= srcinfo
->image_width
||
1394 dstinfo
->jpeg_height
!= srcinfo
->image_height
)
1395 /* Align data segment to start of TIFF structure for parsing */
1396 adjust_exif_parameters(srcinfo
->marker_list
->data
+ 6,
1397 srcinfo
->marker_list
->data_length
- 6,
1398 dstinfo
->jpeg_width
, dstinfo
->jpeg_height
);
1401 /* Return the appropriate output data set */
1402 if (info
->workspace_coef_arrays
!= NULL
)
1403 return info
->workspace_coef_arrays
;
1404 return src_coef_arrays
;
1408 /* Execute the actual transformation, if any.
1410 * This must be called *after* jpeg_write_coefficients, because it depends
1411 * on jpeg_write_coefficients to have computed subsidiary values such as
1412 * the per-component width and height fields in the destination object.
1414 * Note that some transformations will modify the source data arrays!
1418 jtransform_execute_transform (j_decompress_ptr srcinfo
,
1419 j_compress_ptr dstinfo
,
1420 jvirt_barray_ptr
*src_coef_arrays
,
1421 jpeg_transform_info
*info
)
1423 jvirt_barray_ptr
*dst_coef_arrays
= info
->workspace_coef_arrays
;
1425 /* Note: conditions tested here should match those in switch statement
1426 * in jtransform_request_workspace()
1428 switch (info
->transform
) {
1430 if (info
->x_crop_offset
!= 0 || info
->y_crop_offset
!= 0)
1431 do_crop(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1432 src_coef_arrays
, dst_coef_arrays
);
1435 if (info
->y_crop_offset
!= 0)
1436 do_flip_h(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1437 src_coef_arrays
, dst_coef_arrays
);
1439 do_flip_h_no_crop(srcinfo
, dstinfo
, info
->x_crop_offset
,
1443 do_flip_v(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1444 src_coef_arrays
, dst_coef_arrays
);
1446 case JXFORM_TRANSPOSE
:
1447 do_transpose(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1448 src_coef_arrays
, dst_coef_arrays
);
1450 case JXFORM_TRANSVERSE
:
1451 do_transverse(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1452 src_coef_arrays
, dst_coef_arrays
);
1455 do_rot_90(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1456 src_coef_arrays
, dst_coef_arrays
);
1458 case JXFORM_ROT_180
:
1459 do_rot_180(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1460 src_coef_arrays
, dst_coef_arrays
);
1462 case JXFORM_ROT_270
:
1463 do_rot_270(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1464 src_coef_arrays
, dst_coef_arrays
);
1469 /* jtransform_perfect_transform
1471 * Determine whether lossless transformation is perfectly
1472 * possible for a specified image and transformation.
1475 * image_width, image_height: source image dimensions.
1476 * MCU_width, MCU_height: pixel dimensions of MCU.
1477 * transform: transformation identifier.
1478 * Parameter sources from initialized jpeg_struct
1479 * (after reading source header):
1480 * image_width = cinfo.image_width
1481 * image_height = cinfo.image_height
1482 * MCU_width = cinfo.max_h_samp_factor * cinfo.block_size
1483 * MCU_height = cinfo.max_v_samp_factor * cinfo.block_size
1485 * TRUE = perfect transformation possible
1486 * FALSE = perfect transformation not possible
1487 * (may use custom action then)
1491 jtransform_perfect_transform(JDIMENSION image_width
, JDIMENSION image_height
,
1492 int MCU_width
, int MCU_height
,
1493 JXFORM_CODE transform
)
1495 boolean result
= TRUE
; /* initialize TRUE */
1497 switch (transform
) {
1499 case JXFORM_ROT_270
:
1500 if (image_width
% (JDIMENSION
) MCU_width
)
1505 if (image_height
% (JDIMENSION
) MCU_height
)
1508 case JXFORM_TRANSVERSE
:
1509 case JXFORM_ROT_180
:
1510 if (image_width
% (JDIMENSION
) MCU_width
)
1512 if (image_height
% (JDIMENSION
) MCU_height
)
1522 #endif /* TRANSFORMS_SUPPORTED */
1525 /* Setup decompression object to save desired markers in memory.
1526 * This must be called before jpeg_read_header() to have the desired effect.
1530 jcopy_markers_setup (j_decompress_ptr srcinfo
, JCOPY_OPTION option
)
1532 #ifdef SAVE_MARKERS_SUPPORTED
1535 /* Save comments except under NONE option */
1536 if (option
!= JCOPYOPT_NONE
) {
1537 jpeg_save_markers(srcinfo
, JPEG_COM
, 0xFFFF);
1539 /* Save all types of APPn markers iff ALL option */
1540 if (option
== JCOPYOPT_ALL
) {
1541 for (m
= 0; m
< 16; m
++)
1542 jpeg_save_markers(srcinfo
, JPEG_APP0
+ m
, 0xFFFF);
1544 #endif /* SAVE_MARKERS_SUPPORTED */
1547 /* Copy markers saved in the given source object to the destination object.
1548 * This should be called just after jpeg_start_compress() or
1549 * jpeg_write_coefficients().
1550 * Note that those routines will have written the SOI, and also the
1551 * JFIF APP0 or Adobe APP14 markers if selected.
1555 jcopy_markers_execute (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
1556 JCOPY_OPTION option
)
1558 jpeg_saved_marker_ptr marker
;
1560 /* In the current implementation, we don't actually need to examine the
1561 * option flag here; we just copy everything that got saved.
1562 * But to avoid confusion, we do not output JFIF and Adobe APP14 markers
1563 * if the encoder library already wrote one.
1565 for (marker
= srcinfo
->marker_list
; marker
!= NULL
; marker
= marker
->next
) {
1566 if (dstinfo
->write_JFIF_header
&&
1567 marker
->marker
== JPEG_APP0
&&
1568 marker
->data_length
>= 5 &&
1569 GETJOCTET(marker
->data
[0]) == 0x4A &&
1570 GETJOCTET(marker
->data
[1]) == 0x46 &&
1571 GETJOCTET(marker
->data
[2]) == 0x49 &&
1572 GETJOCTET(marker
->data
[3]) == 0x46 &&
1573 GETJOCTET(marker
->data
[4]) == 0)
1574 continue; /* reject duplicate JFIF */
1575 if (dstinfo
->write_Adobe_marker
&&
1576 marker
->marker
== JPEG_APP0
+14 &&
1577 marker
->data_length
>= 5 &&
1578 GETJOCTET(marker
->data
[0]) == 0x41 &&
1579 GETJOCTET(marker
->data
[1]) == 0x64 &&
1580 GETJOCTET(marker
->data
[2]) == 0x6F &&
1581 GETJOCTET(marker
->data
[3]) == 0x62 &&
1582 GETJOCTET(marker
->data
[4]) == 0x65)
1583 continue; /* reject duplicate Adobe */
1584 #ifdef NEED_FAR_POINTERS
1585 /* We could use jpeg_write_marker if the data weren't FAR... */
1588 jpeg_write_m_header(dstinfo
, marker
->marker
, marker
->data_length
);
1589 for (i
= 0; i
< marker
->data_length
; i
++)
1590 jpeg_write_m_byte(dstinfo
, marker
->data
[i
]);
1593 jpeg_write_marker(dstinfo
, marker
->marker
,
1594 marker
->data
, marker
->data_length
);