By default, Bugzilla does not search the list of RESOLVED bugs.
You can force it to do so by putting the upper-case word ALL in front of your search query, e.g.: ALL tdelibs
We recommend searching for bugs this way, as you may discover that your bug has already been resolved and fixed in a later release. View | Details | Raw Unified | Return to bug 1444
Collapse All | Expand All

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

Return to bug 1444