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