4 * Copyright (C) 1997-2001, Thomas G. Lane.
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.
78 /* Drop code may be used with or without virtual memory adaptation code.
79 * This code has some dependencies on internal library behavior, so you
80 * may choose to disable it. For example, it doesn't make a difference
81 * if you only use jmemnobs anyway.
83 #ifndef DROP_REQUEST_FROM_SRC
84 #define DROP_REQUEST_FROM_SRC 1 /* 0 disables adaptation */
88 #if DROP_REQUEST_FROM_SRC
89 /* Force jpeg_read_coefficients to request
90 * the virtual coefficient arrays from
91 * the source decompression object.
93 METHODDEF(jvirt_barray_ptr
)
94 drop_request_virt_barray (j_common_ptr cinfo
, int pool_id
, boolean pre_zero
,
95 JDIMENSION blocksperrow
, JDIMENSION numrows
,
98 j_decompress_ptr srcinfo
= (j_decompress_ptr
) cinfo
->client_data
;
100 return (*srcinfo
->mem
->request_virt_barray
)
101 ((j_common_ptr
) srcinfo
, pool_id
, pre_zero
,
102 blocksperrow
, numrows
, maxaccess
);
106 /* Force jpeg_read_coefficients to return
107 * after requesting and before accessing
108 * the virtual coefficient arrays.
111 drop_consume_input (j_decompress_ptr cinfo
)
113 return JPEG_SUSPENDED
;
118 drop_start_input_pass (j_decompress_ptr cinfo
)
120 cinfo
->inputctl
->consume_input
= drop_consume_input
;
125 drop_request_from_src (j_decompress_ptr dropinfo
, j_decompress_ptr srcinfo
)
127 void *save_client_data
;
128 JMETHOD(jvirt_barray_ptr
, save_request_virt_barray
,
129 (j_common_ptr cinfo
, int pool_id
, boolean pre_zero
,
130 JDIMENSION blocksperrow
, JDIMENSION numrows
, JDIMENSION maxaccess
));
131 JMETHOD(void, save_start_input_pass
, (j_decompress_ptr cinfo
));
133 /* Set custom method pointers, save original pointers */
134 save_client_data
= dropinfo
->client_data
;
135 dropinfo
->client_data
= (void *) srcinfo
;
136 save_request_virt_barray
= dropinfo
->mem
->request_virt_barray
;
137 dropinfo
->mem
->request_virt_barray
= drop_request_virt_barray
;
138 save_start_input_pass
= dropinfo
->inputctl
->start_input_pass
;
139 dropinfo
->inputctl
->start_input_pass
= drop_start_input_pass
;
141 /* Execute only initialization part.
142 * Requested coefficient arrays will be realized later by the srcinfo object.
143 * Next call to the same function will then do the actual data reading.
144 * NB: since we request the coefficient arrays from another object,
145 * the inherent realization call is effectively a no-op.
147 (void) jpeg_read_coefficients(dropinfo
);
149 /* Reset method pointers */
150 dropinfo
->client_data
= save_client_data
;
151 dropinfo
->mem
->request_virt_barray
= save_request_virt_barray
;
152 dropinfo
->inputctl
->start_input_pass
= save_start_input_pass
;
153 /* Do input initialization for first scan now,
154 * which also resets the consume_input method.
156 (*save_start_input_pass
)(dropinfo
);
158 #endif /* DROP_REQUEST_FROM_SRC */
162 dequant_comp (j_decompress_ptr cinfo
, jpeg_component_info
*compptr
,
163 jvirt_barray_ptr coef_array
, JQUANT_TBL
*qtblptr1
)
165 JDIMENSION blk_x
, blk_y
;
172 qtblptr
= compptr
->quant_table
;
173 for (blk_y
= 0; blk_y
< compptr
->height_in_blocks
;
174 blk_y
+= compptr
->v_samp_factor
) {
175 buffer
= (*cinfo
->mem
->access_virt_barray
)
176 ((j_common_ptr
) cinfo
, coef_array
, blk_y
,
177 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
178 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
179 block
= buffer
[offset_y
];
180 for (blk_x
= 0; blk_x
< compptr
->width_in_blocks
; blk_x
++) {
182 for (k
= 0; k
< DCTSIZE2
; k
++)
183 if (qtblptr
->quantval
[k
] != qtblptr1
->quantval
[k
])
184 ptr
[k
] *= qtblptr
->quantval
[k
] / qtblptr1
->quantval
[k
];
192 requant_comp (j_decompress_ptr cinfo
, jpeg_component_info
*compptr
,
193 jvirt_barray_ptr coef_array
, JQUANT_TBL
*qtblptr1
)
195 JDIMENSION blk_x
, blk_y
;
203 qtblptr
= compptr
->quant_table
;
204 for (blk_y
= 0; blk_y
< compptr
->height_in_blocks
;
205 blk_y
+= compptr
->v_samp_factor
) {
206 buffer
= (*cinfo
->mem
->access_virt_barray
)
207 ((j_common_ptr
) cinfo
, coef_array
, blk_y
,
208 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
209 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
210 block
= buffer
[offset_y
];
211 for (blk_x
= 0; blk_x
< compptr
->width_in_blocks
; blk_x
++) {
213 for (k
= 0; k
< DCTSIZE2
; k
++) {
214 temp
= qtblptr
->quantval
[k
];
215 qval
= qtblptr1
->quantval
[k
];
218 /* The following quantization code is a copy from jcdctmgr.c */
220 #define DIVIDE_BY(a,b) a /= b
222 #define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0
226 temp
+= qval
>>1; /* for rounding */
227 DIVIDE_BY(temp
, qval
);
230 temp
+= qval
>>1; /* for rounding */
231 DIVIDE_BY(temp
, qval
);
242 /* Calculate largest common denominator with Euklid's algorithm.
245 largest_common_denominator(JCOEF a
, JCOEF b
)
260 adjust_quant(j_decompress_ptr srcinfo
, jvirt_barray_ptr
*src_coef_arrays
,
261 j_decompress_ptr dropinfo
, jvirt_barray_ptr
*drop_coef_arrays
,
262 boolean trim
, j_compress_ptr dstinfo
)
264 jpeg_component_info
*compptr1
, *compptr2
;
265 JQUANT_TBL
*qtblptr1
, *qtblptr2
, *qtblptr3
;
268 for (ci
= 0; ci
< dstinfo
->num_components
&&
269 ci
< dropinfo
->num_components
; ci
++) {
270 compptr1
= srcinfo
->comp_info
+ ci
;
271 compptr2
= dropinfo
->comp_info
+ ci
;
272 qtblptr1
= compptr1
->quant_table
;
273 qtblptr2
= compptr2
->quant_table
;
274 for (k
= 0; k
< DCTSIZE2
; k
++) {
275 if (qtblptr1
->quantval
[k
] != qtblptr2
->quantval
[k
]) {
277 requant_comp(dropinfo
, compptr2
, drop_coef_arrays
[ci
], qtblptr1
);
279 qtblptr3
= dstinfo
->quant_tbl_ptrs
[compptr1
->quant_tbl_no
];
280 for (k
= 0; k
< DCTSIZE2
; k
++)
281 if (qtblptr1
->quantval
[k
] != qtblptr2
->quantval
[k
])
282 qtblptr3
->quantval
[k
] = largest_common_denominator
283 (qtblptr1
->quantval
[k
], qtblptr2
->quantval
[k
]);
284 dequant_comp(srcinfo
, compptr1
, src_coef_arrays
[ci
], qtblptr3
);
285 dequant_comp(dropinfo
, compptr2
, drop_coef_arrays
[ci
], qtblptr3
);
295 do_drop (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
296 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
297 jvirt_barray_ptr
*src_coef_arrays
,
298 j_decompress_ptr dropinfo
, jvirt_barray_ptr
*drop_coef_arrays
,
299 JDIMENSION drop_width
, JDIMENSION drop_height
)
300 /* Drop. If the dropinfo component number is smaller than the destination's,
301 * we fill in the remaining components with zero. This provides the feature
302 * of dropping grayscale into (arbitrarily sampled) color images.
305 JDIMENSION comp_width
, comp_height
;
306 JDIMENSION blk_y
, x_drop_blocks
, y_drop_blocks
;
308 JBLOCKARRAY src_buffer
, dst_buffer
;
309 jpeg_component_info
*compptr
;
311 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
312 compptr
= dstinfo
->comp_info
+ ci
;
313 comp_width
= drop_width
* compptr
->h_samp_factor
;
314 comp_height
= drop_height
* compptr
->v_samp_factor
;
315 x_drop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
316 y_drop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
317 for (blk_y
= 0; blk_y
< comp_height
; blk_y
+= compptr
->v_samp_factor
) {
318 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
319 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
], blk_y
+ y_drop_blocks
,
320 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
321 if (ci
< dropinfo
->num_components
) {
322 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
323 ((j_common_ptr
) srcinfo
, drop_coef_arrays
[ci
], blk_y
,
324 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
325 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
326 jcopy_block_row(src_buffer
[offset_y
],
327 dst_buffer
[offset_y
] + x_drop_blocks
,
331 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
332 jzero_far(dst_buffer
[offset_y
] + x_drop_blocks
,
333 comp_width
* SIZEOF(JBLOCK
));
342 do_crop (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
343 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
344 jvirt_barray_ptr
*src_coef_arrays
,
345 jvirt_barray_ptr
*dst_coef_arrays
)
346 /* Crop. This is only used when no rotate/flip is requested with the crop.
347 * Extension: If the destination size is larger than the source, we fill in
348 * the extra area with zero (neutral gray). Note we also have to zero partial
349 * iMCUs at the right and bottom edge of the source image area in this case.
352 JDIMENSION MCU_cols
, MCU_rows
, comp_width
, comp_height
;
353 JDIMENSION dst_blk_y
, x_crop_blocks
, y_crop_blocks
;
355 JBLOCKARRAY src_buffer
, dst_buffer
;
356 jpeg_component_info
*compptr
;
358 MCU_cols
= srcinfo
->image_width
/ (dstinfo
->max_h_samp_factor
* DCTSIZE
);
359 MCU_rows
= srcinfo
->image_height
/ (dstinfo
->max_v_samp_factor
* DCTSIZE
);
361 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
362 compptr
= dstinfo
->comp_info
+ ci
;
363 comp_width
= MCU_cols
* compptr
->h_samp_factor
;
364 comp_height
= MCU_rows
* compptr
->v_samp_factor
;
365 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
366 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
367 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
368 dst_blk_y
+= compptr
->v_samp_factor
) {
369 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
370 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
371 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
372 if (dstinfo
->image_height
> srcinfo
->image_height
) {
373 if (dst_blk_y
< y_crop_blocks
||
374 dst_blk_y
>= comp_height
+ y_crop_blocks
) {
375 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
376 jzero_far(dst_buffer
[offset_y
],
377 compptr
->width_in_blocks
* SIZEOF(JBLOCK
));
381 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
382 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
383 dst_blk_y
- y_crop_blocks
,
384 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
386 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
387 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
388 dst_blk_y
+ y_crop_blocks
,
389 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
391 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
392 if (dstinfo
->image_width
> srcinfo
->image_width
) {
393 if (x_crop_blocks
> 0) {
394 jzero_far(dst_buffer
[offset_y
],
395 x_crop_blocks
* SIZEOF(JBLOCK
));
397 jcopy_block_row(src_buffer
[offset_y
],
398 dst_buffer
[offset_y
] + x_crop_blocks
,
400 if (compptr
->width_in_blocks
> comp_width
+ x_crop_blocks
) {
401 jzero_far(dst_buffer
[offset_y
] +
402 comp_width
+ x_crop_blocks
,
403 (compptr
->width_in_blocks
-
404 comp_width
- x_crop_blocks
) * SIZEOF(JBLOCK
));
407 jcopy_block_row(src_buffer
[offset_y
] + x_crop_blocks
,
408 dst_buffer
[offset_y
],
409 compptr
->width_in_blocks
);
418 do_flip_h_no_crop (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
419 JDIMENSION x_crop_offset
,
420 jvirt_barray_ptr
*src_coef_arrays
)
421 /* Horizontal flip; done in-place, so no separate dest array is required.
422 * NB: this only works when y_crop_offset is zero.
425 JDIMENSION MCU_cols
, comp_width
, blk_x
, blk_y
, x_crop_blocks
;
430 jpeg_component_info
*compptr
;
432 /* Horizontal mirroring of DCT blocks is accomplished by swapping
433 * pairs of blocks in-place. Within a DCT block, we perform horizontal
434 * mirroring by changing the signs of odd-numbered columns.
435 * Partial iMCUs at the right edge are left untouched.
437 MCU_cols
= srcinfo
->image_width
/ (dstinfo
->max_h_samp_factor
* DCTSIZE
);
439 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
440 compptr
= dstinfo
->comp_info
+ ci
;
441 comp_width
= MCU_cols
* compptr
->h_samp_factor
;
442 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
443 for (blk_y
= 0; blk_y
< compptr
->height_in_blocks
;
444 blk_y
+= compptr
->v_samp_factor
) {
445 buffer
= (*srcinfo
->mem
->access_virt_barray
)
446 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
], blk_y
,
447 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
448 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
449 /* Do the mirroring */
450 for (blk_x
= 0; blk_x
* 2 < comp_width
; blk_x
++) {
451 ptr1
= buffer
[offset_y
][blk_x
];
452 ptr2
= buffer
[offset_y
][comp_width
- blk_x
- 1];
453 /* this unrolled loop doesn't need to know which row it's on... */
454 for (k
= 0; k
< DCTSIZE2
; k
+= 2) {
455 temp1
= *ptr1
; /* swap even column */
459 temp1
= *ptr1
; /* swap odd column with sign change */
465 if (x_crop_blocks
> 0) {
466 /* Now left-justify the portion of the data to be kept.
467 * We can't use a single jcopy_block_row() call because that routine
468 * depends on memcpy(), whose behavior is unspecified for overlapping
469 * source and destination areas. Sigh.
471 for (blk_x
= 0; blk_x
< compptr
->width_in_blocks
; blk_x
++) {
472 jcopy_block_row(buffer
[offset_y
] + blk_x
+ x_crop_blocks
,
473 buffer
[offset_y
] + blk_x
,
484 do_flip_h (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
485 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
486 jvirt_barray_ptr
*src_coef_arrays
,
487 jvirt_barray_ptr
*dst_coef_arrays
)
488 /* Horizontal flip in general cropping case */
490 JDIMENSION MCU_cols
, comp_width
, dst_blk_x
, dst_blk_y
;
491 JDIMENSION x_crop_blocks
, y_crop_blocks
;
493 JBLOCKARRAY src_buffer
, dst_buffer
;
494 JBLOCKROW src_row_ptr
, dst_row_ptr
;
495 JCOEFPTR src_ptr
, dst_ptr
;
496 jpeg_component_info
*compptr
;
498 /* Here we must output into a separate array because we can't touch
499 * different rows of a single virtual array simultaneously. Otherwise,
500 * this is essentially the same as the routine above.
502 MCU_cols
= srcinfo
->image_width
/ (dstinfo
->max_h_samp_factor
* DCTSIZE
);
504 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
505 compptr
= dstinfo
->comp_info
+ ci
;
506 comp_width
= MCU_cols
* compptr
->h_samp_factor
;
507 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
508 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
509 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
510 dst_blk_y
+= compptr
->v_samp_factor
) {
511 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
512 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
513 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
514 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
515 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
516 dst_blk_y
+ y_crop_blocks
,
517 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
518 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
519 dst_row_ptr
= dst_buffer
[offset_y
];
520 src_row_ptr
= src_buffer
[offset_y
];
521 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
; dst_blk_x
++) {
522 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
523 /* Do the mirrorable blocks */
524 dst_ptr
= dst_row_ptr
[dst_blk_x
];
525 src_ptr
= src_row_ptr
[comp_width
- x_crop_blocks
- dst_blk_x
- 1];
526 /* this unrolled loop doesn't need to know which row it's on... */
527 for (k
= 0; k
< DCTSIZE2
; k
+= 2) {
528 *dst_ptr
++ = *src_ptr
++; /* copy even column */
529 *dst_ptr
++ = - *src_ptr
++; /* copy odd column with sign change */
532 /* Copy last partial block(s) verbatim */
533 jcopy_block_row(src_row_ptr
+ dst_blk_x
+ x_crop_blocks
,
534 dst_row_ptr
+ dst_blk_x
,
545 do_flip_v (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
546 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
547 jvirt_barray_ptr
*src_coef_arrays
,
548 jvirt_barray_ptr
*dst_coef_arrays
)
551 JDIMENSION MCU_rows
, comp_height
, dst_blk_x
, dst_blk_y
;
552 JDIMENSION x_crop_blocks
, y_crop_blocks
;
553 int ci
, i
, j
, offset_y
;
554 JBLOCKARRAY src_buffer
, dst_buffer
;
555 JBLOCKROW src_row_ptr
, dst_row_ptr
;
556 JCOEFPTR src_ptr
, dst_ptr
;
557 jpeg_component_info
*compptr
;
559 /* We output into a separate array because we can't touch different
560 * rows of the source virtual array simultaneously. Otherwise, this
561 * is a pretty straightforward analog of horizontal flip.
562 * Within a DCT block, vertical mirroring is done by changing the signs
563 * of odd-numbered rows.
564 * Partial iMCUs at the bottom edge are copied verbatim.
566 MCU_rows
= srcinfo
->image_height
/ (dstinfo
->max_v_samp_factor
* DCTSIZE
);
568 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
569 compptr
= dstinfo
->comp_info
+ ci
;
570 comp_height
= MCU_rows
* compptr
->v_samp_factor
;
571 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
572 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
573 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
574 dst_blk_y
+= compptr
->v_samp_factor
) {
575 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
576 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
577 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
578 if (y_crop_blocks
+ dst_blk_y
< comp_height
) {
579 /* Row is within the mirrorable area. */
580 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
581 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
582 comp_height
- y_crop_blocks
- dst_blk_y
-
583 (JDIMENSION
) compptr
->v_samp_factor
,
584 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
586 /* Bottom-edge blocks will be copied verbatim. */
587 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
588 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
589 dst_blk_y
+ y_crop_blocks
,
590 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
592 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
593 if (y_crop_blocks
+ dst_blk_y
< comp_height
) {
594 /* Row is within the mirrorable area. */
595 dst_row_ptr
= dst_buffer
[offset_y
];
596 src_row_ptr
= src_buffer
[compptr
->v_samp_factor
- offset_y
- 1];
597 src_row_ptr
+= x_crop_blocks
;
598 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
;
600 dst_ptr
= dst_row_ptr
[dst_blk_x
];
601 src_ptr
= src_row_ptr
[dst_blk_x
];
602 for (i
= 0; i
< DCTSIZE
; i
+= 2) {
604 for (j
= 0; j
< DCTSIZE
; j
++)
605 *dst_ptr
++ = *src_ptr
++;
606 /* copy odd row with sign change */
607 for (j
= 0; j
< DCTSIZE
; j
++)
608 *dst_ptr
++ = - *src_ptr
++;
612 /* Just copy row verbatim. */
613 jcopy_block_row(src_buffer
[offset_y
] + x_crop_blocks
,
614 dst_buffer
[offset_y
],
615 compptr
->width_in_blocks
);
624 do_transpose (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
625 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
626 jvirt_barray_ptr
*src_coef_arrays
,
627 jvirt_barray_ptr
*dst_coef_arrays
)
628 /* Transpose source into destination */
630 JDIMENSION dst_blk_x
, dst_blk_y
, x_crop_blocks
, y_crop_blocks
;
631 int ci
, i
, j
, offset_x
, offset_y
;
632 JBLOCKARRAY src_buffer
, dst_buffer
;
633 JCOEFPTR src_ptr
, dst_ptr
;
634 jpeg_component_info
*compptr
;
636 /* Transposing pixels within a block just requires transposing the
638 * Partial iMCUs at the edges require no special treatment; we simply
639 * process all the available DCT blocks for every component.
641 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
642 compptr
= dstinfo
->comp_info
+ ci
;
643 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
644 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
645 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
646 dst_blk_y
+= compptr
->v_samp_factor
) {
647 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
648 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
649 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
650 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
651 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
;
652 dst_blk_x
+= compptr
->h_samp_factor
) {
653 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
654 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
655 dst_blk_x
+ x_crop_blocks
,
656 (JDIMENSION
) compptr
->h_samp_factor
, FALSE
);
657 for (offset_x
= 0; offset_x
< compptr
->h_samp_factor
; offset_x
++) {
658 dst_ptr
= dst_buffer
[offset_y
][dst_blk_x
+ offset_x
];
659 src_ptr
= src_buffer
[offset_x
][dst_blk_y
+ offset_y
+ y_crop_blocks
];
660 for (i
= 0; i
< DCTSIZE
; i
++)
661 for (j
= 0; j
< DCTSIZE
; j
++)
662 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
672 do_rot_90 (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
673 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
674 jvirt_barray_ptr
*src_coef_arrays
,
675 jvirt_barray_ptr
*dst_coef_arrays
)
676 /* 90 degree rotation is equivalent to
677 * 1. Transposing the image;
678 * 2. Horizontal mirroring.
679 * These two steps are merged into a single processing routine.
682 JDIMENSION MCU_cols
, comp_width
, dst_blk_x
, dst_blk_y
;
683 JDIMENSION x_crop_blocks
, y_crop_blocks
;
684 int ci
, i
, j
, offset_x
, offset_y
;
685 JBLOCKARRAY src_buffer
, dst_buffer
;
686 JCOEFPTR src_ptr
, dst_ptr
;
687 jpeg_component_info
*compptr
;
689 /* Because of the horizontal mirror step, we can't process partial iMCUs
690 * at the (output) right edge properly. They just get transposed and
693 MCU_cols
= srcinfo
->image_height
/ (dstinfo
->max_h_samp_factor
* DCTSIZE
);
695 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
696 compptr
= dstinfo
->comp_info
+ ci
;
697 comp_width
= MCU_cols
* compptr
->h_samp_factor
;
698 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
699 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
700 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
701 dst_blk_y
+= compptr
->v_samp_factor
) {
702 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
703 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
704 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
705 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
706 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
;
707 dst_blk_x
+= compptr
->h_samp_factor
) {
708 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
709 /* Block is within the mirrorable area. */
710 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
711 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
712 comp_width
- x_crop_blocks
- dst_blk_x
-
713 (JDIMENSION
) compptr
->h_samp_factor
,
714 (JDIMENSION
) compptr
->h_samp_factor
, FALSE
);
716 /* Edge blocks are transposed but not mirrored. */
717 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
718 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
719 dst_blk_x
+ x_crop_blocks
,
720 (JDIMENSION
) compptr
->h_samp_factor
, FALSE
);
722 for (offset_x
= 0; offset_x
< compptr
->h_samp_factor
; offset_x
++) {
723 dst_ptr
= dst_buffer
[offset_y
][dst_blk_x
+ offset_x
];
724 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
725 /* Block is within the mirrorable area. */
726 src_ptr
= src_buffer
[compptr
->h_samp_factor
- offset_x
- 1]
727 [dst_blk_y
+ offset_y
+ y_crop_blocks
];
728 for (i
= 0; i
< DCTSIZE
; i
++) {
729 for (j
= 0; j
< DCTSIZE
; j
++)
730 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
732 for (j
= 0; j
< DCTSIZE
; j
++)
733 dst_ptr
[j
*DCTSIZE
+i
] = -src_ptr
[i
*DCTSIZE
+j
];
736 /* Edge blocks are transposed but not mirrored. */
737 src_ptr
= src_buffer
[offset_x
]
738 [dst_blk_y
+ offset_y
+ y_crop_blocks
];
739 for (i
= 0; i
< DCTSIZE
; i
++)
740 for (j
= 0; j
< DCTSIZE
; j
++)
741 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
752 do_rot_270 (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
753 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
754 jvirt_barray_ptr
*src_coef_arrays
,
755 jvirt_barray_ptr
*dst_coef_arrays
)
756 /* 270 degree rotation is equivalent to
757 * 1. Horizontal mirroring;
758 * 2. Transposing the image.
759 * These two steps are merged into a single processing routine.
762 JDIMENSION MCU_rows
, comp_height
, dst_blk_x
, dst_blk_y
;
763 JDIMENSION x_crop_blocks
, y_crop_blocks
;
764 int ci
, i
, j
, offset_x
, offset_y
;
765 JBLOCKARRAY src_buffer
, dst_buffer
;
766 JCOEFPTR src_ptr
, dst_ptr
;
767 jpeg_component_info
*compptr
;
769 /* Because of the horizontal mirror step, we can't process partial iMCUs
770 * at the (output) bottom edge properly. They just get transposed and
773 MCU_rows
= srcinfo
->image_width
/ (dstinfo
->max_v_samp_factor
* DCTSIZE
);
775 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
776 compptr
= dstinfo
->comp_info
+ ci
;
777 comp_height
= MCU_rows
* compptr
->v_samp_factor
;
778 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
779 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
780 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
781 dst_blk_y
+= compptr
->v_samp_factor
) {
782 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
783 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
784 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
785 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
786 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
;
787 dst_blk_x
+= compptr
->h_samp_factor
) {
788 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
789 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
790 dst_blk_x
+ x_crop_blocks
,
791 (JDIMENSION
) compptr
->h_samp_factor
, FALSE
);
792 for (offset_x
= 0; offset_x
< compptr
->h_samp_factor
; offset_x
++) {
793 dst_ptr
= dst_buffer
[offset_y
][dst_blk_x
+ offset_x
];
794 if (y_crop_blocks
+ dst_blk_y
< comp_height
) {
795 /* Block is within the mirrorable area. */
796 src_ptr
= src_buffer
[offset_x
]
797 [comp_height
- y_crop_blocks
- dst_blk_y
- offset_y
- 1];
798 for (i
= 0; i
< DCTSIZE
; i
++) {
799 for (j
= 0; j
< DCTSIZE
; j
++) {
800 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
802 dst_ptr
[j
*DCTSIZE
+i
] = -src_ptr
[i
*DCTSIZE
+j
];
806 /* Edge blocks are transposed but not mirrored. */
807 src_ptr
= src_buffer
[offset_x
]
808 [dst_blk_y
+ offset_y
+ y_crop_blocks
];
809 for (i
= 0; i
< DCTSIZE
; i
++)
810 for (j
= 0; j
< DCTSIZE
; j
++)
811 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
822 do_rot_180 (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
823 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
824 jvirt_barray_ptr
*src_coef_arrays
,
825 jvirt_barray_ptr
*dst_coef_arrays
)
826 /* 180 degree rotation is equivalent to
827 * 1. Vertical mirroring;
828 * 2. Horizontal mirroring.
829 * These two steps are merged into a single processing routine.
832 JDIMENSION MCU_cols
, MCU_rows
, comp_width
, comp_height
, dst_blk_x
, dst_blk_y
;
833 JDIMENSION x_crop_blocks
, y_crop_blocks
;
834 int ci
, i
, j
, offset_y
;
835 JBLOCKARRAY src_buffer
, dst_buffer
;
836 JBLOCKROW src_row_ptr
, dst_row_ptr
;
837 JCOEFPTR src_ptr
, dst_ptr
;
838 jpeg_component_info
*compptr
;
840 MCU_cols
= srcinfo
->image_width
/ (dstinfo
->max_h_samp_factor
* DCTSIZE
);
841 MCU_rows
= srcinfo
->image_height
/ (dstinfo
->max_v_samp_factor
* DCTSIZE
);
843 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
844 compptr
= dstinfo
->comp_info
+ ci
;
845 comp_width
= MCU_cols
* compptr
->h_samp_factor
;
846 comp_height
= MCU_rows
* compptr
->v_samp_factor
;
847 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
848 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
849 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
850 dst_blk_y
+= compptr
->v_samp_factor
) {
851 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
852 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
853 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
854 if (y_crop_blocks
+ dst_blk_y
< comp_height
) {
855 /* Row is within the vertically mirrorable area. */
856 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
857 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
858 comp_height
- y_crop_blocks
- dst_blk_y
-
859 (JDIMENSION
) compptr
->v_samp_factor
,
860 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
862 /* Bottom-edge rows are only mirrored horizontally. */
863 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
864 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
865 dst_blk_y
+ y_crop_blocks
,
866 (JDIMENSION
) compptr
->v_samp_factor
, FALSE
);
868 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
869 dst_row_ptr
= dst_buffer
[offset_y
];
870 if (y_crop_blocks
+ dst_blk_y
< comp_height
) {
871 /* Row is within the mirrorable area. */
872 src_row_ptr
= src_buffer
[compptr
->v_samp_factor
- offset_y
- 1];
873 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
; dst_blk_x
++) {
874 dst_ptr
= dst_row_ptr
[dst_blk_x
];
875 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
876 /* Process the blocks that can be mirrored both ways. */
877 src_ptr
= src_row_ptr
[comp_width
- x_crop_blocks
- dst_blk_x
- 1];
878 for (i
= 0; i
< DCTSIZE
; i
+= 2) {
879 /* For even row, negate every odd column. */
880 for (j
= 0; j
< DCTSIZE
; j
+= 2) {
881 *dst_ptr
++ = *src_ptr
++;
882 *dst_ptr
++ = - *src_ptr
++;
884 /* For odd row, negate every even column. */
885 for (j
= 0; j
< DCTSIZE
; j
+= 2) {
886 *dst_ptr
++ = - *src_ptr
++;
887 *dst_ptr
++ = *src_ptr
++;
891 /* Any remaining right-edge blocks are only mirrored vertically. */
892 src_ptr
= src_row_ptr
[x_crop_blocks
+ dst_blk_x
];
893 for (i
= 0; i
< DCTSIZE
; i
+= 2) {
894 for (j
= 0; j
< DCTSIZE
; j
++)
895 *dst_ptr
++ = *src_ptr
++;
896 for (j
= 0; j
< DCTSIZE
; j
++)
897 *dst_ptr
++ = - *src_ptr
++;
902 /* Remaining rows are just mirrored horizontally. */
903 src_row_ptr
= src_buffer
[offset_y
];
904 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
; dst_blk_x
++) {
905 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
906 /* Process the blocks that can be mirrored. */
907 dst_ptr
= dst_row_ptr
[dst_blk_x
];
908 src_ptr
= src_row_ptr
[comp_width
- x_crop_blocks
- dst_blk_x
- 1];
909 for (i
= 0; i
< DCTSIZE2
; i
+= 2) {
910 *dst_ptr
++ = *src_ptr
++;
911 *dst_ptr
++ = - *src_ptr
++;
914 /* Any remaining right-edge blocks are only copied. */
915 jcopy_block_row(src_row_ptr
+ dst_blk_x
+ x_crop_blocks
,
916 dst_row_ptr
+ dst_blk_x
,
928 do_transverse (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
929 JDIMENSION x_crop_offset
, JDIMENSION y_crop_offset
,
930 jvirt_barray_ptr
*src_coef_arrays
,
931 jvirt_barray_ptr
*dst_coef_arrays
)
932 /* Transverse transpose is equivalent to
933 * 1. 180 degree rotation;
936 * 1. Horizontal mirroring;
938 * 3. Horizontal mirroring.
939 * These steps are merged into a single processing routine.
942 JDIMENSION MCU_cols
, MCU_rows
, comp_width
, comp_height
, dst_blk_x
, dst_blk_y
;
943 JDIMENSION x_crop_blocks
, y_crop_blocks
;
944 int ci
, i
, j
, offset_x
, offset_y
;
945 JBLOCKARRAY src_buffer
, dst_buffer
;
946 JCOEFPTR src_ptr
, dst_ptr
;
947 jpeg_component_info
*compptr
;
949 MCU_cols
= srcinfo
->image_height
/ (dstinfo
->max_h_samp_factor
* DCTSIZE
);
950 MCU_rows
= srcinfo
->image_width
/ (dstinfo
->max_v_samp_factor
* DCTSIZE
);
952 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
953 compptr
= dstinfo
->comp_info
+ ci
;
954 comp_width
= MCU_cols
* compptr
->h_samp_factor
;
955 comp_height
= MCU_rows
* compptr
->v_samp_factor
;
956 x_crop_blocks
= x_crop_offset
* compptr
->h_samp_factor
;
957 y_crop_blocks
= y_crop_offset
* compptr
->v_samp_factor
;
958 for (dst_blk_y
= 0; dst_blk_y
< compptr
->height_in_blocks
;
959 dst_blk_y
+= compptr
->v_samp_factor
) {
960 dst_buffer
= (*srcinfo
->mem
->access_virt_barray
)
961 ((j_common_ptr
) srcinfo
, dst_coef_arrays
[ci
], dst_blk_y
,
962 (JDIMENSION
) compptr
->v_samp_factor
, TRUE
);
963 for (offset_y
= 0; offset_y
< compptr
->v_samp_factor
; offset_y
++) {
964 for (dst_blk_x
= 0; dst_blk_x
< compptr
->width_in_blocks
;
965 dst_blk_x
+= compptr
->h_samp_factor
) {
966 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
967 /* Block is within the mirrorable area. */
968 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
969 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
970 comp_width
- x_crop_blocks
- dst_blk_x
-
971 (JDIMENSION
) compptr
->h_samp_factor
,
972 (JDIMENSION
) compptr
->h_samp_factor
, FALSE
);
974 src_buffer
= (*srcinfo
->mem
->access_virt_barray
)
975 ((j_common_ptr
) srcinfo
, src_coef_arrays
[ci
],
976 dst_blk_x
+ x_crop_blocks
,
977 (JDIMENSION
) compptr
->h_samp_factor
, FALSE
);
979 for (offset_x
= 0; offset_x
< compptr
->h_samp_factor
; offset_x
++) {
980 dst_ptr
= dst_buffer
[offset_y
][dst_blk_x
+ offset_x
];
981 if (y_crop_blocks
+ dst_blk_y
< comp_height
) {
982 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
983 /* Block is within the mirrorable area. */
984 src_ptr
= src_buffer
[compptr
->h_samp_factor
- offset_x
- 1]
985 [comp_height
- y_crop_blocks
- dst_blk_y
- offset_y
- 1];
986 for (i
= 0; i
< DCTSIZE
; i
++) {
987 for (j
= 0; j
< DCTSIZE
; j
++) {
988 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
990 dst_ptr
[j
*DCTSIZE
+i
] = -src_ptr
[i
*DCTSIZE
+j
];
993 for (j
= 0; j
< DCTSIZE
; j
++) {
994 dst_ptr
[j
*DCTSIZE
+i
] = -src_ptr
[i
*DCTSIZE
+j
];
996 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
1000 /* Right-edge blocks are mirrored in y only */
1001 src_ptr
= src_buffer
[offset_x
]
1002 [comp_height
- y_crop_blocks
- dst_blk_y
- offset_y
- 1];
1003 for (i
= 0; i
< DCTSIZE
; i
++) {
1004 for (j
= 0; j
< DCTSIZE
; j
++) {
1005 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
1007 dst_ptr
[j
*DCTSIZE
+i
] = -src_ptr
[i
*DCTSIZE
+j
];
1012 if (x_crop_blocks
+ dst_blk_x
< comp_width
) {
1013 /* Bottom-edge blocks are mirrored in x only */
1014 src_ptr
= src_buffer
[compptr
->h_samp_factor
- offset_x
- 1]
1015 [dst_blk_y
+ offset_y
+ y_crop_blocks
];
1016 for (i
= 0; i
< DCTSIZE
; i
++) {
1017 for (j
= 0; j
< DCTSIZE
; j
++)
1018 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
1020 for (j
= 0; j
< DCTSIZE
; j
++)
1021 dst_ptr
[j
*DCTSIZE
+i
] = -src_ptr
[i
*DCTSIZE
+j
];
1024 /* At lower right corner, just transpose, no mirroring */
1025 src_ptr
= src_buffer
[offset_x
]
1026 [dst_blk_y
+ offset_y
+ y_crop_blocks
];
1027 for (i
= 0; i
< DCTSIZE
; i
++)
1028 for (j
= 0; j
< DCTSIZE
; j
++)
1029 dst_ptr
[j
*DCTSIZE
+i
] = src_ptr
[i
*DCTSIZE
+j
];
1040 /* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec.
1041 * Returns TRUE if valid integer found, FALSE if not.
1042 * *strptr is advanced over the digit string, and *result is set to its value.
1046 jt_read_integer (const char ** strptr
, JDIMENSION
* result
)
1048 const char * ptr
= *strptr
;
1051 for (; isdigit(*ptr
); ptr
++) {
1052 val
= val
* 10 + (JDIMENSION
) (*ptr
- '0');
1056 return FALSE
; /* oops, no digits */
1062 /* Parse a crop specification (written in X11 geometry style).
1063 * The routine returns TRUE if the spec string is valid, FALSE if not.
1065 * The crop spec string should have the format
1066 * <width>x<height>{+-}<xoffset>{+-}<yoffset>
1067 * where width, height, xoffset, and yoffset are unsigned integers.
1068 * Each of the elements can be omitted to indicate a default value.
1069 * (A weakness of this style is that it is not possible to omit xoffset
1070 * while specifying yoffset, since they look alike.)
1072 * This code is loosely based on XParseGeometry from the X11 distribution.
1076 jtransform_parse_crop_spec (jpeg_transform_info
*info
, const char *spec
)
1079 info
->crop_width_set
= JCROP_UNSET
;
1080 info
->crop_height_set
= JCROP_UNSET
;
1081 info
->crop_xoffset_set
= JCROP_UNSET
;
1082 info
->crop_yoffset_set
= JCROP_UNSET
;
1084 if (isdigit(*spec
)) {
1086 if (! jt_read_integer(&spec
, &info
->crop_width
))
1088 info
->crop_width_set
= JCROP_POS
;
1090 if (*spec
== 'x' || *spec
== 'X') {
1093 if (! jt_read_integer(&spec
, &info
->crop_height
))
1095 info
->crop_height_set
= JCROP_POS
;
1097 if (*spec
== '+' || *spec
== '-') {
1099 info
->crop_xoffset_set
= (*spec
== '-') ? JCROP_NEG
: JCROP_POS
;
1101 if (! jt_read_integer(&spec
, &info
->crop_xoffset
))
1104 if (*spec
== '+' || *spec
== '-') {
1106 info
->crop_yoffset_set
= (*spec
== '-') ? JCROP_NEG
: JCROP_POS
;
1108 if (! jt_read_integer(&spec
, &info
->crop_yoffset
))
1111 /* We had better have gotten to the end of the string. */
1119 /* Trim off any partial iMCUs on the indicated destination edge */
1122 trim_right_edge (jpeg_transform_info
*info
, JDIMENSION full_width
)
1124 JDIMENSION MCU_cols
;
1126 MCU_cols
= info
->output_width
/ (info
->max_h_samp_factor
* DCTSIZE
);
1127 if (MCU_cols
> 0 && info
->x_crop_offset
+ MCU_cols
==
1128 full_width
/ (info
->max_h_samp_factor
* DCTSIZE
))
1129 info
->output_width
= MCU_cols
* (info
->max_h_samp_factor
* DCTSIZE
);
1133 trim_bottom_edge (jpeg_transform_info
*info
, JDIMENSION full_height
)
1135 JDIMENSION MCU_rows
;
1137 MCU_rows
= info
->output_height
/ (info
->max_v_samp_factor
* DCTSIZE
);
1138 if (MCU_rows
> 0 && info
->y_crop_offset
+ MCU_rows
==
1139 full_height
/ (info
->max_v_samp_factor
* DCTSIZE
))
1140 info
->output_height
= MCU_rows
* (info
->max_v_samp_factor
* DCTSIZE
);
1144 /* Request any required workspace.
1146 * This routine figures out the size that the output image will be
1147 * (which implies that all the transform parameters must be set before
1150 * We allocate the workspace virtual arrays from the source decompression
1151 * object, so that all the arrays (both the original data and the workspace)
1152 * will be taken into account while making memory management decisions.
1153 * Hence, this routine must be called after jpeg_read_header (which reads
1154 * the image dimensions) and before jpeg_read_coefficients (which realizes
1155 * the source's virtual arrays).
1159 jtransform_request_workspace (j_decompress_ptr srcinfo
,
1160 jpeg_transform_info
*info
)
1162 jvirt_barray_ptr
*coef_arrays
= NULL
;
1163 boolean need_workspace
, transpose_it
;
1164 jpeg_component_info
*compptr
;
1165 JDIMENSION xoffset
, yoffset
, dtemp
, width_in_iMCUs
, height_in_iMCUs
;
1166 JDIMENSION width_in_blocks
, height_in_blocks
;
1167 int itemp
, ci
, h_samp_factor
, v_samp_factor
;
1169 /* Determine number of components in output image */
1170 if (info
->force_grayscale
&&
1171 srcinfo
->jpeg_color_space
== JCS_YCbCr
&&
1172 srcinfo
->num_components
== 3) {
1173 /* We'll only process the first component */
1174 info
->num_components
= 1;
1176 /* Process all the components */
1177 info
->num_components
= srcinfo
->num_components
;
1179 /* If there is only one output component, force the iMCU size to be 1;
1180 * else use the source iMCU size. (This allows us to do the right thing
1181 * when reducing color to grayscale, and also provides a handy way of
1182 * cleaning up "funny" grayscale images whose sampling factors are not 1x1.)
1185 switch (info
->transform
) {
1186 case JXFORM_TRANSPOSE
:
1187 case JXFORM_TRANSVERSE
:
1189 case JXFORM_ROT_270
:
1190 info
->output_width
= srcinfo
->image_height
;
1191 info
->output_height
= srcinfo
->image_width
;
1192 if (info
->num_components
== 1) {
1193 info
->max_h_samp_factor
= 1;
1194 info
->max_v_samp_factor
= 1;
1196 info
->max_h_samp_factor
= srcinfo
->max_v_samp_factor
;
1197 info
->max_v_samp_factor
= srcinfo
->max_h_samp_factor
;
1201 info
->output_width
= srcinfo
->image_width
;
1202 info
->output_height
= srcinfo
->image_height
;
1203 if (info
->num_components
== 1) {
1204 info
->max_h_samp_factor
= 1;
1205 info
->max_v_samp_factor
= 1;
1207 info
->max_h_samp_factor
= srcinfo
->max_h_samp_factor
;
1208 info
->max_v_samp_factor
= srcinfo
->max_v_samp_factor
;
1213 /* If cropping has been requested, compute the crop area's position and
1214 * dimensions, ensuring that its upper left corner falls at an iMCU boundary.
1217 /* Insert default values for unset crop parameters */
1218 if (info
->crop_xoffset_set
== JCROP_UNSET
)
1219 info
->crop_xoffset
= 0; /* default to +0 */
1220 if (info
->crop_yoffset_set
== JCROP_UNSET
)
1221 info
->crop_yoffset
= 0; /* default to +0 */
1222 if (info
->crop_width_set
== JCROP_UNSET
) {
1223 if (info
->crop_xoffset
>= info
->output_width
)
1224 ERREXIT(srcinfo
, JERR_BAD_CROP_SPEC
);
1225 info
->crop_width
= info
->output_width
- info
->crop_xoffset
;
1227 /* Check for crop extension */
1228 if (info
->crop_width
> info
->output_width
) {
1229 /* Crop extension does not work when transforming! */
1230 if (info
->transform
!= JXFORM_NONE
||
1231 info
->crop_xoffset
>= info
->crop_width
||
1232 info
->crop_xoffset
> info
->crop_width
- info
->output_width
)
1233 ERREXIT(srcinfo
, JERR_BAD_CROP_SPEC
);
1235 if (info
->crop_xoffset
>= info
->output_width
||
1236 info
->crop_width
<= 0 ||
1237 info
->crop_xoffset
> info
->output_width
- info
->crop_width
)
1238 ERREXIT(srcinfo
, JERR_BAD_CROP_SPEC
);
1241 if (info
->crop_height_set
== JCROP_UNSET
) {
1242 if (info
->crop_yoffset
>= info
->output_height
)
1243 ERREXIT(srcinfo
, JERR_BAD_CROP_SPEC
);
1244 info
->crop_height
= info
->output_height
- info
->crop_yoffset
;
1246 /* Check for crop extension */
1247 if (info
->crop_height
> info
->output_height
) {
1248 /* Crop extension does not work when transforming! */
1249 if (info
->transform
!= JXFORM_NONE
||
1250 info
->crop_yoffset
>= info
->crop_height
||
1251 info
->crop_yoffset
> info
->crop_height
- info
->output_height
)
1252 ERREXIT(srcinfo
, JERR_BAD_CROP_SPEC
);
1254 if (info
->crop_yoffset
>= info
->output_height
||
1255 info
->crop_height
<= 0 ||
1256 info
->crop_yoffset
> info
->output_height
- info
->crop_height
)
1257 ERREXIT(srcinfo
, JERR_BAD_CROP_SPEC
);
1260 /* Convert negative crop offsets into regular offsets */
1261 if (info
->crop_xoffset_set
== JCROP_NEG
) {
1262 if (info
->crop_width
> info
->output_width
)
1263 xoffset
= info
->crop_width
- info
->output_width
- info
->crop_xoffset
;
1265 xoffset
= info
->output_width
- info
->crop_width
- info
->crop_xoffset
;
1267 xoffset
= info
->crop_xoffset
;
1268 if (info
->crop_yoffset_set
== JCROP_NEG
) {
1269 if (info
->crop_height
> info
->output_height
)
1270 yoffset
= info
->crop_height
- info
->output_height
- info
->crop_yoffset
;
1272 yoffset
= info
->output_height
- info
->crop_height
- info
->crop_yoffset
;
1274 yoffset
= info
->crop_yoffset
;
1275 /* Now adjust so that upper left corner falls at an iMCU boundary */
1276 if (info
->transform
== JXFORM_DROP
) {
1277 /* Ensure the effective drop region will not exceed the requested */
1278 itemp
= info
->max_h_samp_factor
* DCTSIZE
;
1279 dtemp
= itemp
- 1 - ((xoffset
+ itemp
- 1) % itemp
);
1281 if (info
->crop_width
> dtemp
)
1282 info
->drop_width
= (info
->crop_width
- dtemp
) / itemp
;
1284 info
->drop_width
= 0;
1285 itemp
= info
->max_v_samp_factor
* DCTSIZE
;
1286 dtemp
= itemp
- 1 - ((yoffset
+ itemp
- 1) % itemp
);
1288 if (info
->crop_height
> dtemp
)
1289 info
->drop_height
= (info
->crop_height
- dtemp
) / itemp
;
1291 info
->drop_height
= 0;
1292 /* Check if sampling factors match for dropping */
1293 if (info
->drop_width
!= 0 && info
->drop_height
!= 0)
1294 for (ci
= 0; ci
< info
->num_components
&&
1295 ci
< info
->drop_ptr
->num_components
; ci
++) {
1296 if (info
->drop_ptr
->comp_info
[ci
].h_samp_factor
*
1297 srcinfo
->max_h_samp_factor
!=
1298 srcinfo
->comp_info
[ci
].h_samp_factor
*
1299 info
->drop_ptr
->max_h_samp_factor
)
1300 ERREXIT6(srcinfo
, JERR_BAD_DROP_SAMPLING
, ci
,
1301 info
->drop_ptr
->comp_info
[ci
].h_samp_factor
,
1302 info
->drop_ptr
->max_h_samp_factor
,
1303 srcinfo
->comp_info
[ci
].h_samp_factor
,
1304 srcinfo
->max_h_samp_factor
, 'h');
1305 if (info
->drop_ptr
->comp_info
[ci
].v_samp_factor
*
1306 srcinfo
->max_v_samp_factor
!=
1307 srcinfo
->comp_info
[ci
].v_samp_factor
*
1308 info
->drop_ptr
->max_v_samp_factor
)
1309 ERREXIT6(srcinfo
, JERR_BAD_DROP_SAMPLING
, ci
,
1310 info
->drop_ptr
->comp_info
[ci
].v_samp_factor
,
1311 info
->drop_ptr
->max_v_samp_factor
,
1312 srcinfo
->comp_info
[ci
].v_samp_factor
,
1313 srcinfo
->max_v_samp_factor
, 'v');
1316 /* Ensure the effective crop region will cover the requested */
1317 if (info
->crop_width
> info
->output_width
)
1318 info
->output_width
= info
->crop_width
;
1320 info
->output_width
=
1321 info
->crop_width
+ (xoffset
% (info
->max_h_samp_factor
* DCTSIZE
));
1322 if (info
->crop_height
> info
->output_height
)
1323 info
->output_height
= info
->crop_height
;
1325 info
->output_height
=
1326 info
->crop_height
+ (yoffset
% (info
->max_v_samp_factor
* DCTSIZE
));
1328 /* Save x/y offsets measured in iMCUs */
1329 info
->x_crop_offset
= xoffset
/ (info
->max_h_samp_factor
* DCTSIZE
);
1330 info
->y_crop_offset
= yoffset
/ (info
->max_v_samp_factor
* DCTSIZE
);
1332 info
->x_crop_offset
= 0;
1333 info
->y_crop_offset
= 0;
1336 /* Figure out whether we need workspace arrays,
1337 * and if so whether they are transposed relative to the source.
1339 need_workspace
= FALSE
;
1340 transpose_it
= FALSE
;
1341 switch (info
->transform
) {
1343 if (info
->x_crop_offset
!= 0 || info
->y_crop_offset
!= 0 ||
1344 info
->output_width
> srcinfo
->image_width
||
1345 info
->output_height
> srcinfo
->image_height
)
1346 need_workspace
= TRUE
;
1347 /* No workspace needed if neither cropping nor transforming */
1351 trim_right_edge(info
, srcinfo
->image_width
);
1352 if (info
->y_crop_offset
!= 0)
1353 need_workspace
= TRUE
;
1354 /* do_flip_h_no_crop doesn't need a workspace array */
1358 trim_bottom_edge(info
, srcinfo
->image_height
);
1359 /* Need workspace arrays having same dimensions as source image. */
1360 need_workspace
= TRUE
;
1362 case JXFORM_TRANSPOSE
:
1363 /* transpose does NOT have to trim anything */
1364 /* Need workspace arrays having transposed dimensions. */
1365 need_workspace
= TRUE
;
1366 transpose_it
= TRUE
;
1368 case JXFORM_TRANSVERSE
:
1370 trim_right_edge(info
, srcinfo
->image_height
);
1371 trim_bottom_edge(info
, srcinfo
->image_width
);
1373 /* Need workspace arrays having transposed dimensions. */
1374 need_workspace
= TRUE
;
1375 transpose_it
= TRUE
;
1379 trim_right_edge(info
, srcinfo
->image_height
);
1380 /* Need workspace arrays having transposed dimensions. */
1381 need_workspace
= TRUE
;
1382 transpose_it
= TRUE
;
1384 case JXFORM_ROT_180
:
1386 trim_right_edge(info
, srcinfo
->image_width
);
1387 trim_bottom_edge(info
, srcinfo
->image_height
);
1389 /* Need workspace arrays having same dimensions as source image. */
1390 need_workspace
= TRUE
;
1392 case JXFORM_ROT_270
:
1394 trim_bottom_edge(info
, srcinfo
->image_width
);
1395 /* Need workspace arrays having transposed dimensions. */
1396 need_workspace
= TRUE
;
1397 transpose_it
= TRUE
;
1400 #if DROP_REQUEST_FROM_SRC
1401 drop_request_from_src(info
->drop_ptr
, srcinfo
);
1406 /* Allocate workspace if needed.
1407 * Note that we allocate arrays padded out to the next iMCU boundary,
1408 * so that transform routines need not worry about missing edge blocks.
1410 if (need_workspace
) {
1411 coef_arrays
= (jvirt_barray_ptr
*)
1412 (*srcinfo
->mem
->alloc_small
) ((j_common_ptr
) srcinfo
, JPOOL_IMAGE
,
1413 SIZEOF(jvirt_barray_ptr
) * info
->num_components
);
1414 width_in_iMCUs
= (JDIMENSION
)
1415 jdiv_round_up((long) info
->output_width
,
1416 (long) (info
->max_h_samp_factor
* DCTSIZE
));
1417 height_in_iMCUs
= (JDIMENSION
)
1418 jdiv_round_up((long) info
->output_height
,
1419 (long) (info
->max_v_samp_factor
* DCTSIZE
));
1420 for (ci
= 0; ci
< info
->num_components
; ci
++) {
1421 compptr
= srcinfo
->comp_info
+ ci
;
1422 if (info
->num_components
== 1) {
1423 /* we're going to force samp factors to 1x1 in this case */
1424 h_samp_factor
= v_samp_factor
= 1;
1425 } else if (transpose_it
) {
1426 h_samp_factor
= compptr
->v_samp_factor
;
1427 v_samp_factor
= compptr
->h_samp_factor
;
1429 h_samp_factor
= compptr
->h_samp_factor
;
1430 v_samp_factor
= compptr
->v_samp_factor
;
1432 width_in_blocks
= width_in_iMCUs
* h_samp_factor
;
1433 height_in_blocks
= height_in_iMCUs
* v_samp_factor
;
1434 coef_arrays
[ci
] = (*srcinfo
->mem
->request_virt_barray
)
1435 ((j_common_ptr
) srcinfo
, JPOOL_IMAGE
, FALSE
,
1436 width_in_blocks
, height_in_blocks
, (JDIMENSION
) v_samp_factor
);
1440 info
->workspace_coef_arrays
= coef_arrays
;
1444 /* Transpose destination image parameters */
1447 transpose_critical_parameters (j_compress_ptr dstinfo
)
1449 int tblno
, i
, j
, ci
, itemp
;
1450 jpeg_component_info
*compptr
;
1451 JQUANT_TBL
*qtblptr
;
1454 /* Transpose sampling factors */
1455 for (ci
= 0; ci
< dstinfo
->num_components
; ci
++) {
1456 compptr
= dstinfo
->comp_info
+ ci
;
1457 itemp
= compptr
->h_samp_factor
;
1458 compptr
->h_samp_factor
= compptr
->v_samp_factor
;
1459 compptr
->v_samp_factor
= itemp
;
1462 /* Transpose quantization tables */
1463 for (tblno
= 0; tblno
< NUM_QUANT_TBLS
; tblno
++) {
1464 qtblptr
= dstinfo
->quant_tbl_ptrs
[tblno
];
1465 if (qtblptr
!= NULL
) {
1466 for (i
= 0; i
< DCTSIZE
; i
++) {
1467 for (j
= 0; j
< i
; j
++) {
1468 qtemp
= qtblptr
->quantval
[i
*DCTSIZE
+j
];
1469 qtblptr
->quantval
[i
*DCTSIZE
+j
] = qtblptr
->quantval
[j
*DCTSIZE
+i
];
1470 qtblptr
->quantval
[j
*DCTSIZE
+i
] = qtemp
;
1478 /* Adjust Exif image parameters.
1480 * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible.
1484 adjust_exif_parameters (JOCTET FAR
* data
, unsigned int length
,
1485 JDIMENSION new_width
, JDIMENSION new_height
)
1487 boolean is_motorola
; /* Flag for byte order */
1488 unsigned int number_of_tags
, tagnum
;
1489 unsigned int firstoffset
, offset
;
1490 JDIMENSION new_value
;
1492 if (length
< 12) return; /* Length of an IFD entry */
1494 /* Discover byte order */
1495 if (GETJOCTET(data
[0]) == 0x49 && GETJOCTET(data
[1]) == 0x49)
1496 is_motorola
= FALSE
;
1497 else if (GETJOCTET(data
[0]) == 0x4D && GETJOCTET(data
[1]) == 0x4D)
1502 /* Check Tag Mark */
1504 if (GETJOCTET(data
[2]) != 0) return;
1505 if (GETJOCTET(data
[3]) != 0x2A) return;
1507 if (GETJOCTET(data
[3]) != 0) return;
1508 if (GETJOCTET(data
[2]) != 0x2A) return;
1511 /* Get first IFD offset (offset to IFD0) */
1513 if (GETJOCTET(data
[4]) != 0) return;
1514 if (GETJOCTET(data
[5]) != 0) return;
1515 firstoffset
= GETJOCTET(data
[6]);
1517 firstoffset
+= GETJOCTET(data
[7]);
1519 if (GETJOCTET(data
[7]) != 0) return;
1520 if (GETJOCTET(data
[6]) != 0) return;
1521 firstoffset
= GETJOCTET(data
[5]);
1523 firstoffset
+= GETJOCTET(data
[4]);
1525 if (firstoffset
> length
- 2) return; /* check end of data segment */
1527 /* Get the number of directory entries contained in this IFD */
1529 number_of_tags
= GETJOCTET(data
[firstoffset
]);
1530 number_of_tags
<<= 8;
1531 number_of_tags
+= GETJOCTET(data
[firstoffset
+1]);
1533 number_of_tags
= GETJOCTET(data
[firstoffset
+1]);
1534 number_of_tags
<<= 8;
1535 number_of_tags
+= GETJOCTET(data
[firstoffset
]);
1537 if (number_of_tags
== 0) return;
1540 /* Search for ExifSubIFD offset Tag in IFD0 */
1542 if (firstoffset
> length
- 12) return; /* check end of data segment */
1543 /* Get Tag number */
1545 tagnum
= GETJOCTET(data
[firstoffset
]);
1547 tagnum
+= GETJOCTET(data
[firstoffset
+1]);
1549 tagnum
= GETJOCTET(data
[firstoffset
+1]);
1551 tagnum
+= GETJOCTET(data
[firstoffset
]);
1553 if (tagnum
== 0x8769) break; /* found ExifSubIFD offset Tag */
1554 if (--number_of_tags
== 0) return;
1558 /* Get the ExifSubIFD offset */
1560 if (GETJOCTET(data
[firstoffset
+8]) != 0) return;
1561 if (GETJOCTET(data
[firstoffset
+9]) != 0) return;
1562 offset
= GETJOCTET(data
[firstoffset
+10]);
1564 offset
+= GETJOCTET(data
[firstoffset
+11]);
1566 if (GETJOCTET(data
[firstoffset
+11]) != 0) return;
1567 if (GETJOCTET(data
[firstoffset
+10]) != 0) return;
1568 offset
= GETJOCTET(data
[firstoffset
+9]);
1570 offset
+= GETJOCTET(data
[firstoffset
+8]);
1572 if (offset
> length
- 2) return; /* check end of data segment */
1574 /* Get the number of directory entries contained in this SubIFD */
1576 number_of_tags
= GETJOCTET(data
[offset
]);
1577 number_of_tags
<<= 8;
1578 number_of_tags
+= GETJOCTET(data
[offset
+1]);
1580 number_of_tags
= GETJOCTET(data
[offset
+1]);
1581 number_of_tags
<<= 8;
1582 number_of_tags
+= GETJOCTET(data
[offset
]);
1584 if (number_of_tags
< 2) return;
1587 /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */
1589 if (offset
> length
- 12) return; /* check end of data segment */
1590 /* Get Tag number */
1592 tagnum
= GETJOCTET(data
[offset
]);
1594 tagnum
+= GETJOCTET(data
[offset
+1]);
1596 tagnum
= GETJOCTET(data
[offset
+1]);
1598 tagnum
+= GETJOCTET(data
[offset
]);
1600 if (tagnum
== 0xA002 || tagnum
== 0xA003) {
1601 if (tagnum
== 0xA002)
1602 new_value
= new_width
; /* ExifImageWidth Tag */
1604 new_value
= new_height
; /* ExifImageHeight Tag */
1606 data
[offset
+2] = 0; /* Format = unsigned long (4 octets) */
1608 data
[offset
+4] = 0; /* Number Of Components = 1 */
1614 data
[offset
+10] = (JOCTET
)((new_value
>> 8) & 0xFF);
1615 data
[offset
+11] = (JOCTET
)(new_value
& 0xFF);
1617 data
[offset
+2] = 4; /* Format = unsigned long (4 octets) */
1619 data
[offset
+4] = 1; /* Number Of Components = 1 */
1623 data
[offset
+8] = (JOCTET
)(new_value
& 0xFF);
1624 data
[offset
+9] = (JOCTET
)((new_value
>> 8) & 0xFF);
1625 data
[offset
+10] = 0;
1626 data
[offset
+11] = 0;
1630 } while (--number_of_tags
);
1634 /* Adjust output image parameters as needed.
1636 * This must be called after jpeg_copy_critical_parameters()
1637 * and before jpeg_write_coefficients().
1639 * The return value is the set of virtual coefficient arrays to be written
1640 * (either the ones allocated by jtransform_request_workspace, or the
1641 * original source data arrays). The caller will need to pass this value
1642 * to jpeg_write_coefficients().
1645 GLOBAL(jvirt_barray_ptr
*)
1646 jtransform_adjust_parameters (j_decompress_ptr srcinfo
,
1647 j_compress_ptr dstinfo
,
1648 jvirt_barray_ptr
*src_coef_arrays
,
1649 jpeg_transform_info
*info
)
1651 /* If force-to-grayscale is requested, adjust destination parameters */
1652 if (info
->force_grayscale
) {
1653 /* First, ensure we have YCbCr or grayscale data, and that the source's
1654 * Y channel is full resolution. (No reasonable person would make Y
1655 * be less than full resolution, so actually coping with that case
1656 * isn't worth extra code space. But we check it to avoid crashing.)
1658 if (((dstinfo
->jpeg_color_space
== JCS_YCbCr
&&
1659 dstinfo
->num_components
== 3) ||
1660 (dstinfo
->jpeg_color_space
== JCS_GRAYSCALE
&&
1661 dstinfo
->num_components
== 1)) &&
1662 srcinfo
->comp_info
[0].h_samp_factor
== srcinfo
->max_h_samp_factor
&&
1663 srcinfo
->comp_info
[0].v_samp_factor
== srcinfo
->max_v_samp_factor
) {
1664 /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
1665 * properly. Among other things, it sets the target h_samp_factor &
1666 * v_samp_factor to 1, which typically won't match the source.
1667 * We have to preserve the source's quantization table number, however.
1669 int sv_quant_tbl_no
= dstinfo
->comp_info
[0].quant_tbl_no
;
1670 jpeg_set_colorspace(dstinfo
, JCS_GRAYSCALE
);
1671 dstinfo
->comp_info
[0].quant_tbl_no
= sv_quant_tbl_no
;
1673 /* Sorry, can't do it */
1674 ERREXIT(dstinfo
, JERR_CONVERSION_NOTIMPL
);
1676 } else if (info
->num_components
== 1) {
1677 /* For a single-component source, we force the destination sampling factors
1678 * to 1x1, with or without force_grayscale. This is useful because some
1679 * decoders choke on grayscale images with other sampling factors.
1681 dstinfo
->comp_info
[0].h_samp_factor
= 1;
1682 dstinfo
->comp_info
[0].v_samp_factor
= 1;
1685 /* Correct the destination's image dimensions etc as necessary
1686 * for crop and rotate/flip operations.
1688 dstinfo
->image_width
= info
->output_width
;
1689 dstinfo
->image_height
= info
->output_height
;
1690 switch (info
->transform
) {
1691 case JXFORM_TRANSPOSE
:
1692 case JXFORM_TRANSVERSE
:
1694 case JXFORM_ROT_270
:
1695 transpose_critical_parameters(dstinfo
);
1698 if (info
->drop_width
!= 0 && info
->drop_height
!= 0)
1699 adjust_quant(srcinfo
, src_coef_arrays
,
1700 info
->drop_ptr
, info
->drop_coef_arrays
,
1701 info
->trim
, dstinfo
);
1705 /* Adjust Exif properties */
1706 if (srcinfo
->marker_list
!= NULL
&&
1707 srcinfo
->marker_list
->marker
== JPEG_APP0
+1 &&
1708 srcinfo
->marker_list
->data_length
>= 6 &&
1709 GETJOCTET(srcinfo
->marker_list
->data
[0]) == 0x45 &&
1710 GETJOCTET(srcinfo
->marker_list
->data
[1]) == 0x78 &&
1711 GETJOCTET(srcinfo
->marker_list
->data
[2]) == 0x69 &&
1712 GETJOCTET(srcinfo
->marker_list
->data
[3]) == 0x66 &&
1713 GETJOCTET(srcinfo
->marker_list
->data
[4]) == 0 &&
1714 GETJOCTET(srcinfo
->marker_list
->data
[5]) == 0) {
1715 /* Suppress output of JFIF marker */
1716 dstinfo
->write_JFIF_header
= FALSE
;
1717 /* Adjust Exif image parameters */
1718 if (dstinfo
->image_width
!= srcinfo
->image_width
||
1719 dstinfo
->image_height
!= srcinfo
->image_height
)
1720 /* Align data segment to start of TIFF structure for parsing */
1721 adjust_exif_parameters(srcinfo
->marker_list
->data
+ 6,
1722 srcinfo
->marker_list
->data_length
- 6,
1723 dstinfo
->image_width
, dstinfo
->image_height
);
1726 /* Return the appropriate output data set */
1727 if (info
->workspace_coef_arrays
!= NULL
)
1728 return info
->workspace_coef_arrays
;
1729 return src_coef_arrays
;
1733 /* Execute the actual transformation, if any.
1735 * This must be called *after* jpeg_write_coefficients, because it depends
1736 * on jpeg_write_coefficients to have computed subsidiary values such as
1737 * the per-component width and height fields in the destination object.
1739 * Note that some transformations will modify the source data arrays!
1743 jtransform_execute_transform (j_decompress_ptr srcinfo
,
1744 j_compress_ptr dstinfo
,
1745 jvirt_barray_ptr
*src_coef_arrays
,
1746 jpeg_transform_info
*info
)
1748 jvirt_barray_ptr
*dst_coef_arrays
= info
->workspace_coef_arrays
;
1750 /* Note: conditions tested here should match those in switch statement
1751 * in jtransform_request_workspace()
1753 switch (info
->transform
) {
1755 if (info
->x_crop_offset
!= 0 || info
->y_crop_offset
!= 0 ||
1756 info
->output_width
> srcinfo
->image_width
||
1757 info
->output_height
> srcinfo
->image_height
)
1758 do_crop(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1759 src_coef_arrays
, dst_coef_arrays
);
1762 if (info
->y_crop_offset
!= 0)
1763 do_flip_h(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1764 src_coef_arrays
, dst_coef_arrays
);
1766 do_flip_h_no_crop(srcinfo
, dstinfo
, info
->x_crop_offset
,
1770 do_flip_v(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1771 src_coef_arrays
, dst_coef_arrays
);
1773 case JXFORM_TRANSPOSE
:
1774 do_transpose(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1775 src_coef_arrays
, dst_coef_arrays
);
1777 case JXFORM_TRANSVERSE
:
1778 do_transverse(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1779 src_coef_arrays
, dst_coef_arrays
);
1782 do_rot_90(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1783 src_coef_arrays
, dst_coef_arrays
);
1785 case JXFORM_ROT_180
:
1786 do_rot_180(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1787 src_coef_arrays
, dst_coef_arrays
);
1789 case JXFORM_ROT_270
:
1790 do_rot_270(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1791 src_coef_arrays
, dst_coef_arrays
);
1794 if (info
->drop_width
!= 0 && info
->drop_height
!= 0)
1795 do_drop(srcinfo
, dstinfo
, info
->x_crop_offset
, info
->y_crop_offset
,
1796 src_coef_arrays
, info
->drop_ptr
, info
->drop_coef_arrays
,
1797 info
->drop_width
, info
->drop_height
);
1802 /* jtransform_perfect_transform
1804 * Determine whether lossless transformation is perfectly
1805 * possible for a specified image and transformation.
1808 * image_width, image_height: source image dimensions.
1809 * MCU_width, MCU_height: pixel dimensions of MCU.
1810 * transform: transformation identifier.
1811 * Parameter sources from initialized jpeg_struct
1812 * (after reading source header):
1813 * image_width = cinfo.image_width
1814 * image_height = cinfo.image_height
1815 * MCU_width = cinfo.max_h_samp_factor * DCTSIZE
1816 * MCU_height = cinfo.max_v_samp_factor * DCTSIZE
1818 * TRUE = perfect transformation possible
1819 * FALSE = perfect transformation not possible
1820 * (may use custom action then)
1824 jtransform_perfect_transform(JDIMENSION image_width
, JDIMENSION image_height
,
1825 int MCU_width
, int MCU_height
,
1826 JXFORM_CODE transform
)
1828 boolean result
= TRUE
; /* initialize TRUE */
1830 switch (transform
) {
1832 case JXFORM_ROT_270
:
1833 if (image_width
% (JDIMENSION
) MCU_width
)
1838 if (image_height
% (JDIMENSION
) MCU_height
)
1841 case JXFORM_TRANSVERSE
:
1842 case JXFORM_ROT_180
:
1843 if (image_width
% (JDIMENSION
) MCU_width
)
1845 if (image_height
% (JDIMENSION
) MCU_height
)
1853 #endif /* TRANSFORMS_SUPPORTED */
1856 /* Setup decompression object to save desired markers in memory.
1857 * This must be called before jpeg_read_header() to have the desired effect.
1861 jcopy_markers_setup (j_decompress_ptr srcinfo
, JCOPY_OPTION option
)
1863 #ifdef SAVE_MARKERS_SUPPORTED
1866 /* Save comments except under NONE option */
1867 if (option
!= JCOPYOPT_NONE
) {
1868 jpeg_save_markers(srcinfo
, JPEG_COM
, 0xFFFF);
1870 /* Save all types of APPn markers iff ALL option */
1871 if (option
== JCOPYOPT_ALL
) {
1872 for (m
= 0; m
< 16; m
++)
1873 jpeg_save_markers(srcinfo
, JPEG_APP0
+ m
, 0xFFFF);
1875 #endif /* SAVE_MARKERS_SUPPORTED */
1878 /* Copy markers saved in the given source object to the destination object.
1879 * This should be called just after jpeg_start_compress() or
1880 * jpeg_write_coefficients().
1881 * Note that those routines will have written the SOI, and also the
1882 * JFIF APP0 or Adobe APP14 markers if selected.
1886 jcopy_markers_execute (j_decompress_ptr srcinfo
, j_compress_ptr dstinfo
,
1887 JCOPY_OPTION option
)
1889 jpeg_saved_marker_ptr marker
;
1891 /* In the current implementation, we don't actually need to examine the
1892 * option flag here; we just copy everything that got saved.
1893 * But to avoid confusion, we do not output JFIF and Adobe APP14 markers
1894 * if the encoder library already wrote one.
1896 for (marker
= srcinfo
->marker_list
; marker
!= NULL
; marker
= marker
->next
) {
1897 if (dstinfo
->write_JFIF_header
&&
1898 marker
->marker
== JPEG_APP0
&&
1899 marker
->data_length
>= 5 &&
1900 GETJOCTET(marker
->data
[0]) == 0x4A &&
1901 GETJOCTET(marker
->data
[1]) == 0x46 &&
1902 GETJOCTET(marker
->data
[2]) == 0x49 &&
1903 GETJOCTET(marker
->data
[3]) == 0x46 &&
1904 GETJOCTET(marker
->data
[4]) == 0)
1905 continue; /* reject duplicate JFIF */
1906 if (dstinfo
->write_Adobe_marker
&&
1907 marker
->marker
== JPEG_APP0
+14 &&
1908 marker
->data_length
>= 5 &&
1909 GETJOCTET(marker
->data
[0]) == 0x41 &&
1910 GETJOCTET(marker
->data
[1]) == 0x64 &&
1911 GETJOCTET(marker
->data
[2]) == 0x6F &&
1912 GETJOCTET(marker
->data
[3]) == 0x62 &&
1913 GETJOCTET(marker
->data
[4]) == 0x65)
1914 continue; /* reject duplicate Adobe */
1915 #ifdef NEED_FAR_POINTERS
1916 /* We could use jpeg_write_marker if the data weren't FAR... */
1919 jpeg_write_m_header(dstinfo
, marker
->marker
, marker
->data_length
);
1920 for (i
= 0; i
< marker
->data_length
; i
++)
1921 jpeg_write_m_byte(dstinfo
, marker
->data
[i
]);
1924 jpeg_write_marker(dstinfo
, marker
->marker
,
1925 marker
->data
, marker
->data_length
);