Coverage Report

Created: 2023-06-07 06:03

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