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