4 * This file was part of the Independent JPEG Group's software:
5 * Copyright (C) 1997-2011, Thomas G. Lane, Guido Vollbeding.
7 * Copyright (C) 2010, D. R. Commander.
8 * For conditions of distribution and use, see the accompanying README file.
10 * This file contains image transformation routines and other utility code
11 * used by the jpegtran sample application. These are NOT part of the core
12 * JPEG library. But we keep these routines separate from jpegtran.c to
13 * ease the task of maintaining jpegtran-like programs that have other user
17 #include <sal/config.h>
22 #include "transupp.h" /* My own external interface */
24 #include <ctype.h> /* to declare isdigit() */
26 /* Definition of jdiv_round_up is copied here from jutils.c in jpeg-8c.tar.gz,
27 just as the rest of this file appears to be copied here from transupp.c in
30 jdiv_round_up (long a
, long b
)
31 /* Compute a/b rounded up to next integer, ie, ceil(a/b) */
32 /* Assumes a >= 0, b > 0 */
34 return (a
+ b
- 1L) / b
;
37 #if JPEG_LIB_VERSION >= 70
38 #define dstinfo_min_DCT_h_scaled_size dstinfo->min_DCT_h_scaled_size
39 #define dstinfo_min_DCT_v_scaled_size dstinfo->min_DCT_v_scaled_size
41 #define dstinfo_min_DCT_h_scaled_size DCTSIZE
42 #define dstinfo_min_DCT_v_scaled_size DCTSIZE
46 #if TRANSFORMS_SUPPORTED
49 * Lossless image transformation routines. These routines work on DCT
50 * coefficient arrays and thus do not require any lossy decompression
51 * or recompression of the image.
52 * Thanks to Guido Vollbeding for the initial design and code of this feature,
53 * and to Ben Jackson for introducing the cropping feature.
55 * Horizontal flipping is done in-place, using a single top-to-bottom
56 * pass through the virtual source array. It will thus be much the
57 * fastest option for images larger than main memory.
59 * The other routines require a set of destination virtual arrays, so they
60 * need twice as much memory as jpegtran normally does. The destination
61 * arrays are always written in normal scan order (top to bottom) because
62 * the virtual array manager expects this. The source arrays will be scanned
63 * in the corresponding order, which means multiple passes through the source
64 * arrays for most of the transforms. That could result in much thrashing
65 * if the image is larger than main memory.
67 * If cropping or trimming is involved, the destination arrays may be smaller
68 * than the source arrays. Note it is not possible to do horizontal flip
69 * in-place when a nonzero Y crop offset is specified, since we'd have to move
70 * data from one block row to another but the virtual array manager doesn't
71 * guarantee we can touch more than one row at a time. So in that case,
72 * we have to use a separate destination array.
74 * Some notes about the operating environment of the individual transform
76 * 1. Both the source and destination virtual arrays are allocated from the
77 * source JPEG object, and therefore should be manipulated by calling the
78 * source's memory manager.
79 * 2. The destination's component count should be used. It may be smaller
80 * than the source's when forcing to grayscale.
81 * 3. Likewise the destination's sampling factors should be used. When
82 * forcing to grayscale the destination's sampling factors will be all 1,
83 * and we may as well take that as the effective iMCU size.
84 * 4. When "trim" is in effect, the destination's dimensions will be the
85 * trimmed values but the source's will be untrimmed.
86 * 5. When "crop" is in effect, the destination's dimensions will be the
87 * cropped values but the source's will be uncropped. Each transform
88 * routine is responsible for picking up source data starting at the
89 * correct X and Y offset for the crop region. (The X and Y offsets
90 * passed to the transform routines are measured in iMCU blocks of the
92 * 6. All the routines assume that the source and destination buffers are
93 * padded out to a full iMCU boundary. This is true, although for the
94 * source buffer it is an undocumented property of jdcoefct.c.
97 static void lcl_jcopy_block_row (JBLOCKROW input_row
, JBLOCKROW output_row
, JDIMENSION num_blocks
)
98 /* Copy a row of coefficient blocks from one place to another. */
101 FMEMCOPY(output_row
, input_row
, num_blocks
* (DCTSIZE2
* SIZEOF(JCOEF
)));
103 JCOEFPTR inptr
, outptr
;
106 inptr
= (JCOEFPTR
) input_row
;
107 outptr
= (JCOEFPTR
) output_row
;
108 for (count
= (long) num_blocks
* DCTSIZE2
; count
> 0; count
--) {
109 *outptr
++ = *inptr
++;
115 do_crop (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
116 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
117 jvirt_barray_ptr
*src_coef_arrays
,
118 jvirt_barray_ptr
*dst_coef_arrays
)
119 /* Crop. This is only used when no rotate/flip is requested with the crop. */
121 JDIMENSION dst_blk_y
, x_crop_blocks
, y_crop_blocks
;
123 JBLOCKARRAY src_buffer
, dst_buffer
;
124 jpeg_component_info
*compptr
;
126 /* We simply have to copy the right amount of data (the destination's
127 * image size) starting at the given X and Y offsets in the source.
129 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
130 compptr
= dstinfo
->comp_info
+ ci
;
131 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
132 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
133 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
134 dst_blk_y
+= compptr
->v_samp_factor
) {
135 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
136 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
137 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
138 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
139 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
140 dst_blk_y
+ y_crop_blocks
,
141 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
142 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
143 lcl_jcopy_block_row(src_buffer
[offset_y
] + x_crop_blocks
,
144 dst_buffer
[offset_y
],
145 compptr
->width_in_blocks
);
153 do_flip_h_no_crop (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
154 JDIMENSION x_crop_offset
,
155 jvirt_barray_ptr
*src_coef_arrays
)
156 /* Horizontal flip; done in-place, so no separate dest array is required.
157 * NB: this only works when y_crop_offset is zero.
160 JDIMENSION MCU_cols
, comp_width
, blk_x
, blk_y
, x_crop_blocks
;
165 jpeg_component_info
*compptr
;
167 /* Horizontal mirroring of DCT blocks is accomplished by swapping
168 * pairs of blocks in-place. Within a DCT block, we perform horizontal
169 * mirroring by changing the signs of odd-numbered columns.
170 * Partial iMCUs at the right edge are left untouched.
172 MCU_cols
= srcinfo
->output_width
/
173 (dstinfo
->max_h_samp_factor
* dstinfo_min_DCT_h_scaled_size
);
175 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
176 compptr
= dstinfo
->comp_info
+ ci
;
177 comp_width
= MCU_cols
* compptr
->h_samp_factor
;
178 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
179 for (blk_y
= 0; blk_y
< compptr
->height_in_blocks
;
180 blk_y
+= compptr
->v_samp_factor
) {
181 buffer
= (*srcinfo
->mem
->access_virt_barray
)
182 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
], blk_y
,
183 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
184 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
185 /* Do the mirroring */
186 for (blk_x
= 0; blk_x
* 2 < comp_width
; blk_x
++) {
187 ptr1
= buffer
[offset_y
][blk_x
];
188 ptr2
= buffer
[offset_y
][comp_width
- blk_x
- 1];
189 /* this unrolled loop doesn't need to know which row it's on... */
190 for (k
= 0; k
< DCTSIZE2
; k
+= 2) {
191 temp1
= *ptr1
; /* swap even column */
195 temp1
= *ptr1
; /* swap odd column with sign change */
201 if (x_crop_blocks
> 0) {
202 /* Now left-justify the portion of the data to be kept.
203 * We can't use a single lcl_jcopy_block_row() call because that routine
204 * depends on memcpy(), whose behavior is unspecified for overlapping
205 * source and destination areas. Sigh.
207 for (blk_x
= 0; blk_x
< compptr
->width_in_blocks
; blk_x
++) {
208 lcl_jcopy_block_row(buffer
[offset_y
] + blk_x
+ x_crop_blocks
,
209 buffer
[offset_y
] + blk_x
,
220 do_flip_h (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
221 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
222 jvirt_barray_ptr
*src_coef_arrays
,
223 jvirt_barray_ptr
*dst_coef_arrays
)
224 /* Horizontal flip in general cropping case */
226 JDIMENSION MCU_cols
, comp_width
, dst_blk_x
, dst_blk_y
;
227 JDIMENSION x_crop_blocks
, y_crop_blocks
;
229 JBLOCKARRAY src_buffer
, dst_buffer
;
230 JBLOCKROW src_row_ptr
, dst_row_ptr
;
231 JCOEFPTR src_ptr
, dst_ptr
;
232 jpeg_component_info
*compptr
;
234 /* Here we must output into a separate array because we can't touch
235 * different rows of a single virtual array simultaneously. Otherwise,
236 * this is essentially the same as the routine above.
238 MCU_cols
= srcinfo
->output_width
/
239 (dstinfo
->max_h_samp_factor
* dstinfo_min_DCT_h_scaled_size
);
241 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
242 compptr
= dstinfo
->comp_info
+ ci
;
243 comp_width
= MCU_cols
* compptr
->h_samp_factor
;
244 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
245 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
246 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
247 dst_blk_y
+= compptr
->v_samp_factor
) {
248 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
249 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
250 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
251 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
252 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
253 dst_blk_y
+ y_crop_blocks
,
254 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
255 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
256 dst_row_ptr
= dst_buffer
[offset_y
];
257 src_row_ptr
= src_buffer
[offset_y
];
258 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
; dst_blk_x
++) {
259 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
260 /* Do the mirrorable blocks */
261 dst_ptr
= dst_row_ptr
[dst_blk_x
];
262 src_ptr
= src_row_ptr
[comp_width
- x_crop_blocks
- dst_blk_x
- 1];
263 /* this unrolled loop doesn't need to know which row it's on... */
264 for (k
= 0; k
< DCTSIZE2
; k
+= 2) {
265 *dst_ptr
++ = *src_ptr
++; /* copy even column */
266 *dst_ptr
++ = - *src_ptr
++; /* copy odd column with sign change */
269 /* Copy last partial block(s) verbatim */
270 lcl_jcopy_block_row(src_row_ptr
+ dst_blk_x
+ x_crop_blocks
,
271 dst_row_ptr
+ dst_blk_x
,
282 do_flip_v (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
283 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
284 jvirt_barray_ptr
*src_coef_arrays
,
285 jvirt_barray_ptr
*dst_coef_arrays
)
288 JDIMENSION MCU_rows
, comp_height
, dst_blk_x
, dst_blk_y
;
289 JDIMENSION x_crop_blocks
, y_crop_blocks
;
290 int ci
, i
, j
, offset_y
;
291 JBLOCKARRAY src_buffer
, dst_buffer
;
292 JBLOCKROW src_row_ptr
, dst_row_ptr
;
293 JCOEFPTR src_ptr
, dst_ptr
;
294 jpeg_component_info
*compptr
;
296 /* We output into a separate array because we can't touch different
297 * rows of the source virtual array simultaneously. Otherwise, this
298 * is a pretty straightforward analog of horizontal flip.
299 * Within a DCT block, vertical mirroring is done by changing the signs
300 * of odd-numbered rows.
301 * Partial iMCUs at the bottom edge are copied verbatim.
303 MCU_rows
= srcinfo
->output_height
/
304 (dstinfo
->max_v_samp_factor
* dstinfo_min_DCT_v_scaled_size
);
306 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
307 compptr
= dstinfo
->comp_info
+ ci
;
308 comp_height
= MCU_rows
* compptr
->v_samp_factor
;
309 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
310 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
311 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
312 dst_blk_y
+= compptr
->v_samp_factor
) {
313 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
314 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
315 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
316 if (y_crop_blocks
+ dst_blk_y
< comp_height
) {
317 /* Row is within the mirrorable area. */
318 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
319 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
320 comp_height
- y_crop_blocks
- dst_blk_y
-
321 (JDIMENSION
) compptr
->v_samp_factor
,
322 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
324 /* Bottom-edge blocks will be copied verbatim. */
325 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
326 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
327 dst_blk_y
+ y_crop_blocks
,
328 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
330 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
331 if (y_crop_blocks
+ dst_blk_y
< comp_height
) {
332 /* Row is within the mirrorable area. */
333 dst_row_ptr
= dst_buffer
[offset_y
];
334 src_row_ptr
= src_buffer
[compptr
->v_samp_factor
- offset_y
- 1];
335 src_row_ptr
+= x_crop_blocks
;
336 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
;
338 dst_ptr
= dst_row_ptr
[dst_blk_x
];
339 src_ptr
= src_row_ptr
[dst_blk_x
];
340 for (i
= 0; i
< DCTSIZE
; i
+= 2) {
342 for (j
= 0; j
< DCTSIZE
; j
++)
343 *dst_ptr
++ = *src_ptr
++;
344 /* copy odd row with sign change */
345 for (j
= 0; j
< DCTSIZE
; j
++)
346 *dst_ptr
++ = - *src_ptr
++;
350 /* Just copy row verbatim. */
351 lcl_jcopy_block_row(src_buffer
[offset_y
] + x_crop_blocks
,
352 dst_buffer
[offset_y
],
353 compptr
->width_in_blocks
);
362 do_transpose (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
363 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
364 jvirt_barray_ptr
*src_coef_arrays
,
365 jvirt_barray_ptr
*dst_coef_arrays
)
366 /* Transpose source into destination */
368 JDIMENSION dst_blk_x
, dst_blk_y
, x_crop_blocks
, y_crop_blocks
;
369 int ci
, i
, j
, offset_x
, offset_y
;
370 JBLOCKARRAY src_buffer
, dst_buffer
;
371 JCOEFPTR src_ptr
, dst_ptr
;
372 jpeg_component_info
*compptr
;
374 /* Transposing pixels within a block just requires transposing the
376 * Partial iMCUs at the edges require no special treatment; we simply
377 * process all the available DCT blocks for every component.
379 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
380 compptr
= dstinfo
->comp_info
+ ci
;
381 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
382 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
383 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
384 dst_blk_y
+= compptr
->v_samp_factor
) {
385 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
386 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
387 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
388 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
389 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
;
390 dst_blk_x
+= compptr
->h_samp_factor
) {
391 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
392 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
393 dst_blk_x
+ x_crop_blocks
,
394 (JDIMENSION
) compptr
->h_samp_factor
, FALSE
);
395 for (offset_x
= 0; offset_x
< compptr
->h_samp_factor
; offset_x
++) {
396 dst_ptr
= dst_buffer
[offset_y
][dst_blk_x
+ offset_x
];
397 src_ptr
= src_buffer
[offset_x
][dst_blk_y
+ offset_y
+ y_crop_blocks
];
398 for (i
= 0; i
< DCTSIZE
; i
++)
399 for (j
= 0; j
< DCTSIZE
; j
++)
400 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
410 do_rot_90 (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
411 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
412 jvirt_barray_ptr
*src_coef_arrays
,
413 jvirt_barray_ptr
*dst_coef_arrays
)
414 /* 90 degree rotation is equivalent to
415 * 1. Transposing the image;
416 * 2. Horizontal mirroring.
417 * These two steps are merged into a single processing routine.
420 JDIMENSION MCU_cols
, comp_width
, dst_blk_x
, dst_blk_y
;
421 JDIMENSION x_crop_blocks
, y_crop_blocks
;
422 int ci
, i
, j
, offset_x
, offset_y
;
423 JBLOCKARRAY src_buffer
, dst_buffer
;
424 JCOEFPTR src_ptr
, dst_ptr
;
425 jpeg_component_info
*compptr
;
427 /* Because of the horizontal mirror step, we can't process partial iMCUs
428 * at the (output) right edge properly. They just get transposed and
431 MCU_cols
= srcinfo
->output_height
/
432 (dstinfo
->max_h_samp_factor
* dstinfo_min_DCT_h_scaled_size
);
434 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
435 compptr
= dstinfo
->comp_info
+ ci
;
436 comp_width
= MCU_cols
* compptr
->h_samp_factor
;
437 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
438 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
439 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
440 dst_blk_y
+= compptr
->v_samp_factor
) {
441 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
442 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
443 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
444 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
445 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
;
446 dst_blk_x
+= compptr
->h_samp_factor
) {
447 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
448 /* Block is within the mirrorable area. */
449 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
450 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
451 comp_width
- x_crop_blocks
- dst_blk_x
-
452 (JDIMENSION
) compptr
->h_samp_factor
,
453 (JDIMENSION
) compptr
->h_samp_factor
, FALSE
);
455 /* Edge blocks are transposed but not mirrored. */
456 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
457 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
458 dst_blk_x
+ x_crop_blocks
,
459 (JDIMENSION
) compptr
->h_samp_factor
, FALSE
);
461 for (offset_x
= 0; offset_x
< compptr
->h_samp_factor
; offset_x
++) {
462 dst_ptr
= dst_buffer
[offset_y
][dst_blk_x
+ offset_x
];
463 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
464 /* Block is within the mirrorable area. */
465 src_ptr
= src_buffer
[compptr
->h_samp_factor
- offset_x
- 1]
466 [dst_blk_y
+ offset_y
+ y_crop_blocks
];
467 for (i
= 0; i
< DCTSIZE
; i
++) {
468 for (j
= 0; j
< DCTSIZE
; j
++)
469 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
471 for (j
= 0; j
< DCTSIZE
; j
++)
472 dst_ptr
[j
*DCTSIZE
+i
] = -src_ptr
[i
*DCTSIZE
+j
];
475 /* Edge blocks are transposed but not mirrored. */
476 src_ptr
= src_buffer
[offset_x
]
477 [dst_blk_y
+ offset_y
+ y_crop_blocks
];
478 for (i
= 0; i
< DCTSIZE
; i
++)
479 for (j
= 0; j
< DCTSIZE
; j
++)
480 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
491 do_rot_270 (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
492 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
493 jvirt_barray_ptr
*src_coef_arrays
,
494 jvirt_barray_ptr
*dst_coef_arrays
)
495 /* 270 degree rotation is equivalent to
496 * 1. Horizontal mirroring;
497 * 2. Transposing the image.
498 * These two steps are merged into a single processing routine.
501 JDIMENSION MCU_rows
, comp_height
, dst_blk_x
, dst_blk_y
;
502 JDIMENSION x_crop_blocks
, y_crop_blocks
;
503 int ci
, i
, j
, offset_x
, offset_y
;
504 JBLOCKARRAY src_buffer
, dst_buffer
;
505 JCOEFPTR src_ptr
, dst_ptr
;
506 jpeg_component_info
*compptr
;
508 /* Because of the horizontal mirror step, we can't process partial iMCUs
509 * at the (output) bottom edge properly. They just get transposed and
512 MCU_rows
= srcinfo
->output_width
/
513 (dstinfo
->max_v_samp_factor
* dstinfo_min_DCT_v_scaled_size
);
515 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
516 compptr
= dstinfo
->comp_info
+ ci
;
517 comp_height
= MCU_rows
* compptr
->v_samp_factor
;
518 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
519 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
520 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
521 dst_blk_y
+= compptr
->v_samp_factor
) {
522 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
523 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
524 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
525 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
526 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
;
527 dst_blk_x
+= compptr
->h_samp_factor
) {
528 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
529 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
530 dst_blk_x
+ x_crop_blocks
,
531 (JDIMENSION
) compptr
->h_samp_factor
, FALSE
);
532 for (offset_x
= 0; offset_x
< compptr
->h_samp_factor
; offset_x
++) {
533 dst_ptr
= dst_buffer
[offset_y
][dst_blk_x
+ offset_x
];
534 if (y_crop_blocks
+ dst_blk_y
< comp_height
) {
535 /* Block is within the mirrorable area. */
536 src_ptr
= src_buffer
[offset_x
]
537 [comp_height
- y_crop_blocks
- dst_blk_y
- offset_y
- 1];
538 for (i
= 0; i
< DCTSIZE
; i
++) {
539 for (j
= 0; j
< DCTSIZE
; j
++) {
540 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
542 dst_ptr
[j
*DCTSIZE
+i
] = -src_ptr
[i
*DCTSIZE
+j
];
546 /* Edge blocks are transposed but not mirrored. */
547 src_ptr
= src_buffer
[offset_x
]
548 [dst_blk_y
+ offset_y
+ y_crop_blocks
];
549 for (i
= 0; i
< DCTSIZE
; i
++)
550 for (j
= 0; j
< DCTSIZE
; j
++)
551 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
562 do_rot_180 (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
563 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
564 jvirt_barray_ptr
*src_coef_arrays
,
565 jvirt_barray_ptr
*dst_coef_arrays
)
566 /* 180 degree rotation is equivalent to
567 * 1. Vertical mirroring;
568 * 2. Horizontal mirroring.
569 * These two steps are merged into a single processing routine.
572 JDIMENSION MCU_cols
, MCU_rows
, comp_width
, comp_height
, dst_blk_x
, dst_blk_y
;
573 JDIMENSION x_crop_blocks
, y_crop_blocks
;
574 int ci
, i
, j
, offset_y
;
575 JBLOCKARRAY src_buffer
, dst_buffer
;
576 JBLOCKROW src_row_ptr
, dst_row_ptr
;
577 JCOEFPTR src_ptr
, dst_ptr
;
578 jpeg_component_info
*compptr
;
580 MCU_cols
= srcinfo
->output_width
/
581 (dstinfo
->max_h_samp_factor
* dstinfo_min_DCT_h_scaled_size
);
582 MCU_rows
= srcinfo
->output_height
/
583 (dstinfo
->max_v_samp_factor
* dstinfo_min_DCT_v_scaled_size
);
585 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
586 compptr
= dstinfo
->comp_info
+ ci
;
587 comp_width
= MCU_cols
* compptr
->h_samp_factor
;
588 comp_height
= MCU_rows
* compptr
->v_samp_factor
;
589 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
590 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
591 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
592 dst_blk_y
+= compptr
->v_samp_factor
) {
593 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
594 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
595 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
596 if (y_crop_blocks
+ dst_blk_y
< comp_height
) {
597 /* Row is within the vertically mirrorable area. */
598 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
599 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
600 comp_height
- y_crop_blocks
- dst_blk_y
-
601 (JDIMENSION
) compptr
->v_samp_factor
,
602 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
604 /* Bottom-edge rows are only mirrored horizontally. */
605 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
606 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
607 dst_blk_y
+ y_crop_blocks
,
608 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
610 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
611 dst_row_ptr
= dst_buffer
[offset_y
];
612 if (y_crop_blocks
+ dst_blk_y
< comp_height
) {
613 /* Row is within the mirrorable area. */
614 src_row_ptr
= src_buffer
[compptr
->v_samp_factor
- offset_y
- 1];
615 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
; dst_blk_x
++) {
616 dst_ptr
= dst_row_ptr
[dst_blk_x
];
617 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
618 /* Process the blocks that can be mirrored both ways. */
619 src_ptr
= src_row_ptr
[comp_width
- x_crop_blocks
- dst_blk_x
- 1];
620 for (i
= 0; i
< DCTSIZE
; i
+= 2) {
621 /* For even row, negate every odd column. */
622 for (j
= 0; j
< DCTSIZE
; j
+= 2) {
623 *dst_ptr
++ = *src_ptr
++;
624 *dst_ptr
++ = - *src_ptr
++;
626 /* For odd row, negate every even column. */
627 for (j
= 0; j
< DCTSIZE
; j
+= 2) {
628 *dst_ptr
++ = - *src_ptr
++;
629 *dst_ptr
++ = *src_ptr
++;
633 /* Any remaining right-edge blocks are only mirrored vertically. */
634 src_ptr
= src_row_ptr
[x_crop_blocks
+ dst_blk_x
];
635 for (i
= 0; i
< DCTSIZE
; i
+= 2) {
636 for (j
= 0; j
< DCTSIZE
; j
++)
637 *dst_ptr
++ = *src_ptr
++;
638 for (j
= 0; j
< DCTSIZE
; j
++)
639 *dst_ptr
++ = - *src_ptr
++;
644 /* Remaining rows are just mirrored horizontally. */
645 src_row_ptr
= src_buffer
[offset_y
];
646 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
; dst_blk_x
++) {
647 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
648 /* Process the blocks that can be mirrored. */
649 dst_ptr
= dst_row_ptr
[dst_blk_x
];
650 src_ptr
= src_row_ptr
[comp_width
- x_crop_blocks
- dst_blk_x
- 1];
651 for (i
= 0; i
< DCTSIZE2
; i
+= 2) {
652 *dst_ptr
++ = *src_ptr
++;
653 *dst_ptr
++ = - *src_ptr
++;
656 /* Any remaining right-edge blocks are only copied. */
657 lcl_jcopy_block_row(src_row_ptr
+ dst_blk_x
+ x_crop_blocks
,
658 dst_row_ptr
+ dst_blk_x
,
670 do_transverse (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
671 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
672 jvirt_barray_ptr
*src_coef_arrays
,
673 jvirt_barray_ptr
*dst_coef_arrays
)
674 /* Transverse transpose is equivalent to
675 * 1. 180 degree rotation;
678 * 1. Horizontal mirroring;
680 * 3. Horizontal mirroring.
681 * These steps are merged into a single processing routine.
684 JDIMENSION MCU_cols
, MCU_rows
, comp_width
, comp_height
, dst_blk_x
, dst_blk_y
;
685 JDIMENSION x_crop_blocks
, y_crop_blocks
;
686 int ci
, i
, j
, offset_x
, offset_y
;
687 JBLOCKARRAY src_buffer
, dst_buffer
;
688 JCOEFPTR src_ptr
, dst_ptr
;
689 jpeg_component_info
*compptr
;
691 MCU_cols
= srcinfo
->output_height
/
692 (dstinfo
->max_h_samp_factor
* dstinfo_min_DCT_h_scaled_size
);
693 MCU_rows
= srcinfo
->output_width
/
694 (dstinfo
->max_v_samp_factor
* dstinfo_min_DCT_v_scaled_size
);
696 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
697 compptr
= dstinfo
->comp_info
+ ci
;
698 comp_width
= MCU_cols
* compptr
->h_samp_factor
;
699 comp_height
= MCU_rows
* compptr
->v_samp_factor
;
700 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
701 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
702 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
703 dst_blk_y
+= compptr
->v_samp_factor
) {
704 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
705 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
706 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
707 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
708 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
;
709 dst_blk_x
+= compptr
->h_samp_factor
) {
710 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
711 /* Block is within the mirrorable area. */
712 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
713 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
714 comp_width
- x_crop_blocks
- dst_blk_x
-
715 (JDIMENSION
) compptr
->h_samp_factor
,
716 (JDIMENSION
) compptr
->h_samp_factor
, FALSE
);
718 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
719 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
720 dst_blk_x
+ x_crop_blocks
,
721 (JDIMENSION
) compptr
->h_samp_factor
, FALSE
);
723 for (offset_x
= 0; offset_x
< compptr
->h_samp_factor
; offset_x
++) {
724 dst_ptr
= dst_buffer
[offset_y
][dst_blk_x
+ offset_x
];
725 if (y_crop_blocks
+ dst_blk_y
< comp_height
) {
726 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
727 /* Block is within the mirrorable area. */
728 src_ptr
= src_buffer
[compptr
->h_samp_factor
- offset_x
- 1]
729 [comp_height
- y_crop_blocks
- dst_blk_y
- offset_y
- 1];
730 for (i
= 0; i
< DCTSIZE
; i
++) {
731 for (j
= 0; j
< DCTSIZE
; j
++) {
732 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
734 dst_ptr
[j
*DCTSIZE
+i
] = -src_ptr
[i
*DCTSIZE
+j
];
737 for (j
= 0; j
< DCTSIZE
; j
++) {
738 dst_ptr
[j
*DCTSIZE
+i
] = -src_ptr
[i
*DCTSIZE
+j
];
740 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
744 /* Right-edge blocks are mirrored in y only */
745 src_ptr
= src_buffer
[offset_x
]
746 [comp_height
- y_crop_blocks
- dst_blk_y
- offset_y
- 1];
747 for (i
= 0; i
< DCTSIZE
; i
++) {
748 for (j
= 0; j
< DCTSIZE
; j
++) {
749 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
751 dst_ptr
[j
*DCTSIZE
+i
] = -src_ptr
[i
*DCTSIZE
+j
];
756 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
757 /* Bottom-edge blocks are mirrored in x only */
758 src_ptr
= src_buffer
[compptr
->h_samp_factor
- offset_x
- 1]
759 [dst_blk_y
+ offset_y
+ y_crop_blocks
];
760 for (i
= 0; i
< DCTSIZE
; i
++) {
761 for (j
= 0; j
< DCTSIZE
; j
++)
762 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
764 for (j
= 0; j
< DCTSIZE
; j
++)
765 dst_ptr
[j
*DCTSIZE
+i
] = -src_ptr
[i
*DCTSIZE
+j
];
768 /* At lower right corner, just transpose, no mirroring */
769 src_ptr
= src_buffer
[offset_x
]
770 [dst_blk_y
+ offset_y
+ y_crop_blocks
];
771 for (i
= 0; i
< DCTSIZE
; i
++)
772 for (j
= 0; j
< DCTSIZE
; j
++)
773 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
784 /* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec.
785 * Returns TRUE if valid integer found, FALSE if not.
786 * *strptr is advanced over the digit string, and *result is set to its value.
790 jt_read_integer (const char ** strptr
, JDIMENSION
* result
)
792 const char * ptr
= *strptr
;
795 for (; isdigit(*ptr
); ptr
++) {
796 val
= val
* 10 + (JDIMENSION
) (*ptr
- '0');
800 return FALSE
; /* oops, no digits */
806 /* Parse a crop specification (written in X11 geometry style).
807 * The routine returns TRUE if the spec string is valid, FALSE if not.
809 * The crop spec string should have the format
810 * <width>[f]x<height>[f]{+-}<xoffset>{+-}<yoffset>
811 * where width, height, xoffset, and yoffset are unsigned integers.
812 * Each of the elements can be omitted to indicate a default value.
813 * (A weakness of this style is that it is not possible to omit xoffset
814 * while specifying yoffset, since they look alike.)
816 * This code is loosely based on XParseGeometry from the X11 distribution.
820 jtransform_parse_crop_spec (jpeg_transform_info
*info
, const char *spec
)
823 info
->crop_width_set
= JCROP_UNSET
;
824 info
->crop_height_set
= JCROP_UNSET
;
825 info
->crop_xoffset_set
= JCROP_UNSET
;
826 info
->crop_yoffset_set
= JCROP_UNSET
;
828 if (isdigit(*spec
)) {
830 if (! jt_read_integer(&spec
, &info
->crop_width
))
832 if (*spec
== 'f' || *spec
== 'F') {
834 info
->crop_width_set
= JCROP_FORCE
;
836 info
->crop_width_set
= JCROP_POS
;
838 if (*spec
== 'x' || *spec
== 'X') {
841 if (! jt_read_integer(&spec
, &info
->crop_height
))
843 if (*spec
== 'f' || *spec
== 'F') {
845 info
->crop_height_set
= JCROP_FORCE
;
847 info
->crop_height_set
= JCROP_POS
;
849 if (*spec
== '+' || *spec
== '-') {
851 info
->crop_xoffset_set
= (*spec
== '-') ? JCROP_NEG
: JCROP_POS
;
853 if (! jt_read_integer(&spec
, &info
->crop_xoffset
))
856 if (*spec
== '+' || *spec
== '-') {
858 info
->crop_yoffset_set
= (*spec
== '-') ? JCROP_NEG
: JCROP_POS
;
860 if (! jt_read_integer(&spec
, &info
->crop_yoffset
))
863 /* We had better have gotten to the end of the string. */
871 /* Trim off any partial iMCUs on the indicated destination edge */
874 trim_right_edge (jpeg_transform_info
*info
, JDIMENSION full_width
)
878 MCU_cols
= info
->output_width
/ info
->iMCU_sample_width
;
879 if (MCU_cols
> 0 && info
->x_crop_offset
+ MCU_cols
==
880 full_width
/ info
->iMCU_sample_width
)
881 info
->output_width
= MCU_cols
* info
->iMCU_sample_width
;
885 trim_bottom_edge (jpeg_transform_info
*info
, JDIMENSION full_height
)
889 MCU_rows
= info
->output_height
/ info
->iMCU_sample_height
;
890 if (MCU_rows
> 0 && info
->y_crop_offset
+ MCU_rows
==
891 full_height
/ info
->iMCU_sample_height
)
892 info
->output_height
= MCU_rows
* info
->iMCU_sample_height
;
896 /* Request any required workspace.
898 * This routine figures out the size that the output image will be
899 * (which implies that all the transform parameters must be set before
902 * We allocate the workspace virtual arrays from the source decompression
903 * object, so that all the arrays (both the original data and the workspace)
904 * will be taken into account while making memory management decisions.
905 * Hence, this routine must be called after jpeg_read_header (which reads
906 * the image dimensions) and before jpeg_read_coefficients (which realizes
907 * the source's virtual arrays).
909 * This function returns FALSE right away if -perfect is given
910 * and transformation is not perfect. Otherwise returns TRUE.
914 jtransform_request_workspace (j_decompress_ptr srcinfo
,
915 jpeg_transform_info
*info
)
917 jvirt_barray_ptr
*coef_arrays
;
918 boolean need_workspace
, transpose_it
;
919 jpeg_component_info
*compptr
;
920 JDIMENSION xoffset
, yoffset
;
921 JDIMENSION width_in_iMCUs
, height_in_iMCUs
;
922 JDIMENSION width_in_blocks
, height_in_blocks
;
923 int ci
, h_samp_factor
, v_samp_factor
;
925 /* Determine number of components in output image */
926 if (info
->force_grayscale
&&
927 srcinfo
->jpeg_color_space
== JCS_YCbCr
&&
928 srcinfo
->num_components
== 3)
929 /* We'll only process the first component */
930 info
->num_components
= 1;
932 /* Process all the components */
933 info
->num_components
= srcinfo
->num_components
;
935 /* Compute output image dimensions and related values. */
936 #if JPEG_LIB_VERSION >= 80
937 jpeg_core_output_dimensions(srcinfo
);
939 srcinfo
->output_width
= srcinfo
->image_width
;
940 srcinfo
->output_height
= srcinfo
->image_height
;
943 /* Return right away if -perfect is given and transformation is not perfect.
946 if (info
->num_components
== 1) {
947 if (!jtransform_perfect_transform(srcinfo
->output_width
,
948 srcinfo
->output_height
,
949 srcinfo
->_min_DCT_h_scaled_size
,
950 srcinfo
->_min_DCT_v_scaled_size
,
954 if (!jtransform_perfect_transform(srcinfo
->output_width
,
955 srcinfo
->output_height
,
956 srcinfo
->max_h_samp_factor
* srcinfo
->_min_DCT_h_scaled_size
,
957 srcinfo
->max_v_samp_factor
* srcinfo
->_min_DCT_v_scaled_size
,
963 /* If there is only one output component, force the iMCU size to be 1;
964 * else use the source iMCU size. (This allows us to do the right thing
965 * when reducing color to grayscale, and also provides a handy way of
966 * cleaning up "funny" grayscale images whose sampling factors are not 1x1.)
968 switch (info
->transform
) {
969 case JXFORM_TRANSPOSE
:
970 case JXFORM_TRANSVERSE
:
973 info
->output_width
= srcinfo
->output_height
;
974 info
->output_height
= srcinfo
->output_width
;
975 if (info
->num_components
== 1) {
976 info
->iMCU_sample_width
= srcinfo
->_min_DCT_v_scaled_size
;
977 info
->iMCU_sample_height
= srcinfo
->_min_DCT_h_scaled_size
;
979 info
->iMCU_sample_width
=
980 srcinfo
->max_v_samp_factor
* srcinfo
->_min_DCT_v_scaled_size
;
981 info
->iMCU_sample_height
=
982 srcinfo
->max_h_samp_factor
* srcinfo
->_min_DCT_h_scaled_size
;
986 info
->output_width
= srcinfo
->output_width
;
987 info
->output_height
= srcinfo
->output_height
;
988 if (info
->num_components
== 1) {
989 info
->iMCU_sample_width
= srcinfo
->_min_DCT_h_scaled_size
;
990 info
->iMCU_sample_height
= srcinfo
->_min_DCT_v_scaled_size
;
992 info
->iMCU_sample_width
=
993 srcinfo
->max_h_samp_factor
* srcinfo
->_min_DCT_h_scaled_size
;
994 info
->iMCU_sample_height
=
995 srcinfo
->max_v_samp_factor
* srcinfo
->_min_DCT_v_scaled_size
;
1000 /* If cropping has been requested, compute the crop area's position and
1001 * dimensions, ensuring that its upper left corner falls at an iMCU boundary.
1004 /* Insert default values for unset crop parameters */
1005 if (info
->crop_xoffset_set
== JCROP_UNSET
)
1006 info
->crop_xoffset
= 0; /* default to +0 */
1007 if (info
->crop_yoffset_set
== JCROP_UNSET
)
1008 info
->crop_yoffset
= 0; /* default to +0 */
1009 if (info
->crop_xoffset
>= info
->output_width
||
1010 info
->crop_yoffset
>= info
->output_height
)
1011 ERREXIT(srcinfo
, JERR_CONVERSION_NOTIMPL
);
1012 if (info
->crop_width_set
== JCROP_UNSET
)
1013 info
->crop_width
= info
->output_width
- info
->crop_xoffset
;
1014 if (info
->crop_height_set
== JCROP_UNSET
)
1015 info
->crop_height
= info
->output_height
- info
->crop_yoffset
;
1016 /* Ensure parameters are valid */
1017 if (info
->crop_width
<= 0 || info
->crop_width
> info
->output_width
||
1018 info
->crop_height
<= 0 || info
->crop_height
> info
->output_height
||
1019 info
->crop_xoffset
> info
->output_width
- info
->crop_width
||
1020 info
->crop_yoffset
> info
->output_height
- info
->crop_height
)
1021 ERREXIT(srcinfo
, JERR_CONVERSION_NOTIMPL
);
1022 /* Convert negative crop offsets into regular offsets */
1023 if (info
->crop_xoffset_set
== JCROP_NEG
)
1024 xoffset
= info
->output_width
- info
->crop_width
- info
->crop_xoffset
;
1026 xoffset
= info
->crop_xoffset
;
1027 if (info
->crop_yoffset_set
== JCROP_NEG
)
1028 yoffset
= info
->output_height
- info
->crop_height
- info
->crop_yoffset
;
1030 yoffset
= info
->crop_yoffset
;
1031 /* Now adjust so that upper left corner falls at an iMCU boundary */
1032 if (info
->crop_width_set
== JCROP_FORCE
)
1033 info
->output_width
= info
->crop_width
;
1035 info
->output_width
=
1036 info
->crop_width
+ (xoffset
% info
->iMCU_sample_width
);
1037 if (info
->crop_height_set
== JCROP_FORCE
)
1038 info
->output_height
= info
->crop_height
;
1040 info
->output_height
=
1041 info
->crop_height
+ (yoffset
% info
->iMCU_sample_height
);
1042 /* Save x/y offsets measured in iMCUs */
1043 info
->x_crop_offset
= xoffset
/ info
->iMCU_sample_width
;
1044 info
->y_crop_offset
= yoffset
/ info
->iMCU_sample_height
;
1046 info
->x_crop_offset
= 0;
1047 info
->y_crop_offset
= 0;
1050 /* Figure out whether we need workspace arrays,
1051 * and if so whether they are transposed relative to the source.
1053 need_workspace
= FALSE
;
1054 transpose_it
= FALSE
;
1055 switch (info
->transform
) {
1057 if (info
->x_crop_offset
!= 0 || info
->y_crop_offset
!= 0)
1058 need_workspace
= TRUE
;
1059 /* No workspace needed if neither cropping nor transforming */
1063 trim_right_edge(info
, srcinfo
->output_width
);
1064 if (info
->y_crop_offset
!= 0 || info
->slow_hflip
)
1065 need_workspace
= TRUE
;
1066 /* do_flip_h_no_crop doesn't need a workspace array */
1070 trim_bottom_edge(info
, srcinfo
->output_height
);
1071 /* Need workspace arrays having same dimensions as source image. */
1072 need_workspace
= TRUE
;
1074 case JXFORM_TRANSPOSE
:
1075 /* transpose does NOT have to trim anything */
1076 /* Need workspace arrays having transposed dimensions. */
1077 need_workspace
= TRUE
;
1078 transpose_it
= TRUE
;
1080 case JXFORM_TRANSVERSE
:
1082 trim_right_edge(info
, srcinfo
->output_height
);
1083 trim_bottom_edge(info
, srcinfo
->output_width
);
1085 /* Need workspace arrays having transposed dimensions. */
1086 need_workspace
= TRUE
;
1087 transpose_it
= TRUE
;
1091 trim_right_edge(info
, srcinfo
->output_height
);
1092 /* Need workspace arrays having transposed dimensions. */
1093 need_workspace
= TRUE
;
1094 transpose_it
= TRUE
;
1096 case JXFORM_ROT_180
:
1098 trim_right_edge(info
, srcinfo
->output_width
);
1099 trim_bottom_edge(info
, srcinfo
->output_height
);
1101 /* Need workspace arrays having same dimensions as source image. */
1102 need_workspace
= TRUE
;
1104 case JXFORM_ROT_270
:
1106 trim_bottom_edge(info
, srcinfo
->output_width
);
1107 /* Need workspace arrays having transposed dimensions. */
1108 need_workspace
= TRUE
;
1109 transpose_it
= TRUE
;
1113 /* Allocate workspace if needed.
1114 * Note that we allocate arrays padded out to the next iMCU boundary,
1115 * so that transform routines need not worry about missing edge blocks.
1117 if (need_workspace
) {
1118 coef_arrays
= (jvirt_barray_ptr
*)
1119 (*srcinfo
->mem
->alloc_small
) ((j_common_ptr
) srcinfo
, JPOOL_IMAGE
,
1120 SIZEOF(jvirt_barray_ptr
) * info
->num_components
);
1121 width_in_iMCUs
= (JDIMENSION
)
1122 jdiv_round_up((long) info
->output_width
,
1123 (long) info
->iMCU_sample_width
);
1124 height_in_iMCUs
= (JDIMENSION
)
1125 jdiv_round_up((long) info
->output_height
,
1126 (long) info
->iMCU_sample_height
);
1127 for (ci
= 0; ci
< info
->num_components
; ci
++) {
1128 compptr
= srcinfo
->comp_info
+ ci
;
1129 if (info
->num_components
== 1) {
1130 /* we're going to force samp factors to 1x1 in this case */
1131 h_samp_factor
= v_samp_factor
= 1;
1132 } else if (transpose_it
) {
1133 h_samp_factor
= compptr
->v_samp_factor
;
1134 v_samp_factor
= compptr
->h_samp_factor
;
1136 h_samp_factor
= compptr
->h_samp_factor
;
1137 v_samp_factor
= compptr
->v_samp_factor
;
1139 width_in_blocks
= width_in_iMCUs
* h_samp_factor
;
1140 height_in_blocks
= height_in_iMCUs
* v_samp_factor
;
1141 coef_arrays
[ci
] = (*srcinfo
->mem
->request_virt_barray
)
1142 ((j_common_ptr
) srcinfo
, JPOOL_IMAGE
, FALSE
,
1143 width_in_blocks
, height_in_blocks
, (JDIMENSION
) v_samp_factor
);
1145 info
->workspace_coef_arrays
= coef_arrays
;
1147 info
->workspace_coef_arrays
= NULL
;
1153 /* Transpose destination image parameters */
1156 transpose_critical_parameters (j_compress_ptr dstinfo
)
1158 int tblno
, i
, j
, ci
, itemp
;
1159 jpeg_component_info
*compptr
;
1160 JQUANT_TBL
*qtblptr
;
1164 /* Transpose image dimensions */
1165 jtemp
= dstinfo
->image_width
;
1166 dstinfo
->image_width
= dstinfo
->image_height
;
1167 dstinfo
->image_height
= jtemp
;
1168 #if JPEG_LIB_VERSION >= 70
1169 itemp
= dstinfo
->min_DCT_h_scaled_size
;
1170 dstinfo
->min_DCT_h_scaled_size
= dstinfo
->min_DCT_v_scaled_size
;
1171 dstinfo
->min_DCT_v_scaled_size
= itemp
;
1174 /* Transpose sampling factors */
1175 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
1176 compptr
= dstinfo
->comp_info
+ ci
;
1177 itemp
= compptr
->h_samp_factor
;
1178 compptr
->h_samp_factor
= compptr
->v_samp_factor
;
1179 compptr
->v_samp_factor
= itemp
;
1182 /* Transpose quantization tables */
1183 for (tblno
= 0; tblno
< NUM_QUANT_TBLS
; tblno
++) {
1184 qtblptr
= dstinfo
->quant_tbl_ptrs
[tblno
];
1185 if (qtblptr
!= NULL
) {
1186 for (i
= 0; i
< DCTSIZE
; i
++) {
1187 for (j
= 0; j
< i
; j
++) {
1188 qtemp
= qtblptr
->quantval
[i
*DCTSIZE
+j
];
1189 qtblptr
->quantval
[i
*DCTSIZE
+j
] = qtblptr
->quantval
[j
*DCTSIZE
+i
];
1190 qtblptr
->quantval
[j
*DCTSIZE
+i
] = qtemp
;
1198 /* Adjust Exif image parameters.
1200 * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible.
1203 #if JPEG_LIB_VERSION >= 70
1205 adjust_exif_parameters (JOCTET FAR
* data
, unsigned int length
,
1206 JDIMENSION new_width
, JDIMENSION new_height
)
1208 boolean is_motorola
; /* Flag for byte order */
1209 unsigned int number_of_tags
, tagnum
;
1210 unsigned int firstoffset
, offset
;
1211 JDIMENSION new_value
;
1213 if (length
< 12) return; /* Length of an IFD entry */
1215 /* Discover byte order */
1216 if (GETJOCTET(data
[0]) == 0x49 && GETJOCTET(data
[1]) == 0x49)
1217 is_motorola
= FALSE
;
1218 else if (GETJOCTET(data
[0]) == 0x4D && GETJOCTET(data
[1]) == 0x4D)
1223 /* Check Tag Mark */
1225 if (GETJOCTET(data
[2]) != 0) return;
1226 if (GETJOCTET(data
[3]) != 0x2A) return;
1228 if (GETJOCTET(data
[3]) != 0) return;
1229 if (GETJOCTET(data
[2]) != 0x2A) return;
1232 /* Get first IFD offset (offset to IFD0) */
1234 if (GETJOCTET(data
[4]) != 0) return;
1235 if (GETJOCTET(data
[5]) != 0) return;
1236 firstoffset
= GETJOCTET(data
[6]);
1238 firstoffset
+= GETJOCTET(data
[7]);
1240 if (GETJOCTET(data
[7]) != 0) return;
1241 if (GETJOCTET(data
[6]) != 0) return;
1242 firstoffset
= GETJOCTET(data
[5]);
1244 firstoffset
+= GETJOCTET(data
[4]);
1246 if (firstoffset
> length
- 2) return; /* check end of data segment */
1248 /* Get the number of directory entries contained in this IFD */
1250 number_of_tags
= GETJOCTET(data
[firstoffset
]);
1251 number_of_tags
<<= 8;
1252 number_of_tags
+= GETJOCTET(data
[firstoffset
+1]);
1254 number_of_tags
= GETJOCTET(data
[firstoffset
+1]);
1255 number_of_tags
<<= 8;
1256 number_of_tags
+= GETJOCTET(data
[firstoffset
]);
1258 if (number_of_tags
== 0) return;
1261 /* Search for ExifSubIFD offset Tag in IFD0 */
1263 if (firstoffset
> length
- 12) return; /* check end of data segment */
1264 /* Get Tag number */
1266 tagnum
= GETJOCTET(data
[firstoffset
]);
1268 tagnum
+= GETJOCTET(data
[firstoffset
+1]);
1270 tagnum
= GETJOCTET(data
[firstoffset
+1]);
1272 tagnum
+= GETJOCTET(data
[firstoffset
]);
1274 if (tagnum
== 0x8769) break; /* found ExifSubIFD offset Tag */
1275 if (--number_of_tags
== 0) return;
1279 /* Get the ExifSubIFD offset */
1281 if (GETJOCTET(data
[firstoffset
+8]) != 0) return;
1282 if (GETJOCTET(data
[firstoffset
+9]) != 0) return;
1283 offset
= GETJOCTET(data
[firstoffset
+10]);
1285 offset
+= GETJOCTET(data
[firstoffset
+11]);
1287 if (GETJOCTET(data
[firstoffset
+11]) != 0) return;
1288 if (GETJOCTET(data
[firstoffset
+10]) != 0) return;
1289 offset
= GETJOCTET(data
[firstoffset
+9]);
1291 offset
+= GETJOCTET(data
[firstoffset
+8]);
1293 if (offset
> length
- 2) return; /* check end of data segment */
1295 /* Get the number of directory entries contained in this SubIFD */
1297 number_of_tags
= GETJOCTET(data
[offset
]);
1298 number_of_tags
<<= 8;
1299 number_of_tags
+= GETJOCTET(data
[offset
+1]);
1301 number_of_tags
= GETJOCTET(data
[offset
+1]);
1302 number_of_tags
<<= 8;
1303 number_of_tags
+= GETJOCTET(data
[offset
]);
1305 if (number_of_tags
< 2) return;
1308 /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */
1310 if (offset
> length
- 12) return; /* check end of data segment */
1311 /* Get Tag number */
1313 tagnum
= GETJOCTET(data
[offset
]);
1315 tagnum
+= GETJOCTET(data
[offset
+1]);
1317 tagnum
= GETJOCTET(data
[offset
+1]);
1319 tagnum
+= GETJOCTET(data
[offset
]);
1321 if (tagnum
== 0xA002 || tagnum
== 0xA003) {
1322 if (tagnum
== 0xA002)
1323 new_value
= new_width
; /* ExifImageWidth Tag */
1325 new_value
= new_height
; /* ExifImageHeight Tag */
1327 data
[offset
+2] = 0; /* Format = unsigned long (4 octets) */
1329 data
[offset
+4] = 0; /* Number Of Components = 1 */
1335 data
[offset
+10] = (JOCTET
)((new_value
>> 8) & 0xFF);
1336 data
[offset
+11] = (JOCTET
)(new_value
& 0xFF);
1338 data
[offset
+2] = 4; /* Format = unsigned long (4 octets) */
1340 data
[offset
+4] = 1; /* Number Of Components = 1 */
1344 data
[offset
+8] = (JOCTET
)(new_value
& 0xFF);
1345 data
[offset
+9] = (JOCTET
)((new_value
>> 8) & 0xFF);
1346 data
[offset
+10] = 0;
1347 data
[offset
+11] = 0;
1351 } while (--number_of_tags
);
1356 /* Adjust output image parameters as needed.
1358 * This must be called after jpeg_copy_critical_parameters()
1359 * and before jpeg_write_coefficients().
1361 * The return value is the set of virtual coefficient arrays to be written
1362 * (either the ones allocated by jtransform_request_workspace, or the
1363 * original source data arrays). The caller will need to pass this value
1364 * to jpeg_write_coefficients().
1367 GLOBAL(jvirt_barray_ptr
*)
1368 jtransform_adjust_parameters (j_decompress_ptr srcinfo
,
1369 j_compress_ptr dstinfo
,
1370 jvirt_barray_ptr
*src_coef_arrays
,
1371 jpeg_transform_info
*info
)
1373 /* If force-to-grayscale is requested, adjust destination parameters */
1374 if (info
->force_grayscale
) {
1375 /* First, ensure we have YCbCr or grayscale data, and that the source's
1376 * Y channel is full resolution. (No reasonable person would make Y
1377 * be less than full resolution, so actually coping with that case
1378 * isn't worth extra code space. But we check it to avoid crashing.)
1380 if (((dstinfo
->jpeg_color_space
== JCS_YCbCr
&&
1381 dstinfo
->num_components
== 3) ||
1382 (dstinfo
->jpeg_color_space
== JCS_GRAYSCALE
&&
1383 dstinfo
->num_components
== 1)) &&
1384 srcinfo
->comp_info
[0].h_samp_factor
== srcinfo
->max_h_samp_factor
&&
1385 srcinfo
->comp_info
[0].v_samp_factor
== srcinfo
->max_v_samp_factor
) {
1386 /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
1387 * properly. Among other things, it sets the target h_samp_factor &
1388 * v_samp_factor to 1, which typically won't match the source.
1389 * We have to preserve the source's quantization table number, however.
1391 int sv_quant_tbl_no
= dstinfo
->comp_info
[0].quant_tbl_no
;
1392 jpeg_set_colorspace(dstinfo
, JCS_GRAYSCALE
);
1393 dstinfo
->comp_info
[0].quant_tbl_no
= sv_quant_tbl_no
;
1395 /* Sorry, can't do it */
1396 ERREXIT(dstinfo
, JERR_CONVERSION_NOTIMPL
);
1398 } else if (info
->num_components
== 1) {
1399 /* For a single-component source, we force the destination sampling factors
1400 * to 1x1, with or without force_grayscale. This is useful because some
1401 * decoders choke on grayscale images with other sampling factors.
1403 dstinfo
->comp_info
[0].h_samp_factor
= 1;
1404 dstinfo
->comp_info
[0].v_samp_factor
= 1;
1407 /* Correct the destination's image dimensions as necessary
1408 * for rotate/flip, resize, and crop operations.
1410 #if JPEG_LIB_VERSION >= 70
1411 dstinfo
->jpeg_width
= info
->output_width
;
1412 dstinfo
->jpeg_height
= info
->output_height
;
1415 /* Transpose destination image parameters */
1416 switch (info
->transform
) {
1417 case JXFORM_TRANSPOSE
:
1418 case JXFORM_TRANSVERSE
:
1420 case JXFORM_ROT_270
:
1421 #if JPEG_LIB_VERSION < 70
1422 dstinfo
->image_width
= info
->output_height
;
1423 dstinfo
->image_height
= info
->output_width
;
1425 transpose_critical_parameters(dstinfo
);
1428 #if JPEG_LIB_VERSION < 70
1429 dstinfo
->image_width
= info
->output_width
;
1430 dstinfo
->image_height
= info
->output_height
;
1435 /* Adjust Exif properties */
1436 if (srcinfo
->marker_list
!= NULL
&&
1437 srcinfo
->marker_list
->marker
== JPEG_APP0
+1 &&
1438 srcinfo
->marker_list
->data_length
>= 6 &&
1439 GETJOCTET(srcinfo
->marker_list
->data
[0]) == 0x45 &&
1440 GETJOCTET(srcinfo
->marker_list
->data
[1]) == 0x78 &&
1441 GETJOCTET(srcinfo
->marker_list
->data
[2]) == 0x69 &&
1442 GETJOCTET(srcinfo
->marker_list
->data
[3]) == 0x66 &&
1443 GETJOCTET(srcinfo
->marker_list
->data
[4]) == 0 &&
1444 GETJOCTET(srcinfo
->marker_list
->data
[5]) == 0) {
1445 /* Suppress output of JFIF marker */
1446 dstinfo
->write_JFIF_header
= FALSE
;
1447 #if JPEG_LIB_VERSION >= 70
1448 /* Adjust Exif image parameters */
1449 if (dstinfo
->jpeg_width
!= srcinfo
->image_width
||
1450 dstinfo
->jpeg_height
!= srcinfo
->image_height
)
1451 /* Align data segment to start of TIFF structure for parsing */
1452 adjust_exif_parameters(srcinfo
->marker_list
->data
+ 6,
1453 srcinfo
->marker_list
->data_length
- 6,
1454 dstinfo
->jpeg_width
, dstinfo
->jpeg_height
);
1458 /* Return the appropriate output data set */
1459 if (info
->workspace_coef_arrays
!= NULL
)
1460 return info
->workspace_coef_arrays
;
1461 return src_coef_arrays
;
1465 /* Execute the actual transformation, if any.
1467 * This must be called *after* jpeg_write_coefficients, because it depends
1468 * on jpeg_write_coefficients to have computed subsidiary values such as
1469 * the per-component width and height fields in the destination object.
1471 * Note that some transformations will modify the source data arrays!
1475 jtransform_execute_transform (j_decompress_ptr srcinfo
,
1476 j_compress_ptr dstinfo
,
1477 jvirt_barray_ptr
*src_coef_arrays
,
1478 jpeg_transform_info
*info
)
1480 jvirt_barray_ptr
*dst_coef_arrays
= info
->workspace_coef_arrays
;
1482 /* Note: conditions tested here should match those in switch statement
1483 * in jtransform_request_workspace()
1485 switch (info
->transform
) {
1487 if (info
->x_crop_offset
!= 0 || info
->y_crop_offset
!= 0)
1488 do_crop(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1489 src_coef_arrays
, dst_coef_arrays
);
1492 if (info
->y_crop_offset
!= 0 || info
->slow_hflip
)
1493 do_flip_h(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1494 src_coef_arrays
, dst_coef_arrays
);
1496 do_flip_h_no_crop(srcinfo
, dstinfo
, info
->x_crop_offset
,
1500 do_flip_v(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1501 src_coef_arrays
, dst_coef_arrays
);
1503 case JXFORM_TRANSPOSE
:
1504 do_transpose(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1505 src_coef_arrays
, dst_coef_arrays
);
1507 case JXFORM_TRANSVERSE
:
1508 do_transverse(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1509 src_coef_arrays
, dst_coef_arrays
);
1512 do_rot_90(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1513 src_coef_arrays
, dst_coef_arrays
);
1515 case JXFORM_ROT_180
:
1516 do_rot_180(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1517 src_coef_arrays
, dst_coef_arrays
);
1519 case JXFORM_ROT_270
:
1520 do_rot_270(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1521 src_coef_arrays
, dst_coef_arrays
);
1526 /* jtransform_perfect_transform
1528 * Determine whether lossless transformation is perfectly
1529 * possible for a specified image and transformation.
1532 * image_width, image_height: source image dimensions.
1533 * MCU_width, MCU_height: pixel dimensions of MCU.
1534 * transform: transformation identifier.
1535 * Parameter sources from initialized jpeg_struct
1536 * (after reading source header):
1537 * image_width = cinfo.image_width
1538 * image_height = cinfo.image_height
1539 * MCU_width = cinfo.max_h_samp_factor * cinfo.block_size
1540 * MCU_height = cinfo.max_v_samp_factor * cinfo.block_size
1542 * TRUE = perfect transformation possible
1543 * FALSE = perfect transformation not possible
1544 * (may use custom action then)
1548 jtransform_perfect_transform(JDIMENSION image_width
, JDIMENSION image_height
,
1549 int MCU_width
, int MCU_height
,
1550 JXFORM_CODE transform
)
1552 boolean result
= TRUE
; /* initialize TRUE */
1554 switch (transform
) {
1556 case JXFORM_ROT_270
:
1557 if (image_width
% (JDIMENSION
) MCU_width
)
1562 if (image_height
% (JDIMENSION
) MCU_height
)
1565 case JXFORM_TRANSVERSE
:
1566 case JXFORM_ROT_180
:
1567 if (image_width
% (JDIMENSION
) MCU_width
)
1569 if (image_height
% (JDIMENSION
) MCU_height
)
1579 #endif /* TRANSFORMS_SUPPORTED */
1582 /* Setup decompression object to save desired markers in memory.
1583 * This must be called before jpeg_read_header() to have the desired effect.
1587 jcopy_markers_setup (j_decompress_ptr srcinfo
, JCOPY_OPTION option
)
1589 #ifdef SAVE_MARKERS_SUPPORTED
1592 /* Save comments except under NONE option */
1593 if (option
!= JCOPYOPT_NONE
) {
1594 jpeg_save_markers(srcinfo
, JPEG_COM
, 0xFFFF);
1596 /* Save all types of APPn markers iff ALL option */
1597 if (option
== JCOPYOPT_ALL
) {
1598 for (m
= 0; m
< 16; m
++)
1599 jpeg_save_markers(srcinfo
, JPEG_APP0
+ m
, 0xFFFF);
1602 (void) srcinfo
; (void) option
;
1603 #endif /* SAVE_MARKERS_SUPPORTED */
1606 /* Copy markers saved in the given source object to the destination object.
1607 * This should be called just after jpeg_start_compress() or
1608 * jpeg_write_coefficients().
1609 * Note that those routines will have written the SOI, and also the
1610 * JFIF APP0 or Adobe APP14 markers if selected.
1614 jcopy_markers_execute (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
1615 JCOPY_OPTION option
)
1617 jpeg_saved_marker_ptr marker
;
1619 /* In the current implementation, we don't actually need to examine the
1620 * option flag here; we just copy everything that got saved.
1621 * But to avoid confusion, we do not output JFIF and Adobe APP14 markers
1622 * if the encoder library already wrote one.
1626 for (marker
= srcinfo
->marker_list
; marker
!= NULL
; marker
= marker
->next
) {
1627 if (dstinfo
->write_JFIF_header
&&
1628 marker
->marker
== JPEG_APP0
&&
1629 marker
->data_length
>= 5 &&
1630 GETJOCTET(marker
->data
[0]) == 0x4A &&
1631 GETJOCTET(marker
->data
[1]) == 0x46 &&
1632 GETJOCTET(marker
->data
[2]) == 0x49 &&
1633 GETJOCTET(marker
->data
[3]) == 0x46 &&
1634 GETJOCTET(marker
->data
[4]) == 0)
1635 continue; /* reject duplicate JFIF */
1636 if (dstinfo
->write_Adobe_marker
&&
1637 marker
->marker
== JPEG_APP0
+14 &&
1638 marker
->data_length
>= 5 &&
1639 GETJOCTET(marker
->data
[0]) == 0x41 &&
1640 GETJOCTET(marker
->data
[1]) == 0x64 &&
1641 GETJOCTET(marker
->data
[2]) == 0x6F &&
1642 GETJOCTET(marker
->data
[3]) == 0x62 &&
1643 GETJOCTET(marker
->data
[4]) == 0x65)
1644 continue; /* reject duplicate Adobe */
1645 #ifdef NEED_FAR_POINTERS
1646 /* We could use jpeg_write_marker if the data weren't FAR... */
1649 jpeg_write_m_header(dstinfo
, marker
->marker
, marker
->data_length
);
1650 for (i
= 0; i
< marker
->data_length
; i
++)
1651 jpeg_write_m_byte(dstinfo
, marker
->data
[i
]);
1654 jpeg_write_marker(dstinfo
, marker
->marker
,
1655 marker
->data
, marker
->data_length
);