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