Fixed compilation with DEBUG enabled.
[AROS.git] / compiler / libjpeg / transupp.c
blob4060544828ecc5c462f982f8b2c75fb19093bde7
1 /*
2 * transupp.c
4 * Copyright (C) 1997-2009, Thomas G. Lane, Guido Vollbeding.
5 * This file is part of the Independent JPEG Group's software.
6 * For conditions of distribution and use, see the accompanying README file.
8 * This file contains image transformation routines and other utility code
9 * used by the jpegtran sample application. These are NOT part of the core
10 * JPEG library. But we keep these routines separate from jpegtran.c to
11 * ease the task of maintaining jpegtran-like programs that have other user
12 * interfaces.
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
20 #include "jinclude.h"
21 #include "jpeglib.h"
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
55 * routines:
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
71 * destination.)
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 LOCAL(void)
79 do_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
80 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
81 jvirt_barray_ptr *src_coef_arrays,
82 jvirt_barray_ptr *dst_coef_arrays)
83 /* Crop. This is only used when no rotate/flip is requested with the crop. */
85 JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks;
86 int ci, offset_y;
87 JBLOCKARRAY src_buffer, dst_buffer;
88 jpeg_component_info *compptr;
90 /* We simply have to copy the right amount of data (the destination's
91 * image size) starting at the given X and Y offsets in the source.
93 for (ci = 0; ci < dstinfo->num_components; ci++) {
94 compptr = dstinfo->comp_info + ci;
95 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
96 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
97 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
98 dst_blk_y += compptr->v_samp_factor) {
99 dst_buffer = (*srcinfo->mem->access_virt_barray)
100 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
101 (JDIMENSION) compptr->v_samp_factor, TRUE);
102 src_buffer = (*srcinfo->mem->access_virt_barray)
103 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
104 dst_blk_y + y_crop_blocks,
105 (JDIMENSION) compptr->v_samp_factor, FALSE);
106 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
107 jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
108 dst_buffer[offset_y],
109 compptr->width_in_blocks);
116 LOCAL(void)
117 do_flip_h_no_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
118 JDIMENSION x_crop_offset,
119 jvirt_barray_ptr *src_coef_arrays)
120 /* Horizontal flip; done in-place, so no separate dest array is required.
121 * NB: this only works when y_crop_offset is zero.
124 JDIMENSION MCU_cols, comp_width, blk_x, blk_y, x_crop_blocks;
125 int ci, k, offset_y;
126 JBLOCKARRAY buffer;
127 JCOEFPTR ptr1, ptr2;
128 JCOEF temp1, temp2;
129 jpeg_component_info *compptr;
131 /* Horizontal mirroring of DCT blocks is accomplished by swapping
132 * pairs of blocks in-place. Within a DCT block, we perform horizontal
133 * mirroring by changing the signs of odd-numbered columns.
134 * Partial iMCUs at the right edge are left untouched.
136 MCU_cols = srcinfo->output_width /
137 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size);
139 for (ci = 0; ci < dstinfo->num_components; ci++) {
140 compptr = dstinfo->comp_info + ci;
141 comp_width = MCU_cols * compptr->h_samp_factor;
142 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
143 for (blk_y = 0; blk_y < compptr->height_in_blocks;
144 blk_y += compptr->v_samp_factor) {
145 buffer = (*srcinfo->mem->access_virt_barray)
146 ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y,
147 (JDIMENSION) compptr->v_samp_factor, TRUE);
148 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
149 /* Do the mirroring */
150 for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) {
151 ptr1 = buffer[offset_y][blk_x];
152 ptr2 = buffer[offset_y][comp_width - blk_x - 1];
153 /* this unrolled loop doesn't need to know which row it's on... */
154 for (k = 0; k < DCTSIZE2; k += 2) {
155 temp1 = *ptr1; /* swap even column */
156 temp2 = *ptr2;
157 *ptr1++ = temp2;
158 *ptr2++ = temp1;
159 temp1 = *ptr1; /* swap odd column with sign change */
160 temp2 = *ptr2;
161 *ptr1++ = -temp2;
162 *ptr2++ = -temp1;
165 if (x_crop_blocks > 0) {
166 /* Now left-justify the portion of the data to be kept.
167 * We can't use a single jcopy_block_row() call because that routine
168 * depends on memcpy(), whose behavior is unspecified for overlapping
169 * source and destination areas. Sigh.
171 for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
172 jcopy_block_row(buffer[offset_y] + blk_x + x_crop_blocks,
173 buffer[offset_y] + blk_x,
174 (JDIMENSION) 1);
183 LOCAL(void)
184 do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
185 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
186 jvirt_barray_ptr *src_coef_arrays,
187 jvirt_barray_ptr *dst_coef_arrays)
188 /* Horizontal flip in general cropping case */
190 JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
191 JDIMENSION x_crop_blocks, y_crop_blocks;
192 int ci, k, offset_y;
193 JBLOCKARRAY src_buffer, dst_buffer;
194 JBLOCKROW src_row_ptr, dst_row_ptr;
195 JCOEFPTR src_ptr, dst_ptr;
196 jpeg_component_info *compptr;
198 /* Here we must output into a separate array because we can't touch
199 * different rows of a single virtual array simultaneously. Otherwise,
200 * this is essentially the same as the routine above.
202 MCU_cols = srcinfo->output_width /
203 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size);
205 for (ci = 0; ci < dstinfo->num_components; ci++) {
206 compptr = dstinfo->comp_info + ci;
207 comp_width = MCU_cols * compptr->h_samp_factor;
208 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
209 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
210 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
211 dst_blk_y += compptr->v_samp_factor) {
212 dst_buffer = (*srcinfo->mem->access_virt_barray)
213 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
214 (JDIMENSION) compptr->v_samp_factor, TRUE);
215 src_buffer = (*srcinfo->mem->access_virt_barray)
216 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
217 dst_blk_y + y_crop_blocks,
218 (JDIMENSION) compptr->v_samp_factor, FALSE);
219 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
220 dst_row_ptr = dst_buffer[offset_y];
221 src_row_ptr = src_buffer[offset_y];
222 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
223 if (x_crop_blocks + dst_blk_x < comp_width) {
224 /* Do the mirrorable blocks */
225 dst_ptr = dst_row_ptr[dst_blk_x];
226 src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
227 /* this unrolled loop doesn't need to know which row it's on... */
228 for (k = 0; k < DCTSIZE2; k += 2) {
229 *dst_ptr++ = *src_ptr++; /* copy even column */
230 *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */
232 } else {
233 /* Copy last partial block(s) verbatim */
234 jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
235 dst_row_ptr + dst_blk_x,
236 (JDIMENSION) 1);
245 LOCAL(void)
246 do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
247 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
248 jvirt_barray_ptr *src_coef_arrays,
249 jvirt_barray_ptr *dst_coef_arrays)
250 /* Vertical flip */
252 JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
253 JDIMENSION x_crop_blocks, y_crop_blocks;
254 int ci, i, j, offset_y;
255 JBLOCKARRAY src_buffer, dst_buffer;
256 JBLOCKROW src_row_ptr, dst_row_ptr;
257 JCOEFPTR src_ptr, dst_ptr;
258 jpeg_component_info *compptr;
260 /* We output into a separate array because we can't touch different
261 * rows of the source virtual array simultaneously. Otherwise, this
262 * is a pretty straightforward analog of horizontal flip.
263 * Within a DCT block, vertical mirroring is done by changing the signs
264 * of odd-numbered rows.
265 * Partial iMCUs at the bottom edge are copied verbatim.
267 MCU_rows = srcinfo->output_height /
268 (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size);
270 for (ci = 0; ci < dstinfo->num_components; ci++) {
271 compptr = dstinfo->comp_info + ci;
272 comp_height = MCU_rows * compptr->v_samp_factor;
273 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
274 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
275 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
276 dst_blk_y += compptr->v_samp_factor) {
277 dst_buffer = (*srcinfo->mem->access_virt_barray)
278 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
279 (JDIMENSION) compptr->v_samp_factor, TRUE);
280 if (y_crop_blocks + dst_blk_y < comp_height) {
281 /* Row is within the mirrorable area. */
282 src_buffer = (*srcinfo->mem->access_virt_barray)
283 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
284 comp_height - y_crop_blocks - dst_blk_y -
285 (JDIMENSION) compptr->v_samp_factor,
286 (JDIMENSION) compptr->v_samp_factor, FALSE);
287 } else {
288 /* Bottom-edge blocks will be copied verbatim. */
289 src_buffer = (*srcinfo->mem->access_virt_barray)
290 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
291 dst_blk_y + y_crop_blocks,
292 (JDIMENSION) compptr->v_samp_factor, FALSE);
294 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
295 if (y_crop_blocks + dst_blk_y < comp_height) {
296 /* Row is within the mirrorable area. */
297 dst_row_ptr = dst_buffer[offset_y];
298 src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
299 src_row_ptr += x_crop_blocks;
300 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
301 dst_blk_x++) {
302 dst_ptr = dst_row_ptr[dst_blk_x];
303 src_ptr = src_row_ptr[dst_blk_x];
304 for (i = 0; i < DCTSIZE; i += 2) {
305 /* copy even row */
306 for (j = 0; j < DCTSIZE; j++)
307 *dst_ptr++ = *src_ptr++;
308 /* copy odd row with sign change */
309 for (j = 0; j < DCTSIZE; j++)
310 *dst_ptr++ = - *src_ptr++;
313 } else {
314 /* Just copy row verbatim. */
315 jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
316 dst_buffer[offset_y],
317 compptr->width_in_blocks);
325 LOCAL(void)
326 do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
327 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
328 jvirt_barray_ptr *src_coef_arrays,
329 jvirt_barray_ptr *dst_coef_arrays)
330 /* Transpose source into destination */
332 JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks;
333 int ci, i, j, offset_x, offset_y;
334 JBLOCKARRAY src_buffer, dst_buffer;
335 JCOEFPTR src_ptr, dst_ptr;
336 jpeg_component_info *compptr;
338 /* Transposing pixels within a block just requires transposing the
339 * DCT coefficients.
340 * Partial iMCUs at the edges require no special treatment; we simply
341 * process all the available DCT blocks for every component.
343 for (ci = 0; ci < dstinfo->num_components; ci++) {
344 compptr = dstinfo->comp_info + ci;
345 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
346 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
347 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
348 dst_blk_y += compptr->v_samp_factor) {
349 dst_buffer = (*srcinfo->mem->access_virt_barray)
350 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
351 (JDIMENSION) compptr->v_samp_factor, TRUE);
352 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
353 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
354 dst_blk_x += compptr->h_samp_factor) {
355 src_buffer = (*srcinfo->mem->access_virt_barray)
356 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
357 dst_blk_x + x_crop_blocks,
358 (JDIMENSION) compptr->h_samp_factor, FALSE);
359 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
360 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
361 src_ptr = src_buffer[offset_x][dst_blk_y + offset_y + y_crop_blocks];
362 for (i = 0; i < DCTSIZE; i++)
363 for (j = 0; j < DCTSIZE; j++)
364 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
373 LOCAL(void)
374 do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
375 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
376 jvirt_barray_ptr *src_coef_arrays,
377 jvirt_barray_ptr *dst_coef_arrays)
378 /* 90 degree rotation is equivalent to
379 * 1. Transposing the image;
380 * 2. Horizontal mirroring.
381 * These two steps are merged into a single processing routine.
384 JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
385 JDIMENSION x_crop_blocks, y_crop_blocks;
386 int ci, i, j, offset_x, offset_y;
387 JBLOCKARRAY src_buffer, dst_buffer;
388 JCOEFPTR src_ptr, dst_ptr;
389 jpeg_component_info *compptr;
391 /* Because of the horizontal mirror step, we can't process partial iMCUs
392 * at the (output) right edge properly. They just get transposed and
393 * not mirrored.
395 MCU_cols = srcinfo->output_height /
396 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size);
398 for (ci = 0; ci < dstinfo->num_components; ci++) {
399 compptr = dstinfo->comp_info + ci;
400 comp_width = MCU_cols * compptr->h_samp_factor;
401 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
402 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
403 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
404 dst_blk_y += compptr->v_samp_factor) {
405 dst_buffer = (*srcinfo->mem->access_virt_barray)
406 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
407 (JDIMENSION) compptr->v_samp_factor, TRUE);
408 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
409 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
410 dst_blk_x += compptr->h_samp_factor) {
411 if (x_crop_blocks + dst_blk_x < comp_width) {
412 /* Block is within the mirrorable area. */
413 src_buffer = (*srcinfo->mem->access_virt_barray)
414 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
415 comp_width - x_crop_blocks - dst_blk_x -
416 (JDIMENSION) compptr->h_samp_factor,
417 (JDIMENSION) compptr->h_samp_factor, FALSE);
418 } else {
419 /* Edge blocks are transposed but not mirrored. */
420 src_buffer = (*srcinfo->mem->access_virt_barray)
421 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
422 dst_blk_x + x_crop_blocks,
423 (JDIMENSION) compptr->h_samp_factor, FALSE);
425 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
426 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
427 if (x_crop_blocks + dst_blk_x < comp_width) {
428 /* Block is within the mirrorable area. */
429 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
430 [dst_blk_y + offset_y + y_crop_blocks];
431 for (i = 0; i < DCTSIZE; i++) {
432 for (j = 0; j < DCTSIZE; j++)
433 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
434 i++;
435 for (j = 0; j < DCTSIZE; j++)
436 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
438 } else {
439 /* Edge blocks are transposed but not mirrored. */
440 src_ptr = src_buffer[offset_x]
441 [dst_blk_y + offset_y + y_crop_blocks];
442 for (i = 0; i < DCTSIZE; i++)
443 for (j = 0; j < DCTSIZE; j++)
444 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
454 LOCAL(void)
455 do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
456 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
457 jvirt_barray_ptr *src_coef_arrays,
458 jvirt_barray_ptr *dst_coef_arrays)
459 /* 270 degree rotation is equivalent to
460 * 1. Horizontal mirroring;
461 * 2. Transposing the image.
462 * These two steps are merged into a single processing routine.
465 JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
466 JDIMENSION x_crop_blocks, y_crop_blocks;
467 int ci, i, j, offset_x, offset_y;
468 JBLOCKARRAY src_buffer, dst_buffer;
469 JCOEFPTR src_ptr, dst_ptr;
470 jpeg_component_info *compptr;
472 /* Because of the horizontal mirror step, we can't process partial iMCUs
473 * at the (output) bottom edge properly. They just get transposed and
474 * not mirrored.
476 MCU_rows = srcinfo->output_width /
477 (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size);
479 for (ci = 0; ci < dstinfo->num_components; ci++) {
480 compptr = dstinfo->comp_info + ci;
481 comp_height = MCU_rows * compptr->v_samp_factor;
482 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
483 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
484 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
485 dst_blk_y += compptr->v_samp_factor) {
486 dst_buffer = (*srcinfo->mem->access_virt_barray)
487 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
488 (JDIMENSION) compptr->v_samp_factor, TRUE);
489 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
490 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
491 dst_blk_x += compptr->h_samp_factor) {
492 src_buffer = (*srcinfo->mem->access_virt_barray)
493 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
494 dst_blk_x + x_crop_blocks,
495 (JDIMENSION) compptr->h_samp_factor, FALSE);
496 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
497 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
498 if (y_crop_blocks + dst_blk_y < comp_height) {
499 /* Block is within the mirrorable area. */
500 src_ptr = src_buffer[offset_x]
501 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
502 for (i = 0; i < DCTSIZE; i++) {
503 for (j = 0; j < DCTSIZE; j++) {
504 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
505 j++;
506 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
509 } else {
510 /* Edge blocks are transposed but not mirrored. */
511 src_ptr = src_buffer[offset_x]
512 [dst_blk_y + offset_y + y_crop_blocks];
513 for (i = 0; i < DCTSIZE; i++)
514 for (j = 0; j < DCTSIZE; j++)
515 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
525 LOCAL(void)
526 do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
527 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
528 jvirt_barray_ptr *src_coef_arrays,
529 jvirt_barray_ptr *dst_coef_arrays)
530 /* 180 degree rotation is equivalent to
531 * 1. Vertical mirroring;
532 * 2. Horizontal mirroring.
533 * These two steps are merged into a single processing routine.
536 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
537 JDIMENSION x_crop_blocks, y_crop_blocks;
538 int ci, i, j, offset_y;
539 JBLOCKARRAY src_buffer, dst_buffer;
540 JBLOCKROW src_row_ptr, dst_row_ptr;
541 JCOEFPTR src_ptr, dst_ptr;
542 jpeg_component_info *compptr;
544 MCU_cols = srcinfo->output_width /
545 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size);
546 MCU_rows = srcinfo->output_height /
547 (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size);
549 for (ci = 0; ci < dstinfo->num_components; ci++) {
550 compptr = dstinfo->comp_info + ci;
551 comp_width = MCU_cols * compptr->h_samp_factor;
552 comp_height = MCU_rows * compptr->v_samp_factor;
553 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
554 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
555 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
556 dst_blk_y += compptr->v_samp_factor) {
557 dst_buffer = (*srcinfo->mem->access_virt_barray)
558 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
559 (JDIMENSION) compptr->v_samp_factor, TRUE);
560 if (y_crop_blocks + dst_blk_y < comp_height) {
561 /* Row is within the vertically mirrorable area. */
562 src_buffer = (*srcinfo->mem->access_virt_barray)
563 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
564 comp_height - y_crop_blocks - dst_blk_y -
565 (JDIMENSION) compptr->v_samp_factor,
566 (JDIMENSION) compptr->v_samp_factor, FALSE);
567 } else {
568 /* Bottom-edge rows are only mirrored horizontally. */
569 src_buffer = (*srcinfo->mem->access_virt_barray)
570 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
571 dst_blk_y + y_crop_blocks,
572 (JDIMENSION) compptr->v_samp_factor, FALSE);
574 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
575 dst_row_ptr = dst_buffer[offset_y];
576 if (y_crop_blocks + dst_blk_y < comp_height) {
577 /* Row is within the mirrorable area. */
578 src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
579 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
580 dst_ptr = dst_row_ptr[dst_blk_x];
581 if (x_crop_blocks + dst_blk_x < comp_width) {
582 /* Process the blocks that can be mirrored both ways. */
583 src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
584 for (i = 0; i < DCTSIZE; i += 2) {
585 /* For even row, negate every odd column. */
586 for (j = 0; j < DCTSIZE; j += 2) {
587 *dst_ptr++ = *src_ptr++;
588 *dst_ptr++ = - *src_ptr++;
590 /* For odd row, negate every even column. */
591 for (j = 0; j < DCTSIZE; j += 2) {
592 *dst_ptr++ = - *src_ptr++;
593 *dst_ptr++ = *src_ptr++;
596 } else {
597 /* Any remaining right-edge blocks are only mirrored vertically. */
598 src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x];
599 for (i = 0; i < DCTSIZE; i += 2) {
600 for (j = 0; j < DCTSIZE; j++)
601 *dst_ptr++ = *src_ptr++;
602 for (j = 0; j < DCTSIZE; j++)
603 *dst_ptr++ = - *src_ptr++;
607 } else {
608 /* Remaining rows are just mirrored horizontally. */
609 src_row_ptr = src_buffer[offset_y];
610 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
611 if (x_crop_blocks + dst_blk_x < comp_width) {
612 /* Process the blocks that can be mirrored. */
613 dst_ptr = dst_row_ptr[dst_blk_x];
614 src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
615 for (i = 0; i < DCTSIZE2; i += 2) {
616 *dst_ptr++ = *src_ptr++;
617 *dst_ptr++ = - *src_ptr++;
619 } else {
620 /* Any remaining right-edge blocks are only copied. */
621 jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
622 dst_row_ptr + dst_blk_x,
623 (JDIMENSION) 1);
633 LOCAL(void)
634 do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
635 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
636 jvirt_barray_ptr *src_coef_arrays,
637 jvirt_barray_ptr *dst_coef_arrays)
638 /* Transverse transpose is equivalent to
639 * 1. 180 degree rotation;
640 * 2. Transposition;
641 * or
642 * 1. Horizontal mirroring;
643 * 2. Transposition;
644 * 3. Horizontal mirroring.
645 * These steps are merged into a single processing routine.
648 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
649 JDIMENSION x_crop_blocks, y_crop_blocks;
650 int ci, i, j, offset_x, offset_y;
651 JBLOCKARRAY src_buffer, dst_buffer;
652 JCOEFPTR src_ptr, dst_ptr;
653 jpeg_component_info *compptr;
655 MCU_cols = srcinfo->output_height /
656 (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size);
657 MCU_rows = srcinfo->output_width /
658 (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size);
660 for (ci = 0; ci < dstinfo->num_components; ci++) {
661 compptr = dstinfo->comp_info + ci;
662 comp_width = MCU_cols * compptr->h_samp_factor;
663 comp_height = MCU_rows * compptr->v_samp_factor;
664 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
665 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
666 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
667 dst_blk_y += compptr->v_samp_factor) {
668 dst_buffer = (*srcinfo->mem->access_virt_barray)
669 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
670 (JDIMENSION) compptr->v_samp_factor, TRUE);
671 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
672 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
673 dst_blk_x += compptr->h_samp_factor) {
674 if (x_crop_blocks + dst_blk_x < comp_width) {
675 /* Block is within the mirrorable area. */
676 src_buffer = (*srcinfo->mem->access_virt_barray)
677 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
678 comp_width - x_crop_blocks - dst_blk_x -
679 (JDIMENSION) compptr->h_samp_factor,
680 (JDIMENSION) compptr->h_samp_factor, FALSE);
681 } else {
682 src_buffer = (*srcinfo->mem->access_virt_barray)
683 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
684 dst_blk_x + x_crop_blocks,
685 (JDIMENSION) compptr->h_samp_factor, FALSE);
687 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
688 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
689 if (y_crop_blocks + dst_blk_y < comp_height) {
690 if (x_crop_blocks + dst_blk_x < comp_width) {
691 /* Block is within the mirrorable area. */
692 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
693 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
694 for (i = 0; i < DCTSIZE; i++) {
695 for (j = 0; j < DCTSIZE; j++) {
696 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
697 j++;
698 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
700 i++;
701 for (j = 0; j < DCTSIZE; j++) {
702 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
703 j++;
704 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
707 } else {
708 /* Right-edge blocks are mirrored in y only */
709 src_ptr = src_buffer[offset_x]
710 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
711 for (i = 0; i < DCTSIZE; i++) {
712 for (j = 0; j < DCTSIZE; j++) {
713 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
714 j++;
715 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
719 } else {
720 if (x_crop_blocks + dst_blk_x < comp_width) {
721 /* Bottom-edge blocks are mirrored in x only */
722 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
723 [dst_blk_y + offset_y + y_crop_blocks];
724 for (i = 0; i < DCTSIZE; i++) {
725 for (j = 0; j < DCTSIZE; j++)
726 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
727 i++;
728 for (j = 0; j < DCTSIZE; j++)
729 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
731 } else {
732 /* At lower right corner, just transpose, no mirroring */
733 src_ptr = src_buffer[offset_x]
734 [dst_blk_y + offset_y + y_crop_blocks];
735 for (i = 0; i < DCTSIZE; i++)
736 for (j = 0; j < DCTSIZE; j++)
737 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
748 /* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec.
749 * Returns TRUE if valid integer found, FALSE if not.
750 * *strptr is advanced over the digit string, and *result is set to its value.
753 LOCAL(boolean)
754 jt_read_integer (const char ** strptr, JDIMENSION * result)
756 const char * ptr = *strptr;
757 JDIMENSION val = 0;
759 for (; isdigit(*ptr); ptr++) {
760 val = val * 10 + (JDIMENSION) (*ptr - '0');
762 *result = val;
763 if (ptr == *strptr)
764 return FALSE; /* oops, no digits */
765 *strptr = ptr;
766 return TRUE;
770 /* Parse a crop specification (written in X11 geometry style).
771 * The routine returns TRUE if the spec string is valid, FALSE if not.
773 * The crop spec string should have the format
774 * <width>x<height>{+-}<xoffset>{+-}<yoffset>
775 * where width, height, xoffset, and yoffset are unsigned integers.
776 * Each of the elements can be omitted to indicate a default value.
777 * (A weakness of this style is that it is not possible to omit xoffset
778 * while specifying yoffset, since they look alike.)
780 * This code is loosely based on XParseGeometry from the X11 distribution.
783 GLOBAL(boolean)
784 jtransform_parse_crop_spec (jpeg_transform_info *info, const char *spec)
786 info->crop = FALSE;
787 info->crop_width_set = JCROP_UNSET;
788 info->crop_height_set = JCROP_UNSET;
789 info->crop_xoffset_set = JCROP_UNSET;
790 info->crop_yoffset_set = JCROP_UNSET;
792 if (isdigit(*spec)) {
793 /* fetch width */
794 if (! jt_read_integer(&spec, &info->crop_width))
795 return FALSE;
796 info->crop_width_set = JCROP_POS;
798 if (*spec == 'x' || *spec == 'X') {
799 /* fetch height */
800 spec++;
801 if (! jt_read_integer(&spec, &info->crop_height))
802 return FALSE;
803 info->crop_height_set = JCROP_POS;
805 if (*spec == '+' || *spec == '-') {
806 /* fetch xoffset */
807 info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
808 spec++;
809 if (! jt_read_integer(&spec, &info->crop_xoffset))
810 return FALSE;
812 if (*spec == '+' || *spec == '-') {
813 /* fetch yoffset */
814 info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
815 spec++;
816 if (! jt_read_integer(&spec, &info->crop_yoffset))
817 return FALSE;
819 /* We had better have gotten to the end of the string. */
820 if (*spec != '\0')
821 return FALSE;
822 info->crop = TRUE;
823 return TRUE;
827 /* Trim off any partial iMCUs on the indicated destination edge */
829 LOCAL(void)
830 trim_right_edge (jpeg_transform_info *info, JDIMENSION full_width)
832 JDIMENSION MCU_cols;
834 MCU_cols = info->output_width / info->iMCU_sample_width;
835 if (MCU_cols > 0 && info->x_crop_offset + MCU_cols ==
836 full_width / info->iMCU_sample_width)
837 info->output_width = MCU_cols * info->iMCU_sample_width;
840 LOCAL(void)
841 trim_bottom_edge (jpeg_transform_info *info, JDIMENSION full_height)
843 JDIMENSION MCU_rows;
845 MCU_rows = info->output_height / info->iMCU_sample_height;
846 if (MCU_rows > 0 && info->y_crop_offset + MCU_rows ==
847 full_height / info->iMCU_sample_height)
848 info->output_height = MCU_rows * info->iMCU_sample_height;
852 /* Request any required workspace.
854 * This routine figures out the size that the output image will be
855 * (which implies that all the transform parameters must be set before
856 * it is called).
858 * We allocate the workspace virtual arrays from the source decompression
859 * object, so that all the arrays (both the original data and the workspace)
860 * will be taken into account while making memory management decisions.
861 * Hence, this routine must be called after jpeg_read_header (which reads
862 * the image dimensions) and before jpeg_read_coefficients (which realizes
863 * the source's virtual arrays).
865 * This function returns FALSE right away if -perfect is given
866 * and transformation is not perfect. Otherwise returns TRUE.
869 GLOBAL(boolean)
870 jtransform_request_workspace (j_decompress_ptr srcinfo,
871 jpeg_transform_info *info)
873 jvirt_barray_ptr *coef_arrays;
874 boolean need_workspace, transpose_it;
875 jpeg_component_info *compptr;
876 JDIMENSION xoffset, yoffset;
877 JDIMENSION width_in_iMCUs, height_in_iMCUs;
878 JDIMENSION width_in_blocks, height_in_blocks;
879 int ci, h_samp_factor, v_samp_factor;
881 /* Determine number of components in output image */
882 if (info->force_grayscale &&
883 srcinfo->jpeg_color_space == JCS_YCbCr &&
884 srcinfo->num_components == 3)
885 /* We'll only process the first component */
886 info->num_components = 1;
887 else
888 /* Process all the components */
889 info->num_components = srcinfo->num_components;
891 /* Compute output image dimensions and related values. */
892 jpeg_core_output_dimensions(srcinfo);
894 /* Return right away if -perfect is given and transformation is not perfect.
896 if (info->perfect) {
897 if (info->num_components == 1) {
898 if (!jtransform_perfect_transform(srcinfo->output_width,
899 srcinfo->output_height,
900 srcinfo->min_DCT_h_scaled_size,
901 srcinfo->min_DCT_v_scaled_size,
902 info->transform))
903 return FALSE;
904 } else {
905 if (!jtransform_perfect_transform(srcinfo->output_width,
906 srcinfo->output_height,
907 srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size,
908 srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size,
909 info->transform))
910 return FALSE;
914 /* If there is only one output component, force the iMCU size to be 1;
915 * else use the source iMCU size. (This allows us to do the right thing
916 * when reducing color to grayscale, and also provides a handy way of
917 * cleaning up "funny" grayscale images whose sampling factors are not 1x1.)
919 switch (info->transform) {
920 case JXFORM_TRANSPOSE:
921 case JXFORM_TRANSVERSE:
922 case JXFORM_ROT_90:
923 case JXFORM_ROT_270:
924 info->output_width = srcinfo->output_height;
925 info->output_height = srcinfo->output_width;
926 if (info->num_components == 1) {
927 info->iMCU_sample_width = srcinfo->min_DCT_v_scaled_size;
928 info->iMCU_sample_height = srcinfo->min_DCT_h_scaled_size;
929 } else {
930 info->iMCU_sample_width =
931 srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size;
932 info->iMCU_sample_height =
933 srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size;
935 break;
936 default:
937 info->output_width = srcinfo->output_width;
938 info->output_height = srcinfo->output_height;
939 if (info->num_components == 1) {
940 info->iMCU_sample_width = srcinfo->min_DCT_h_scaled_size;
941 info->iMCU_sample_height = srcinfo->min_DCT_v_scaled_size;
942 } else {
943 info->iMCU_sample_width =
944 srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size;
945 info->iMCU_sample_height =
946 srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size;
948 break;
951 /* If cropping has been requested, compute the crop area's position and
952 * dimensions, ensuring that its upper left corner falls at an iMCU boundary.
954 if (info->crop) {
955 /* Insert default values for unset crop parameters */
956 if (info->crop_xoffset_set == JCROP_UNSET)
957 info->crop_xoffset = 0; /* default to +0 */
958 if (info->crop_yoffset_set == JCROP_UNSET)
959 info->crop_yoffset = 0; /* default to +0 */
960 if (info->crop_xoffset >= info->output_width ||
961 info->crop_yoffset >= info->output_height)
962 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
963 if (info->crop_width_set == JCROP_UNSET)
964 info->crop_width = info->output_width - info->crop_xoffset;
965 if (info->crop_height_set == JCROP_UNSET)
966 info->crop_height = info->output_height - info->crop_yoffset;
967 /* Ensure parameters are valid */
968 if (info->crop_width <= 0 || info->crop_width > info->output_width ||
969 info->crop_height <= 0 || info->crop_height > info->output_height ||
970 info->crop_xoffset > info->output_width - info->crop_width ||
971 info->crop_yoffset > info->output_height - info->crop_height)
972 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
973 /* Convert negative crop offsets into regular offsets */
974 if (info->crop_xoffset_set == JCROP_NEG)
975 xoffset = info->output_width - info->crop_width - info->crop_xoffset;
976 else
977 xoffset = info->crop_xoffset;
978 if (info->crop_yoffset_set == JCROP_NEG)
979 yoffset = info->output_height - info->crop_height - info->crop_yoffset;
980 else
981 yoffset = info->crop_yoffset;
982 /* Now adjust so that upper left corner falls at an iMCU boundary */
983 info->output_width =
984 info->crop_width + (xoffset % info->iMCU_sample_width);
985 info->output_height =
986 info->crop_height + (yoffset % info->iMCU_sample_height);
987 /* Save x/y offsets measured in iMCUs */
988 info->x_crop_offset = xoffset / info->iMCU_sample_width;
989 info->y_crop_offset = yoffset / info->iMCU_sample_height;
990 } else {
991 info->x_crop_offset = 0;
992 info->y_crop_offset = 0;
995 /* Figure out whether we need workspace arrays,
996 * and if so whether they are transposed relative to the source.
998 need_workspace = FALSE;
999 transpose_it = FALSE;
1000 switch (info->transform) {
1001 case JXFORM_NONE:
1002 if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
1003 need_workspace = TRUE;
1004 /* No workspace needed if neither cropping nor transforming */
1005 break;
1006 case JXFORM_FLIP_H:
1007 if (info->trim)
1008 trim_right_edge(info, srcinfo->output_width);
1009 if (info->y_crop_offset != 0)
1010 need_workspace = TRUE;
1011 /* do_flip_h_no_crop doesn't need a workspace array */
1012 break;
1013 case JXFORM_FLIP_V:
1014 if (info->trim)
1015 trim_bottom_edge(info, srcinfo->output_height);
1016 /* Need workspace arrays having same dimensions as source image. */
1017 need_workspace = TRUE;
1018 break;
1019 case JXFORM_TRANSPOSE:
1020 /* transpose does NOT have to trim anything */
1021 /* Need workspace arrays having transposed dimensions. */
1022 need_workspace = TRUE;
1023 transpose_it = TRUE;
1024 break;
1025 case JXFORM_TRANSVERSE:
1026 if (info->trim) {
1027 trim_right_edge(info, srcinfo->output_height);
1028 trim_bottom_edge(info, srcinfo->output_width);
1030 /* Need workspace arrays having transposed dimensions. */
1031 need_workspace = TRUE;
1032 transpose_it = TRUE;
1033 break;
1034 case JXFORM_ROT_90:
1035 if (info->trim)
1036 trim_right_edge(info, srcinfo->output_height);
1037 /* Need workspace arrays having transposed dimensions. */
1038 need_workspace = TRUE;
1039 transpose_it = TRUE;
1040 break;
1041 case JXFORM_ROT_180:
1042 if (info->trim) {
1043 trim_right_edge(info, srcinfo->output_width);
1044 trim_bottom_edge(info, srcinfo->output_height);
1046 /* Need workspace arrays having same dimensions as source image. */
1047 need_workspace = TRUE;
1048 break;
1049 case JXFORM_ROT_270:
1050 if (info->trim)
1051 trim_bottom_edge(info, srcinfo->output_width);
1052 /* Need workspace arrays having transposed dimensions. */
1053 need_workspace = TRUE;
1054 transpose_it = TRUE;
1055 break;
1058 /* Allocate workspace if needed.
1059 * Note that we allocate arrays padded out to the next iMCU boundary,
1060 * so that transform routines need not worry about missing edge blocks.
1062 if (need_workspace) {
1063 coef_arrays = (jvirt_barray_ptr *)
1064 (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
1065 SIZEOF(jvirt_barray_ptr) * info->num_components);
1066 width_in_iMCUs = (JDIMENSION)
1067 jdiv_round_up((long) info->output_width,
1068 (long) info->iMCU_sample_width);
1069 height_in_iMCUs = (JDIMENSION)
1070 jdiv_round_up((long) info->output_height,
1071 (long) info->iMCU_sample_height);
1072 for (ci = 0; ci < info->num_components; ci++) {
1073 compptr = srcinfo->comp_info + ci;
1074 if (info->num_components == 1) {
1075 /* we're going to force samp factors to 1x1 in this case */
1076 h_samp_factor = v_samp_factor = 1;
1077 } else if (transpose_it) {
1078 h_samp_factor = compptr->v_samp_factor;
1079 v_samp_factor = compptr->h_samp_factor;
1080 } else {
1081 h_samp_factor = compptr->h_samp_factor;
1082 v_samp_factor = compptr->v_samp_factor;
1084 width_in_blocks = width_in_iMCUs * h_samp_factor;
1085 height_in_blocks = height_in_iMCUs * v_samp_factor;
1086 coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
1087 ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
1088 width_in_blocks, height_in_blocks, (JDIMENSION) v_samp_factor);
1090 info->workspace_coef_arrays = coef_arrays;
1091 } else
1092 info->workspace_coef_arrays = NULL;
1094 return TRUE;
1098 /* Transpose destination image parameters */
1100 LOCAL(void)
1101 transpose_critical_parameters (j_compress_ptr dstinfo)
1103 int tblno, i, j, ci, itemp;
1104 jpeg_component_info *compptr;
1105 JQUANT_TBL *qtblptr;
1106 JDIMENSION jtemp;
1107 UINT16 qtemp;
1109 /* Transpose image dimensions */
1110 jtemp = dstinfo->image_width;
1111 dstinfo->image_width = dstinfo->image_height;
1112 dstinfo->image_height = jtemp;
1113 itemp = dstinfo->min_DCT_h_scaled_size;
1114 dstinfo->min_DCT_h_scaled_size = dstinfo->min_DCT_v_scaled_size;
1115 dstinfo->min_DCT_v_scaled_size = itemp;
1117 /* Transpose sampling factors */
1118 for (ci = 0; ci < dstinfo->num_components; ci++) {
1119 compptr = dstinfo->comp_info + ci;
1120 itemp = compptr->h_samp_factor;
1121 compptr->h_samp_factor = compptr->v_samp_factor;
1122 compptr->v_samp_factor = itemp;
1125 /* Transpose quantization tables */
1126 for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
1127 qtblptr = dstinfo->quant_tbl_ptrs[tblno];
1128 if (qtblptr != NULL) {
1129 for (i = 0; i < DCTSIZE; i++) {
1130 for (j = 0; j < i; j++) {
1131 qtemp = qtblptr->quantval[i*DCTSIZE+j];
1132 qtblptr->quantval[i*DCTSIZE+j] = qtblptr->quantval[j*DCTSIZE+i];
1133 qtblptr->quantval[j*DCTSIZE+i] = qtemp;
1141 /* Adjust Exif image parameters.
1143 * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible.
1146 LOCAL(void)
1147 adjust_exif_parameters (JOCTET FAR * data, unsigned int length,
1148 JDIMENSION new_width, JDIMENSION new_height)
1150 boolean is_motorola; /* Flag for byte order */
1151 unsigned int number_of_tags, tagnum;
1152 unsigned int firstoffset, offset;
1153 JDIMENSION new_value;
1155 if (length < 12) return; /* Length of an IFD entry */
1157 /* Discover byte order */
1158 if (GETJOCTET(data[0]) == 0x49 && GETJOCTET(data[1]) == 0x49)
1159 is_motorola = FALSE;
1160 else if (GETJOCTET(data[0]) == 0x4D && GETJOCTET(data[1]) == 0x4D)
1161 is_motorola = TRUE;
1162 else
1163 return;
1165 /* Check Tag Mark */
1166 if (is_motorola) {
1167 if (GETJOCTET(data[2]) != 0) return;
1168 if (GETJOCTET(data[3]) != 0x2A) return;
1169 } else {
1170 if (GETJOCTET(data[3]) != 0) return;
1171 if (GETJOCTET(data[2]) != 0x2A) return;
1174 /* Get first IFD offset (offset to IFD0) */
1175 if (is_motorola) {
1176 if (GETJOCTET(data[4]) != 0) return;
1177 if (GETJOCTET(data[5]) != 0) return;
1178 firstoffset = GETJOCTET(data[6]);
1179 firstoffset <<= 8;
1180 firstoffset += GETJOCTET(data[7]);
1181 } else {
1182 if (GETJOCTET(data[7]) != 0) return;
1183 if (GETJOCTET(data[6]) != 0) return;
1184 firstoffset = GETJOCTET(data[5]);
1185 firstoffset <<= 8;
1186 firstoffset += GETJOCTET(data[4]);
1188 if (firstoffset > length - 2) return; /* check end of data segment */
1190 /* Get the number of directory entries contained in this IFD */
1191 if (is_motorola) {
1192 number_of_tags = GETJOCTET(data[firstoffset]);
1193 number_of_tags <<= 8;
1194 number_of_tags += GETJOCTET(data[firstoffset+1]);
1195 } else {
1196 number_of_tags = GETJOCTET(data[firstoffset+1]);
1197 number_of_tags <<= 8;
1198 number_of_tags += GETJOCTET(data[firstoffset]);
1200 if (number_of_tags == 0) return;
1201 firstoffset += 2;
1203 /* Search for ExifSubIFD offset Tag in IFD0 */
1204 for (;;) {
1205 if (firstoffset > length - 12) return; /* check end of data segment */
1206 /* Get Tag number */
1207 if (is_motorola) {
1208 tagnum = GETJOCTET(data[firstoffset]);
1209 tagnum <<= 8;
1210 tagnum += GETJOCTET(data[firstoffset+1]);
1211 } else {
1212 tagnum = GETJOCTET(data[firstoffset+1]);
1213 tagnum <<= 8;
1214 tagnum += GETJOCTET(data[firstoffset]);
1216 if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */
1217 if (--number_of_tags == 0) return;
1218 firstoffset += 12;
1221 /* Get the ExifSubIFD offset */
1222 if (is_motorola) {
1223 if (GETJOCTET(data[firstoffset+8]) != 0) return;
1224 if (GETJOCTET(data[firstoffset+9]) != 0) return;
1225 offset = GETJOCTET(data[firstoffset+10]);
1226 offset <<= 8;
1227 offset += GETJOCTET(data[firstoffset+11]);
1228 } else {
1229 if (GETJOCTET(data[firstoffset+11]) != 0) return;
1230 if (GETJOCTET(data[firstoffset+10]) != 0) return;
1231 offset = GETJOCTET(data[firstoffset+9]);
1232 offset <<= 8;
1233 offset += GETJOCTET(data[firstoffset+8]);
1235 if (offset > length - 2) return; /* check end of data segment */
1237 /* Get the number of directory entries contained in this SubIFD */
1238 if (is_motorola) {
1239 number_of_tags = GETJOCTET(data[offset]);
1240 number_of_tags <<= 8;
1241 number_of_tags += GETJOCTET(data[offset+1]);
1242 } else {
1243 number_of_tags = GETJOCTET(data[offset+1]);
1244 number_of_tags <<= 8;
1245 number_of_tags += GETJOCTET(data[offset]);
1247 if (number_of_tags < 2) return;
1248 offset += 2;
1250 /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */
1251 do {
1252 if (offset > length - 12) return; /* check end of data segment */
1253 /* Get Tag number */
1254 if (is_motorola) {
1255 tagnum = GETJOCTET(data[offset]);
1256 tagnum <<= 8;
1257 tagnum += GETJOCTET(data[offset+1]);
1258 } else {
1259 tagnum = GETJOCTET(data[offset+1]);
1260 tagnum <<= 8;
1261 tagnum += GETJOCTET(data[offset]);
1263 if (tagnum == 0xA002 || tagnum == 0xA003) {
1264 if (tagnum == 0xA002)
1265 new_value = new_width; /* ExifImageWidth Tag */
1266 else
1267 new_value = new_height; /* ExifImageHeight Tag */
1268 if (is_motorola) {
1269 data[offset+2] = 0; /* Format = unsigned long (4 octets) */
1270 data[offset+3] = 4;
1271 data[offset+4] = 0; /* Number Of Components = 1 */
1272 data[offset+5] = 0;
1273 data[offset+6] = 0;
1274 data[offset+7] = 1;
1275 data[offset+8] = 0;
1276 data[offset+9] = 0;
1277 data[offset+10] = (JOCTET)((new_value >> 8) & 0xFF);
1278 data[offset+11] = (JOCTET)(new_value & 0xFF);
1279 } else {
1280 data[offset+2] = 4; /* Format = unsigned long (4 octets) */
1281 data[offset+3] = 0;
1282 data[offset+4] = 1; /* Number Of Components = 1 */
1283 data[offset+5] = 0;
1284 data[offset+6] = 0;
1285 data[offset+7] = 0;
1286 data[offset+8] = (JOCTET)(new_value & 0xFF);
1287 data[offset+9] = (JOCTET)((new_value >> 8) & 0xFF);
1288 data[offset+10] = 0;
1289 data[offset+11] = 0;
1292 offset += 12;
1293 } while (--number_of_tags);
1297 /* Adjust output image parameters as needed.
1299 * This must be called after jpeg_copy_critical_parameters()
1300 * and before jpeg_write_coefficients().
1302 * The return value is the set of virtual coefficient arrays to be written
1303 * (either the ones allocated by jtransform_request_workspace, or the
1304 * original source data arrays). The caller will need to pass this value
1305 * to jpeg_write_coefficients().
1308 GLOBAL(jvirt_barray_ptr *)
1309 jtransform_adjust_parameters (j_decompress_ptr srcinfo,
1310 j_compress_ptr dstinfo,
1311 jvirt_barray_ptr *src_coef_arrays,
1312 jpeg_transform_info *info)
1314 /* If force-to-grayscale is requested, adjust destination parameters */
1315 if (info->force_grayscale) {
1316 /* First, ensure we have YCbCr or grayscale data, and that the source's
1317 * Y channel is full resolution. (No reasonable person would make Y
1318 * be less than full resolution, so actually coping with that case
1319 * isn't worth extra code space. But we check it to avoid crashing.)
1321 if (((dstinfo->jpeg_color_space == JCS_YCbCr &&
1322 dstinfo->num_components == 3) ||
1323 (dstinfo->jpeg_color_space == JCS_GRAYSCALE &&
1324 dstinfo->num_components == 1)) &&
1325 srcinfo->comp_info[0].h_samp_factor == srcinfo->max_h_samp_factor &&
1326 srcinfo->comp_info[0].v_samp_factor == srcinfo->max_v_samp_factor) {
1327 /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
1328 * properly. Among other things, it sets the target h_samp_factor &
1329 * v_samp_factor to 1, which typically won't match the source.
1330 * We have to preserve the source's quantization table number, however.
1332 int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no;
1333 jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE);
1334 dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no;
1335 } else {
1336 /* Sorry, can't do it */
1337 ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL);
1339 } else if (info->num_components == 1) {
1340 /* For a single-component source, we force the destination sampling factors
1341 * to 1x1, with or without force_grayscale. This is useful because some
1342 * decoders choke on grayscale images with other sampling factors.
1344 dstinfo->comp_info[0].h_samp_factor = 1;
1345 dstinfo->comp_info[0].v_samp_factor = 1;
1348 /* Correct the destination's image dimensions as necessary
1349 * for rotate/flip, resize, and crop operations.
1351 dstinfo->jpeg_width = info->output_width;
1352 dstinfo->jpeg_height = info->output_height;
1354 /* Transpose destination image parameters */
1355 switch (info->transform) {
1356 case JXFORM_TRANSPOSE:
1357 case JXFORM_TRANSVERSE:
1358 case JXFORM_ROT_90:
1359 case JXFORM_ROT_270:
1360 transpose_critical_parameters(dstinfo);
1361 break;
1362 default:
1363 break;
1366 /* Adjust Exif properties */
1367 if (srcinfo->marker_list != NULL &&
1368 srcinfo->marker_list->marker == JPEG_APP0+1 &&
1369 srcinfo->marker_list->data_length >= 6 &&
1370 GETJOCTET(srcinfo->marker_list->data[0]) == 0x45 &&
1371 GETJOCTET(srcinfo->marker_list->data[1]) == 0x78 &&
1372 GETJOCTET(srcinfo->marker_list->data[2]) == 0x69 &&
1373 GETJOCTET(srcinfo->marker_list->data[3]) == 0x66 &&
1374 GETJOCTET(srcinfo->marker_list->data[4]) == 0 &&
1375 GETJOCTET(srcinfo->marker_list->data[5]) == 0) {
1376 /* Suppress output of JFIF marker */
1377 dstinfo->write_JFIF_header = FALSE;
1378 /* Adjust Exif image parameters */
1379 if (dstinfo->jpeg_width != srcinfo->image_width ||
1380 dstinfo->jpeg_height != srcinfo->image_height)
1381 /* Align data segment to start of TIFF structure for parsing */
1382 adjust_exif_parameters(srcinfo->marker_list->data + 6,
1383 srcinfo->marker_list->data_length - 6,
1384 dstinfo->jpeg_width, dstinfo->jpeg_height);
1387 /* Return the appropriate output data set */
1388 if (info->workspace_coef_arrays != NULL)
1389 return info->workspace_coef_arrays;
1390 return src_coef_arrays;
1394 /* Execute the actual transformation, if any.
1396 * This must be called *after* jpeg_write_coefficients, because it depends
1397 * on jpeg_write_coefficients to have computed subsidiary values such as
1398 * the per-component width and height fields in the destination object.
1400 * Note that some transformations will modify the source data arrays!
1403 GLOBAL(void)
1404 jtransform_execute_transform (j_decompress_ptr srcinfo,
1405 j_compress_ptr dstinfo,
1406 jvirt_barray_ptr *src_coef_arrays,
1407 jpeg_transform_info *info)
1409 jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays;
1411 /* Note: conditions tested here should match those in switch statement
1412 * in jtransform_request_workspace()
1414 switch (info->transform) {
1415 case JXFORM_NONE:
1416 if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
1417 do_crop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
1418 src_coef_arrays, dst_coef_arrays);
1419 break;
1420 case JXFORM_FLIP_H:
1421 if (info->y_crop_offset != 0)
1422 do_flip_h(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
1423 src_coef_arrays, dst_coef_arrays);
1424 else
1425 do_flip_h_no_crop(srcinfo, dstinfo, info->x_crop_offset,
1426 src_coef_arrays);
1427 break;
1428 case JXFORM_FLIP_V:
1429 do_flip_v(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
1430 src_coef_arrays, dst_coef_arrays);
1431 break;
1432 case JXFORM_TRANSPOSE:
1433 do_transpose(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
1434 src_coef_arrays, dst_coef_arrays);
1435 break;
1436 case JXFORM_TRANSVERSE:
1437 do_transverse(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
1438 src_coef_arrays, dst_coef_arrays);
1439 break;
1440 case JXFORM_ROT_90:
1441 do_rot_90(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
1442 src_coef_arrays, dst_coef_arrays);
1443 break;
1444 case JXFORM_ROT_180:
1445 do_rot_180(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
1446 src_coef_arrays, dst_coef_arrays);
1447 break;
1448 case JXFORM_ROT_270:
1449 do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
1450 src_coef_arrays, dst_coef_arrays);
1451 break;
1455 /* jtransform_perfect_transform
1457 * Determine whether lossless transformation is perfectly
1458 * possible for a specified image and transformation.
1460 * Inputs:
1461 * image_width, image_height: source image dimensions.
1462 * MCU_width, MCU_height: pixel dimensions of MCU.
1463 * transform: transformation identifier.
1464 * Parameter sources from initialized jpeg_struct
1465 * (after reading source header):
1466 * image_width = cinfo.image_width
1467 * image_height = cinfo.image_height
1468 * MCU_width = cinfo.max_h_samp_factor * cinfo.block_size
1469 * MCU_height = cinfo.max_v_samp_factor * cinfo.block_size
1470 * Result:
1471 * TRUE = perfect transformation possible
1472 * FALSE = perfect transformation not possible
1473 * (may use custom action then)
1476 GLOBAL(boolean)
1477 jtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height,
1478 int MCU_width, int MCU_height,
1479 JXFORM_CODE transform)
1481 boolean result = TRUE; /* initialize TRUE */
1483 switch (transform) {
1484 case JXFORM_FLIP_H:
1485 case JXFORM_ROT_270:
1486 if (image_width % (JDIMENSION) MCU_width)
1487 result = FALSE;
1488 break;
1489 case JXFORM_FLIP_V:
1490 case JXFORM_ROT_90:
1491 if (image_height % (JDIMENSION) MCU_height)
1492 result = FALSE;
1493 break;
1494 case JXFORM_TRANSVERSE:
1495 case JXFORM_ROT_180:
1496 if (image_width % (JDIMENSION) MCU_width)
1497 result = FALSE;
1498 if (image_height % (JDIMENSION) MCU_height)
1499 result = FALSE;
1500 break;
1501 default:
1502 break;
1505 return result;
1508 #endif /* TRANSFORMS_SUPPORTED */
1511 /* Setup decompression object to save desired markers in memory.
1512 * This must be called before jpeg_read_header() to have the desired effect.
1515 GLOBAL(void)
1516 jcopy_markers_setup (j_decompress_ptr srcinfo, JCOPY_OPTION option)
1518 #ifdef SAVE_MARKERS_SUPPORTED
1519 int m;
1521 /* Save comments except under NONE option */
1522 if (option != JCOPYOPT_NONE) {
1523 jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF);
1525 /* Save all types of APPn markers iff ALL option */
1526 if (option == JCOPYOPT_ALL) {
1527 for (m = 0; m < 16; m++)
1528 jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF);
1530 #endif /* SAVE_MARKERS_SUPPORTED */
1533 /* Copy markers saved in the given source object to the destination object.
1534 * This should be called just after jpeg_start_compress() or
1535 * jpeg_write_coefficients().
1536 * Note that those routines will have written the SOI, and also the
1537 * JFIF APP0 or Adobe APP14 markers if selected.
1540 GLOBAL(void)
1541 jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
1542 JCOPY_OPTION option)
1544 jpeg_saved_marker_ptr marker;
1546 /* In the current implementation, we don't actually need to examine the
1547 * option flag here; we just copy everything that got saved.
1548 * But to avoid confusion, we do not output JFIF and Adobe APP14 markers
1549 * if the encoder library already wrote one.
1551 for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) {
1552 if (dstinfo->write_JFIF_header &&
1553 marker->marker == JPEG_APP0 &&
1554 marker->data_length >= 5 &&
1555 GETJOCTET(marker->data[0]) == 0x4A &&
1556 GETJOCTET(marker->data[1]) == 0x46 &&
1557 GETJOCTET(marker->data[2]) == 0x49 &&
1558 GETJOCTET(marker->data[3]) == 0x46 &&
1559 GETJOCTET(marker->data[4]) == 0)
1560 continue; /* reject duplicate JFIF */
1561 if (dstinfo->write_Adobe_marker &&
1562 marker->marker == JPEG_APP0+14 &&
1563 marker->data_length >= 5 &&
1564 GETJOCTET(marker->data[0]) == 0x41 &&
1565 GETJOCTET(marker->data[1]) == 0x64 &&
1566 GETJOCTET(marker->data[2]) == 0x6F &&
1567 GETJOCTET(marker->data[3]) == 0x62 &&
1568 GETJOCTET(marker->data[4]) == 0x65)
1569 continue; /* reject duplicate Adobe */
1570 #ifdef NEED_FAR_POINTERS
1571 /* We could use jpeg_write_marker if the data weren't FAR... */
1573 unsigned int i;
1574 jpeg_write_m_header(dstinfo, marker->marker, marker->data_length);
1575 for (i = 0; i < marker->data_length; i++)
1576 jpeg_write_m_byte(dstinfo, marker->data[i]);
1578 #else
1579 jpeg_write_marker(dstinfo, marker->marker,
1580 marker->data, marker->data_length);
1581 #endif