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