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