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