~baltix/+junk/irrlicht-test

« back to all changes in this revision

Viewing changes to source/Irrlicht/jpeglib/transupp.c

  • Committer: Mantas Kriaučiūnas
  • Date: 2011-07-18 13:06:25 UTC
  • Revision ID: mantas@akl.lt-20110718130625-c5pvifp61e7kj1ol
Included whole irrlicht SVN libraries to work around launchpad recipe issue with quilt, see https://answers.launchpad.net/launchpad/+question/165193

Show diffs side-by-side

added added

removed removed

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