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