blob: b51ef3923dd962d1a34ab536f81e4dbadbf73c01 [file] [log] [blame]
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001/*
2 * transupp.c
3 *
DRCcf763c02013-01-01 09:51:37 +00004 * This file was part of the Independent JPEG Group's software:
Guido Vollbeding5829cb22012-01-15 00:00:00 +00005 * Copyright (C) 1997-2011, Thomas G. Lane, Guido Vollbeding.
DRCa6ef2822013-09-28 03:23:49 +00006 * libjpeg-turbo Modifications:
Leon Scroggins IIIbd7903e2018-02-28 14:05:04 -05007 * Copyright (C) 2010, 2017, D. R. Commander.
Alex Naidis6eb7d372016-10-16 23:10:08 +02008 * For conditions of distribution and use, see the accompanying README.ijg
9 * file.
Thomas G. Lane5ead57a1998-03-27 00:00:00 +000010 *
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"
DRCe5eaf372014-05-09 18:00:32 +000025#include "transupp.h" /* My own external interface */
DRCc04bd3c2010-10-10 02:15:56 +000026#include "jpegcomp.h"
DRCe5eaf372014-05-09 18:00:32 +000027#include <ctype.h> /* to declare isdigit() */
Thomas G. Lane5ead57a1998-03-27 00:00:00 +000028
29
DRCc04bd3c2010-10-10 02:15:56 +000030#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#define dstinfo_min_DCT_h_scaled_size DCTSIZE
35#define dstinfo_min_DCT_v_scaled_size DCTSIZE
36#endif
Thomas G. Lane5ead57a1998-03-27 00:00:00 +000037
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.
Guido Vollbeding5996a252009-06-27 00:00:00 +000045 * Thanks to Guido Vollbeding for the initial design and code of this feature,
46 * and to Ben Jackson for introducing the cropping feature.
Thomas G. Lane5ead57a1998-03-27 00:00:00 +000047 *
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 *
Guido Vollbeding5996a252009-06-27 00:00:00 +000060 * 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 *
Thomas G. Lane5ead57a1998-03-27 00:00:00 +000067 * 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.
Guido Vollbeding5996a252009-06-27 00:00:00 +000079 * 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
Thomas G. Lane5ead57a1998-03-27 00:00:00 +000086 * padded out to a full iMCU boundary. This is true, although for the
87 * source buffer it is an undocumented property of jdcoefct.c.
Thomas G. Lane5ead57a1998-03-27 00:00:00 +000088 */
89
90
91LOCAL(void)
Guido Vollbeding5996a252009-06-27 00:00:00 +000092do_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
DRCe5eaf372014-05-09 18:00:32 +000093 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
94 jvirt_barray_ptr *src_coef_arrays,
95 jvirt_barray_ptr *dst_coef_arrays)
Guido Vollbeding5996a252009-06-27 00:00:00 +000096/* Crop. This is only used when no rotate/flip is requested with the crop. */
Thomas G. Lane5ead57a1998-03-27 00:00:00 +000097{
Guido Vollbeding5996a252009-06-27 00:00:00 +000098 JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks;
99 int ci, offset_y;
100 JBLOCKARRAY src_buffer, dst_buffer;
101 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 for (ci = 0; ci < dstinfo->num_components; ci++) {
107 compptr = dstinfo->comp_info + ci;
108 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
109 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
110 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
DRCe5eaf372014-05-09 18:00:32 +0000111 dst_blk_y += compptr->v_samp_factor) {
Guido Vollbeding5996a252009-06-27 00:00:00 +0000112 dst_buffer = (*srcinfo->mem->access_virt_barray)
DRCe5eaf372014-05-09 18:00:32 +0000113 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
114 (JDIMENSION) compptr->v_samp_factor, TRUE);
Guido Vollbeding5996a252009-06-27 00:00:00 +0000115 src_buffer = (*srcinfo->mem->access_virt_barray)
DRCe5eaf372014-05-09 18:00:32 +0000116 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
117 dst_blk_y + y_crop_blocks,
118 (JDIMENSION) compptr->v_samp_factor, FALSE);
Guido Vollbeding5996a252009-06-27 00:00:00 +0000119 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
DRCe5eaf372014-05-09 18:00:32 +0000120 jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
121 dst_buffer[offset_y],
122 compptr->width_in_blocks);
Guido Vollbeding5996a252009-06-27 00:00:00 +0000123 }
124 }
125 }
126}
127
128
129LOCAL(void)
130do_flip_h_no_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
DRCe5eaf372014-05-09 18:00:32 +0000131 JDIMENSION x_crop_offset,
132 jvirt_barray_ptr *src_coef_arrays)
Guido Vollbeding5996a252009-06-27 00:00:00 +0000133/* Horizontal flip; done in-place, so no separate dest array is required.
134 * NB: this only works when y_crop_offset is zero.
135 */
136{
137 JDIMENSION MCU_cols, comp_width, blk_x, blk_y, x_crop_blocks;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000138 int ci, k, offset_y;
139 JBLOCKARRAY buffer;
140 JCOEFPTR ptr1, ptr2;
141 JCOEF temp1, temp2;
142 jpeg_component_info *compptr;
143
144 /* Horizontal mirroring of DCT blocks is accomplished by swapping
145 * pairs of blocks in-place. Within a DCT block, we perform horizontal
146 * mirroring by changing the signs of odd-numbered columns.
147 * Partial iMCUs at the right edge are left untouched.
148 */
Guido Vollbeding989630f2010-01-10 00:00:00 +0000149 MCU_cols = srcinfo->output_width /
DRCc04bd3c2010-10-10 02:15:56 +0000150 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000151
152 for (ci = 0; ci < dstinfo->num_components; ci++) {
153 compptr = dstinfo->comp_info + ci;
154 comp_width = MCU_cols * compptr->h_samp_factor;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000155 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000156 for (blk_y = 0; blk_y < compptr->height_in_blocks;
DRCe5eaf372014-05-09 18:00:32 +0000157 blk_y += compptr->v_samp_factor) {
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000158 buffer = (*srcinfo->mem->access_virt_barray)
DRCe5eaf372014-05-09 18:00:32 +0000159 ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y,
160 (JDIMENSION) compptr->v_samp_factor, TRUE);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000161 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
DRCe5eaf372014-05-09 18:00:32 +0000162 /* Do the mirroring */
163 for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) {
164 ptr1 = buffer[offset_y][blk_x];
165 ptr2 = buffer[offset_y][comp_width - blk_x - 1];
166 /* this unrolled loop doesn't need to know which row it's on... */
167 for (k = 0; k < DCTSIZE2; k += 2) {
168 temp1 = *ptr1; /* swap even column */
169 temp2 = *ptr2;
170 *ptr1++ = temp2;
171 *ptr2++ = temp1;
172 temp1 = *ptr1; /* swap odd column with sign change */
173 temp2 = *ptr2;
174 *ptr1++ = -temp2;
175 *ptr2++ = -temp1;
176 }
177 }
178 if (x_crop_blocks > 0) {
179 /* Now left-justify the portion of the data to be kept.
180 * We can't use a single jcopy_block_row() call because that routine
181 * depends on memcpy(), whose behavior is unspecified for overlapping
182 * source and destination areas. Sigh.
183 */
184 for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
185 jcopy_block_row(buffer[offset_y] + blk_x + x_crop_blocks,
186 buffer[offset_y] + blk_x,
187 (JDIMENSION) 1);
188 }
189 }
Guido Vollbeding5996a252009-06-27 00:00:00 +0000190 }
191 }
192 }
193}
194
195
196LOCAL(void)
197do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
DRCe5eaf372014-05-09 18:00:32 +0000198 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
199 jvirt_barray_ptr *src_coef_arrays,
200 jvirt_barray_ptr *dst_coef_arrays)
Guido Vollbeding5996a252009-06-27 00:00:00 +0000201/* Horizontal flip in general cropping case */
202{
203 JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
204 JDIMENSION x_crop_blocks, y_crop_blocks;
205 int ci, k, offset_y;
206 JBLOCKARRAY src_buffer, dst_buffer;
207 JBLOCKROW src_row_ptr, dst_row_ptr;
208 JCOEFPTR src_ptr, dst_ptr;
209 jpeg_component_info *compptr;
210
211 /* Here we must output into a separate array because we can't touch
212 * different rows of a single virtual array simultaneously. Otherwise,
213 * this is essentially the same as the routine above.
214 */
Guido Vollbeding989630f2010-01-10 00:00:00 +0000215 MCU_cols = srcinfo->output_width /
DRCc04bd3c2010-10-10 02:15:56 +0000216 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
Guido Vollbeding5996a252009-06-27 00:00:00 +0000217
218 for (ci = 0; ci < dstinfo->num_components; ci++) {
219 compptr = dstinfo->comp_info + ci;
220 comp_width = MCU_cols * compptr->h_samp_factor;
221 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
222 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
223 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
DRCe5eaf372014-05-09 18:00:32 +0000224 dst_blk_y += compptr->v_samp_factor) {
Guido Vollbeding5996a252009-06-27 00:00:00 +0000225 dst_buffer = (*srcinfo->mem->access_virt_barray)
DRCe5eaf372014-05-09 18:00:32 +0000226 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
227 (JDIMENSION) compptr->v_samp_factor, TRUE);
Guido Vollbeding5996a252009-06-27 00:00:00 +0000228 src_buffer = (*srcinfo->mem->access_virt_barray)
DRCe5eaf372014-05-09 18:00:32 +0000229 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
230 dst_blk_y + y_crop_blocks,
231 (JDIMENSION) compptr->v_samp_factor, FALSE);
Guido Vollbeding5996a252009-06-27 00:00:00 +0000232 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
DRCe5eaf372014-05-09 18:00:32 +0000233 dst_row_ptr = dst_buffer[offset_y];
234 src_row_ptr = src_buffer[offset_y];
235 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
236 if (x_crop_blocks + dst_blk_x < comp_width) {
237 /* Do the mirrorable blocks */
238 dst_ptr = dst_row_ptr[dst_blk_x];
239 src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
240 /* this unrolled loop doesn't need to know which row it's on... */
241 for (k = 0; k < DCTSIZE2; k += 2) {
242 *dst_ptr++ = *src_ptr++; /* copy even column */
243 *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */
244 }
245 } else {
246 /* Copy last partial block(s) verbatim */
247 jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
248 dst_row_ptr + dst_blk_x,
249 (JDIMENSION) 1);
250 }
251 }
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000252 }
253 }
254 }
255}
256
257
258LOCAL(void)
259do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
DRCe5eaf372014-05-09 18:00:32 +0000260 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
261 jvirt_barray_ptr *src_coef_arrays,
262 jvirt_barray_ptr *dst_coef_arrays)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000263/* Vertical flip */
264{
265 JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000266 JDIMENSION x_crop_blocks, y_crop_blocks;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000267 int ci, i, j, offset_y;
268 JBLOCKARRAY src_buffer, dst_buffer;
269 JBLOCKROW src_row_ptr, dst_row_ptr;
270 JCOEFPTR src_ptr, dst_ptr;
271 jpeg_component_info *compptr;
272
273 /* We output into a separate array because we can't touch different
274 * rows of the source virtual array simultaneously. Otherwise, this
275 * is a pretty straightforward analog of horizontal flip.
276 * Within a DCT block, vertical mirroring is done by changing the signs
277 * of odd-numbered rows.
278 * Partial iMCUs at the bottom edge are copied verbatim.
279 */
Guido Vollbeding989630f2010-01-10 00:00:00 +0000280 MCU_rows = srcinfo->output_height /
DRCc04bd3c2010-10-10 02:15:56 +0000281 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000282
283 for (ci = 0; ci < dstinfo->num_components; ci++) {
284 compptr = dstinfo->comp_info + ci;
285 comp_height = MCU_rows * compptr->v_samp_factor;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000286 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
287 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000288 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
DRCe5eaf372014-05-09 18:00:32 +0000289 dst_blk_y += compptr->v_samp_factor) {
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000290 dst_buffer = (*srcinfo->mem->access_virt_barray)
DRCe5eaf372014-05-09 18:00:32 +0000291 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
292 (JDIMENSION) compptr->v_samp_factor, TRUE);
Guido Vollbeding5996a252009-06-27 00:00:00 +0000293 if (y_crop_blocks + dst_blk_y < comp_height) {
DRCe5eaf372014-05-09 18:00:32 +0000294 /* Row is within the mirrorable area. */
295 src_buffer = (*srcinfo->mem->access_virt_barray)
296 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
297 comp_height - y_crop_blocks - dst_blk_y -
298 (JDIMENSION) compptr->v_samp_factor,
299 (JDIMENSION) compptr->v_samp_factor, FALSE);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000300 } else {
DRCe5eaf372014-05-09 18:00:32 +0000301 /* Bottom-edge blocks will be copied verbatim. */
302 src_buffer = (*srcinfo->mem->access_virt_barray)
303 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
304 dst_blk_y + y_crop_blocks,
305 (JDIMENSION) compptr->v_samp_factor, FALSE);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000306 }
307 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
DRCe5eaf372014-05-09 18:00:32 +0000308 if (y_crop_blocks + dst_blk_y < comp_height) {
309 /* Row is within the mirrorable area. */
310 dst_row_ptr = dst_buffer[offset_y];
311 src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
312 src_row_ptr += x_crop_blocks;
313 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
314 dst_blk_x++) {
315 dst_ptr = dst_row_ptr[dst_blk_x];
316 src_ptr = src_row_ptr[dst_blk_x];
317 for (i = 0; i < DCTSIZE; i += 2) {
318 /* copy even row */
319 for (j = 0; j < DCTSIZE; j++)
320 *dst_ptr++ = *src_ptr++;
321 /* copy odd row with sign change */
322 for (j = 0; j < DCTSIZE; j++)
323 *dst_ptr++ = - *src_ptr++;
324 }
325 }
326 } else {
327 /* Just copy row verbatim. */
328 jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
329 dst_buffer[offset_y],
330 compptr->width_in_blocks);
331 }
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000332 }
333 }
334 }
335}
336
337
338LOCAL(void)
339do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
DRCe5eaf372014-05-09 18:00:32 +0000340 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
341 jvirt_barray_ptr *src_coef_arrays,
342 jvirt_barray_ptr *dst_coef_arrays)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000343/* Transpose source into destination */
344{
Guido Vollbeding5996a252009-06-27 00:00:00 +0000345 JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000346 int ci, i, j, offset_x, offset_y;
347 JBLOCKARRAY src_buffer, dst_buffer;
348 JCOEFPTR src_ptr, dst_ptr;
349 jpeg_component_info *compptr;
350
351 /* Transposing pixels within a block just requires transposing the
352 * DCT coefficients.
353 * Partial iMCUs at the edges require no special treatment; we simply
354 * process all the available DCT blocks for every component.
355 */
356 for (ci = 0; ci < dstinfo->num_components; ci++) {
357 compptr = dstinfo->comp_info + ci;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000358 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
359 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000360 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
DRCe5eaf372014-05-09 18:00:32 +0000361 dst_blk_y += compptr->v_samp_factor) {
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000362 dst_buffer = (*srcinfo->mem->access_virt_barray)
DRCe5eaf372014-05-09 18:00:32 +0000363 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
364 (JDIMENSION) compptr->v_samp_factor, TRUE);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000365 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
DRCe5eaf372014-05-09 18:00:32 +0000366 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
367 dst_blk_x += compptr->h_samp_factor) {
368 src_buffer = (*srcinfo->mem->access_virt_barray)
369 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
370 dst_blk_x + x_crop_blocks,
371 (JDIMENSION) compptr->h_samp_factor, FALSE);
372 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
373 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
374 src_ptr = src_buffer[offset_x][dst_blk_y + offset_y + y_crop_blocks];
375 for (i = 0; i < DCTSIZE; i++)
376 for (j = 0; j < DCTSIZE; j++)
377 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
378 }
379 }
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000380 }
381 }
382 }
383}
384
385
386LOCAL(void)
387do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
DRCe5eaf372014-05-09 18:00:32 +0000388 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
389 jvirt_barray_ptr *src_coef_arrays,
390 jvirt_barray_ptr *dst_coef_arrays)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000391/* 90 degree rotation is equivalent to
392 * 1. Transposing the image;
393 * 2. Horizontal mirroring.
394 * These two steps are merged into a single processing routine.
395 */
396{
397 JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000398 JDIMENSION x_crop_blocks, y_crop_blocks;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000399 int ci, i, j, offset_x, offset_y;
400 JBLOCKARRAY src_buffer, dst_buffer;
401 JCOEFPTR src_ptr, dst_ptr;
402 jpeg_component_info *compptr;
403
404 /* Because of the horizontal mirror step, we can't process partial iMCUs
405 * at the (output) right edge properly. They just get transposed and
406 * not mirrored.
407 */
Guido Vollbeding989630f2010-01-10 00:00:00 +0000408 MCU_cols = srcinfo->output_height /
DRCc04bd3c2010-10-10 02:15:56 +0000409 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000410
411 for (ci = 0; ci < dstinfo->num_components; ci++) {
412 compptr = dstinfo->comp_info + ci;
413 comp_width = MCU_cols * compptr->h_samp_factor;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000414 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
415 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000416 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
DRCe5eaf372014-05-09 18:00:32 +0000417 dst_blk_y += compptr->v_samp_factor) {
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000418 dst_buffer = (*srcinfo->mem->access_virt_barray)
DRCe5eaf372014-05-09 18:00:32 +0000419 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
420 (JDIMENSION) compptr->v_samp_factor, TRUE);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000421 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
DRCe5eaf372014-05-09 18:00:32 +0000422 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
423 dst_blk_x += compptr->h_samp_factor) {
424 if (x_crop_blocks + dst_blk_x < comp_width) {
425 /* Block is within the mirrorable area. */
426 src_buffer = (*srcinfo->mem->access_virt_barray)
427 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
428 comp_width - x_crop_blocks - dst_blk_x -
429 (JDIMENSION) compptr->h_samp_factor,
430 (JDIMENSION) compptr->h_samp_factor, FALSE);
431 } else {
432 /* Edge blocks are transposed but not mirrored. */
433 src_buffer = (*srcinfo->mem->access_virt_barray)
434 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
435 dst_blk_x + x_crop_blocks,
436 (JDIMENSION) compptr->h_samp_factor, FALSE);
437 }
438 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
439 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
440 if (x_crop_blocks + dst_blk_x < comp_width) {
441 /* Block is within the mirrorable area. */
442 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
443 [dst_blk_y + offset_y + y_crop_blocks];
444 for (i = 0; i < DCTSIZE; i++) {
445 for (j = 0; j < DCTSIZE; j++)
446 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
447 i++;
448 for (j = 0; j < DCTSIZE; j++)
449 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
450 }
451 } else {
452 /* Edge blocks are transposed but not mirrored. */
453 src_ptr = src_buffer[offset_x]
454 [dst_blk_y + offset_y + y_crop_blocks];
455 for (i = 0; i < DCTSIZE; i++)
456 for (j = 0; j < DCTSIZE; j++)
457 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
458 }
459 }
460 }
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000461 }
462 }
463 }
464}
465
466
467LOCAL(void)
468do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
DRCe5eaf372014-05-09 18:00:32 +0000469 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
470 jvirt_barray_ptr *src_coef_arrays,
471 jvirt_barray_ptr *dst_coef_arrays)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000472/* 270 degree rotation is equivalent to
473 * 1. Horizontal mirroring;
474 * 2. Transposing the image.
475 * These two steps are merged into a single processing routine.
476 */
477{
478 JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000479 JDIMENSION x_crop_blocks, y_crop_blocks;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000480 int ci, i, j, offset_x, offset_y;
481 JBLOCKARRAY src_buffer, dst_buffer;
482 JCOEFPTR src_ptr, dst_ptr;
483 jpeg_component_info *compptr;
484
485 /* Because of the horizontal mirror step, we can't process partial iMCUs
486 * at the (output) bottom edge properly. They just get transposed and
487 * not mirrored.
488 */
Guido Vollbeding989630f2010-01-10 00:00:00 +0000489 MCU_rows = srcinfo->output_width /
DRCc04bd3c2010-10-10 02:15:56 +0000490 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000491
492 for (ci = 0; ci < dstinfo->num_components; ci++) {
493 compptr = dstinfo->comp_info + ci;
494 comp_height = MCU_rows * compptr->v_samp_factor;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000495 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
496 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000497 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
DRCe5eaf372014-05-09 18:00:32 +0000498 dst_blk_y += compptr->v_samp_factor) {
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000499 dst_buffer = (*srcinfo->mem->access_virt_barray)
DRCe5eaf372014-05-09 18:00:32 +0000500 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
501 (JDIMENSION) compptr->v_samp_factor, TRUE);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000502 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
DRCe5eaf372014-05-09 18:00:32 +0000503 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
504 dst_blk_x += compptr->h_samp_factor) {
505 src_buffer = (*srcinfo->mem->access_virt_barray)
506 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
507 dst_blk_x + x_crop_blocks,
508 (JDIMENSION) compptr->h_samp_factor, FALSE);
509 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
510 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
511 if (y_crop_blocks + dst_blk_y < comp_height) {
512 /* Block is within the mirrorable area. */
513 src_ptr = src_buffer[offset_x]
514 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
515 for (i = 0; i < DCTSIZE; i++) {
516 for (j = 0; j < DCTSIZE; j++) {
517 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
518 j++;
519 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
520 }
521 }
522 } else {
523 /* Edge blocks are transposed but not mirrored. */
524 src_ptr = src_buffer[offset_x]
525 [dst_blk_y + offset_y + y_crop_blocks];
526 for (i = 0; i < DCTSIZE; i++)
527 for (j = 0; j < DCTSIZE; j++)
528 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
529 }
530 }
531 }
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000532 }
533 }
534 }
535}
536
537
538LOCAL(void)
539do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
DRCe5eaf372014-05-09 18:00:32 +0000540 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
541 jvirt_barray_ptr *src_coef_arrays,
542 jvirt_barray_ptr *dst_coef_arrays)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000543/* 180 degree rotation is equivalent to
544 * 1. Vertical mirroring;
545 * 2. Horizontal mirroring.
546 * These two steps are merged into a single processing routine.
547 */
548{
549 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000550 JDIMENSION x_crop_blocks, y_crop_blocks;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000551 int ci, i, j, offset_y;
552 JBLOCKARRAY src_buffer, dst_buffer;
553 JBLOCKROW src_row_ptr, dst_row_ptr;
554 JCOEFPTR src_ptr, dst_ptr;
555 jpeg_component_info *compptr;
556
Guido Vollbeding989630f2010-01-10 00:00:00 +0000557 MCU_cols = srcinfo->output_width /
DRCc04bd3c2010-10-10 02:15:56 +0000558 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
Guido Vollbeding989630f2010-01-10 00:00:00 +0000559 MCU_rows = srcinfo->output_height /
DRCc04bd3c2010-10-10 02:15:56 +0000560 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000561
562 for (ci = 0; ci < dstinfo->num_components; ci++) {
563 compptr = dstinfo->comp_info + ci;
564 comp_width = MCU_cols * compptr->h_samp_factor;
565 comp_height = MCU_rows * compptr->v_samp_factor;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000566 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
567 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000568 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
DRCe5eaf372014-05-09 18:00:32 +0000569 dst_blk_y += compptr->v_samp_factor) {
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000570 dst_buffer = (*srcinfo->mem->access_virt_barray)
DRCe5eaf372014-05-09 18:00:32 +0000571 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
572 (JDIMENSION) compptr->v_samp_factor, TRUE);
Guido Vollbeding5996a252009-06-27 00:00:00 +0000573 if (y_crop_blocks + dst_blk_y < comp_height) {
DRCe5eaf372014-05-09 18:00:32 +0000574 /* Row is within the vertically mirrorable area. */
575 src_buffer = (*srcinfo->mem->access_virt_barray)
576 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
577 comp_height - y_crop_blocks - dst_blk_y -
578 (JDIMENSION) compptr->v_samp_factor,
579 (JDIMENSION) compptr->v_samp_factor, FALSE);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000580 } else {
DRCe5eaf372014-05-09 18:00:32 +0000581 /* Bottom-edge rows are only mirrored horizontally. */
582 src_buffer = (*srcinfo->mem->access_virt_barray)
583 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
584 dst_blk_y + y_crop_blocks,
585 (JDIMENSION) compptr->v_samp_factor, FALSE);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000586 }
587 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
DRCe5eaf372014-05-09 18:00:32 +0000588 dst_row_ptr = dst_buffer[offset_y];
589 if (y_crop_blocks + dst_blk_y < comp_height) {
590 /* Row is within the mirrorable area. */
591 src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
592 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
593 dst_ptr = dst_row_ptr[dst_blk_x];
594 if (x_crop_blocks + dst_blk_x < comp_width) {
595 /* Process the blocks that can be mirrored both ways. */
596 src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
597 for (i = 0; i < DCTSIZE; i += 2) {
598 /* For even row, negate every odd column. */
599 for (j = 0; j < DCTSIZE; j += 2) {
600 *dst_ptr++ = *src_ptr++;
601 *dst_ptr++ = - *src_ptr++;
602 }
603 /* For odd row, negate every even column. */
604 for (j = 0; j < DCTSIZE; j += 2) {
605 *dst_ptr++ = - *src_ptr++;
606 *dst_ptr++ = *src_ptr++;
607 }
608 }
609 } else {
610 /* Any remaining right-edge blocks are only mirrored vertically. */
611 src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x];
612 for (i = 0; i < DCTSIZE; i += 2) {
613 for (j = 0; j < DCTSIZE; j++)
614 *dst_ptr++ = *src_ptr++;
615 for (j = 0; j < DCTSIZE; j++)
616 *dst_ptr++ = - *src_ptr++;
617 }
618 }
619 }
620 } else {
621 /* Remaining rows are just mirrored horizontally. */
622 src_row_ptr = src_buffer[offset_y];
623 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
624 if (x_crop_blocks + dst_blk_x < comp_width) {
625 /* Process the blocks that can be mirrored. */
626 dst_ptr = dst_row_ptr[dst_blk_x];
627 src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
628 for (i = 0; i < DCTSIZE2; i += 2) {
629 *dst_ptr++ = *src_ptr++;
630 *dst_ptr++ = - *src_ptr++;
631 }
632 } else {
633 /* Any remaining right-edge blocks are only copied. */
634 jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
635 dst_row_ptr + dst_blk_x,
636 (JDIMENSION) 1);
637 }
638 }
639 }
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000640 }
641 }
642 }
643}
644
645
646LOCAL(void)
647do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
DRCe5eaf372014-05-09 18:00:32 +0000648 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
649 jvirt_barray_ptr *src_coef_arrays,
650 jvirt_barray_ptr *dst_coef_arrays)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000651/* Transverse transpose is equivalent to
652 * 1. 180 degree rotation;
653 * 2. Transposition;
654 * or
655 * 1. Horizontal mirroring;
656 * 2. Transposition;
657 * 3. Horizontal mirroring.
658 * These steps are merged into a single processing routine.
659 */
660{
661 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000662 JDIMENSION x_crop_blocks, y_crop_blocks;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000663 int ci, i, j, offset_x, offset_y;
664 JBLOCKARRAY src_buffer, dst_buffer;
665 JCOEFPTR src_ptr, dst_ptr;
666 jpeg_component_info *compptr;
667
Guido Vollbeding989630f2010-01-10 00:00:00 +0000668 MCU_cols = srcinfo->output_height /
DRCc04bd3c2010-10-10 02:15:56 +0000669 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
Guido Vollbeding989630f2010-01-10 00:00:00 +0000670 MCU_rows = srcinfo->output_width /
DRCc04bd3c2010-10-10 02:15:56 +0000671 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000672
673 for (ci = 0; ci < dstinfo->num_components; ci++) {
674 compptr = dstinfo->comp_info + ci;
675 comp_width = MCU_cols * compptr->h_samp_factor;
676 comp_height = MCU_rows * compptr->v_samp_factor;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000677 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
678 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000679 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
DRCe5eaf372014-05-09 18:00:32 +0000680 dst_blk_y += compptr->v_samp_factor) {
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000681 dst_buffer = (*srcinfo->mem->access_virt_barray)
DRCe5eaf372014-05-09 18:00:32 +0000682 ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
683 (JDIMENSION) compptr->v_samp_factor, TRUE);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000684 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
DRCe5eaf372014-05-09 18:00:32 +0000685 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
686 dst_blk_x += compptr->h_samp_factor) {
687 if (x_crop_blocks + dst_blk_x < comp_width) {
688 /* Block is within the mirrorable area. */
689 src_buffer = (*srcinfo->mem->access_virt_barray)
690 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
691 comp_width - x_crop_blocks - dst_blk_x -
692 (JDIMENSION) compptr->h_samp_factor,
693 (JDIMENSION) compptr->h_samp_factor, FALSE);
694 } else {
695 src_buffer = (*srcinfo->mem->access_virt_barray)
696 ((j_common_ptr) srcinfo, src_coef_arrays[ci],
697 dst_blk_x + x_crop_blocks,
698 (JDIMENSION) compptr->h_samp_factor, FALSE);
699 }
700 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
701 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
702 if (y_crop_blocks + dst_blk_y < comp_height) {
703 if (x_crop_blocks + dst_blk_x < comp_width) {
704 /* Block is within the mirrorable area. */
705 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
706 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
707 for (i = 0; i < DCTSIZE; i++) {
708 for (j = 0; j < DCTSIZE; j++) {
709 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
710 j++;
711 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
712 }
713 i++;
714 for (j = 0; j < DCTSIZE; j++) {
715 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
716 j++;
717 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
718 }
719 }
720 } else {
721 /* Right-edge blocks are mirrored in y only */
722 src_ptr = src_buffer[offset_x]
723 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
724 for (i = 0; i < DCTSIZE; i++) {
725 for (j = 0; j < DCTSIZE; j++) {
726 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
727 j++;
728 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
729 }
730 }
731 }
732 } else {
733 if (x_crop_blocks + dst_blk_x < comp_width) {
734 /* Bottom-edge blocks are mirrored in x only */
735 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
736 [dst_blk_y + offset_y + y_crop_blocks];
737 for (i = 0; i < DCTSIZE; i++) {
738 for (j = 0; j < DCTSIZE; j++)
739 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
740 i++;
741 for (j = 0; j < DCTSIZE; j++)
742 dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
743 }
744 } else {
745 /* At lower right corner, just transpose, no mirroring */
746 src_ptr = src_buffer[offset_x]
747 [dst_blk_y + offset_y + y_crop_blocks];
748 for (i = 0; i < DCTSIZE; i++)
749 for (j = 0; j < DCTSIZE; j++)
750 dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
751 }
752 }
753 }
754 }
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000755 }
756 }
757 }
758}
759
760
Guido Vollbeding5996a252009-06-27 00:00:00 +0000761/* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec.
762 * Returns TRUE if valid integer found, FALSE if not.
763 * *strptr is advanced over the digit string, and *result is set to its value.
764 */
765
766LOCAL(boolean)
Alex Naidis6eb7d372016-10-16 23:10:08 +0200767jt_read_integer (const char **strptr, JDIMENSION *result)
Guido Vollbeding5996a252009-06-27 00:00:00 +0000768{
Alex Naidis6eb7d372016-10-16 23:10:08 +0200769 const char *ptr = *strptr;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000770 JDIMENSION val = 0;
771
772 for (; isdigit(*ptr); ptr++) {
773 val = val * 10 + (JDIMENSION) (*ptr - '0');
774 }
775 *result = val;
776 if (ptr == *strptr)
DRCe5eaf372014-05-09 18:00:32 +0000777 return FALSE; /* oops, no digits */
Guido Vollbeding5996a252009-06-27 00:00:00 +0000778 *strptr = ptr;
779 return TRUE;
780}
781
782
783/* Parse a crop specification (written in X11 geometry style).
784 * The routine returns TRUE if the spec string is valid, FALSE if not.
785 *
786 * The crop spec string should have the format
DRCe5eaf372014-05-09 18:00:32 +0000787 * <width>[f]x<height>[f]{+-}<xoffset>{+-}<yoffset>
Guido Vollbeding5996a252009-06-27 00:00:00 +0000788 * where width, height, xoffset, and yoffset are unsigned integers.
789 * Each of the elements can be omitted to indicate a default value.
790 * (A weakness of this style is that it is not possible to omit xoffset
791 * while specifying yoffset, since they look alike.)
792 *
793 * This code is loosely based on XParseGeometry from the X11 distribution.
794 */
795
796GLOBAL(boolean)
797jtransform_parse_crop_spec (jpeg_transform_info *info, const char *spec)
798{
799 info->crop = FALSE;
800 info->crop_width_set = JCROP_UNSET;
801 info->crop_height_set = JCROP_UNSET;
802 info->crop_xoffset_set = JCROP_UNSET;
803 info->crop_yoffset_set = JCROP_UNSET;
804
805 if (isdigit(*spec)) {
806 /* fetch width */
807 if (! jt_read_integer(&spec, &info->crop_width))
808 return FALSE;
Guido Vollbeding5829cb22012-01-15 00:00:00 +0000809 if (*spec == 'f' || *spec == 'F') {
810 spec++;
811 info->crop_width_set = JCROP_FORCE;
812 } else
813 info->crop_width_set = JCROP_POS;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000814 }
Guido Vollbeding5829cb22012-01-15 00:00:00 +0000815 if (*spec == 'x' || *spec == 'X') {
Guido Vollbeding5996a252009-06-27 00:00:00 +0000816 /* fetch height */
817 spec++;
818 if (! jt_read_integer(&spec, &info->crop_height))
819 return FALSE;
Guido Vollbeding5829cb22012-01-15 00:00:00 +0000820 if (*spec == 'f' || *spec == 'F') {
821 spec++;
822 info->crop_height_set = JCROP_FORCE;
823 } else
824 info->crop_height_set = JCROP_POS;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000825 }
826 if (*spec == '+' || *spec == '-') {
827 /* fetch xoffset */
828 info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
829 spec++;
830 if (! jt_read_integer(&spec, &info->crop_xoffset))
831 return FALSE;
832 }
833 if (*spec == '+' || *spec == '-') {
834 /* fetch yoffset */
835 info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
836 spec++;
837 if (! jt_read_integer(&spec, &info->crop_yoffset))
838 return FALSE;
839 }
840 /* We had better have gotten to the end of the string. */
841 if (*spec != '\0')
842 return FALSE;
843 info->crop = TRUE;
844 return TRUE;
845}
846
847
848/* Trim off any partial iMCUs on the indicated destination edge */
849
850LOCAL(void)
851trim_right_edge (jpeg_transform_info *info, JDIMENSION full_width)
852{
853 JDIMENSION MCU_cols;
854
Guido Vollbeding989630f2010-01-10 00:00:00 +0000855 MCU_cols = info->output_width / info->iMCU_sample_width;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000856 if (MCU_cols > 0 && info->x_crop_offset + MCU_cols ==
Guido Vollbeding989630f2010-01-10 00:00:00 +0000857 full_width / info->iMCU_sample_width)
858 info->output_width = MCU_cols * info->iMCU_sample_width;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000859}
860
861LOCAL(void)
862trim_bottom_edge (jpeg_transform_info *info, JDIMENSION full_height)
863{
864 JDIMENSION MCU_rows;
865
Guido Vollbeding989630f2010-01-10 00:00:00 +0000866 MCU_rows = info->output_height / info->iMCU_sample_height;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000867 if (MCU_rows > 0 && info->y_crop_offset + MCU_rows ==
Guido Vollbeding989630f2010-01-10 00:00:00 +0000868 full_height / info->iMCU_sample_height)
869 info->output_height = MCU_rows * info->iMCU_sample_height;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000870}
871
872
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000873/* Request any required workspace.
874 *
Guido Vollbeding5996a252009-06-27 00:00:00 +0000875 * This routine figures out the size that the output image will be
876 * (which implies that all the transform parameters must be set before
877 * it is called).
878 *
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000879 * We allocate the workspace virtual arrays from the source decompression
880 * object, so that all the arrays (both the original data and the workspace)
881 * will be taken into account while making memory management decisions.
882 * Hence, this routine must be called after jpeg_read_header (which reads
883 * the image dimensions) and before jpeg_read_coefficients (which realizes
884 * the source's virtual arrays).
Guido Vollbeding989630f2010-01-10 00:00:00 +0000885 *
886 * This function returns FALSE right away if -perfect is given
887 * and transformation is not perfect. Otherwise returns TRUE.
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000888 */
889
Guido Vollbeding989630f2010-01-10 00:00:00 +0000890GLOBAL(boolean)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000891jtransform_request_workspace (j_decompress_ptr srcinfo,
DRCe5eaf372014-05-09 18:00:32 +0000892 jpeg_transform_info *info)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000893{
Guido Vollbeding989630f2010-01-10 00:00:00 +0000894 jvirt_barray_ptr *coef_arrays;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000895 boolean need_workspace, transpose_it;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000896 jpeg_component_info *compptr;
Guido Vollbeding989630f2010-01-10 00:00:00 +0000897 JDIMENSION xoffset, yoffset;
898 JDIMENSION width_in_iMCUs, height_in_iMCUs;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000899 JDIMENSION width_in_blocks, height_in_blocks;
900 int ci, h_samp_factor, v_samp_factor;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000901
Guido Vollbeding5996a252009-06-27 00:00:00 +0000902 /* Determine number of components in output image */
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000903 if (info->force_grayscale &&
904 srcinfo->jpeg_color_space == JCS_YCbCr &&
Guido Vollbeding989630f2010-01-10 00:00:00 +0000905 srcinfo->num_components == 3)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000906 /* We'll only process the first component */
907 info->num_components = 1;
Guido Vollbeding989630f2010-01-10 00:00:00 +0000908 else
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000909 /* Process all the components */
910 info->num_components = srcinfo->num_components;
Guido Vollbeding989630f2010-01-10 00:00:00 +0000911
912 /* Compute output image dimensions and related values. */
DRCc04bd3c2010-10-10 02:15:56 +0000913#if JPEG_LIB_VERSION >= 80
Guido Vollbeding989630f2010-01-10 00:00:00 +0000914 jpeg_core_output_dimensions(srcinfo);
DRCc04bd3c2010-10-10 02:15:56 +0000915#else
916 srcinfo->output_width = srcinfo->image_width;
917 srcinfo->output_height = srcinfo->image_height;
918#endif
Guido Vollbeding989630f2010-01-10 00:00:00 +0000919
920 /* Return right away if -perfect is given and transformation is not perfect.
921 */
922 if (info->perfect) {
923 if (info->num_components == 1) {
924 if (!jtransform_perfect_transform(srcinfo->output_width,
DRCe5eaf372014-05-09 18:00:32 +0000925 srcinfo->output_height,
926 srcinfo->_min_DCT_h_scaled_size,
927 srcinfo->_min_DCT_v_scaled_size,
928 info->transform))
929 return FALSE;
Guido Vollbeding989630f2010-01-10 00:00:00 +0000930 } else {
931 if (!jtransform_perfect_transform(srcinfo->output_width,
DRCe5eaf372014-05-09 18:00:32 +0000932 srcinfo->output_height,
933 srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size,
934 srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size,
935 info->transform))
936 return FALSE;
Guido Vollbeding989630f2010-01-10 00:00:00 +0000937 }
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000938 }
939
Guido Vollbeding5996a252009-06-27 00:00:00 +0000940 /* If there is only one output component, force the iMCU size to be 1;
941 * else use the source iMCU size. (This allows us to do the right thing
942 * when reducing color to grayscale, and also provides a handy way of
943 * cleaning up "funny" grayscale images whose sampling factors are not 1x1.)
944 */
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000945 switch (info->transform) {
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000946 case JXFORM_TRANSPOSE:
947 case JXFORM_TRANSVERSE:
948 case JXFORM_ROT_90:
949 case JXFORM_ROT_270:
Guido Vollbeding989630f2010-01-10 00:00:00 +0000950 info->output_width = srcinfo->output_height;
951 info->output_height = srcinfo->output_width;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000952 if (info->num_components == 1) {
DRCc04bd3c2010-10-10 02:15:56 +0000953 info->iMCU_sample_width = srcinfo->_min_DCT_v_scaled_size;
954 info->iMCU_sample_height = srcinfo->_min_DCT_h_scaled_size;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000955 } else {
Guido Vollbeding989630f2010-01-10 00:00:00 +0000956 info->iMCU_sample_width =
DRCe5eaf372014-05-09 18:00:32 +0000957 srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size;
Guido Vollbeding989630f2010-01-10 00:00:00 +0000958 info->iMCU_sample_height =
DRCe5eaf372014-05-09 18:00:32 +0000959 srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000960 }
961 break;
962 default:
Guido Vollbeding989630f2010-01-10 00:00:00 +0000963 info->output_width = srcinfo->output_width;
964 info->output_height = srcinfo->output_height;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000965 if (info->num_components == 1) {
DRCc04bd3c2010-10-10 02:15:56 +0000966 info->iMCU_sample_width = srcinfo->_min_DCT_h_scaled_size;
967 info->iMCU_sample_height = srcinfo->_min_DCT_v_scaled_size;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000968 } else {
Guido Vollbeding989630f2010-01-10 00:00:00 +0000969 info->iMCU_sample_width =
DRCe5eaf372014-05-09 18:00:32 +0000970 srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size;
Guido Vollbeding989630f2010-01-10 00:00:00 +0000971 info->iMCU_sample_height =
DRCe5eaf372014-05-09 18:00:32 +0000972 srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000973 }
974 break;
975 }
Guido Vollbeding5996a252009-06-27 00:00:00 +0000976
977 /* If cropping has been requested, compute the crop area's position and
978 * dimensions, ensuring that its upper left corner falls at an iMCU boundary.
979 */
980 if (info->crop) {
981 /* Insert default values for unset crop parameters */
982 if (info->crop_xoffset_set == JCROP_UNSET)
DRCe5eaf372014-05-09 18:00:32 +0000983 info->crop_xoffset = 0; /* default to +0 */
Guido Vollbeding5996a252009-06-27 00:00:00 +0000984 if (info->crop_yoffset_set == JCROP_UNSET)
DRCe5eaf372014-05-09 18:00:32 +0000985 info->crop_yoffset = 0; /* default to +0 */
Guido Vollbeding5996a252009-06-27 00:00:00 +0000986 if (info->crop_xoffset >= info->output_width ||
DRCe5eaf372014-05-09 18:00:32 +0000987 info->crop_yoffset >= info->output_height)
Guido Vollbeding5996a252009-06-27 00:00:00 +0000988 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
989 if (info->crop_width_set == JCROP_UNSET)
990 info->crop_width = info->output_width - info->crop_xoffset;
991 if (info->crop_height_set == JCROP_UNSET)
992 info->crop_height = info->output_height - info->crop_yoffset;
993 /* Ensure parameters are valid */
994 if (info->crop_width <= 0 || info->crop_width > info->output_width ||
DRCe5eaf372014-05-09 18:00:32 +0000995 info->crop_height <= 0 || info->crop_height > info->output_height ||
996 info->crop_xoffset > info->output_width - info->crop_width ||
997 info->crop_yoffset > info->output_height - info->crop_height)
Guido Vollbeding5996a252009-06-27 00:00:00 +0000998 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
999 /* Convert negative crop offsets into regular offsets */
1000 if (info->crop_xoffset_set == JCROP_NEG)
1001 xoffset = info->output_width - info->crop_width - info->crop_xoffset;
1002 else
1003 xoffset = info->crop_xoffset;
1004 if (info->crop_yoffset_set == JCROP_NEG)
1005 yoffset = info->output_height - info->crop_height - info->crop_yoffset;
1006 else
1007 yoffset = info->crop_yoffset;
1008 /* Now adjust so that upper left corner falls at an iMCU boundary */
Guido Vollbeding5829cb22012-01-15 00:00:00 +00001009 if (info->crop_width_set == JCROP_FORCE)
1010 info->output_width = info->crop_width;
1011 else
1012 info->output_width =
1013 info->crop_width + (xoffset % info->iMCU_sample_width);
1014 if (info->crop_height_set == JCROP_FORCE)
1015 info->output_height = info->crop_height;
1016 else
1017 info->output_height =
1018 info->crop_height + (yoffset % info->iMCU_sample_height);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001019 /* Save x/y offsets measured in iMCUs */
Guido Vollbeding989630f2010-01-10 00:00:00 +00001020 info->x_crop_offset = xoffset / info->iMCU_sample_width;
1021 info->y_crop_offset = yoffset / info->iMCU_sample_height;
Guido Vollbeding5996a252009-06-27 00:00:00 +00001022 } else {
1023 info->x_crop_offset = 0;
1024 info->y_crop_offset = 0;
1025 }
1026
1027 /* Figure out whether we need workspace arrays,
1028 * and if so whether they are transposed relative to the source.
1029 */
1030 need_workspace = FALSE;
1031 transpose_it = FALSE;
1032 switch (info->transform) {
1033 case JXFORM_NONE:
1034 if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
1035 need_workspace = TRUE;
1036 /* No workspace needed if neither cropping nor transforming */
1037 break;
1038 case JXFORM_FLIP_H:
1039 if (info->trim)
Guido Vollbeding989630f2010-01-10 00:00:00 +00001040 trim_right_edge(info, srcinfo->output_width);
DRCba5ea512011-03-04 03:20:34 +00001041 if (info->y_crop_offset != 0 || info->slow_hflip)
Guido Vollbeding5996a252009-06-27 00:00:00 +00001042 need_workspace = TRUE;
1043 /* do_flip_h_no_crop doesn't need a workspace array */
1044 break;
1045 case JXFORM_FLIP_V:
1046 if (info->trim)
Guido Vollbeding989630f2010-01-10 00:00:00 +00001047 trim_bottom_edge(info, srcinfo->output_height);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001048 /* Need workspace arrays having same dimensions as source image. */
1049 need_workspace = TRUE;
1050 break;
1051 case JXFORM_TRANSPOSE:
1052 /* transpose does NOT have to trim anything */
1053 /* Need workspace arrays having transposed dimensions. */
1054 need_workspace = TRUE;
1055 transpose_it = TRUE;
1056 break;
1057 case JXFORM_TRANSVERSE:
1058 if (info->trim) {
Guido Vollbeding989630f2010-01-10 00:00:00 +00001059 trim_right_edge(info, srcinfo->output_height);
1060 trim_bottom_edge(info, srcinfo->output_width);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001061 }
1062 /* Need workspace arrays having transposed dimensions. */
1063 need_workspace = TRUE;
1064 transpose_it = TRUE;
1065 break;
1066 case JXFORM_ROT_90:
1067 if (info->trim)
Guido Vollbeding989630f2010-01-10 00:00:00 +00001068 trim_right_edge(info, srcinfo->output_height);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001069 /* Need workspace arrays having transposed dimensions. */
1070 need_workspace = TRUE;
1071 transpose_it = TRUE;
1072 break;
1073 case JXFORM_ROT_180:
1074 if (info->trim) {
Guido Vollbeding989630f2010-01-10 00:00:00 +00001075 trim_right_edge(info, srcinfo->output_width);
1076 trim_bottom_edge(info, srcinfo->output_height);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001077 }
1078 /* Need workspace arrays having same dimensions as source image. */
1079 need_workspace = TRUE;
1080 break;
1081 case JXFORM_ROT_270:
1082 if (info->trim)
Guido Vollbeding989630f2010-01-10 00:00:00 +00001083 trim_bottom_edge(info, srcinfo->output_width);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001084 /* Need workspace arrays having transposed dimensions. */
1085 need_workspace = TRUE;
1086 transpose_it = TRUE;
1087 break;
1088 }
1089
1090 /* Allocate workspace if needed.
1091 * Note that we allocate arrays padded out to the next iMCU boundary,
1092 * so that transform routines need not worry about missing edge blocks.
1093 */
1094 if (need_workspace) {
1095 coef_arrays = (jvirt_barray_ptr *)
1096 (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
DRC5de454b2014-05-18 19:04:03 +00001097 sizeof(jvirt_barray_ptr) * info->num_components);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001098 width_in_iMCUs = (JDIMENSION)
1099 jdiv_round_up((long) info->output_width,
DRCe5eaf372014-05-09 18:00:32 +00001100 (long) info->iMCU_sample_width);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001101 height_in_iMCUs = (JDIMENSION)
1102 jdiv_round_up((long) info->output_height,
DRCe5eaf372014-05-09 18:00:32 +00001103 (long) info->iMCU_sample_height);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001104 for (ci = 0; ci < info->num_components; ci++) {
1105 compptr = srcinfo->comp_info + ci;
1106 if (info->num_components == 1) {
DRCe5eaf372014-05-09 18:00:32 +00001107 /* we're going to force samp factors to 1x1 in this case */
1108 h_samp_factor = v_samp_factor = 1;
Guido Vollbeding5996a252009-06-27 00:00:00 +00001109 } else if (transpose_it) {
DRCe5eaf372014-05-09 18:00:32 +00001110 h_samp_factor = compptr->v_samp_factor;
1111 v_samp_factor = compptr->h_samp_factor;
Guido Vollbeding5996a252009-06-27 00:00:00 +00001112 } else {
DRCe5eaf372014-05-09 18:00:32 +00001113 h_samp_factor = compptr->h_samp_factor;
1114 v_samp_factor = compptr->v_samp_factor;
Guido Vollbeding5996a252009-06-27 00:00:00 +00001115 }
1116 width_in_blocks = width_in_iMCUs * h_samp_factor;
1117 height_in_blocks = height_in_iMCUs * v_samp_factor;
1118 coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
DRCe5eaf372014-05-09 18:00:32 +00001119 ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
1120 width_in_blocks, height_in_blocks, (JDIMENSION) v_samp_factor);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001121 }
Guido Vollbeding989630f2010-01-10 00:00:00 +00001122 info->workspace_coef_arrays = coef_arrays;
1123 } else
1124 info->workspace_coef_arrays = NULL;
Guido Vollbeding5996a252009-06-27 00:00:00 +00001125
Guido Vollbeding989630f2010-01-10 00:00:00 +00001126 return TRUE;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001127}
1128
1129
1130/* Transpose destination image parameters */
1131
1132LOCAL(void)
1133transpose_critical_parameters (j_compress_ptr dstinfo)
1134{
1135 int tblno, i, j, ci, itemp;
1136 jpeg_component_info *compptr;
1137 JQUANT_TBL *qtblptr;
Guido Vollbeding989630f2010-01-10 00:00:00 +00001138 JDIMENSION jtemp;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001139 UINT16 qtemp;
1140
Guido Vollbeding989630f2010-01-10 00:00:00 +00001141 /* Transpose image dimensions */
1142 jtemp = dstinfo->image_width;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001143 dstinfo->image_width = dstinfo->image_height;
Guido Vollbeding989630f2010-01-10 00:00:00 +00001144 dstinfo->image_height = jtemp;
DRC36a6eec2010-10-08 08:05:44 +00001145#if JPEG_LIB_VERSION >= 70
Guido Vollbeding989630f2010-01-10 00:00:00 +00001146 itemp = dstinfo->min_DCT_h_scaled_size;
1147 dstinfo->min_DCT_h_scaled_size = dstinfo->min_DCT_v_scaled_size;
1148 dstinfo->min_DCT_v_scaled_size = itemp;
DRC36a6eec2010-10-08 08:05:44 +00001149#endif
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001150
1151 /* Transpose sampling factors */
1152 for (ci = 0; ci < dstinfo->num_components; ci++) {
1153 compptr = dstinfo->comp_info + ci;
1154 itemp = compptr->h_samp_factor;
1155 compptr->h_samp_factor = compptr->v_samp_factor;
1156 compptr->v_samp_factor = itemp;
1157 }
1158
1159 /* Transpose quantization tables */
1160 for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
1161 qtblptr = dstinfo->quant_tbl_ptrs[tblno];
1162 if (qtblptr != NULL) {
1163 for (i = 0; i < DCTSIZE; i++) {
DRCe5eaf372014-05-09 18:00:32 +00001164 for (j = 0; j < i; j++) {
1165 qtemp = qtblptr->quantval[i*DCTSIZE+j];
1166 qtblptr->quantval[i*DCTSIZE+j] = qtblptr->quantval[j*DCTSIZE+i];
1167 qtblptr->quantval[j*DCTSIZE+i] = qtemp;
1168 }
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001169 }
1170 }
1171 }
1172}
1173
1174
Guido Vollbeding5996a252009-06-27 00:00:00 +00001175/* Adjust Exif image parameters.
1176 *
1177 * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible.
1178 */
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001179
1180LOCAL(void)
Alex Naidis6eb7d372016-10-16 23:10:08 +02001181adjust_exif_parameters (JOCTET *data, unsigned int length,
DRCe5eaf372014-05-09 18:00:32 +00001182 JDIMENSION new_width, JDIMENSION new_height)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001183{
Guido Vollbeding5996a252009-06-27 00:00:00 +00001184 boolean is_motorola; /* Flag for byte order */
1185 unsigned int number_of_tags, tagnum;
1186 unsigned int firstoffset, offset;
1187 JDIMENSION new_value;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001188
Guido Vollbeding5996a252009-06-27 00:00:00 +00001189 if (length < 12) return; /* Length of an IFD entry */
1190
1191 /* Discover byte order */
1192 if (GETJOCTET(data[0]) == 0x49 && GETJOCTET(data[1]) == 0x49)
1193 is_motorola = FALSE;
1194 else if (GETJOCTET(data[0]) == 0x4D && GETJOCTET(data[1]) == 0x4D)
1195 is_motorola = TRUE;
1196 else
1197 return;
1198
1199 /* Check Tag Mark */
1200 if (is_motorola) {
1201 if (GETJOCTET(data[2]) != 0) return;
1202 if (GETJOCTET(data[3]) != 0x2A) return;
1203 } else {
1204 if (GETJOCTET(data[3]) != 0) return;
1205 if (GETJOCTET(data[2]) != 0x2A) return;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001206 }
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001207
Guido Vollbeding5996a252009-06-27 00:00:00 +00001208 /* Get first IFD offset (offset to IFD0) */
1209 if (is_motorola) {
1210 if (GETJOCTET(data[4]) != 0) return;
1211 if (GETJOCTET(data[5]) != 0) return;
1212 firstoffset = GETJOCTET(data[6]);
1213 firstoffset <<= 8;
1214 firstoffset += GETJOCTET(data[7]);
1215 } else {
1216 if (GETJOCTET(data[7]) != 0) return;
1217 if (GETJOCTET(data[6]) != 0) return;
1218 firstoffset = GETJOCTET(data[5]);
1219 firstoffset <<= 8;
1220 firstoffset += GETJOCTET(data[4]);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001221 }
Guido Vollbeding5996a252009-06-27 00:00:00 +00001222 if (firstoffset > length - 2) return; /* check end of data segment */
1223
1224 /* Get the number of directory entries contained in this IFD */
1225 if (is_motorola) {
1226 number_of_tags = GETJOCTET(data[firstoffset]);
1227 number_of_tags <<= 8;
1228 number_of_tags += GETJOCTET(data[firstoffset+1]);
1229 } else {
1230 number_of_tags = GETJOCTET(data[firstoffset+1]);
1231 number_of_tags <<= 8;
1232 number_of_tags += GETJOCTET(data[firstoffset]);
1233 }
1234 if (number_of_tags == 0) return;
1235 firstoffset += 2;
1236
1237 /* Search for ExifSubIFD offset Tag in IFD0 */
1238 for (;;) {
1239 if (firstoffset > length - 12) return; /* check end of data segment */
1240 /* Get Tag number */
1241 if (is_motorola) {
1242 tagnum = GETJOCTET(data[firstoffset]);
1243 tagnum <<= 8;
1244 tagnum += GETJOCTET(data[firstoffset+1]);
1245 } else {
1246 tagnum = GETJOCTET(data[firstoffset+1]);
1247 tagnum <<= 8;
1248 tagnum += GETJOCTET(data[firstoffset]);
1249 }
1250 if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */
1251 if (--number_of_tags == 0) return;
1252 firstoffset += 12;
1253 }
1254
1255 /* Get the ExifSubIFD offset */
1256 if (is_motorola) {
1257 if (GETJOCTET(data[firstoffset+8]) != 0) return;
1258 if (GETJOCTET(data[firstoffset+9]) != 0) return;
1259 offset = GETJOCTET(data[firstoffset+10]);
1260 offset <<= 8;
1261 offset += GETJOCTET(data[firstoffset+11]);
1262 } else {
1263 if (GETJOCTET(data[firstoffset+11]) != 0) return;
1264 if (GETJOCTET(data[firstoffset+10]) != 0) return;
1265 offset = GETJOCTET(data[firstoffset+9]);
1266 offset <<= 8;
1267 offset += GETJOCTET(data[firstoffset+8]);
1268 }
1269 if (offset > length - 2) return; /* check end of data segment */
1270
1271 /* Get the number of directory entries contained in this SubIFD */
1272 if (is_motorola) {
1273 number_of_tags = GETJOCTET(data[offset]);
1274 number_of_tags <<= 8;
1275 number_of_tags += GETJOCTET(data[offset+1]);
1276 } else {
1277 number_of_tags = GETJOCTET(data[offset+1]);
1278 number_of_tags <<= 8;
1279 number_of_tags += GETJOCTET(data[offset]);
1280 }
1281 if (number_of_tags < 2) return;
1282 offset += 2;
1283
1284 /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */
1285 do {
1286 if (offset > length - 12) return; /* check end of data segment */
1287 /* Get Tag number */
1288 if (is_motorola) {
1289 tagnum = GETJOCTET(data[offset]);
1290 tagnum <<= 8;
1291 tagnum += GETJOCTET(data[offset+1]);
1292 } else {
1293 tagnum = GETJOCTET(data[offset+1]);
1294 tagnum <<= 8;
1295 tagnum += GETJOCTET(data[offset]);
1296 }
1297 if (tagnum == 0xA002 || tagnum == 0xA003) {
1298 if (tagnum == 0xA002)
DRCe5eaf372014-05-09 18:00:32 +00001299 new_value = new_width; /* ExifImageWidth Tag */
Guido Vollbeding5996a252009-06-27 00:00:00 +00001300 else
DRCe5eaf372014-05-09 18:00:32 +00001301 new_value = new_height; /* ExifImageHeight Tag */
Guido Vollbeding5996a252009-06-27 00:00:00 +00001302 if (is_motorola) {
DRCe5eaf372014-05-09 18:00:32 +00001303 data[offset+2] = 0; /* Format = unsigned long (4 octets) */
1304 data[offset+3] = 4;
1305 data[offset+4] = 0; /* Number Of Components = 1 */
1306 data[offset+5] = 0;
1307 data[offset+6] = 0;
1308 data[offset+7] = 1;
1309 data[offset+8] = 0;
1310 data[offset+9] = 0;
1311 data[offset+10] = (JOCTET)((new_value >> 8) & 0xFF);
1312 data[offset+11] = (JOCTET)(new_value & 0xFF);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001313 } else {
DRCe5eaf372014-05-09 18:00:32 +00001314 data[offset+2] = 4; /* Format = unsigned long (4 octets) */
1315 data[offset+3] = 0;
1316 data[offset+4] = 1; /* Number Of Components = 1 */
1317 data[offset+5] = 0;
1318 data[offset+6] = 0;
1319 data[offset+7] = 0;
1320 data[offset+8] = (JOCTET)(new_value & 0xFF);
1321 data[offset+9] = (JOCTET)((new_value >> 8) & 0xFF);
1322 data[offset+10] = 0;
1323 data[offset+11] = 0;
Guido Vollbeding5996a252009-06-27 00:00:00 +00001324 }
1325 }
1326 offset += 12;
1327 } while (--number_of_tags);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001328}
1329
1330
1331/* Adjust output image parameters as needed.
1332 *
1333 * This must be called after jpeg_copy_critical_parameters()
1334 * and before jpeg_write_coefficients().
1335 *
1336 * The return value is the set of virtual coefficient arrays to be written
1337 * (either the ones allocated by jtransform_request_workspace, or the
1338 * original source data arrays). The caller will need to pass this value
1339 * to jpeg_write_coefficients().
1340 */
1341
1342GLOBAL(jvirt_barray_ptr *)
1343jtransform_adjust_parameters (j_decompress_ptr srcinfo,
DRCe5eaf372014-05-09 18:00:32 +00001344 j_compress_ptr dstinfo,
1345 jvirt_barray_ptr *src_coef_arrays,
1346 jpeg_transform_info *info)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001347{
1348 /* If force-to-grayscale is requested, adjust destination parameters */
1349 if (info->force_grayscale) {
Guido Vollbeding5996a252009-06-27 00:00:00 +00001350 /* First, ensure we have YCbCr or grayscale data, and that the source's
1351 * Y channel is full resolution. (No reasonable person would make Y
1352 * be less than full resolution, so actually coping with that case
1353 * isn't worth extra code space. But we check it to avoid crashing.)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001354 */
Guido Vollbeding5996a252009-06-27 00:00:00 +00001355 if (((dstinfo->jpeg_color_space == JCS_YCbCr &&
DRCe5eaf372014-05-09 18:00:32 +00001356 dstinfo->num_components == 3) ||
1357 (dstinfo->jpeg_color_space == JCS_GRAYSCALE &&
1358 dstinfo->num_components == 1)) &&
1359 srcinfo->comp_info[0].h_samp_factor == srcinfo->max_h_samp_factor &&
1360 srcinfo->comp_info[0].v_samp_factor == srcinfo->max_v_samp_factor) {
Guido Vollbeding5996a252009-06-27 00:00:00 +00001361 /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
1362 * properly. Among other things, it sets the target h_samp_factor &
1363 * v_samp_factor to 1, which typically won't match the source.
1364 * We have to preserve the source's quantization table number, however.
1365 */
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001366 int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no;
1367 jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE);
1368 dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no;
1369 } else {
1370 /* Sorry, can't do it */
1371 ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL);
1372 }
Guido Vollbeding5996a252009-06-27 00:00:00 +00001373 } else if (info->num_components == 1) {
1374 /* For a single-component source, we force the destination sampling factors
1375 * to 1x1, with or without force_grayscale. This is useful because some
1376 * decoders choke on grayscale images with other sampling factors.
1377 */
1378 dstinfo->comp_info[0].h_samp_factor = 1;
1379 dstinfo->comp_info[0].v_samp_factor = 1;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001380 }
1381
Guido Vollbeding5996a252009-06-27 00:00:00 +00001382 /* Correct the destination's image dimensions as necessary
Guido Vollbeding989630f2010-01-10 00:00:00 +00001383 * for rotate/flip, resize, and crop operations.
Guido Vollbeding5996a252009-06-27 00:00:00 +00001384 */
Leon Scroggins IIIbd7903e2018-02-28 14:05:04 -05001385#if JPEG_LIB_VERSION >= 80
Guido Vollbeding989630f2010-01-10 00:00:00 +00001386 dstinfo->jpeg_width = info->output_width;
1387 dstinfo->jpeg_height = info->output_height;
DRCc04bd3c2010-10-10 02:15:56 +00001388#endif
Guido Vollbeding5996a252009-06-27 00:00:00 +00001389
1390 /* Transpose destination image parameters */
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001391 switch (info->transform) {
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001392 case JXFORM_TRANSPOSE:
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001393 case JXFORM_TRANSVERSE:
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001394 case JXFORM_ROT_90:
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001395 case JXFORM_ROT_270:
Leon Scroggins IIIbd7903e2018-02-28 14:05:04 -05001396#if JPEG_LIB_VERSION < 80
DRC9a648cc2010-10-10 02:48:21 +00001397 dstinfo->image_width = info->output_height;
1398 dstinfo->image_height = info->output_width;
1399#endif
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001400 transpose_critical_parameters(dstinfo);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001401 break;
Guido Vollbeding5996a252009-06-27 00:00:00 +00001402 default:
Leon Scroggins IIIbd7903e2018-02-28 14:05:04 -05001403#if JPEG_LIB_VERSION < 80
DRC9a648cc2010-10-10 02:48:21 +00001404 dstinfo->image_width = info->output_width;
1405 dstinfo->image_height = info->output_height;
1406#endif
Guido Vollbeding5996a252009-06-27 00:00:00 +00001407 break;
1408 }
1409
1410 /* Adjust Exif properties */
1411 if (srcinfo->marker_list != NULL &&
1412 srcinfo->marker_list->marker == JPEG_APP0+1 &&
1413 srcinfo->marker_list->data_length >= 6 &&
1414 GETJOCTET(srcinfo->marker_list->data[0]) == 0x45 &&
1415 GETJOCTET(srcinfo->marker_list->data[1]) == 0x78 &&
1416 GETJOCTET(srcinfo->marker_list->data[2]) == 0x69 &&
1417 GETJOCTET(srcinfo->marker_list->data[3]) == 0x66 &&
1418 GETJOCTET(srcinfo->marker_list->data[4]) == 0 &&
1419 GETJOCTET(srcinfo->marker_list->data[5]) == 0) {
1420 /* Suppress output of JFIF marker */
1421 dstinfo->write_JFIF_header = FALSE;
1422 /* Adjust Exif image parameters */
Leon Scroggins IIIbd7903e2018-02-28 14:05:04 -05001423#if JPEG_LIB_VERSION >= 80
Guido Vollbeding989630f2010-01-10 00:00:00 +00001424 if (dstinfo->jpeg_width != srcinfo->image_width ||
DRCe5eaf372014-05-09 18:00:32 +00001425 dstinfo->jpeg_height != srcinfo->image_height)
Guido Vollbeding5996a252009-06-27 00:00:00 +00001426 /* Align data segment to start of TIFF structure for parsing */
1427 adjust_exif_parameters(srcinfo->marker_list->data + 6,
DRCe5eaf372014-05-09 18:00:32 +00001428 srcinfo->marker_list->data_length - 6,
1429 dstinfo->jpeg_width, dstinfo->jpeg_height);
Leon Scroggins IIIbd7903e2018-02-28 14:05:04 -05001430#else
1431 if (dstinfo->image_width != srcinfo->image_width ||
1432 dstinfo->image_height != srcinfo->image_height)
1433 /* Align data segment to start of TIFF structure for parsing */
1434 adjust_exif_parameters(srcinfo->marker_list->data + 6,
1435 srcinfo->marker_list->data_length - 6,
1436 dstinfo->image_width, dstinfo->image_height);
DRCc04bd3c2010-10-10 02:15:56 +00001437#endif
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001438 }
1439
1440 /* Return the appropriate output data set */
1441 if (info->workspace_coef_arrays != NULL)
1442 return info->workspace_coef_arrays;
1443 return src_coef_arrays;
1444}
1445
1446
1447/* Execute the actual transformation, if any.
1448 *
1449 * This must be called *after* jpeg_write_coefficients, because it depends
1450 * on jpeg_write_coefficients to have computed subsidiary values such as
1451 * the per-component width and height fields in the destination object.
1452 *
1453 * Note that some transformations will modify the source data arrays!
1454 */
1455
1456GLOBAL(void)
Guido Vollbeding5996a252009-06-27 00:00:00 +00001457jtransform_execute_transform (j_decompress_ptr srcinfo,
DRCe5eaf372014-05-09 18:00:32 +00001458 j_compress_ptr dstinfo,
1459 jvirt_barray_ptr *src_coef_arrays,
1460 jpeg_transform_info *info)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001461{
1462 jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays;
1463
Guido Vollbeding5996a252009-06-27 00:00:00 +00001464 /* Note: conditions tested here should match those in switch statement
1465 * in jtransform_request_workspace()
1466 */
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001467 switch (info->transform) {
1468 case JXFORM_NONE:
Guido Vollbeding5996a252009-06-27 00:00:00 +00001469 if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
1470 do_crop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
DRCe5eaf372014-05-09 18:00:32 +00001471 src_coef_arrays, dst_coef_arrays);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001472 break;
1473 case JXFORM_FLIP_H:
DRCba5ea512011-03-04 03:20:34 +00001474 if (info->y_crop_offset != 0 || info->slow_hflip)
Guido Vollbeding5996a252009-06-27 00:00:00 +00001475 do_flip_h(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
DRCe5eaf372014-05-09 18:00:32 +00001476 src_coef_arrays, dst_coef_arrays);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001477 else
1478 do_flip_h_no_crop(srcinfo, dstinfo, info->x_crop_offset,
DRCe5eaf372014-05-09 18:00:32 +00001479 src_coef_arrays);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001480 break;
1481 case JXFORM_FLIP_V:
Guido Vollbeding5996a252009-06-27 00:00:00 +00001482 do_flip_v(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
DRCe5eaf372014-05-09 18:00:32 +00001483 src_coef_arrays, dst_coef_arrays);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001484 break;
1485 case JXFORM_TRANSPOSE:
Guido Vollbeding5996a252009-06-27 00:00:00 +00001486 do_transpose(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
DRCe5eaf372014-05-09 18:00:32 +00001487 src_coef_arrays, dst_coef_arrays);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001488 break;
1489 case JXFORM_TRANSVERSE:
Guido Vollbeding5996a252009-06-27 00:00:00 +00001490 do_transverse(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
DRCe5eaf372014-05-09 18:00:32 +00001491 src_coef_arrays, dst_coef_arrays);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001492 break;
1493 case JXFORM_ROT_90:
Guido Vollbeding5996a252009-06-27 00:00:00 +00001494 do_rot_90(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
DRCe5eaf372014-05-09 18:00:32 +00001495 src_coef_arrays, dst_coef_arrays);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001496 break;
1497 case JXFORM_ROT_180:
Guido Vollbeding5996a252009-06-27 00:00:00 +00001498 do_rot_180(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
DRCe5eaf372014-05-09 18:00:32 +00001499 src_coef_arrays, dst_coef_arrays);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001500 break;
1501 case JXFORM_ROT_270:
Guido Vollbeding5996a252009-06-27 00:00:00 +00001502 do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
DRCe5eaf372014-05-09 18:00:32 +00001503 src_coef_arrays, dst_coef_arrays);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001504 break;
1505 }
1506}
1507
Guido Vollbeding5996a252009-06-27 00:00:00 +00001508/* jtransform_perfect_transform
1509 *
1510 * Determine whether lossless transformation is perfectly
1511 * possible for a specified image and transformation.
1512 *
1513 * Inputs:
1514 * image_width, image_height: source image dimensions.
1515 * MCU_width, MCU_height: pixel dimensions of MCU.
1516 * transform: transformation identifier.
1517 * Parameter sources from initialized jpeg_struct
1518 * (after reading source header):
1519 * image_width = cinfo.image_width
1520 * image_height = cinfo.image_height
Guido Vollbeding989630f2010-01-10 00:00:00 +00001521 * MCU_width = cinfo.max_h_samp_factor * cinfo.block_size
1522 * MCU_height = cinfo.max_v_samp_factor * cinfo.block_size
Guido Vollbeding5996a252009-06-27 00:00:00 +00001523 * Result:
1524 * TRUE = perfect transformation possible
1525 * FALSE = perfect transformation not possible
1526 * (may use custom action then)
1527 */
1528
1529GLOBAL(boolean)
1530jtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height,
DRCe5eaf372014-05-09 18:00:32 +00001531 int MCU_width, int MCU_height,
1532 JXFORM_CODE transform)
Guido Vollbeding5996a252009-06-27 00:00:00 +00001533{
1534 boolean result = TRUE; /* initialize TRUE */
1535
1536 switch (transform) {
1537 case JXFORM_FLIP_H:
1538 case JXFORM_ROT_270:
1539 if (image_width % (JDIMENSION) MCU_width)
1540 result = FALSE;
1541 break;
1542 case JXFORM_FLIP_V:
1543 case JXFORM_ROT_90:
1544 if (image_height % (JDIMENSION) MCU_height)
1545 result = FALSE;
1546 break;
1547 case JXFORM_TRANSVERSE:
1548 case JXFORM_ROT_180:
1549 if (image_width % (JDIMENSION) MCU_width)
1550 result = FALSE;
1551 if (image_height % (JDIMENSION) MCU_height)
1552 result = FALSE;
1553 break;
1554 default:
1555 break;
1556 }
1557
1558 return result;
1559}
1560
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001561#endif /* TRANSFORMS_SUPPORTED */
1562
1563
1564/* Setup decompression object to save desired markers in memory.
1565 * This must be called before jpeg_read_header() to have the desired effect.
1566 */
1567
1568GLOBAL(void)
1569jcopy_markers_setup (j_decompress_ptr srcinfo, JCOPY_OPTION option)
1570{
1571#ifdef SAVE_MARKERS_SUPPORTED
1572 int m;
1573
1574 /* Save comments except under NONE option */
1575 if (option != JCOPYOPT_NONE) {
1576 jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF);
1577 }
1578 /* Save all types of APPn markers iff ALL option */
1579 if (option == JCOPYOPT_ALL) {
1580 for (m = 0; m < 16; m++)
1581 jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF);
1582 }
1583#endif /* SAVE_MARKERS_SUPPORTED */
1584}
1585
1586/* Copy markers saved in the given source object to the destination object.
1587 * This should be called just after jpeg_start_compress() or
1588 * jpeg_write_coefficients().
1589 * Note that those routines will have written the SOI, and also the
1590 * JFIF APP0 or Adobe APP14 markers if selected.
1591 */
1592
1593GLOBAL(void)
1594jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
DRCe5eaf372014-05-09 18:00:32 +00001595 JCOPY_OPTION option)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001596{
1597 jpeg_saved_marker_ptr marker;
1598
1599 /* In the current implementation, we don't actually need to examine the
1600 * option flag here; we just copy everything that got saved.
1601 * But to avoid confusion, we do not output JFIF and Adobe APP14 markers
1602 * if the encoder library already wrote one.
1603 */
1604 for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) {
1605 if (dstinfo->write_JFIF_header &&
DRCe5eaf372014-05-09 18:00:32 +00001606 marker->marker == JPEG_APP0 &&
1607 marker->data_length >= 5 &&
1608 GETJOCTET(marker->data[0]) == 0x4A &&
1609 GETJOCTET(marker->data[1]) == 0x46 &&
1610 GETJOCTET(marker->data[2]) == 0x49 &&
1611 GETJOCTET(marker->data[3]) == 0x46 &&
1612 GETJOCTET(marker->data[4]) == 0)
1613 continue; /* reject duplicate JFIF */
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001614 if (dstinfo->write_Adobe_marker &&
DRCe5eaf372014-05-09 18:00:32 +00001615 marker->marker == JPEG_APP0+14 &&
1616 marker->data_length >= 5 &&
1617 GETJOCTET(marker->data[0]) == 0x41 &&
1618 GETJOCTET(marker->data[1]) == 0x64 &&
1619 GETJOCTET(marker->data[2]) == 0x6F &&
1620 GETJOCTET(marker->data[3]) == 0x62 &&
1621 GETJOCTET(marker->data[4]) == 0x65)
1622 continue; /* reject duplicate Adobe */
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001623 jpeg_write_marker(dstinfo, marker->marker,
DRCe5eaf372014-05-09 18:00:32 +00001624 marker->data, marker->data_length);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001625 }
1626}