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