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