source: rtems-graphics-toolkit/jpeg-7/transupp.c @ 2abf143

base initial
Last change on this file since 2abf143 was 2abf143, checked in by Joel Sherrill <joel.sherrill@…>, on 12/20/09 at 00:59:55

Initial import of jpeg and tiff libraries.

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