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