4 * This file was part of the Independent JPEG Group's software:
5 * Copyright (C) 1997-2019, Thomas G. Lane, Guido Vollbeding.
6 * libjpeg-turbo Modifications:
7 * Copyright (C) 2010, 2017, 2021-2022, D. R. Commander.
8 * For conditions of distribution and use, see the accompanying README.ijg
11 * This file contains image transformation routines and other utility code
12 * used by the jpegtran sample application. These are NOT part of the core
13 * JPEG library. But we keep these routines separate from jpegtran.c to
14 * ease the task of maintaining jpegtran-like programs that have other user
18 /* Although this file really shouldn't have access to the library internals,
19 * it's helpful to let it call jround_up() and jcopy_block_row().
21 #define JPEG_INTERNALS
25 #include "transupp.h" /* My own external interface */
27 #include <ctype.h> /* to declare isdigit() */
30 #if JPEG_LIB_VERSION >= 70
31 #define dstinfo_min_DCT_h_scaled_size dstinfo->min_DCT_h_scaled_size
32 #define dstinfo_min_DCT_v_scaled_size dstinfo->min_DCT_v_scaled_size
34 #define dstinfo_min_DCT_h_scaled_size DCTSIZE
35 #define dstinfo_min_DCT_v_scaled_size DCTSIZE
39 #if TRANSFORMS_SUPPORTED
42 * Lossless image transformation routines. These routines work on DCT
43 * coefficient arrays and thus do not require any lossy decompression
44 * or recompression of the image.
45 * Thanks to Guido Vollbeding for the initial design and code of this feature,
46 * and to Ben Jackson for introducing the cropping feature.
48 * Horizontal flipping is done in-place, using a single top-to-bottom
49 * pass through the virtual source array. It will thus be much the
50 * fastest option for images larger than main memory.
52 * The other routines require a set of destination virtual arrays, so they
53 * need twice as much memory as jpegtran normally does. The destination
54 * arrays are always written in normal scan order (top to bottom) because
55 * the virtual array manager expects this. The source arrays will be scanned
56 * in the corresponding order, which means multiple passes through the source
57 * arrays for most of the transforms. That could result in much thrashing
58 * if the image is larger than main memory.
60 * If cropping or trimming is involved, the destination arrays may be smaller
61 * than the source arrays. Note it is not possible to do horizontal flip
62 * in-place when a nonzero Y crop offset is specified, since we'd have to move
63 * data from one block row to another but the virtual array manager doesn't
64 * guarantee we can touch more than one row at a time. So in that case,
65 * we have to use a separate destination array.
67 * Some notes about the operating environment of the individual transform
69 * 1. Both the source and destination virtual arrays are allocated from the
70 * source JPEG object, and therefore should be manipulated by calling the
71 * source's memory manager.
72 * 2. The destination's component count should be used. It may be smaller
73 * than the source's when forcing to grayscale.
74 * 3. Likewise the destination's sampling factors should be used. When
75 * forcing to grayscale the destination's sampling factors will be all 1,
76 * and we may as well take that as the effective iMCU size.
77 * 4. When "trim" is in effect, the destination's dimensions will be the
78 * trimmed values but the source's will be untrimmed.
79 * 5. When "crop" is in effect, the destination's dimensions will be the
80 * cropped values but the source's will be uncropped. Each transform
81 * routine is responsible for picking up source data starting at the
82 * correct X and Y offset for the crop region. (The X and Y offsets
83 * passed to the transform routines are measured in iMCU blocks of the
85 * 6. All the routines assume that the source and destination buffers are
86 * padded out to a full iMCU boundary. This is true, although for the
87 * source buffer it is an undocumented property of jdcoefct.c.
92 dequant_comp(j_decompress_ptr cinfo, jpeg_component_info *compptr,
93 jvirt_barray_ptr coef_array, JQUANT_TBL *qtblptr1)
95 JDIMENSION blk_x, blk_y;
102 qtblptr = compptr->quant_table;
103 for (blk_y = 0; blk_y < compptr->height_in_blocks;
104 blk_y += compptr->v_samp_factor) {
105 buffer = (*cinfo->mem->access_virt_barray)
106 ((j_common_ptr)cinfo, coef_array, blk_y,
107 (JDIMENSION)compptr->v_samp_factor, TRUE);
108 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
109 block = buffer[offset_y];
110 for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
112 for (k = 0; k < DCTSIZE2; k++)
113 if (qtblptr->quantval[k] != qtblptr1->quantval[k])
114 ptr[k] *= qtblptr->quantval[k] / qtblptr1->quantval[k];
122 requant_comp(j_decompress_ptr cinfo, jpeg_component_info *compptr,
123 jvirt_barray_ptr coef_array, JQUANT_TBL *qtblptr1)
125 JDIMENSION blk_x, blk_y;
133 qtblptr = compptr->quant_table;
134 for (blk_y = 0; blk_y < compptr->height_in_blocks;
135 blk_y += compptr->v_samp_factor) {
136 buffer = (*cinfo->mem->access_virt_barray)
137 ((j_common_ptr)cinfo, coef_array, blk_y,
138 (JDIMENSION)compptr->v_samp_factor, TRUE);
139 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
140 block = buffer[offset_y];
141 for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
143 for (k = 0; k < DCTSIZE2; k++) {
144 temp = qtblptr->quantval[k];
145 qval = qtblptr1->quantval[k];
148 /* The following quantization code is copied from jcdctmgr.c */
150 #define DIVIDE_BY(a, b) a /= b
152 #define DIVIDE_BY(a, b) if (a >= b) a /= b; else a = 0
156 temp += qval >> 1; /* for rounding */
157 DIVIDE_BY(temp, qval);
160 temp += qval >> 1; /* for rounding */
161 DIVIDE_BY(temp, qval);
173 * Calculate largest common denominator using Euclid's algorithm.
176 largest_common_denominator(JCOEF a, JCOEF b)
191 adjust_quant(j_decompress_ptr srcinfo, jvirt_barray_ptr *src_coef_arrays,
192 j_decompress_ptr dropinfo, jvirt_barray_ptr *drop_coef_arrays,
193 boolean trim, j_compress_ptr dstinfo)
195 jpeg_component_info *compptr1, *compptr2;
196 JQUANT_TBL *qtblptr1, *qtblptr2, *qtblptr3;
199 for (ci = 0; ci < dstinfo->num_components && ci < dropinfo->num_components;
201 compptr1 = srcinfo->comp_info + ci;
202 compptr2 = dropinfo->comp_info + ci;
203 qtblptr1 = compptr1->quant_table;
204 qtblptr2 = compptr2->quant_table;
205 for (k = 0; k < DCTSIZE2; k++) {
206 if (qtblptr1->quantval[k] != qtblptr2->quantval[k]) {
208 requant_comp(dropinfo, compptr2, drop_coef_arrays[ci], qtblptr1);
210 qtblptr3 = dstinfo->quant_tbl_ptrs[compptr1->quant_tbl_no];
211 for (k = 0; k < DCTSIZE2; k++)
212 if (qtblptr1->quantval[k] != qtblptr2->quantval[k])
213 qtblptr3->quantval[k] =
214 largest_common_denominator(qtblptr1->quantval[k],
215 qtblptr2->quantval[k]);
216 dequant_comp(srcinfo, compptr1, src_coef_arrays[ci], qtblptr3);
217 dequant_comp(dropinfo, compptr2, drop_coef_arrays[ci], qtblptr3);
227 do_drop(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
228 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
229 jvirt_barray_ptr *src_coef_arrays,
230 j_decompress_ptr dropinfo, jvirt_barray_ptr *drop_coef_arrays,
231 JDIMENSION drop_width, JDIMENSION drop_height)
232 /* Drop (insert) the contents of another image into the source image. If the
233 * number of components in the drop image is smaller than the number of
234 * components in the destination image, then we fill in the remaining
235 * components with zero. This allows for dropping the contents of grayscale
236 * images into (arbitrarily sampled) color images.
239 JDIMENSION comp_width, comp_height;
240 JDIMENSION blk_y, x_drop_blocks, y_drop_blocks;
242 JBLOCKARRAY src_buffer, dst_buffer;
243 jpeg_component_info *compptr;
245 for (ci = 0; ci < dstinfo->num_components; ci++) {
246 compptr = dstinfo->comp_info + ci;
247 comp_width = drop_width * compptr->h_samp_factor;
248 comp_height = drop_height * compptr->v_samp_factor;
249 x_drop_blocks = x_crop_offset * compptr->h_samp_factor;
250 y_drop_blocks = y_crop_offset * compptr->v_samp_factor;
251 for (blk_y = 0; blk_y < comp_height; blk_y += compptr->v_samp_factor) {
252 dst_buffer = (*srcinfo->mem->access_virt_barray)
253 ((j_common_ptr)srcinfo, src_coef_arrays[ci], blk_y + y_drop_blocks,
254 (JDIMENSION)compptr->v_samp_factor, TRUE);
255 if (ci < dropinfo->num_components) {
256 src_buffer = (*dropinfo->mem->access_virt_barray)
257 ((j_common_ptr)dropinfo, drop_coef_arrays[ci], blk_y,
258 (JDIMENSION)compptr->v_samp_factor, FALSE);
259 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
260 jcopy_block_row(src_buffer[offset_y],
261 dst_buffer[offset_y] + x_drop_blocks, comp_width);
264 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
265 memset(dst_buffer[offset_y] + x_drop_blocks, 0,
266 comp_width * sizeof(JBLOCK));
275 do_crop(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
276 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
277 jvirt_barray_ptr *src_coef_arrays,
278 jvirt_barray_ptr *dst_coef_arrays)
279 /* Crop. This is only used when no rotate/flip is requested with the crop. */
281 JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks;
283 JBLOCKARRAY src_buffer, dst_buffer;
284 jpeg_component_info *compptr;
286 /* We simply have to copy the right amount of data (the destination's
287 * image size) starting at the given X and Y offsets in the source.
289 for (ci = 0; ci < dstinfo->num_components; ci++) {
290 compptr = dstinfo->comp_info + ci;
291 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
292 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
293 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
294 dst_blk_y += compptr->v_samp_factor) {
295 dst_buffer = (*srcinfo->mem->access_virt_barray)
296 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
297 (JDIMENSION)compptr->v_samp_factor, TRUE);
298 src_buffer = (*srcinfo->mem->access_virt_barray)
299 ((j_common_ptr)srcinfo, src_coef_arrays[ci], dst_blk_y + y_crop_blocks,
300 (JDIMENSION)compptr->v_samp_factor, FALSE);
301 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
302 jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
303 dst_buffer[offset_y], compptr->width_in_blocks);
311 do_crop_ext_zero(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
312 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
313 jvirt_barray_ptr *src_coef_arrays,
314 jvirt_barray_ptr *dst_coef_arrays)
315 /* Crop. This is only used when no rotate/flip is requested with the crop.
316 * Extension: If the destination size is larger than the source, we fill in the
317 * expanded region with zero (neutral gray). Note that we also have to zero
318 * partial iMCUs at the right and bottom edge of the source image area in this
322 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height;
323 JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks;
325 JBLOCKARRAY src_buffer, dst_buffer;
326 jpeg_component_info *compptr;
328 MCU_cols = srcinfo->output_width /
329 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
330 MCU_rows = srcinfo->output_height /
331 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
333 for (ci = 0; ci < dstinfo->num_components; ci++) {
334 compptr = dstinfo->comp_info + ci;
335 comp_width = MCU_cols * compptr->h_samp_factor;
336 comp_height = MCU_rows * compptr->v_samp_factor;
337 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
338 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
339 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
340 dst_blk_y += compptr->v_samp_factor) {
341 dst_buffer = (*srcinfo->mem->access_virt_barray)
342 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
343 (JDIMENSION)compptr->v_samp_factor, TRUE);
344 if (dstinfo->_jpeg_height > srcinfo->output_height) {
345 if (dst_blk_y < y_crop_blocks ||
346 dst_blk_y >= y_crop_blocks + comp_height) {
347 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
348 memset(dst_buffer[offset_y], 0,
349 compptr->width_in_blocks * sizeof(JBLOCK));
353 src_buffer = (*srcinfo->mem->access_virt_barray)
354 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
355 dst_blk_y - y_crop_blocks, (JDIMENSION)compptr->v_samp_factor,
358 src_buffer = (*srcinfo->mem->access_virt_barray)
359 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
360 dst_blk_y + y_crop_blocks, (JDIMENSION)compptr->v_samp_factor,
363 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
364 if (dstinfo->_jpeg_width > srcinfo->output_width) {
365 if (x_crop_blocks > 0) {
366 memset(dst_buffer[offset_y], 0, x_crop_blocks * sizeof(JBLOCK));
368 jcopy_block_row(src_buffer[offset_y],
369 dst_buffer[offset_y] + x_crop_blocks, comp_width);
370 if (compptr->width_in_blocks > x_crop_blocks + comp_width) {
371 memset(dst_buffer[offset_y] + x_crop_blocks + comp_width, 0,
372 (compptr->width_in_blocks - x_crop_blocks - comp_width) *
376 jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
377 dst_buffer[offset_y], compptr->width_in_blocks);
386 do_crop_ext_flat(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
387 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
388 jvirt_barray_ptr *src_coef_arrays,
389 jvirt_barray_ptr *dst_coef_arrays)
390 /* Crop. This is only used when no rotate/flip is requested with the crop.
391 * Extension: The destination width is larger than the source, and we fill in
392 * the expanded region with the DC coefficient of the adjacent block. Note
393 * that we also have to fill partial iMCUs at the right and bottom edge of the
394 * source image area in this case.
397 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height;
398 JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks;
401 JBLOCKARRAY src_buffer, dst_buffer;
402 jpeg_component_info *compptr;
404 MCU_cols = srcinfo->output_width /
405 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
406 MCU_rows = srcinfo->output_height /
407 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
409 for (ci = 0; ci < dstinfo->num_components; ci++) {
410 compptr = dstinfo->comp_info + ci;
411 comp_width = MCU_cols * compptr->h_samp_factor;
412 comp_height = MCU_rows * compptr->v_samp_factor;
413 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
414 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
415 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
416 dst_blk_y += compptr->v_samp_factor) {
417 dst_buffer = (*srcinfo->mem->access_virt_barray)
418 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
419 (JDIMENSION)compptr->v_samp_factor, TRUE);
420 if (dstinfo->_jpeg_height > srcinfo->output_height) {
421 if (dst_blk_y < y_crop_blocks ||
422 dst_blk_y >= y_crop_blocks + comp_height) {
423 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
424 memset(dst_buffer[offset_y], 0,
425 compptr->width_in_blocks * sizeof(JBLOCK));
429 src_buffer = (*srcinfo->mem->access_virt_barray)
430 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
431 dst_blk_y - y_crop_blocks, (JDIMENSION)compptr->v_samp_factor,
434 src_buffer = (*srcinfo->mem->access_virt_barray)
435 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
436 dst_blk_y + y_crop_blocks, (JDIMENSION)compptr->v_samp_factor,
439 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
440 if (x_crop_blocks > 0) {
441 memset(dst_buffer[offset_y], 0, x_crop_blocks * sizeof(JBLOCK));
442 dc = src_buffer[offset_y][0][0];
443 for (dst_blk_x = 0; dst_blk_x < x_crop_blocks; dst_blk_x++) {
444 dst_buffer[offset_y][dst_blk_x][0] = dc;
447 jcopy_block_row(src_buffer[offset_y],
448 dst_buffer[offset_y] + x_crop_blocks, comp_width);
449 if (compptr->width_in_blocks > x_crop_blocks + comp_width) {
450 memset(dst_buffer[offset_y] + x_crop_blocks + comp_width, 0,
451 (compptr->width_in_blocks - x_crop_blocks - comp_width) *
453 dc = src_buffer[offset_y][comp_width - 1][0];
454 for (dst_blk_x = x_crop_blocks + comp_width;
455 dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
456 dst_buffer[offset_y][dst_blk_x][0] = dc;
466 do_crop_ext_reflect(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
467 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
468 jvirt_barray_ptr *src_coef_arrays,
469 jvirt_barray_ptr *dst_coef_arrays)
470 /* Crop. This is only used when no rotate/flip is requested with the crop.
471 * Extension: The destination width is larger than the source, and we fill in
472 * the expanded region with repeated reflections of the source image. Note
473 * that we also have to fill partial iMCUs at the right and bottom edge of the
474 * source image area in this case.
477 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, src_blk_x;
478 JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks;
480 JBLOCKARRAY src_buffer, dst_buffer;
481 JBLOCKROW src_row_ptr, dst_row_ptr;
482 JCOEFPTR src_ptr, dst_ptr;
483 jpeg_component_info *compptr;
485 MCU_cols = srcinfo->output_width /
486 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
487 MCU_rows = srcinfo->output_height /
488 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
490 for (ci = 0; ci < dstinfo->num_components; ci++) {
491 compptr = dstinfo->comp_info + ci;
492 comp_width = MCU_cols * compptr->h_samp_factor;
493 comp_height = MCU_rows * compptr->v_samp_factor;
494 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
495 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
496 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
497 dst_blk_y += compptr->v_samp_factor) {
498 dst_buffer = (*srcinfo->mem->access_virt_barray)
499 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
500 (JDIMENSION)compptr->v_samp_factor, TRUE);
501 if (dstinfo->_jpeg_height > srcinfo->output_height) {
502 if (dst_blk_y < y_crop_blocks ||
503 dst_blk_y >= y_crop_blocks + comp_height) {
504 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
505 memset(dst_buffer[offset_y], 0,
506 compptr->width_in_blocks * sizeof(JBLOCK));
510 src_buffer = (*srcinfo->mem->access_virt_barray)
511 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
512 dst_blk_y - y_crop_blocks, (JDIMENSION)compptr->v_samp_factor,
515 src_buffer = (*srcinfo->mem->access_virt_barray)
516 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
517 dst_blk_y + y_crop_blocks, (JDIMENSION)compptr->v_samp_factor,
520 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
521 /* Copy source region */
522 jcopy_block_row(src_buffer[offset_y],
523 dst_buffer[offset_y] + x_crop_blocks, comp_width);
524 if (x_crop_blocks > 0) {
525 /* Reflect to left */
526 dst_row_ptr = dst_buffer[offset_y] + x_crop_blocks;
527 for (dst_blk_x = x_crop_blocks; dst_blk_x > 0;) {
528 src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */
529 for (src_blk_x = comp_width; src_blk_x > 0 && dst_blk_x > 0;
530 src_blk_x--, dst_blk_x--) {
531 dst_ptr = *(--dst_row_ptr); /* destination goes left */
532 src_ptr = *src_row_ptr++; /* source goes right */
533 /* This unrolled loop doesn't need to know which row it's on. */
534 for (k = 0; k < DCTSIZE2; k += 2) {
535 *dst_ptr++ = *src_ptr++; /* copy even column */
536 *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign
542 if (compptr->width_in_blocks > x_crop_blocks + comp_width) {
543 /* Reflect to right */
544 dst_row_ptr = dst_buffer[offset_y] + x_crop_blocks + comp_width;
545 for (dst_blk_x = compptr->width_in_blocks - x_crop_blocks - comp_width;
547 src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */
548 for (src_blk_x = comp_width; src_blk_x > 0 && dst_blk_x > 0;
549 src_blk_x--, dst_blk_x--) {
550 dst_ptr = *dst_row_ptr++; /* destination goes right */
551 src_ptr = *(--src_row_ptr); /* source goes left */
552 /* This unrolled loop doesn't need to know which row it's on. */
553 for (k = 0; k < DCTSIZE2; k += 2) {
554 *dst_ptr++ = *src_ptr++; /* copy even column */
555 *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign
568 do_wipe(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
569 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
570 jvirt_barray_ptr *src_coef_arrays,
571 JDIMENSION drop_width, JDIMENSION drop_height)
572 /* Wipe - discard image contents of specified region and fill with zero
576 JDIMENSION x_wipe_blocks, wipe_width;
577 JDIMENSION y_wipe_blocks, wipe_bottom;
580 jpeg_component_info *compptr;
582 for (ci = 0; ci < dstinfo->num_components; ci++) {
583 compptr = dstinfo->comp_info + ci;
584 x_wipe_blocks = x_crop_offset * compptr->h_samp_factor;
585 wipe_width = drop_width * compptr->h_samp_factor;
586 y_wipe_blocks = y_crop_offset * compptr->v_samp_factor;
587 wipe_bottom = drop_height * compptr->v_samp_factor + y_wipe_blocks;
588 for (; y_wipe_blocks < wipe_bottom;
589 y_wipe_blocks += compptr->v_samp_factor) {
590 buffer = (*srcinfo->mem->access_virt_barray)
591 ((j_common_ptr)srcinfo, src_coef_arrays[ci], y_wipe_blocks,
592 (JDIMENSION)compptr->v_samp_factor, TRUE);
593 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
594 memset(buffer[offset_y] + x_wipe_blocks, 0,
595 wipe_width * sizeof(JBLOCK));
603 do_flatten(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
604 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
605 jvirt_barray_ptr *src_coef_arrays,
606 JDIMENSION drop_width, JDIMENSION drop_height)
607 /* Flatten - discard image contents of specified region, similarly to wipe,
608 * but fill with the average of adjacent blocks instead of zero.
611 JDIMENSION x_wipe_blocks, wipe_width, wipe_right;
612 JDIMENSION y_wipe_blocks, wipe_bottom, blk_x;
613 int ci, offset_y, dc_left_value, dc_right_value, average;
615 jpeg_component_info *compptr;
617 for (ci = 0; ci < dstinfo->num_components; ci++) {
618 compptr = dstinfo->comp_info + ci;
619 x_wipe_blocks = x_crop_offset * compptr->h_samp_factor;
620 wipe_width = drop_width * compptr->h_samp_factor;
621 wipe_right = wipe_width + x_wipe_blocks;
622 y_wipe_blocks = y_crop_offset * compptr->v_samp_factor;
623 wipe_bottom = drop_height * compptr->v_samp_factor + y_wipe_blocks;
624 for (; y_wipe_blocks < wipe_bottom;
625 y_wipe_blocks += compptr->v_samp_factor) {
626 buffer = (*srcinfo->mem->access_virt_barray)
627 ((j_common_ptr)srcinfo, src_coef_arrays[ci], y_wipe_blocks,
628 (JDIMENSION)compptr->v_samp_factor, TRUE);
629 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
630 memset(buffer[offset_y] + x_wipe_blocks, 0,
631 wipe_width * sizeof(JBLOCK));
632 if (x_wipe_blocks > 0) {
633 dc_left_value = buffer[offset_y][x_wipe_blocks - 1][0];
634 if (wipe_right < compptr->width_in_blocks) {
635 dc_right_value = buffer[offset_y][wipe_right][0];
636 average = (dc_left_value + dc_right_value) >> 1;
638 average = dc_left_value;
640 } else if (wipe_right < compptr->width_in_blocks) {
641 average = buffer[offset_y][wipe_right][0];
643 for (blk_x = x_wipe_blocks; blk_x < wipe_right; blk_x++) {
644 buffer[offset_y][blk_x][0] = (JCOEF)average;
653 do_reflect(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
654 JDIMENSION x_crop_offset, jvirt_barray_ptr *src_coef_arrays,
655 JDIMENSION drop_width, JDIMENSION drop_height)
656 /* Reflect - discard image contents of specified region, similarly to wipe,
657 * but fill with repeated reflections of the outside region instead of zero.
658 * NB: y_crop_offset is assumed to be zero.
661 JDIMENSION x_wipe_blocks, wipe_width;
662 JDIMENSION y_wipe_blocks, wipe_bottom;
663 JDIMENSION src_blk_x, dst_blk_x;
666 JBLOCKROW src_row_ptr, dst_row_ptr;
667 JCOEFPTR src_ptr, dst_ptr;
668 jpeg_component_info *compptr;
670 for (ci = 0; ci < dstinfo->num_components; ci++) {
671 compptr = dstinfo->comp_info + ci;
672 x_wipe_blocks = x_crop_offset * compptr->h_samp_factor;
673 wipe_width = drop_width * compptr->h_samp_factor;
674 wipe_bottom = drop_height * compptr->v_samp_factor;
675 for (y_wipe_blocks = 0; y_wipe_blocks < wipe_bottom;
676 y_wipe_blocks += compptr->v_samp_factor) {
677 buffer = (*srcinfo->mem->access_virt_barray)
678 ((j_common_ptr)srcinfo, src_coef_arrays[ci], y_wipe_blocks,
679 (JDIMENSION)compptr->v_samp_factor, TRUE);
680 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
681 if (x_wipe_blocks > 0) {
682 /* Reflect from left */
683 dst_row_ptr = buffer[offset_y] + x_wipe_blocks;
684 for (dst_blk_x = wipe_width; dst_blk_x > 0;) {
685 src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */
686 for (src_blk_x = x_wipe_blocks;
687 src_blk_x > 0 && dst_blk_x > 0; src_blk_x--, dst_blk_x--) {
688 dst_ptr = *dst_row_ptr++; /* destination goes right */
689 src_ptr = *(--src_row_ptr); /* source goes left */
690 /* this unrolled loop doesn't need to know which row it's on... */
691 for (k = 0; k < DCTSIZE2; k += 2) {
692 *dst_ptr++ = *src_ptr++; /* copy even column */
693 *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign change */
697 } else if (compptr->width_in_blocks > x_wipe_blocks + wipe_width) {
698 /* Reflect from right */
699 dst_row_ptr = buffer[offset_y] + x_wipe_blocks + wipe_width;
700 for (dst_blk_x = wipe_width; dst_blk_x > 0;) {
701 src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */
702 src_blk_x = compptr->width_in_blocks - x_wipe_blocks - wipe_width;
703 for (; src_blk_x > 0 && dst_blk_x > 0; src_blk_x--, dst_blk_x--) {
704 dst_ptr = *(--dst_row_ptr); /* destination goes left */
705 src_ptr = *src_row_ptr++; /* source goes right */
706 /* this unrolled loop doesn't need to know which row it's on... */
707 for (k = 0; k < DCTSIZE2; k += 2) {
708 *dst_ptr++ = *src_ptr++; /* copy even column */
709 *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign change */
714 memset(buffer[offset_y] + x_wipe_blocks, 0,
715 wipe_width * sizeof(JBLOCK));
724 do_flip_h_no_crop(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
725 JDIMENSION x_crop_offset, jvirt_barray_ptr *src_coef_arrays)
726 /* Horizontal flip; done in-place, so no separate dest array is required.
727 * NB: this only works when y_crop_offset is zero.
730 JDIMENSION MCU_cols, comp_width, blk_x, blk_y, x_crop_blocks;
735 jpeg_component_info *compptr;
737 /* Horizontal mirroring of DCT blocks is accomplished by swapping
738 * pairs of blocks in-place. Within a DCT block, we perform horizontal
739 * mirroring by changing the signs of odd-numbered columns.
740 * Partial iMCUs at the right edge are left untouched.
742 MCU_cols = srcinfo->output_width /
743 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
745 for (ci = 0; ci < dstinfo->num_components; ci++) {
746 compptr = dstinfo->comp_info + ci;
747 comp_width = MCU_cols * compptr->h_samp_factor;
748 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
749 for (blk_y = 0; blk_y < compptr->height_in_blocks;
750 blk_y += compptr->v_samp_factor) {
751 buffer = (*srcinfo->mem->access_virt_barray)
752 ((j_common_ptr)srcinfo, src_coef_arrays[ci], blk_y,
753 (JDIMENSION)compptr->v_samp_factor, TRUE);
754 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
755 /* Do the mirroring */
756 for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) {
757 ptr1 = buffer[offset_y][blk_x];
758 ptr2 = buffer[offset_y][comp_width - blk_x - 1];
759 /* this unrolled loop doesn't need to know which row it's on... */
760 for (k = 0; k < DCTSIZE2; k += 2) {
761 temp1 = *ptr1; /* swap even column */
765 temp1 = *ptr1; /* swap odd column with sign change */
771 if (x_crop_blocks > 0) {
772 /* Now left-justify the portion of the data to be kept.
773 * We can't use a single jcopy_block_row() call because that routine
774 * depends on memcpy(), whose behavior is unspecified for overlapping
775 * source and destination areas. Sigh.
777 for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
778 jcopy_block_row(buffer[offset_y] + blk_x + x_crop_blocks,
779 buffer[offset_y] + blk_x, (JDIMENSION)1);
789 do_flip_h(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
790 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
791 jvirt_barray_ptr *src_coef_arrays,
792 jvirt_barray_ptr *dst_coef_arrays)
793 /* Horizontal flip in general cropping case */
795 JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
796 JDIMENSION x_crop_blocks, y_crop_blocks;
798 JBLOCKARRAY src_buffer, dst_buffer;
799 JBLOCKROW src_row_ptr, dst_row_ptr;
800 JCOEFPTR src_ptr, dst_ptr;
801 jpeg_component_info *compptr;
803 /* Here we must output into a separate array because we can't touch
804 * different rows of a single virtual array simultaneously. Otherwise,
805 * this is essentially the same as the routine above.
807 MCU_cols = srcinfo->output_width /
808 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
810 for (ci = 0; ci < dstinfo->num_components; ci++) {
811 compptr = dstinfo->comp_info + ci;
812 comp_width = MCU_cols * compptr->h_samp_factor;
813 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
814 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
815 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
816 dst_blk_y += compptr->v_samp_factor) {
817 dst_buffer = (*srcinfo->mem->access_virt_barray)
818 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
819 (JDIMENSION)compptr->v_samp_factor, TRUE);
820 src_buffer = (*srcinfo->mem->access_virt_barray)
821 ((j_common_ptr)srcinfo, src_coef_arrays[ci], dst_blk_y + y_crop_blocks,
822 (JDIMENSION)compptr->v_samp_factor, FALSE);
823 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
824 dst_row_ptr = dst_buffer[offset_y];
825 src_row_ptr = src_buffer[offset_y];
826 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
828 if (x_crop_blocks + dst_blk_x < comp_width) {
829 /* Do the mirrorable blocks */
830 dst_ptr = dst_row_ptr[dst_blk_x];
831 src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
832 /* this unrolled loop doesn't need to know which row it's on... */
833 for (k = 0; k < DCTSIZE2; k += 2) {
834 *dst_ptr++ = *src_ptr++; /* copy even column */
835 *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign
839 /* Copy last partial block(s) verbatim */
840 jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
841 dst_row_ptr + dst_blk_x, (JDIMENSION)1);
851 do_flip_v(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
852 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
853 jvirt_barray_ptr *src_coef_arrays,
854 jvirt_barray_ptr *dst_coef_arrays)
857 JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
858 JDIMENSION x_crop_blocks, y_crop_blocks;
859 int ci, i, j, offset_y;
860 JBLOCKARRAY src_buffer, dst_buffer;
861 JBLOCKROW src_row_ptr, dst_row_ptr;
862 JCOEFPTR src_ptr, dst_ptr;
863 jpeg_component_info *compptr;
865 /* We output into a separate array because we can't touch different
866 * rows of the source virtual array simultaneously. Otherwise, this
867 * is a pretty straightforward analog of horizontal flip.
868 * Within a DCT block, vertical mirroring is done by changing the signs
869 * of odd-numbered rows.
870 * Partial iMCUs at the bottom edge are copied verbatim.
872 MCU_rows = srcinfo->output_height /
873 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
875 for (ci = 0; ci < dstinfo->num_components; ci++) {
876 compptr = dstinfo->comp_info + ci;
877 comp_height = MCU_rows * compptr->v_samp_factor;
878 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
879 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
880 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
881 dst_blk_y += compptr->v_samp_factor) {
882 dst_buffer = (*srcinfo->mem->access_virt_barray)
883 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
884 (JDIMENSION)compptr->v_samp_factor, TRUE);
885 if (y_crop_blocks + dst_blk_y < comp_height) {
886 /* Row is within the mirrorable area. */
887 src_buffer = (*srcinfo->mem->access_virt_barray)
888 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
889 comp_height - y_crop_blocks - dst_blk_y -
890 (JDIMENSION)compptr->v_samp_factor,
891 (JDIMENSION)compptr->v_samp_factor, FALSE);
893 /* Bottom-edge blocks will be copied verbatim. */
894 src_buffer = (*srcinfo->mem->access_virt_barray)
895 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
896 dst_blk_y + y_crop_blocks,
897 (JDIMENSION)compptr->v_samp_factor, FALSE);
899 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
900 if (y_crop_blocks + dst_blk_y < comp_height) {
901 /* Row is within the mirrorable area. */
902 dst_row_ptr = dst_buffer[offset_y];
903 src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
904 src_row_ptr += x_crop_blocks;
905 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
907 dst_ptr = dst_row_ptr[dst_blk_x];
908 src_ptr = src_row_ptr[dst_blk_x];
909 for (i = 0; i < DCTSIZE; i += 2) {
911 for (j = 0; j < DCTSIZE; j++)
912 *dst_ptr++ = *src_ptr++;
913 /* copy odd row with sign change */
914 for (j = 0; j < DCTSIZE; j++)
915 *dst_ptr++ = -(*src_ptr++);
919 /* Just copy row verbatim. */
920 jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
921 dst_buffer[offset_y], compptr->width_in_blocks);
930 do_transpose(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
931 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
932 jvirt_barray_ptr *src_coef_arrays,
933 jvirt_barray_ptr *dst_coef_arrays)
934 /* Transpose source into destination */
936 JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks;
937 int ci, i, j, offset_x, offset_y;
938 JBLOCKARRAY src_buffer, dst_buffer;
939 JCOEFPTR src_ptr, dst_ptr;
940 jpeg_component_info *compptr;
942 /* Transposing pixels within a block just requires transposing the
944 * Partial iMCUs at the edges require no special treatment; we simply
945 * process all the available DCT blocks for every component.
947 for (ci = 0; ci < dstinfo->num_components; ci++) {
948 compptr = dstinfo->comp_info + ci;
949 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
950 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
951 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
952 dst_blk_y += compptr->v_samp_factor) {
953 dst_buffer = (*srcinfo->mem->access_virt_barray)
954 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
955 (JDIMENSION)compptr->v_samp_factor, TRUE);
956 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
957 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
958 dst_blk_x += compptr->h_samp_factor) {
959 src_buffer = (*srcinfo->mem->access_virt_barray)
960 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
961 dst_blk_x + x_crop_blocks,
962 (JDIMENSION)compptr->h_samp_factor, FALSE);
963 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
964 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
966 src_buffer[offset_x][dst_blk_y + offset_y + y_crop_blocks];
967 for (i = 0; i < DCTSIZE; i++)
968 for (j = 0; j < DCTSIZE; j++)
969 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
979 do_rot_90(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
980 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
981 jvirt_barray_ptr *src_coef_arrays,
982 jvirt_barray_ptr *dst_coef_arrays)
983 /* 90 degree rotation is equivalent to
984 * 1. Transposing the image;
985 * 2. Horizontal mirroring.
986 * These two steps are merged into a single processing routine.
989 JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
990 JDIMENSION x_crop_blocks, y_crop_blocks;
991 int ci, i, j, offset_x, offset_y;
992 JBLOCKARRAY src_buffer, dst_buffer;
993 JCOEFPTR src_ptr, dst_ptr;
994 jpeg_component_info *compptr;
996 /* Because of the horizontal mirror step, we can't process partial iMCUs
997 * at the (output) right edge properly. They just get transposed and
1000 MCU_cols = srcinfo->output_height /
1001 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
1003 for (ci = 0; ci < dstinfo->num_components; ci++) {
1004 compptr = dstinfo->comp_info + ci;
1005 comp_width = MCU_cols * compptr->h_samp_factor;
1006 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
1007 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
1008 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
1009 dst_blk_y += compptr->v_samp_factor) {
1010 dst_buffer = (*srcinfo->mem->access_virt_barray)
1011 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
1012 (JDIMENSION)compptr->v_samp_factor, TRUE);
1013 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
1014 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
1015 dst_blk_x += compptr->h_samp_factor) {
1016 if (x_crop_blocks + dst_blk_x < comp_width) {
1017 /* Block is within the mirrorable area. */
1018 src_buffer = (*srcinfo->mem->access_virt_barray)
1019 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1020 comp_width - x_crop_blocks - dst_blk_x -
1021 (JDIMENSION)compptr->h_samp_factor,
1022 (JDIMENSION)compptr->h_samp_factor, FALSE);
1024 /* Edge blocks are transposed but not mirrored. */
1025 src_buffer = (*srcinfo->mem->access_virt_barray)
1026 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1027 dst_blk_x + x_crop_blocks,
1028 (JDIMENSION)compptr->h_samp_factor, FALSE);
1030 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
1031 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
1032 if (x_crop_blocks + dst_blk_x < comp_width) {
1033 /* Block is within the mirrorable area. */
1034 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
1035 [dst_blk_y + offset_y + y_crop_blocks];
1036 for (i = 0; i < DCTSIZE; i++) {
1037 for (j = 0; j < DCTSIZE; j++)
1038 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1040 for (j = 0; j < DCTSIZE; j++)
1041 dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
1044 /* Edge blocks are transposed but not mirrored. */
1045 src_ptr = src_buffer[offset_x]
1046 [dst_blk_y + offset_y + y_crop_blocks];
1047 for (i = 0; i < DCTSIZE; i++)
1048 for (j = 0; j < DCTSIZE; j++)
1049 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1060 do_rot_270(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
1061 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
1062 jvirt_barray_ptr *src_coef_arrays,
1063 jvirt_barray_ptr *dst_coef_arrays)
1064 /* 270 degree rotation is equivalent to
1065 * 1. Horizontal mirroring;
1066 * 2. Transposing the image.
1067 * These two steps are merged into a single processing routine.
1070 JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
1071 JDIMENSION x_crop_blocks, y_crop_blocks;
1072 int ci, i, j, offset_x, offset_y;
1073 JBLOCKARRAY src_buffer, dst_buffer;
1074 JCOEFPTR src_ptr, dst_ptr;
1075 jpeg_component_info *compptr;
1077 /* Because of the horizontal mirror step, we can't process partial iMCUs
1078 * at the (output) bottom edge properly. They just get transposed and
1081 MCU_rows = srcinfo->output_width /
1082 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
1084 for (ci = 0; ci < dstinfo->num_components; ci++) {
1085 compptr = dstinfo->comp_info + ci;
1086 comp_height = MCU_rows * compptr->v_samp_factor;
1087 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
1088 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
1089 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
1090 dst_blk_y += compptr->v_samp_factor) {
1091 dst_buffer = (*srcinfo->mem->access_virt_barray)
1092 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
1093 (JDIMENSION)compptr->v_samp_factor, TRUE);
1094 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
1095 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
1096 dst_blk_x += compptr->h_samp_factor) {
1097 src_buffer = (*srcinfo->mem->access_virt_barray)
1098 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1099 dst_blk_x + x_crop_blocks,
1100 (JDIMENSION)compptr->h_samp_factor, FALSE);
1101 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
1102 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
1103 if (y_crop_blocks + dst_blk_y < comp_height) {
1104 /* Block is within the mirrorable area. */
1105 src_ptr = src_buffer[offset_x]
1106 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
1107 for (i = 0; i < DCTSIZE; i++) {
1108 for (j = 0; j < DCTSIZE; j++) {
1109 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1111 dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
1115 /* Edge blocks are transposed but not mirrored. */
1116 src_ptr = src_buffer[offset_x]
1117 [dst_blk_y + offset_y + y_crop_blocks];
1118 for (i = 0; i < DCTSIZE; i++)
1119 for (j = 0; j < DCTSIZE; j++)
1120 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1131 do_rot_180(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
1132 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
1133 jvirt_barray_ptr *src_coef_arrays,
1134 jvirt_barray_ptr *dst_coef_arrays)
1135 /* 180 degree rotation is equivalent to
1136 * 1. Vertical mirroring;
1137 * 2. Horizontal mirroring.
1138 * These two steps are merged into a single processing routine.
1141 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
1142 JDIMENSION x_crop_blocks, y_crop_blocks;
1143 int ci, i, j, offset_y;
1144 JBLOCKARRAY src_buffer, dst_buffer;
1145 JBLOCKROW src_row_ptr, dst_row_ptr;
1146 JCOEFPTR src_ptr, dst_ptr;
1147 jpeg_component_info *compptr;
1149 MCU_cols = srcinfo->output_width /
1150 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
1151 MCU_rows = srcinfo->output_height /
1152 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
1154 for (ci = 0; ci < dstinfo->num_components; ci++) {
1155 compptr = dstinfo->comp_info + ci;
1156 comp_width = MCU_cols * compptr->h_samp_factor;
1157 comp_height = MCU_rows * compptr->v_samp_factor;
1158 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
1159 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
1160 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
1161 dst_blk_y += compptr->v_samp_factor) {
1162 dst_buffer = (*srcinfo->mem->access_virt_barray)
1163 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
1164 (JDIMENSION)compptr->v_samp_factor, TRUE);
1165 if (y_crop_blocks + dst_blk_y < comp_height) {
1166 /* Row is within the vertically mirrorable area. */
1167 src_buffer = (*srcinfo->mem->access_virt_barray)
1168 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1169 comp_height - y_crop_blocks - dst_blk_y -
1170 (JDIMENSION)compptr->v_samp_factor,
1171 (JDIMENSION)compptr->v_samp_factor, FALSE);
1173 /* Bottom-edge rows are only mirrored horizontally. */
1174 src_buffer = (*srcinfo->mem->access_virt_barray)
1175 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1176 dst_blk_y + y_crop_blocks,
1177 (JDIMENSION)compptr->v_samp_factor, FALSE);
1179 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
1180 dst_row_ptr = dst_buffer[offset_y];
1181 if (y_crop_blocks + dst_blk_y < comp_height) {
1182 /* Row is within the mirrorable area. */
1183 src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
1184 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
1186 dst_ptr = dst_row_ptr[dst_blk_x];
1187 if (x_crop_blocks + dst_blk_x < comp_width) {
1188 /* Process the blocks that can be mirrored both ways. */
1190 src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
1191 for (i = 0; i < DCTSIZE; i += 2) {
1192 /* For even row, negate every odd column. */
1193 for (j = 0; j < DCTSIZE; j += 2) {
1194 *dst_ptr++ = *src_ptr++;
1195 *dst_ptr++ = -(*src_ptr++);
1197 /* For odd row, negate every even column. */
1198 for (j = 0; j < DCTSIZE; j += 2) {
1199 *dst_ptr++ = -(*src_ptr++);
1200 *dst_ptr++ = *src_ptr++;
1204 /* Any remaining right-edge blocks are only mirrored vertically. */
1205 src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x];
1206 for (i = 0; i < DCTSIZE; i += 2) {
1207 for (j = 0; j < DCTSIZE; j++)
1208 *dst_ptr++ = *src_ptr++;
1209 for (j = 0; j < DCTSIZE; j++)
1210 *dst_ptr++ = -(*src_ptr++);
1215 /* Remaining rows are just mirrored horizontally. */
1216 src_row_ptr = src_buffer[offset_y];
1217 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
1219 if (x_crop_blocks + dst_blk_x < comp_width) {
1220 /* Process the blocks that can be mirrored. */
1221 dst_ptr = dst_row_ptr[dst_blk_x];
1223 src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
1224 for (i = 0; i < DCTSIZE2; i += 2) {
1225 *dst_ptr++ = *src_ptr++;
1226 *dst_ptr++ = -(*src_ptr++);
1229 /* Any remaining right-edge blocks are only copied. */
1230 jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
1231 dst_row_ptr + dst_blk_x, (JDIMENSION)1);
1242 do_transverse(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
1243 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
1244 jvirt_barray_ptr *src_coef_arrays,
1245 jvirt_barray_ptr *dst_coef_arrays)
1246 /* Transverse transpose is equivalent to
1247 * 1. 180 degree rotation;
1250 * 1. Horizontal mirroring;
1252 * 3. Horizontal mirroring.
1253 * These steps are merged into a single processing routine.
1256 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
1257 JDIMENSION x_crop_blocks, y_crop_blocks;
1258 int ci, i, j, offset_x, offset_y;
1259 JBLOCKARRAY src_buffer, dst_buffer;
1260 JCOEFPTR src_ptr, dst_ptr;
1261 jpeg_component_info *compptr;
1263 MCU_cols = srcinfo->output_height /
1264 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
1265 MCU_rows = srcinfo->output_width /
1266 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
1268 for (ci = 0; ci < dstinfo->num_components; ci++) {
1269 compptr = dstinfo->comp_info + ci;
1270 comp_width = MCU_cols * compptr->h_samp_factor;
1271 comp_height = MCU_rows * compptr->v_samp_factor;
1272 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
1273 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
1274 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
1275 dst_blk_y += compptr->v_samp_factor) {
1276 dst_buffer = (*srcinfo->mem->access_virt_barray)
1277 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
1278 (JDIMENSION)compptr->v_samp_factor, TRUE);
1279 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
1280 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
1281 dst_blk_x += compptr->h_samp_factor) {
1282 if (x_crop_blocks + dst_blk_x < comp_width) {
1283 /* Block is within the mirrorable area. */
1284 src_buffer = (*srcinfo->mem->access_virt_barray)
1285 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1286 comp_width - x_crop_blocks - dst_blk_x -
1287 (JDIMENSION)compptr->h_samp_factor,
1288 (JDIMENSION)compptr->h_samp_factor, FALSE);
1290 src_buffer = (*srcinfo->mem->access_virt_barray)
1291 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1292 dst_blk_x + x_crop_blocks,
1293 (JDIMENSION)compptr->h_samp_factor, FALSE);
1295 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
1296 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
1297 if (y_crop_blocks + dst_blk_y < comp_height) {
1298 if (x_crop_blocks + dst_blk_x < comp_width) {
1299 /* Block is within the mirrorable area. */
1300 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
1301 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
1302 for (i = 0; i < DCTSIZE; i++) {
1303 for (j = 0; j < DCTSIZE; j++) {
1304 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1306 dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
1309 for (j = 0; j < DCTSIZE; j++) {
1310 dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
1312 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1316 /* Right-edge blocks are mirrored in y only */
1317 src_ptr = src_buffer[offset_x]
1318 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
1319 for (i = 0; i < DCTSIZE; i++) {
1320 for (j = 0; j < DCTSIZE; j++) {
1321 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1323 dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
1328 if (x_crop_blocks + dst_blk_x < comp_width) {
1329 /* Bottom-edge blocks are mirrored in x only */
1330 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
1331 [dst_blk_y + offset_y + y_crop_blocks];
1332 for (i = 0; i < DCTSIZE; i++) {
1333 for (j = 0; j < DCTSIZE; j++)
1334 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1336 for (j = 0; j < DCTSIZE; j++)
1337 dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
1340 /* At lower right corner, just transpose, no mirroring */
1341 src_ptr = src_buffer[offset_x]
1342 [dst_blk_y + offset_y + y_crop_blocks];
1343 for (i = 0; i < DCTSIZE; i++)
1344 for (j = 0; j < DCTSIZE; j++)
1345 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1356 /* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec.
1357 * Returns TRUE if valid integer found, FALSE if not.
1358 * *strptr is advanced over the digit string, and *result is set to its value.
1362 jt_read_integer(const char **strptr, JDIMENSION *result)
1364 const char *ptr = *strptr;
1367 for (; isdigit(*ptr); ptr++) {
1368 val = val * 10 + (JDIMENSION)(*ptr - '0');
1372 return FALSE; /* oops, no digits */
1378 /* Parse a crop specification (written in X11 geometry style).
1379 * The routine returns TRUE if the spec string is valid, FALSE if not.
1381 * The crop spec string should have the format
1382 * <width>[{fr}]x<height>[{fr}]{+-}<xoffset>{+-}<yoffset>
1383 * where width, height, xoffset, and yoffset are unsigned integers.
1384 * Each of the elements can be omitted to indicate a default value.
1385 * (A weakness of this style is that it is not possible to omit xoffset
1386 * while specifying yoffset, since they look alike.)
1388 * This code is loosely based on XParseGeometry from the X11 distribution.
1392 jtransform_parse_crop_spec(jpeg_transform_info *info, const char *spec)
1395 info->crop_width_set = JCROP_UNSET;
1396 info->crop_height_set = JCROP_UNSET;
1397 info->crop_xoffset_set = JCROP_UNSET;
1398 info->crop_yoffset_set = JCROP_UNSET;
1400 if (isdigit(*spec)) {
1402 if (!jt_read_integer(&spec, &info->crop_width))
1404 if (*spec == 'f' || *spec == 'F') {
1406 info->crop_width_set = JCROP_FORCE;
1407 } else if (*spec == 'r' || *spec == 'R') {
1409 info->crop_width_set = JCROP_REFLECT;
1411 info->crop_width_set = JCROP_POS;
1413 if (*spec == 'x' || *spec == 'X') {
1416 if (!jt_read_integer(&spec, &info->crop_height))
1418 if (*spec == 'f' || *spec == 'F') {
1420 info->crop_height_set = JCROP_FORCE;
1421 } else if (*spec == 'r' || *spec == 'R') {
1423 info->crop_height_set = JCROP_REFLECT;
1425 info->crop_height_set = JCROP_POS;
1427 if (*spec == '+' || *spec == '-') {
1429 info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
1431 if (!jt_read_integer(&spec, &info->crop_xoffset))
1434 if (*spec == '+' || *spec == '-') {
1436 info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
1438 if (!jt_read_integer(&spec, &info->crop_yoffset))
1441 /* We had better have gotten to the end of the string. */
1449 /* Trim off any partial iMCUs on the indicated destination edge */
1452 trim_right_edge(jpeg_transform_info *info, JDIMENSION full_width)
1454 JDIMENSION MCU_cols;
1456 MCU_cols = info->output_width / info->iMCU_sample_width;
1457 if (MCU_cols > 0 && info->x_crop_offset + MCU_cols ==
1458 full_width / info->iMCU_sample_width)
1459 info->output_width = MCU_cols * info->iMCU_sample_width;
1463 trim_bottom_edge(jpeg_transform_info *info, JDIMENSION full_height)
1465 JDIMENSION MCU_rows;
1467 MCU_rows = info->output_height / info->iMCU_sample_height;
1468 if (MCU_rows > 0 && info->y_crop_offset + MCU_rows ==
1469 full_height / info->iMCU_sample_height)
1470 info->output_height = MCU_rows * info->iMCU_sample_height;
1474 /* Request any required workspace.
1476 * This routine figures out the size that the output image will be
1477 * (which implies that all the transform parameters must be set before
1480 * We allocate the workspace virtual arrays from the source decompression
1481 * object, so that all the arrays (both the original data and the workspace)
1482 * will be taken into account while making memory management decisions.
1483 * Hence, this routine must be called after jpeg_read_header (which reads
1484 * the image dimensions) and before jpeg_read_coefficients (which realizes
1485 * the source's virtual arrays).
1487 * This function returns FALSE right away if -perfect is given
1488 * and transformation is not perfect. Otherwise returns TRUE.
1492 jtransform_request_workspace(j_decompress_ptr srcinfo,
1493 jpeg_transform_info *info)
1495 jvirt_barray_ptr *coef_arrays;
1496 boolean need_workspace, transpose_it;
1497 jpeg_component_info *compptr;
1498 JDIMENSION xoffset, yoffset, dtemp;
1499 JDIMENSION width_in_iMCUs, height_in_iMCUs;
1500 JDIMENSION width_in_blocks, height_in_blocks;
1501 int itemp, ci, h_samp_factor, v_samp_factor;
1503 /* Determine number of components in output image */
1504 if (info->force_grayscale &&
1505 srcinfo->jpeg_color_space == JCS_YCbCr &&
1506 srcinfo->num_components == 3)
1507 /* We'll only process the first component */
1508 info->num_components = 1;
1510 /* Process all the components */
1511 info->num_components = srcinfo->num_components;
1513 /* Compute output image dimensions and related values. */
1514 #if JPEG_LIB_VERSION >= 80
1515 jpeg_core_output_dimensions(srcinfo);
1517 srcinfo->output_width = srcinfo->image_width;
1518 srcinfo->output_height = srcinfo->image_height;
1521 /* Return right away if -perfect is given and transformation is not perfect.
1523 if (info->perfect) {
1524 if (info->num_components == 1) {
1525 if (!jtransform_perfect_transform(srcinfo->output_width,
1526 srcinfo->output_height,
1527 srcinfo->_min_DCT_h_scaled_size,
1528 srcinfo->_min_DCT_v_scaled_size,
1532 if (!jtransform_perfect_transform(srcinfo->output_width,
1533 srcinfo->output_height,
1534 srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size,
1535 srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size,
1541 /* If there is only one output component, force the iMCU size to be 1;
1542 * else use the source iMCU size. (This allows us to do the right thing
1543 * when reducing color to grayscale, and also provides a handy way of
1544 * cleaning up "funny" grayscale images whose sampling factors are not 1x1.)
1546 switch (info->transform) {
1547 case JXFORM_TRANSPOSE:
1548 case JXFORM_TRANSVERSE:
1550 case JXFORM_ROT_270:
1551 info->output_width = srcinfo->output_height;
1552 info->output_height = srcinfo->output_width;
1553 if (info->num_components == 1) {
1554 info->iMCU_sample_width = srcinfo->_min_DCT_v_scaled_size;
1555 info->iMCU_sample_height = srcinfo->_min_DCT_h_scaled_size;
1557 info->iMCU_sample_width =
1558 srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size;
1559 info->iMCU_sample_height =
1560 srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size;
1564 info->output_width = srcinfo->output_width;
1565 info->output_height = srcinfo->output_height;
1566 if (info->num_components == 1) {
1567 info->iMCU_sample_width = srcinfo->_min_DCT_h_scaled_size;
1568 info->iMCU_sample_height = srcinfo->_min_DCT_v_scaled_size;
1570 info->iMCU_sample_width =
1571 srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size;
1572 info->iMCU_sample_height =
1573 srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size;
1578 /* If cropping has been requested, compute the crop area's position and
1579 * dimensions, ensuring that its upper left corner falls at an iMCU boundary.
1582 /* Insert default values for unset crop parameters */
1583 if (info->crop_xoffset_set == JCROP_UNSET)
1584 info->crop_xoffset = 0; /* default to +0 */
1585 if (info->crop_yoffset_set == JCROP_UNSET)
1586 info->crop_yoffset = 0; /* default to +0 */
1587 if (info->crop_width_set == JCROP_UNSET) {
1588 if (info->crop_xoffset >= info->output_width)
1589 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1590 info->crop_width = info->output_width - info->crop_xoffset;
1592 /* Check for crop extension */
1593 if (info->crop_width > info->output_width) {
1594 /* Crop extension does not work when transforming! */
1595 if (info->transform != JXFORM_NONE ||
1596 info->crop_xoffset >= info->crop_width ||
1597 info->crop_xoffset > info->crop_width - info->output_width)
1598 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1600 if (info->crop_xoffset >= info->output_width ||
1601 info->crop_width <= 0 ||
1602 info->crop_xoffset > info->output_width - info->crop_width)
1603 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1606 if (info->crop_height_set == JCROP_UNSET) {
1607 if (info->crop_yoffset >= info->output_height)
1608 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1609 info->crop_height = info->output_height - info->crop_yoffset;
1611 /* Check for crop extension */
1612 if (info->crop_height > info->output_height) {
1613 /* Crop extension does not work when transforming! */
1614 if (info->transform != JXFORM_NONE ||
1615 info->crop_yoffset >= info->crop_height ||
1616 info->crop_yoffset > info->crop_height - info->output_height)
1617 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1619 if (info->crop_yoffset >= info->output_height ||
1620 info->crop_height <= 0 ||
1621 info->crop_yoffset > info->output_height - info->crop_height)
1622 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1625 /* Convert negative crop offsets into regular offsets */
1626 if (info->crop_xoffset_set != JCROP_NEG)
1627 xoffset = info->crop_xoffset;
1628 else if (info->crop_width > info->output_width) /* crop extension */
1629 xoffset = info->crop_width - info->output_width - info->crop_xoffset;
1631 xoffset = info->output_width - info->crop_width - info->crop_xoffset;
1632 if (info->crop_yoffset_set != JCROP_NEG)
1633 yoffset = info->crop_yoffset;
1634 else if (info->crop_height > info->output_height) /* crop extension */
1635 yoffset = info->crop_height - info->output_height - info->crop_yoffset;
1637 yoffset = info->output_height - info->crop_height - info->crop_yoffset;
1638 /* Now adjust so that upper left corner falls at an iMCU boundary */
1639 switch (info->transform) {
1641 /* Ensure the effective drop region will not exceed the requested */
1642 itemp = info->iMCU_sample_width;
1643 dtemp = itemp - 1 - ((xoffset + itemp - 1) % itemp);
1645 if (info->crop_width <= dtemp)
1646 info->drop_width = 0;
1647 else if (xoffset + info->crop_width - dtemp == info->output_width)
1648 /* Matching right edge: include partial iMCU */
1649 info->drop_width = (info->crop_width - dtemp + itemp - 1) / itemp;
1651 info->drop_width = (info->crop_width - dtemp) / itemp;
1652 itemp = info->iMCU_sample_height;
1653 dtemp = itemp - 1 - ((yoffset + itemp - 1) % itemp);
1655 if (info->crop_height <= dtemp)
1656 info->drop_height = 0;
1657 else if (yoffset + info->crop_height - dtemp == info->output_height)
1658 /* Matching bottom edge: include partial iMCU */
1659 info->drop_height = (info->crop_height - dtemp + itemp - 1) / itemp;
1661 info->drop_height = (info->crop_height - dtemp) / itemp;
1662 /* Check if sampling factors match for dropping */
1663 if (info->drop_width != 0 && info->drop_height != 0)
1664 for (ci = 0; ci < info->num_components &&
1665 ci < info->drop_ptr->num_components; ci++) {
1666 if (info->drop_ptr->comp_info[ci].h_samp_factor *
1667 srcinfo->max_h_samp_factor !=
1668 srcinfo->comp_info[ci].h_samp_factor *
1669 info->drop_ptr->max_h_samp_factor)
1670 ERREXIT6(srcinfo, JERR_BAD_DROP_SAMPLING, ci,
1671 info->drop_ptr->comp_info[ci].h_samp_factor,
1672 info->drop_ptr->max_h_samp_factor,
1673 srcinfo->comp_info[ci].h_samp_factor,
1674 srcinfo->max_h_samp_factor, 'h');
1675 if (info->drop_ptr->comp_info[ci].v_samp_factor *
1676 srcinfo->max_v_samp_factor !=
1677 srcinfo->comp_info[ci].v_samp_factor *
1678 info->drop_ptr->max_v_samp_factor)
1679 ERREXIT6(srcinfo, JERR_BAD_DROP_SAMPLING, ci,
1680 info->drop_ptr->comp_info[ci].v_samp_factor,
1681 info->drop_ptr->max_v_samp_factor,
1682 srcinfo->comp_info[ci].v_samp_factor,
1683 srcinfo->max_v_samp_factor, 'v');
1687 /* Ensure the effective wipe region will cover the requested */
1688 info->drop_width = (JDIMENSION)jdiv_round_up
1689 ((long)(info->crop_width + (xoffset % info->iMCU_sample_width)),
1690 (long)info->iMCU_sample_width);
1691 info->drop_height = (JDIMENSION)jdiv_round_up
1692 ((long)(info->crop_height + (yoffset % info->iMCU_sample_height)),
1693 (long)info->iMCU_sample_height);
1696 /* Ensure the effective crop region will cover the requested */
1697 if (info->crop_width_set == JCROP_FORCE ||
1698 info->crop_width > info->output_width)
1699 info->output_width = info->crop_width;
1701 info->output_width =
1702 info->crop_width + (xoffset % info->iMCU_sample_width);
1703 if (info->crop_height_set == JCROP_FORCE ||
1704 info->crop_height > info->output_height)
1705 info->output_height = info->crop_height;
1707 info->output_height =
1708 info->crop_height + (yoffset % info->iMCU_sample_height);
1710 /* Save x/y offsets measured in iMCUs */
1711 info->x_crop_offset = xoffset / info->iMCU_sample_width;
1712 info->y_crop_offset = yoffset / info->iMCU_sample_height;
1714 info->x_crop_offset = 0;
1715 info->y_crop_offset = 0;
1718 /* Figure out whether we need workspace arrays,
1719 * and if so whether they are transposed relative to the source.
1721 need_workspace = FALSE;
1722 transpose_it = FALSE;
1723 switch (info->transform) {
1725 if (info->x_crop_offset != 0 || info->y_crop_offset != 0 ||
1726 info->output_width > srcinfo->output_width ||
1727 info->output_height > srcinfo->output_height)
1728 need_workspace = TRUE;
1729 /* No workspace needed if neither cropping nor transforming */
1733 trim_right_edge(info, srcinfo->output_width);
1734 if (info->y_crop_offset != 0 || info->slow_hflip)
1735 need_workspace = TRUE;
1736 /* do_flip_h_no_crop doesn't need a workspace array */
1740 trim_bottom_edge(info, srcinfo->output_height);
1741 /* Need workspace arrays having same dimensions as source image. */
1742 need_workspace = TRUE;
1744 case JXFORM_TRANSPOSE:
1745 /* transpose does NOT have to trim anything */
1746 /* Need workspace arrays having transposed dimensions. */
1747 need_workspace = TRUE;
1748 transpose_it = TRUE;
1750 case JXFORM_TRANSVERSE:
1752 trim_right_edge(info, srcinfo->output_height);
1753 trim_bottom_edge(info, srcinfo->output_width);
1755 /* Need workspace arrays having transposed dimensions. */
1756 need_workspace = TRUE;
1757 transpose_it = TRUE;
1761 trim_right_edge(info, srcinfo->output_height);
1762 /* Need workspace arrays having transposed dimensions. */
1763 need_workspace = TRUE;
1764 transpose_it = TRUE;
1766 case JXFORM_ROT_180:
1768 trim_right_edge(info, srcinfo->output_width);
1769 trim_bottom_edge(info, srcinfo->output_height);
1771 /* Need workspace arrays having same dimensions as source image. */
1772 need_workspace = TRUE;
1774 case JXFORM_ROT_270:
1776 trim_bottom_edge(info, srcinfo->output_width);
1777 /* Need workspace arrays having transposed dimensions. */
1778 need_workspace = TRUE;
1779 transpose_it = TRUE;
1787 /* Allocate workspace if needed.
1788 * Note that we allocate arrays padded out to the next iMCU boundary,
1789 * so that transform routines need not worry about missing edge blocks.
1791 if (need_workspace) {
1792 coef_arrays = (jvirt_barray_ptr *)
1793 (*srcinfo->mem->alloc_small) ((j_common_ptr)srcinfo, JPOOL_IMAGE,
1794 sizeof(jvirt_barray_ptr) * info->num_components);
1795 width_in_iMCUs = (JDIMENSION)
1796 jdiv_round_up((long)info->output_width, (long)info->iMCU_sample_width);
1797 height_in_iMCUs = (JDIMENSION)
1798 jdiv_round_up((long)info->output_height, (long)info->iMCU_sample_height);
1799 for (ci = 0; ci < info->num_components; ci++) {
1800 compptr = srcinfo->comp_info + ci;
1801 if (info->num_components == 1) {
1802 /* we're going to force samp factors to 1x1 in this case */
1803 h_samp_factor = v_samp_factor = 1;
1804 } else if (transpose_it) {
1805 h_samp_factor = compptr->v_samp_factor;
1806 v_samp_factor = compptr->h_samp_factor;
1808 h_samp_factor = compptr->h_samp_factor;
1809 v_samp_factor = compptr->v_samp_factor;
1811 width_in_blocks = width_in_iMCUs * h_samp_factor;
1812 height_in_blocks = height_in_iMCUs * v_samp_factor;
1813 coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
1814 ((j_common_ptr)srcinfo, JPOOL_IMAGE, FALSE,
1815 width_in_blocks, height_in_blocks, (JDIMENSION)v_samp_factor);
1817 info->workspace_coef_arrays = coef_arrays;
1819 info->workspace_coef_arrays = NULL;
1825 /* Transpose destination image parameters */
1828 transpose_critical_parameters(j_compress_ptr dstinfo)
1830 int tblno, i, j, ci, itemp;
1831 jpeg_component_info *compptr;
1832 JQUANT_TBL *qtblptr;
1836 /* Transpose image dimensions */
1837 jtemp = dstinfo->image_width;
1838 dstinfo->image_width = dstinfo->image_height;
1839 dstinfo->image_height = jtemp;
1840 #if JPEG_LIB_VERSION >= 70
1841 itemp = dstinfo->min_DCT_h_scaled_size;
1842 dstinfo->min_DCT_h_scaled_size = dstinfo->min_DCT_v_scaled_size;
1843 dstinfo->min_DCT_v_scaled_size = itemp;
1846 /* Transpose sampling factors */
1847 for (ci = 0; ci < dstinfo->num_components; ci++) {
1848 compptr = dstinfo->comp_info + ci;
1849 itemp = compptr->h_samp_factor;
1850 compptr->h_samp_factor = compptr->v_samp_factor;
1851 compptr->v_samp_factor = itemp;
1854 /* Transpose quantization tables */
1855 for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
1856 qtblptr = dstinfo->quant_tbl_ptrs[tblno];
1857 if (qtblptr != NULL) {
1858 for (i = 0; i < DCTSIZE; i++) {
1859 for (j = 0; j < i; j++) {
1860 qtemp = qtblptr->quantval[i * DCTSIZE + j];
1861 qtblptr->quantval[i * DCTSIZE + j] =
1862 qtblptr->quantval[j * DCTSIZE + i];
1863 qtblptr->quantval[j * DCTSIZE + i] = qtemp;
1871 /* Adjust Exif image parameters.
1873 * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible.
1877 adjust_exif_parameters(JOCTET *data, unsigned int length, JDIMENSION new_width,
1878 JDIMENSION new_height)
1880 boolean is_motorola; /* Flag for byte order */
1881 unsigned int number_of_tags, tagnum;
1882 unsigned int firstoffset, offset;
1883 JDIMENSION new_value;
1885 if (length < 12) return; /* Length of an IFD entry */
1887 /* Discover byte order */
1888 if (data[0] == 0x49 && data[1] == 0x49)
1889 is_motorola = FALSE;
1890 else if (data[0] == 0x4D && data[1] == 0x4D)
1895 /* Check Tag Mark */
1897 if (data[2] != 0) return;
1898 if (data[3] != 0x2A) return;
1900 if (data[3] != 0) return;
1901 if (data[2] != 0x2A) return;
1904 /* Get first IFD offset (offset to IFD0) */
1906 if (data[4] != 0) return;
1907 if (data[5] != 0) return;
1908 firstoffset = data[6];
1910 firstoffset += data[7];
1912 if (data[7] != 0) return;
1913 if (data[6] != 0) return;
1914 firstoffset = data[5];
1916 firstoffset += data[4];
1918 if (firstoffset > length - 2) return; /* check end of data segment */
1920 /* Get the number of directory entries contained in this IFD */
1922 number_of_tags = data[firstoffset];
1923 number_of_tags <<= 8;
1924 number_of_tags += data[firstoffset + 1];
1926 number_of_tags = data[firstoffset + 1];
1927 number_of_tags <<= 8;
1928 number_of_tags += data[firstoffset];
1930 if (number_of_tags == 0) return;
1933 /* Search for ExifSubIFD offset Tag in IFD0 */
1935 if (firstoffset > length - 12) return; /* check end of data segment */
1936 /* Get Tag number */
1938 tagnum = data[firstoffset];
1940 tagnum += data[firstoffset + 1];
1942 tagnum = data[firstoffset + 1];
1944 tagnum += data[firstoffset];
1946 if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */
1947 if (--number_of_tags == 0) return;
1951 /* Get the ExifSubIFD offset */
1953 if (data[firstoffset + 8] != 0) return;
1954 if (data[firstoffset + 9] != 0) return;
1955 offset = data[firstoffset + 10];
1957 offset += data[firstoffset + 11];
1959 if (data[firstoffset + 11] != 0) return;
1960 if (data[firstoffset + 10] != 0) return;
1961 offset = data[firstoffset + 9];
1963 offset += data[firstoffset + 8];
1965 if (offset > length - 2) return; /* check end of data segment */
1967 /* Get the number of directory entries contained in this SubIFD */
1969 number_of_tags = data[offset];
1970 number_of_tags <<= 8;
1971 number_of_tags += data[offset + 1];
1973 number_of_tags = data[offset + 1];
1974 number_of_tags <<= 8;
1975 number_of_tags += data[offset];
1977 if (number_of_tags < 2) return;
1980 /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */
1982 if (offset > length - 12) return; /* check end of data segment */
1983 /* Get Tag number */
1985 tagnum = data[offset];
1987 tagnum += data[offset + 1];
1989 tagnum = data[offset + 1];
1991 tagnum += data[offset];
1993 if (tagnum == 0xA002 || tagnum == 0xA003) {
1994 if (tagnum == 0xA002)
1995 new_value = new_width; /* ExifImageWidth Tag */
1997 new_value = new_height; /* ExifImageHeight Tag */
1999 data[offset + 2] = 0; /* Format = unsigned long (4 octets) */
2000 data[offset + 3] = 4;
2001 data[offset + 4] = 0; /* Number Of Components = 1 */
2002 data[offset + 5] = 0;
2003 data[offset + 6] = 0;
2004 data[offset + 7] = 1;
2005 data[offset + 8] = 0;
2006 data[offset + 9] = 0;
2007 data[offset + 10] = (JOCTET)((new_value >> 8) & 0xFF);
2008 data[offset + 11] = (JOCTET)(new_value & 0xFF);
2010 data[offset + 2] = 4; /* Format = unsigned long (4 octets) */
2011 data[offset + 3] = 0;
2012 data[offset + 4] = 1; /* Number Of Components = 1 */
2013 data[offset + 5] = 0;
2014 data[offset + 6] = 0;
2015 data[offset + 7] = 0;
2016 data[offset + 8] = (JOCTET)(new_value & 0xFF);
2017 data[offset + 9] = (JOCTET)((new_value >> 8) & 0xFF);
2018 data[offset + 10] = 0;
2019 data[offset + 11] = 0;
2023 } while (--number_of_tags);
2027 /* Adjust output image parameters as needed.
2029 * This must be called after jpeg_copy_critical_parameters()
2030 * and before jpeg_write_coefficients().
2032 * The return value is the set of virtual coefficient arrays to be written
2033 * (either the ones allocated by jtransform_request_workspace, or the
2034 * original source data arrays). The caller will need to pass this value
2035 * to jpeg_write_coefficients().
2038 GLOBAL(jvirt_barray_ptr *)
2039 jtransform_adjust_parameters(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
2040 jvirt_barray_ptr *src_coef_arrays,
2041 jpeg_transform_info *info)
2043 /* If force-to-grayscale is requested, adjust destination parameters */
2044 if (info->force_grayscale) {
2045 /* First, ensure we have YCbCr or grayscale data, and that the source's
2046 * Y channel is full resolution. (No reasonable person would make Y
2047 * be less than full resolution, so actually coping with that case
2048 * isn't worth extra code space. But we check it to avoid crashing.)
2050 if (((dstinfo->jpeg_color_space == JCS_YCbCr &&
2051 dstinfo->num_components == 3) ||
2052 (dstinfo->jpeg_color_space == JCS_GRAYSCALE &&
2053 dstinfo->num_components == 1)) &&
2054 srcinfo->comp_info[0].h_samp_factor == srcinfo->max_h_samp_factor &&
2055 srcinfo->comp_info[0].v_samp_factor == srcinfo->max_v_samp_factor) {
2056 /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
2057 * properly. Among other things, it sets the target h_samp_factor &
2058 * v_samp_factor to 1, which typically won't match the source.
2059 * We have to preserve the source's quantization table number, however.
2061 int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no;
2062 jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE);
2063 dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no;
2065 /* Sorry, can't do it */
2066 ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL);
2068 } else if (info->num_components == 1) {
2069 /* For a single-component source, we force the destination sampling factors
2070 * to 1x1, with or without force_grayscale. This is useful because some
2071 * decoders choke on grayscale images with other sampling factors.
2073 dstinfo->comp_info[0].h_samp_factor = 1;
2074 dstinfo->comp_info[0].v_samp_factor = 1;
2077 /* Correct the destination's image dimensions as necessary
2078 * for rotate/flip, resize, and crop operations.
2080 #if JPEG_LIB_VERSION >= 80
2081 dstinfo->jpeg_width = info->output_width;
2082 dstinfo->jpeg_height = info->output_height;
2085 /* Transpose destination image parameters, adjust quantization */
2086 switch (info->transform) {
2087 case JXFORM_TRANSPOSE:
2088 case JXFORM_TRANSVERSE:
2090 case JXFORM_ROT_270:
2091 #if JPEG_LIB_VERSION < 80
2092 dstinfo->image_width = info->output_height;
2093 dstinfo->image_height = info->output_width;
2095 transpose_critical_parameters(dstinfo);
2098 if (info->drop_width != 0 && info->drop_height != 0)
2099 adjust_quant(srcinfo, src_coef_arrays,
2100 info->drop_ptr, info->drop_coef_arrays,
2101 info->trim, dstinfo);
2104 #if JPEG_LIB_VERSION < 80
2105 dstinfo->image_width = info->output_width;
2106 dstinfo->image_height = info->output_height;
2111 /* Adjust Exif properties */
2112 if (srcinfo->marker_list != NULL &&
2113 srcinfo->marker_list->marker == JPEG_APP0 + 1 &&
2114 srcinfo->marker_list->data_length >= 6 &&
2115 srcinfo->marker_list->data[0] == 0x45 &&
2116 srcinfo->marker_list->data[1] == 0x78 &&
2117 srcinfo->marker_list->data[2] == 0x69 &&
2118 srcinfo->marker_list->data[3] == 0x66 &&
2119 srcinfo->marker_list->data[4] == 0 &&
2120 srcinfo->marker_list->data[5] == 0) {
2121 /* Suppress output of JFIF marker */
2122 dstinfo->write_JFIF_header = FALSE;
2123 /* Adjust Exif image parameters */
2124 #if JPEG_LIB_VERSION >= 80
2125 if (dstinfo->jpeg_width != srcinfo->image_width ||
2126 dstinfo->jpeg_height != srcinfo->image_height)
2127 /* Align data segment to start of TIFF structure for parsing */
2128 adjust_exif_parameters(srcinfo->marker_list->data + 6,
2129 srcinfo->marker_list->data_length - 6,
2130 dstinfo->jpeg_width, dstinfo->jpeg_height);
2132 if (dstinfo->image_width != srcinfo->image_width ||
2133 dstinfo->image_height != srcinfo->image_height)
2134 /* Align data segment to start of TIFF structure for parsing */
2135 adjust_exif_parameters(srcinfo->marker_list->data + 6,
2136 srcinfo->marker_list->data_length - 6,
2137 dstinfo->image_width, dstinfo->image_height);
2141 /* Return the appropriate output data set */
2142 if (info->workspace_coef_arrays != NULL)
2143 return info->workspace_coef_arrays;
2144 return src_coef_arrays;
2148 /* Execute the actual transformation, if any.
2150 * This must be called *after* jpeg_write_coefficients, because it depends
2151 * on jpeg_write_coefficients to have computed subsidiary values such as
2152 * the per-component width and height fields in the destination object.
2154 * Note that some transformations will modify the source data arrays!
2158 jtransform_execute_transform(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
2159 jvirt_barray_ptr *src_coef_arrays,
2160 jpeg_transform_info *info)
2162 jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays;
2164 /* Note: conditions tested here should match those in switch statement
2165 * in jtransform_request_workspace()
2167 switch (info->transform) {
2169 if (info->output_width > srcinfo->output_width ||
2170 info->output_height > srcinfo->output_height) {
2171 if (info->output_width > srcinfo->output_width &&
2172 info->crop_width_set == JCROP_REFLECT)
2173 do_crop_ext_reflect(srcinfo, dstinfo,
2174 info->x_crop_offset, info->y_crop_offset,
2175 src_coef_arrays, dst_coef_arrays);
2176 else if (info->output_width > srcinfo->output_width &&
2177 info->crop_width_set == JCROP_FORCE)
2178 do_crop_ext_flat(srcinfo, dstinfo,
2179 info->x_crop_offset, info->y_crop_offset,
2180 src_coef_arrays, dst_coef_arrays);
2182 do_crop_ext_zero(srcinfo, dstinfo,
2183 info->x_crop_offset, info->y_crop_offset,
2184 src_coef_arrays, dst_coef_arrays);
2185 } else if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
2186 do_crop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2187 src_coef_arrays, dst_coef_arrays);
2190 if (info->y_crop_offset != 0 || info->slow_hflip)
2191 do_flip_h(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2192 src_coef_arrays, dst_coef_arrays);
2194 do_flip_h_no_crop(srcinfo, dstinfo, info->x_crop_offset,
2198 do_flip_v(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2199 src_coef_arrays, dst_coef_arrays);
2201 case JXFORM_TRANSPOSE:
2202 do_transpose(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2203 src_coef_arrays, dst_coef_arrays);
2205 case JXFORM_TRANSVERSE:
2206 do_transverse(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2207 src_coef_arrays, dst_coef_arrays);
2210 do_rot_90(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2211 src_coef_arrays, dst_coef_arrays);
2213 case JXFORM_ROT_180:
2214 do_rot_180(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2215 src_coef_arrays, dst_coef_arrays);
2217 case JXFORM_ROT_270:
2218 do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2219 src_coef_arrays, dst_coef_arrays);
2222 if (info->crop_width_set == JCROP_REFLECT &&
2223 info->y_crop_offset == 0 && info->drop_height ==
2224 (JDIMENSION)jdiv_round_up
2225 ((long)info->output_height, (long)info->iMCU_sample_height) &&
2226 (info->x_crop_offset == 0 ||
2227 info->x_crop_offset + info->drop_width ==
2228 (JDIMENSION)jdiv_round_up
2229 ((long)info->output_width, (long)info->iMCU_sample_width)))
2230 do_reflect(srcinfo, dstinfo, info->x_crop_offset,
2231 src_coef_arrays, info->drop_width, info->drop_height);
2232 else if (info->crop_width_set == JCROP_FORCE)
2233 do_flatten(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2234 src_coef_arrays, info->drop_width, info->drop_height);
2236 do_wipe(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2237 src_coef_arrays, info->drop_width, info->drop_height);
2240 if (info->drop_width != 0 && info->drop_height != 0)
2241 do_drop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2242 src_coef_arrays, info->drop_ptr, info->drop_coef_arrays,
2243 info->drop_width, info->drop_height);
2248 /* jtransform_perfect_transform
2250 * Determine whether lossless transformation is perfectly
2251 * possible for a specified image and transformation.
2254 * image_width, image_height: source image dimensions.
2255 * MCU_width, MCU_height: pixel dimensions of MCU.
2256 * transform: transformation identifier.
2257 * Parameter sources from initialized jpeg_struct
2258 * (after reading source header):
2259 * image_width = cinfo.image_width
2260 * image_height = cinfo.image_height
2261 * MCU_width = cinfo.max_h_samp_factor * cinfo.block_size
2262 * MCU_height = cinfo.max_v_samp_factor * cinfo.block_size
2264 * TRUE = perfect transformation possible
2265 * FALSE = perfect transformation not possible
2266 * (may use custom action then)
2270 jtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height,
2271 int MCU_width, int MCU_height,
2272 JXFORM_CODE transform)
2274 boolean result = TRUE; /* initialize TRUE */
2276 switch (transform) {
2278 case JXFORM_ROT_270:
2279 if (image_width % (JDIMENSION)MCU_width)
2284 if (image_height % (JDIMENSION)MCU_height)
2287 case JXFORM_TRANSVERSE:
2288 case JXFORM_ROT_180:
2289 if (image_width % (JDIMENSION)MCU_width)
2291 if (image_height % (JDIMENSION)MCU_height)
2301 #endif /* TRANSFORMS_SUPPORTED */
2304 /* Setup decompression object to save desired markers in memory.
2305 * This must be called before jpeg_read_header() to have the desired effect.
2309 jcopy_markers_setup(j_decompress_ptr srcinfo, JCOPY_OPTION option)
2311 #ifdef SAVE_MARKERS_SUPPORTED
2314 /* Save comments except under NONE option */
2315 if (option != JCOPYOPT_NONE && option != JCOPYOPT_ICC) {
2316 jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF);
2318 /* Save all types of APPn markers iff ALL option */
2319 if (option == JCOPYOPT_ALL || option == JCOPYOPT_ALL_EXCEPT_ICC) {
2320 for (m = 0; m < 16; m++) {
2321 if (option == JCOPYOPT_ALL_EXCEPT_ICC && m == 2)
2323 jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF);
2326 /* Save only APP2 markers if ICC option selected */
2327 if (option == JCOPYOPT_ICC) {
2328 jpeg_save_markers(srcinfo, JPEG_APP0 + 2, 0xFFFF);
2330 #endif /* SAVE_MARKERS_SUPPORTED */
2333 /* Copy markers saved in the given source object to the destination object.
2334 * This should be called just after jpeg_start_compress() or
2335 * jpeg_write_coefficients().
2336 * Note that those routines will have written the SOI, and also the
2337 * JFIF APP0 or Adobe APP14 markers if selected.
2341 jcopy_markers_execute(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
2342 JCOPY_OPTION option)
2344 jpeg_saved_marker_ptr marker;
2346 /* In the current implementation, we don't actually need to examine the
2347 * option flag here; we just copy everything that got saved.
2348 * But to avoid confusion, we do not output JFIF and Adobe APP14 markers
2349 * if the encoder library already wrote one.
2351 for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) {
2352 if (dstinfo->write_JFIF_header &&
2353 marker->marker == JPEG_APP0 &&
2354 marker->data_length >= 5 &&
2355 marker->data[0] == 0x4A &&
2356 marker->data[1] == 0x46 &&
2357 marker->data[2] == 0x49 &&
2358 marker->data[3] == 0x46 &&
2359 marker->data[4] == 0)
2360 continue; /* reject duplicate JFIF */
2361 if (dstinfo->write_Adobe_marker &&
2362 marker->marker == JPEG_APP0 + 14 &&
2363 marker->data_length >= 5 &&
2364 marker->data[0] == 0x41 &&
2365 marker->data[1] == 0x64 &&
2366 marker->data[2] == 0x6F &&
2367 marker->data[3] == 0x62 &&
2368 marker->data[4] == 0x65)
2369 continue; /* reject duplicate Adobe */
2370 jpeg_write_marker(dstinfo, marker->marker,
2371 marker->data, marker->data_length);