blob: f3370ace59d6e01bb5fa993c65ad6ae310569e87 [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
Leon Scroggins III3993b372018-07-16 10:43:45 -040031#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
DRCc04bd3c2010-10-10 02:15:56 +000033#else
Leon Scroggins III3993b372018-07-16 10:43:45 -040034#define dstinfo_min_DCT_h_scaled_size DCTSIZE
35#define dstinfo_min_DCT_v_scaled_size DCTSIZE
DRCc04bd3c2010-10-10 02:15:56 +000036#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)
Leon Scroggins III3993b372018-07-16 10:43:45 -040092do_crop(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
93 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
94 jvirt_barray_ptr *src_coef_arrays,
95 jvirt_barray_ptr *dst_coef_arrays)
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)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400113 ((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)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400116 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
DRCe5eaf372014-05-09 18:00:32 +0000117 dst_blk_y + y_crop_blocks,
Leon Scroggins III3993b372018-07-16 10:43:45 -0400118 (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)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400130do_flip_h_no_crop(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
131 JDIMENSION x_crop_offset, jvirt_barray_ptr *src_coef_arrays)
Guido Vollbeding5996a252009-06-27 00:00:00 +0000132/* Horizontal flip; done in-place, so no separate dest array is required.
133 * NB: this only works when y_crop_offset is zero.
134 */
135{
136 JDIMENSION MCU_cols, comp_width, blk_x, blk_y, x_crop_blocks;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000137 int ci, k, offset_y;
138 JBLOCKARRAY buffer;
139 JCOEFPTR ptr1, ptr2;
140 JCOEF temp1, temp2;
141 jpeg_component_info *compptr;
142
143 /* Horizontal mirroring of DCT blocks is accomplished by swapping
144 * pairs of blocks in-place. Within a DCT block, we perform horizontal
145 * mirroring by changing the signs of odd-numbered columns.
146 * Partial iMCUs at the right edge are left untouched.
147 */
Guido Vollbeding989630f2010-01-10 00:00:00 +0000148 MCU_cols = srcinfo->output_width /
Leon Scroggins III3993b372018-07-16 10:43:45 -0400149 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000150
151 for (ci = 0; ci < dstinfo->num_components; ci++) {
152 compptr = dstinfo->comp_info + ci;
153 comp_width = MCU_cols * compptr->h_samp_factor;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000154 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000155 for (blk_y = 0; blk_y < compptr->height_in_blocks;
DRCe5eaf372014-05-09 18:00:32 +0000156 blk_y += compptr->v_samp_factor) {
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000157 buffer = (*srcinfo->mem->access_virt_barray)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400158 ((j_common_ptr)srcinfo, src_coef_arrays[ci], blk_y,
159 (JDIMENSION)compptr->v_samp_factor, TRUE);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000160 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
DRCe5eaf372014-05-09 18:00:32 +0000161 /* Do the mirroring */
162 for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) {
163 ptr1 = buffer[offset_y][blk_x];
164 ptr2 = buffer[offset_y][comp_width - blk_x - 1];
165 /* this unrolled loop doesn't need to know which row it's on... */
166 for (k = 0; k < DCTSIZE2; k += 2) {
167 temp1 = *ptr1; /* swap even column */
168 temp2 = *ptr2;
169 *ptr1++ = temp2;
170 *ptr2++ = temp1;
171 temp1 = *ptr1; /* swap odd column with sign change */
172 temp2 = *ptr2;
173 *ptr1++ = -temp2;
174 *ptr2++ = -temp1;
175 }
176 }
177 if (x_crop_blocks > 0) {
178 /* Now left-justify the portion of the data to be kept.
179 * We can't use a single jcopy_block_row() call because that routine
180 * depends on memcpy(), whose behavior is unspecified for overlapping
181 * source and destination areas. Sigh.
182 */
183 for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
184 jcopy_block_row(buffer[offset_y] + blk_x + x_crop_blocks,
Leon Scroggins III3993b372018-07-16 10:43:45 -0400185 buffer[offset_y] + blk_x, (JDIMENSION)1);
DRCe5eaf372014-05-09 18:00:32 +0000186 }
187 }
Guido Vollbeding5996a252009-06-27 00:00:00 +0000188 }
189 }
190 }
191}
192
193
194LOCAL(void)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400195do_flip_h(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
196 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
197 jvirt_barray_ptr *src_coef_arrays,
198 jvirt_barray_ptr *dst_coef_arrays)
Guido Vollbeding5996a252009-06-27 00:00:00 +0000199/* Horizontal flip in general cropping case */
200{
201 JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
202 JDIMENSION x_crop_blocks, y_crop_blocks;
203 int ci, k, offset_y;
204 JBLOCKARRAY src_buffer, dst_buffer;
205 JBLOCKROW src_row_ptr, dst_row_ptr;
206 JCOEFPTR src_ptr, dst_ptr;
207 jpeg_component_info *compptr;
208
209 /* Here we must output into a separate array because we can't touch
210 * different rows of a single virtual array simultaneously. Otherwise,
211 * this is essentially the same as the routine above.
212 */
Guido Vollbeding989630f2010-01-10 00:00:00 +0000213 MCU_cols = srcinfo->output_width /
Leon Scroggins III3993b372018-07-16 10:43:45 -0400214 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
Guido Vollbeding5996a252009-06-27 00:00:00 +0000215
216 for (ci = 0; ci < dstinfo->num_components; ci++) {
217 compptr = dstinfo->comp_info + ci;
218 comp_width = MCU_cols * compptr->h_samp_factor;
219 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
220 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
221 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
DRCe5eaf372014-05-09 18:00:32 +0000222 dst_blk_y += compptr->v_samp_factor) {
Guido Vollbeding5996a252009-06-27 00:00:00 +0000223 dst_buffer = (*srcinfo->mem->access_virt_barray)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400224 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
225 (JDIMENSION)compptr->v_samp_factor, TRUE);
Guido Vollbeding5996a252009-06-27 00:00:00 +0000226 src_buffer = (*srcinfo->mem->access_virt_barray)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400227 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
DRCe5eaf372014-05-09 18:00:32 +0000228 dst_blk_y + y_crop_blocks,
Leon Scroggins III3993b372018-07-16 10:43:45 -0400229 (JDIMENSION)compptr->v_samp_factor, FALSE);
Guido Vollbeding5996a252009-06-27 00:00:00 +0000230 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
DRCe5eaf372014-05-09 18:00:32 +0000231 dst_row_ptr = dst_buffer[offset_y];
232 src_row_ptr = src_buffer[offset_y];
Leon Scroggins III3993b372018-07-16 10:43:45 -0400233 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
234 dst_blk_x++) {
DRCe5eaf372014-05-09 18:00:32 +0000235 if (x_crop_blocks + dst_blk_x < comp_width) {
236 /* Do the mirrorable blocks */
237 dst_ptr = dst_row_ptr[dst_blk_x];
238 src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
239 /* this unrolled loop doesn't need to know which row it's on... */
240 for (k = 0; k < DCTSIZE2; k += 2) {
241 *dst_ptr++ = *src_ptr++; /* copy even column */
242 *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */
243 }
244 } else {
245 /* Copy last partial block(s) verbatim */
246 jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
Leon Scroggins III3993b372018-07-16 10:43:45 -0400247 dst_row_ptr + dst_blk_x, (JDIMENSION)1);
DRCe5eaf372014-05-09 18:00:32 +0000248 }
249 }
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000250 }
251 }
252 }
253}
254
255
256LOCAL(void)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400257do_flip_v(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
258 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
259 jvirt_barray_ptr *src_coef_arrays,
260 jvirt_barray_ptr *dst_coef_arrays)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000261/* Vertical flip */
262{
263 JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000264 JDIMENSION x_crop_blocks, y_crop_blocks;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000265 int ci, i, j, offset_y;
266 JBLOCKARRAY src_buffer, dst_buffer;
267 JBLOCKROW src_row_ptr, dst_row_ptr;
268 JCOEFPTR src_ptr, dst_ptr;
269 jpeg_component_info *compptr;
270
271 /* We output into a separate array because we can't touch different
272 * rows of the source virtual array simultaneously. Otherwise, this
273 * is a pretty straightforward analog of horizontal flip.
274 * Within a DCT block, vertical mirroring is done by changing the signs
275 * of odd-numbered rows.
276 * Partial iMCUs at the bottom edge are copied verbatim.
277 */
Guido Vollbeding989630f2010-01-10 00:00:00 +0000278 MCU_rows = srcinfo->output_height /
Leon Scroggins III3993b372018-07-16 10:43:45 -0400279 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000280
281 for (ci = 0; ci < dstinfo->num_components; ci++) {
282 compptr = dstinfo->comp_info + ci;
283 comp_height = MCU_rows * compptr->v_samp_factor;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000284 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
285 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000286 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
DRCe5eaf372014-05-09 18:00:32 +0000287 dst_blk_y += compptr->v_samp_factor) {
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000288 dst_buffer = (*srcinfo->mem->access_virt_barray)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400289 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
290 (JDIMENSION)compptr->v_samp_factor, TRUE);
Guido Vollbeding5996a252009-06-27 00:00:00 +0000291 if (y_crop_blocks + dst_blk_y < comp_height) {
DRCe5eaf372014-05-09 18:00:32 +0000292 /* Row is within the mirrorable area. */
293 src_buffer = (*srcinfo->mem->access_virt_barray)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400294 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
DRCe5eaf372014-05-09 18:00:32 +0000295 comp_height - y_crop_blocks - dst_blk_y -
Leon Scroggins III3993b372018-07-16 10:43:45 -0400296 (JDIMENSION)compptr->v_samp_factor,
297 (JDIMENSION)compptr->v_samp_factor, FALSE);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000298 } else {
DRCe5eaf372014-05-09 18:00:32 +0000299 /* Bottom-edge blocks will be copied verbatim. */
300 src_buffer = (*srcinfo->mem->access_virt_barray)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400301 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
DRCe5eaf372014-05-09 18:00:32 +0000302 dst_blk_y + y_crop_blocks,
Leon Scroggins III3993b372018-07-16 10:43:45 -0400303 (JDIMENSION)compptr->v_samp_factor, FALSE);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000304 }
305 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
DRCe5eaf372014-05-09 18:00:32 +0000306 if (y_crop_blocks + dst_blk_y < comp_height) {
307 /* Row is within the mirrorable area. */
308 dst_row_ptr = dst_buffer[offset_y];
309 src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
310 src_row_ptr += x_crop_blocks;
311 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
312 dst_blk_x++) {
313 dst_ptr = dst_row_ptr[dst_blk_x];
314 src_ptr = src_row_ptr[dst_blk_x];
315 for (i = 0; i < DCTSIZE; i += 2) {
316 /* copy even row */
317 for (j = 0; j < DCTSIZE; j++)
318 *dst_ptr++ = *src_ptr++;
319 /* copy odd row with sign change */
320 for (j = 0; j < DCTSIZE; j++)
321 *dst_ptr++ = - *src_ptr++;
322 }
323 }
324 } else {
325 /* Just copy row verbatim. */
326 jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
327 dst_buffer[offset_y],
328 compptr->width_in_blocks);
329 }
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000330 }
331 }
332 }
333}
334
335
336LOCAL(void)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400337do_transpose(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
338 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
339 jvirt_barray_ptr *src_coef_arrays,
340 jvirt_barray_ptr *dst_coef_arrays)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000341/* Transpose source into destination */
342{
Guido Vollbeding5996a252009-06-27 00:00:00 +0000343 JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000344 int ci, i, j, offset_x, offset_y;
345 JBLOCKARRAY src_buffer, dst_buffer;
346 JCOEFPTR src_ptr, dst_ptr;
347 jpeg_component_info *compptr;
348
349 /* Transposing pixels within a block just requires transposing the
350 * DCT coefficients.
351 * Partial iMCUs at the edges require no special treatment; we simply
352 * process all the available DCT blocks for every component.
353 */
354 for (ci = 0; ci < dstinfo->num_components; ci++) {
355 compptr = dstinfo->comp_info + ci;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000356 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
357 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000358 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
DRCe5eaf372014-05-09 18:00:32 +0000359 dst_blk_y += compptr->v_samp_factor) {
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000360 dst_buffer = (*srcinfo->mem->access_virt_barray)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400361 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
362 (JDIMENSION)compptr->v_samp_factor, TRUE);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000363 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
DRCe5eaf372014-05-09 18:00:32 +0000364 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
365 dst_blk_x += compptr->h_samp_factor) {
366 src_buffer = (*srcinfo->mem->access_virt_barray)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400367 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
DRCe5eaf372014-05-09 18:00:32 +0000368 dst_blk_x + x_crop_blocks,
Leon Scroggins III3993b372018-07-16 10:43:45 -0400369 (JDIMENSION)compptr->h_samp_factor, FALSE);
DRCe5eaf372014-05-09 18:00:32 +0000370 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
371 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
Leon Scroggins III3993b372018-07-16 10:43:45 -0400372 src_ptr =
373 src_buffer[offset_x][dst_blk_y + offset_y + y_crop_blocks];
DRCe5eaf372014-05-09 18:00:32 +0000374 for (i = 0; i < DCTSIZE; i++)
375 for (j = 0; j < DCTSIZE; j++)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400376 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
DRCe5eaf372014-05-09 18:00:32 +0000377 }
378 }
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000379 }
380 }
381 }
382}
383
384
385LOCAL(void)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400386do_rot_90(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
387 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
388 jvirt_barray_ptr *src_coef_arrays,
389 jvirt_barray_ptr *dst_coef_arrays)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000390/* 90 degree rotation is equivalent to
391 * 1. Transposing the image;
392 * 2. Horizontal mirroring.
393 * These two steps are merged into a single processing routine.
394 */
395{
396 JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000397 JDIMENSION x_crop_blocks, y_crop_blocks;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000398 int ci, i, j, offset_x, offset_y;
399 JBLOCKARRAY src_buffer, dst_buffer;
400 JCOEFPTR src_ptr, dst_ptr;
401 jpeg_component_info *compptr;
402
403 /* Because of the horizontal mirror step, we can't process partial iMCUs
404 * at the (output) right edge properly. They just get transposed and
405 * not mirrored.
406 */
Guido Vollbeding989630f2010-01-10 00:00:00 +0000407 MCU_cols = srcinfo->output_height /
Leon Scroggins III3993b372018-07-16 10:43:45 -0400408 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000409
410 for (ci = 0; ci < dstinfo->num_components; ci++) {
411 compptr = dstinfo->comp_info + ci;
412 comp_width = MCU_cols * compptr->h_samp_factor;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000413 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
414 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000415 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
DRCe5eaf372014-05-09 18:00:32 +0000416 dst_blk_y += compptr->v_samp_factor) {
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000417 dst_buffer = (*srcinfo->mem->access_virt_barray)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400418 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
419 (JDIMENSION)compptr->v_samp_factor, TRUE);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000420 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
DRCe5eaf372014-05-09 18:00:32 +0000421 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
422 dst_blk_x += compptr->h_samp_factor) {
423 if (x_crop_blocks + dst_blk_x < comp_width) {
424 /* Block is within the mirrorable area. */
425 src_buffer = (*srcinfo->mem->access_virt_barray)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400426 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
DRCe5eaf372014-05-09 18:00:32 +0000427 comp_width - x_crop_blocks - dst_blk_x -
Leon Scroggins III3993b372018-07-16 10:43:45 -0400428 (JDIMENSION)compptr->h_samp_factor,
429 (JDIMENSION)compptr->h_samp_factor, FALSE);
DRCe5eaf372014-05-09 18:00:32 +0000430 } else {
431 /* Edge blocks are transposed but not mirrored. */
432 src_buffer = (*srcinfo->mem->access_virt_barray)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400433 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
DRCe5eaf372014-05-09 18:00:32 +0000434 dst_blk_x + x_crop_blocks,
Leon Scroggins III3993b372018-07-16 10:43:45 -0400435 (JDIMENSION)compptr->h_samp_factor, FALSE);
DRCe5eaf372014-05-09 18:00:32 +0000436 }
437 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
438 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
439 if (x_crop_blocks + dst_blk_x < comp_width) {
440 /* Block is within the mirrorable area. */
441 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
442 [dst_blk_y + offset_y + y_crop_blocks];
443 for (i = 0; i < DCTSIZE; i++) {
444 for (j = 0; j < DCTSIZE; j++)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400445 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
DRCe5eaf372014-05-09 18:00:32 +0000446 i++;
447 for (j = 0; j < DCTSIZE; j++)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400448 dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
DRCe5eaf372014-05-09 18:00:32 +0000449 }
450 } else {
451 /* Edge blocks are transposed but not mirrored. */
452 src_ptr = src_buffer[offset_x]
453 [dst_blk_y + offset_y + y_crop_blocks];
454 for (i = 0; i < DCTSIZE; i++)
455 for (j = 0; j < DCTSIZE; j++)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400456 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
DRCe5eaf372014-05-09 18:00:32 +0000457 }
458 }
459 }
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000460 }
461 }
462 }
463}
464
465
466LOCAL(void)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400467do_rot_270(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
468 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
469 jvirt_barray_ptr *src_coef_arrays,
470 jvirt_barray_ptr *dst_coef_arrays)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000471/* 270 degree rotation is equivalent to
472 * 1. Horizontal mirroring;
473 * 2. Transposing the image.
474 * These two steps are merged into a single processing routine.
475 */
476{
477 JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000478 JDIMENSION x_crop_blocks, y_crop_blocks;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000479 int ci, i, j, offset_x, offset_y;
480 JBLOCKARRAY src_buffer, dst_buffer;
481 JCOEFPTR src_ptr, dst_ptr;
482 jpeg_component_info *compptr;
483
484 /* Because of the horizontal mirror step, we can't process partial iMCUs
485 * at the (output) bottom edge properly. They just get transposed and
486 * not mirrored.
487 */
Guido Vollbeding989630f2010-01-10 00:00:00 +0000488 MCU_rows = srcinfo->output_width /
Leon Scroggins III3993b372018-07-16 10:43:45 -0400489 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000490
491 for (ci = 0; ci < dstinfo->num_components; ci++) {
492 compptr = dstinfo->comp_info + ci;
493 comp_height = MCU_rows * compptr->v_samp_factor;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000494 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
495 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000496 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
DRCe5eaf372014-05-09 18:00:32 +0000497 dst_blk_y += compptr->v_samp_factor) {
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000498 dst_buffer = (*srcinfo->mem->access_virt_barray)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400499 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
500 (JDIMENSION)compptr->v_samp_factor, TRUE);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000501 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
DRCe5eaf372014-05-09 18:00:32 +0000502 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
503 dst_blk_x += compptr->h_samp_factor) {
504 src_buffer = (*srcinfo->mem->access_virt_barray)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400505 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
DRCe5eaf372014-05-09 18:00:32 +0000506 dst_blk_x + x_crop_blocks,
Leon Scroggins III3993b372018-07-16 10:43:45 -0400507 (JDIMENSION)compptr->h_samp_factor, FALSE);
DRCe5eaf372014-05-09 18:00:32 +0000508 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
509 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
510 if (y_crop_blocks + dst_blk_y < comp_height) {
511 /* Block is within the mirrorable area. */
512 src_ptr = src_buffer[offset_x]
513 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
514 for (i = 0; i < DCTSIZE; i++) {
515 for (j = 0; j < DCTSIZE; j++) {
Leon Scroggins III3993b372018-07-16 10:43:45 -0400516 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
DRCe5eaf372014-05-09 18:00:32 +0000517 j++;
Leon Scroggins III3993b372018-07-16 10:43:45 -0400518 dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
DRCe5eaf372014-05-09 18:00:32 +0000519 }
520 }
521 } else {
522 /* Edge blocks are transposed but not mirrored. */
523 src_ptr = src_buffer[offset_x]
524 [dst_blk_y + offset_y + y_crop_blocks];
525 for (i = 0; i < DCTSIZE; i++)
526 for (j = 0; j < DCTSIZE; j++)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400527 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
DRCe5eaf372014-05-09 18:00:32 +0000528 }
529 }
530 }
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000531 }
532 }
533 }
534}
535
536
537LOCAL(void)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400538do_rot_180(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
539 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
540 jvirt_barray_ptr *src_coef_arrays,
541 jvirt_barray_ptr *dst_coef_arrays)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000542/* 180 degree rotation is equivalent to
543 * 1. Vertical mirroring;
544 * 2. Horizontal mirroring.
545 * These two steps are merged into a single processing routine.
546 */
547{
548 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000549 JDIMENSION x_crop_blocks, y_crop_blocks;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000550 int ci, i, j, offset_y;
551 JBLOCKARRAY src_buffer, dst_buffer;
552 JBLOCKROW src_row_ptr, dst_row_ptr;
553 JCOEFPTR src_ptr, dst_ptr;
554 jpeg_component_info *compptr;
555
Guido Vollbeding989630f2010-01-10 00:00:00 +0000556 MCU_cols = srcinfo->output_width /
Leon Scroggins III3993b372018-07-16 10:43:45 -0400557 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
Guido Vollbeding989630f2010-01-10 00:00:00 +0000558 MCU_rows = srcinfo->output_height /
Leon Scroggins III3993b372018-07-16 10:43:45 -0400559 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000560
561 for (ci = 0; ci < dstinfo->num_components; ci++) {
562 compptr = dstinfo->comp_info + ci;
563 comp_width = MCU_cols * compptr->h_samp_factor;
564 comp_height = MCU_rows * compptr->v_samp_factor;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000565 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
566 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000567 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
DRCe5eaf372014-05-09 18:00:32 +0000568 dst_blk_y += compptr->v_samp_factor) {
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000569 dst_buffer = (*srcinfo->mem->access_virt_barray)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400570 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
571 (JDIMENSION)compptr->v_samp_factor, TRUE);
Guido Vollbeding5996a252009-06-27 00:00:00 +0000572 if (y_crop_blocks + dst_blk_y < comp_height) {
DRCe5eaf372014-05-09 18:00:32 +0000573 /* Row is within the vertically mirrorable area. */
574 src_buffer = (*srcinfo->mem->access_virt_barray)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400575 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
DRCe5eaf372014-05-09 18:00:32 +0000576 comp_height - y_crop_blocks - dst_blk_y -
Leon Scroggins III3993b372018-07-16 10:43:45 -0400577 (JDIMENSION)compptr->v_samp_factor,
578 (JDIMENSION)compptr->v_samp_factor, FALSE);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000579 } else {
DRCe5eaf372014-05-09 18:00:32 +0000580 /* Bottom-edge rows are only mirrored horizontally. */
581 src_buffer = (*srcinfo->mem->access_virt_barray)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400582 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
DRCe5eaf372014-05-09 18:00:32 +0000583 dst_blk_y + y_crop_blocks,
Leon Scroggins III3993b372018-07-16 10:43:45 -0400584 (JDIMENSION)compptr->v_samp_factor, FALSE);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000585 }
586 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
DRCe5eaf372014-05-09 18:00:32 +0000587 dst_row_ptr = dst_buffer[offset_y];
588 if (y_crop_blocks + dst_blk_y < comp_height) {
589 /* Row is within the mirrorable area. */
590 src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
Leon Scroggins III3993b372018-07-16 10:43:45 -0400591 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
592 dst_blk_x++) {
DRCe5eaf372014-05-09 18:00:32 +0000593 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. */
Leon Scroggins III3993b372018-07-16 10:43:45 -0400596 src_ptr =
597 src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
DRCe5eaf372014-05-09 18:00:32 +0000598 for (i = 0; i < DCTSIZE; i += 2) {
599 /* For even row, negate every odd column. */
600 for (j = 0; j < DCTSIZE; j += 2) {
601 *dst_ptr++ = *src_ptr++;
602 *dst_ptr++ = - *src_ptr++;
603 }
604 /* For odd row, negate every even column. */
605 for (j = 0; j < DCTSIZE; j += 2) {
606 *dst_ptr++ = - *src_ptr++;
607 *dst_ptr++ = *src_ptr++;
608 }
609 }
610 } else {
611 /* Any remaining right-edge blocks are only mirrored vertically. */
612 src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x];
613 for (i = 0; i < DCTSIZE; i += 2) {
614 for (j = 0; j < DCTSIZE; j++)
615 *dst_ptr++ = *src_ptr++;
616 for (j = 0; j < DCTSIZE; j++)
617 *dst_ptr++ = - *src_ptr++;
618 }
619 }
620 }
621 } else {
622 /* Remaining rows are just mirrored horizontally. */
623 src_row_ptr = src_buffer[offset_y];
Leon Scroggins III3993b372018-07-16 10:43:45 -0400624 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
625 dst_blk_x++) {
DRCe5eaf372014-05-09 18:00:32 +0000626 if (x_crop_blocks + dst_blk_x < comp_width) {
627 /* Process the blocks that can be mirrored. */
628 dst_ptr = dst_row_ptr[dst_blk_x];
Leon Scroggins III3993b372018-07-16 10:43:45 -0400629 src_ptr =
630 src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
DRCe5eaf372014-05-09 18:00:32 +0000631 for (i = 0; i < DCTSIZE2; i += 2) {
632 *dst_ptr++ = *src_ptr++;
633 *dst_ptr++ = - *src_ptr++;
634 }
635 } else {
636 /* Any remaining right-edge blocks are only copied. */
637 jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
Leon Scroggins III3993b372018-07-16 10:43:45 -0400638 dst_row_ptr + dst_blk_x, (JDIMENSION)1);
DRCe5eaf372014-05-09 18:00:32 +0000639 }
640 }
641 }
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000642 }
643 }
644 }
645}
646
647
648LOCAL(void)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400649do_transverse(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
650 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
651 jvirt_barray_ptr *src_coef_arrays,
652 jvirt_barray_ptr *dst_coef_arrays)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000653/* Transverse transpose is equivalent to
654 * 1. 180 degree rotation;
655 * 2. Transposition;
656 * or
657 * 1. Horizontal mirroring;
658 * 2. Transposition;
659 * 3. Horizontal mirroring.
660 * These steps are merged into a single processing routine.
661 */
662{
663 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000664 JDIMENSION x_crop_blocks, y_crop_blocks;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000665 int ci, i, j, offset_x, offset_y;
666 JBLOCKARRAY src_buffer, dst_buffer;
667 JCOEFPTR src_ptr, dst_ptr;
668 jpeg_component_info *compptr;
669
Guido Vollbeding989630f2010-01-10 00:00:00 +0000670 MCU_cols = srcinfo->output_height /
Leon Scroggins III3993b372018-07-16 10:43:45 -0400671 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
Guido Vollbeding989630f2010-01-10 00:00:00 +0000672 MCU_rows = srcinfo->output_width /
Leon Scroggins III3993b372018-07-16 10:43:45 -0400673 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000674
675 for (ci = 0; ci < dstinfo->num_components; ci++) {
676 compptr = dstinfo->comp_info + ci;
677 comp_width = MCU_cols * compptr->h_samp_factor;
678 comp_height = MCU_rows * compptr->v_samp_factor;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000679 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
680 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000681 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
DRCe5eaf372014-05-09 18:00:32 +0000682 dst_blk_y += compptr->v_samp_factor) {
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000683 dst_buffer = (*srcinfo->mem->access_virt_barray)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400684 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
685 (JDIMENSION)compptr->v_samp_factor, TRUE);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000686 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
DRCe5eaf372014-05-09 18:00:32 +0000687 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
688 dst_blk_x += compptr->h_samp_factor) {
689 if (x_crop_blocks + dst_blk_x < comp_width) {
690 /* Block is within the mirrorable area. */
691 src_buffer = (*srcinfo->mem->access_virt_barray)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400692 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
DRCe5eaf372014-05-09 18:00:32 +0000693 comp_width - x_crop_blocks - dst_blk_x -
Leon Scroggins III3993b372018-07-16 10:43:45 -0400694 (JDIMENSION)compptr->h_samp_factor,
695 (JDIMENSION)compptr->h_samp_factor, FALSE);
DRCe5eaf372014-05-09 18:00:32 +0000696 } else {
697 src_buffer = (*srcinfo->mem->access_virt_barray)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400698 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
DRCe5eaf372014-05-09 18:00:32 +0000699 dst_blk_x + x_crop_blocks,
Leon Scroggins III3993b372018-07-16 10:43:45 -0400700 (JDIMENSION)compptr->h_samp_factor, FALSE);
DRCe5eaf372014-05-09 18:00:32 +0000701 }
702 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
703 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
704 if (y_crop_blocks + dst_blk_y < comp_height) {
705 if (x_crop_blocks + dst_blk_x < comp_width) {
706 /* Block is within the mirrorable area. */
707 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
708 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
709 for (i = 0; i < DCTSIZE; i++) {
710 for (j = 0; j < DCTSIZE; j++) {
Leon Scroggins III3993b372018-07-16 10:43:45 -0400711 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
DRCe5eaf372014-05-09 18:00:32 +0000712 j++;
Leon Scroggins III3993b372018-07-16 10:43:45 -0400713 dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
DRCe5eaf372014-05-09 18:00:32 +0000714 }
715 i++;
716 for (j = 0; j < DCTSIZE; j++) {
Leon Scroggins III3993b372018-07-16 10:43:45 -0400717 dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
DRCe5eaf372014-05-09 18:00:32 +0000718 j++;
Leon Scroggins III3993b372018-07-16 10:43:45 -0400719 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
DRCe5eaf372014-05-09 18:00:32 +0000720 }
721 }
722 } else {
723 /* Right-edge blocks are mirrored in y only */
724 src_ptr = src_buffer[offset_x]
725 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
726 for (i = 0; i < DCTSIZE; i++) {
727 for (j = 0; j < DCTSIZE; j++) {
Leon Scroggins III3993b372018-07-16 10:43:45 -0400728 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
DRCe5eaf372014-05-09 18:00:32 +0000729 j++;
Leon Scroggins III3993b372018-07-16 10:43:45 -0400730 dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
DRCe5eaf372014-05-09 18:00:32 +0000731 }
732 }
733 }
734 } else {
735 if (x_crop_blocks + dst_blk_x < comp_width) {
736 /* Bottom-edge blocks are mirrored in x only */
737 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
738 [dst_blk_y + offset_y + y_crop_blocks];
739 for (i = 0; i < DCTSIZE; i++) {
740 for (j = 0; j < DCTSIZE; j++)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400741 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
DRCe5eaf372014-05-09 18:00:32 +0000742 i++;
743 for (j = 0; j < DCTSIZE; j++)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400744 dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
DRCe5eaf372014-05-09 18:00:32 +0000745 }
746 } else {
747 /* At lower right corner, just transpose, no mirroring */
748 src_ptr = src_buffer[offset_x]
749 [dst_blk_y + offset_y + y_crop_blocks];
750 for (i = 0; i < DCTSIZE; i++)
751 for (j = 0; j < DCTSIZE; j++)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400752 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
DRCe5eaf372014-05-09 18:00:32 +0000753 }
754 }
755 }
756 }
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000757 }
758 }
759 }
760}
761
762
Guido Vollbeding5996a252009-06-27 00:00:00 +0000763/* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec.
764 * Returns TRUE if valid integer found, FALSE if not.
765 * *strptr is advanced over the digit string, and *result is set to its value.
766 */
767
768LOCAL(boolean)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400769jt_read_integer(const char **strptr, JDIMENSION *result)
Guido Vollbeding5996a252009-06-27 00:00:00 +0000770{
Alex Naidis6eb7d372016-10-16 23:10:08 +0200771 const char *ptr = *strptr;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000772 JDIMENSION val = 0;
773
774 for (; isdigit(*ptr); ptr++) {
Leon Scroggins III3993b372018-07-16 10:43:45 -0400775 val = val * 10 + (JDIMENSION)(*ptr - '0');
Guido Vollbeding5996a252009-06-27 00:00:00 +0000776 }
777 *result = val;
778 if (ptr == *strptr)
DRCe5eaf372014-05-09 18:00:32 +0000779 return FALSE; /* oops, no digits */
Guido Vollbeding5996a252009-06-27 00:00:00 +0000780 *strptr = ptr;
781 return TRUE;
782}
783
784
785/* Parse a crop specification (written in X11 geometry style).
786 * The routine returns TRUE if the spec string is valid, FALSE if not.
787 *
788 * The crop spec string should have the format
DRCe5eaf372014-05-09 18:00:32 +0000789 * <width>[f]x<height>[f]{+-}<xoffset>{+-}<yoffset>
Guido Vollbeding5996a252009-06-27 00:00:00 +0000790 * where width, height, xoffset, and yoffset are unsigned integers.
791 * Each of the elements can be omitted to indicate a default value.
792 * (A weakness of this style is that it is not possible to omit xoffset
793 * while specifying yoffset, since they look alike.)
794 *
795 * This code is loosely based on XParseGeometry from the X11 distribution.
796 */
797
798GLOBAL(boolean)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400799jtransform_parse_crop_spec(jpeg_transform_info *info, const char *spec)
Guido Vollbeding5996a252009-06-27 00:00:00 +0000800{
801 info->crop = FALSE;
802 info->crop_width_set = JCROP_UNSET;
803 info->crop_height_set = JCROP_UNSET;
804 info->crop_xoffset_set = JCROP_UNSET;
805 info->crop_yoffset_set = JCROP_UNSET;
806
807 if (isdigit(*spec)) {
808 /* fetch width */
Leon Scroggins III3993b372018-07-16 10:43:45 -0400809 if (!jt_read_integer(&spec, &info->crop_width))
Guido Vollbeding5996a252009-06-27 00:00:00 +0000810 return FALSE;
Guido Vollbeding5829cb22012-01-15 00:00:00 +0000811 if (*spec == 'f' || *spec == 'F') {
812 spec++;
813 info->crop_width_set = JCROP_FORCE;
814 } else
815 info->crop_width_set = JCROP_POS;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000816 }
Guido Vollbeding5829cb22012-01-15 00:00:00 +0000817 if (*spec == 'x' || *spec == 'X') {
Guido Vollbeding5996a252009-06-27 00:00:00 +0000818 /* fetch height */
819 spec++;
Leon Scroggins III3993b372018-07-16 10:43:45 -0400820 if (!jt_read_integer(&spec, &info->crop_height))
Guido Vollbeding5996a252009-06-27 00:00:00 +0000821 return FALSE;
Guido Vollbeding5829cb22012-01-15 00:00:00 +0000822 if (*spec == 'f' || *spec == 'F') {
823 spec++;
824 info->crop_height_set = JCROP_FORCE;
825 } else
826 info->crop_height_set = JCROP_POS;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000827 }
828 if (*spec == '+' || *spec == '-') {
829 /* fetch xoffset */
830 info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
831 spec++;
Leon Scroggins III3993b372018-07-16 10:43:45 -0400832 if (!jt_read_integer(&spec, &info->crop_xoffset))
Guido Vollbeding5996a252009-06-27 00:00:00 +0000833 return FALSE;
834 }
835 if (*spec == '+' || *spec == '-') {
836 /* fetch yoffset */
837 info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
838 spec++;
Leon Scroggins III3993b372018-07-16 10:43:45 -0400839 if (!jt_read_integer(&spec, &info->crop_yoffset))
Guido Vollbeding5996a252009-06-27 00:00:00 +0000840 return FALSE;
841 }
842 /* We had better have gotten to the end of the string. */
843 if (*spec != '\0')
844 return FALSE;
845 info->crop = TRUE;
846 return TRUE;
847}
848
849
850/* Trim off any partial iMCUs on the indicated destination edge */
851
852LOCAL(void)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400853trim_right_edge(jpeg_transform_info *info, JDIMENSION full_width)
Guido Vollbeding5996a252009-06-27 00:00:00 +0000854{
855 JDIMENSION MCU_cols;
856
Guido Vollbeding989630f2010-01-10 00:00:00 +0000857 MCU_cols = info->output_width / info->iMCU_sample_width;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000858 if (MCU_cols > 0 && info->x_crop_offset + MCU_cols ==
Guido Vollbeding989630f2010-01-10 00:00:00 +0000859 full_width / info->iMCU_sample_width)
860 info->output_width = MCU_cols * info->iMCU_sample_width;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000861}
862
863LOCAL(void)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400864trim_bottom_edge(jpeg_transform_info *info, JDIMENSION full_height)
Guido Vollbeding5996a252009-06-27 00:00:00 +0000865{
866 JDIMENSION MCU_rows;
867
Guido Vollbeding989630f2010-01-10 00:00:00 +0000868 MCU_rows = info->output_height / info->iMCU_sample_height;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000869 if (MCU_rows > 0 && info->y_crop_offset + MCU_rows ==
Guido Vollbeding989630f2010-01-10 00:00:00 +0000870 full_height / info->iMCU_sample_height)
871 info->output_height = MCU_rows * info->iMCU_sample_height;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000872}
873
874
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000875/* Request any required workspace.
876 *
Guido Vollbeding5996a252009-06-27 00:00:00 +0000877 * This routine figures out the size that the output image will be
878 * (which implies that all the transform parameters must be set before
879 * it is called).
880 *
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000881 * We allocate the workspace virtual arrays from the source decompression
882 * object, so that all the arrays (both the original data and the workspace)
883 * will be taken into account while making memory management decisions.
884 * Hence, this routine must be called after jpeg_read_header (which reads
885 * the image dimensions) and before jpeg_read_coefficients (which realizes
886 * the source's virtual arrays).
Guido Vollbeding989630f2010-01-10 00:00:00 +0000887 *
888 * This function returns FALSE right away if -perfect is given
889 * and transformation is not perfect. Otherwise returns TRUE.
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000890 */
891
Guido Vollbeding989630f2010-01-10 00:00:00 +0000892GLOBAL(boolean)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400893jtransform_request_workspace(j_decompress_ptr srcinfo,
894 jpeg_transform_info *info)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000895{
Guido Vollbeding989630f2010-01-10 00:00:00 +0000896 jvirt_barray_ptr *coef_arrays;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000897 boolean need_workspace, transpose_it;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000898 jpeg_component_info *compptr;
Guido Vollbeding989630f2010-01-10 00:00:00 +0000899 JDIMENSION xoffset, yoffset;
900 JDIMENSION width_in_iMCUs, height_in_iMCUs;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000901 JDIMENSION width_in_blocks, height_in_blocks;
902 int ci, h_samp_factor, v_samp_factor;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000903
Guido Vollbeding5996a252009-06-27 00:00:00 +0000904 /* Determine number of components in output image */
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000905 if (info->force_grayscale &&
906 srcinfo->jpeg_color_space == JCS_YCbCr &&
Guido Vollbeding989630f2010-01-10 00:00:00 +0000907 srcinfo->num_components == 3)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000908 /* We'll only process the first component */
909 info->num_components = 1;
Guido Vollbeding989630f2010-01-10 00:00:00 +0000910 else
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000911 /* Process all the components */
912 info->num_components = srcinfo->num_components;
Guido Vollbeding989630f2010-01-10 00:00:00 +0000913
914 /* Compute output image dimensions and related values. */
DRCc04bd3c2010-10-10 02:15:56 +0000915#if JPEG_LIB_VERSION >= 80
Guido Vollbeding989630f2010-01-10 00:00:00 +0000916 jpeg_core_output_dimensions(srcinfo);
DRCc04bd3c2010-10-10 02:15:56 +0000917#else
918 srcinfo->output_width = srcinfo->image_width;
919 srcinfo->output_height = srcinfo->image_height;
920#endif
Guido Vollbeding989630f2010-01-10 00:00:00 +0000921
922 /* Return right away if -perfect is given and transformation is not perfect.
923 */
924 if (info->perfect) {
925 if (info->num_components == 1) {
926 if (!jtransform_perfect_transform(srcinfo->output_width,
DRCe5eaf372014-05-09 18:00:32 +0000927 srcinfo->output_height,
928 srcinfo->_min_DCT_h_scaled_size,
929 srcinfo->_min_DCT_v_scaled_size,
930 info->transform))
931 return FALSE;
Guido Vollbeding989630f2010-01-10 00:00:00 +0000932 } else {
933 if (!jtransform_perfect_transform(srcinfo->output_width,
DRCe5eaf372014-05-09 18:00:32 +0000934 srcinfo->output_height,
935 srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size,
936 srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size,
937 info->transform))
938 return FALSE;
Guido Vollbeding989630f2010-01-10 00:00:00 +0000939 }
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000940 }
941
Guido Vollbeding5996a252009-06-27 00:00:00 +0000942 /* If there is only one output component, force the iMCU size to be 1;
943 * else use the source iMCU size. (This allows us to do the right thing
944 * when reducing color to grayscale, and also provides a handy way of
945 * cleaning up "funny" grayscale images whose sampling factors are not 1x1.)
946 */
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000947 switch (info->transform) {
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000948 case JXFORM_TRANSPOSE:
949 case JXFORM_TRANSVERSE:
950 case JXFORM_ROT_90:
951 case JXFORM_ROT_270:
Guido Vollbeding989630f2010-01-10 00:00:00 +0000952 info->output_width = srcinfo->output_height;
953 info->output_height = srcinfo->output_width;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000954 if (info->num_components == 1) {
DRCc04bd3c2010-10-10 02:15:56 +0000955 info->iMCU_sample_width = srcinfo->_min_DCT_v_scaled_size;
956 info->iMCU_sample_height = srcinfo->_min_DCT_h_scaled_size;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000957 } else {
Guido Vollbeding989630f2010-01-10 00:00:00 +0000958 info->iMCU_sample_width =
DRCe5eaf372014-05-09 18:00:32 +0000959 srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size;
Guido Vollbeding989630f2010-01-10 00:00:00 +0000960 info->iMCU_sample_height =
DRCe5eaf372014-05-09 18:00:32 +0000961 srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000962 }
963 break;
964 default:
Guido Vollbeding989630f2010-01-10 00:00:00 +0000965 info->output_width = srcinfo->output_width;
966 info->output_height = srcinfo->output_height;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000967 if (info->num_components == 1) {
DRCc04bd3c2010-10-10 02:15:56 +0000968 info->iMCU_sample_width = srcinfo->_min_DCT_h_scaled_size;
969 info->iMCU_sample_height = srcinfo->_min_DCT_v_scaled_size;
Guido Vollbeding5996a252009-06-27 00:00:00 +0000970 } else {
Guido Vollbeding989630f2010-01-10 00:00:00 +0000971 info->iMCU_sample_width =
DRCe5eaf372014-05-09 18:00:32 +0000972 srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size;
Guido Vollbeding989630f2010-01-10 00:00:00 +0000973 info->iMCU_sample_height =
DRCe5eaf372014-05-09 18:00:32 +0000974 srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +0000975 }
976 break;
977 }
Guido Vollbeding5996a252009-06-27 00:00:00 +0000978
979 /* If cropping has been requested, compute the crop area's position and
980 * dimensions, ensuring that its upper left corner falls at an iMCU boundary.
981 */
982 if (info->crop) {
983 /* Insert default values for unset crop parameters */
984 if (info->crop_xoffset_set == JCROP_UNSET)
DRCe5eaf372014-05-09 18:00:32 +0000985 info->crop_xoffset = 0; /* default to +0 */
Guido Vollbeding5996a252009-06-27 00:00:00 +0000986 if (info->crop_yoffset_set == JCROP_UNSET)
DRCe5eaf372014-05-09 18:00:32 +0000987 info->crop_yoffset = 0; /* default to +0 */
Guido Vollbeding5996a252009-06-27 00:00:00 +0000988 if (info->crop_xoffset >= info->output_width ||
DRCe5eaf372014-05-09 18:00:32 +0000989 info->crop_yoffset >= info->output_height)
Guido Vollbeding5996a252009-06-27 00:00:00 +0000990 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
991 if (info->crop_width_set == JCROP_UNSET)
992 info->crop_width = info->output_width - info->crop_xoffset;
993 if (info->crop_height_set == JCROP_UNSET)
994 info->crop_height = info->output_height - info->crop_yoffset;
995 /* Ensure parameters are valid */
996 if (info->crop_width <= 0 || info->crop_width > info->output_width ||
DRCe5eaf372014-05-09 18:00:32 +0000997 info->crop_height <= 0 || info->crop_height > info->output_height ||
998 info->crop_xoffset > info->output_width - info->crop_width ||
999 info->crop_yoffset > info->output_height - info->crop_height)
Guido Vollbeding5996a252009-06-27 00:00:00 +00001000 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1001 /* Convert negative crop offsets into regular offsets */
1002 if (info->crop_xoffset_set == JCROP_NEG)
1003 xoffset = info->output_width - info->crop_width - info->crop_xoffset;
1004 else
1005 xoffset = info->crop_xoffset;
1006 if (info->crop_yoffset_set == JCROP_NEG)
1007 yoffset = info->output_height - info->crop_height - info->crop_yoffset;
1008 else
1009 yoffset = info->crop_yoffset;
1010 /* Now adjust so that upper left corner falls at an iMCU boundary */
Guido Vollbeding5829cb22012-01-15 00:00:00 +00001011 if (info->crop_width_set == JCROP_FORCE)
1012 info->output_width = info->crop_width;
1013 else
1014 info->output_width =
1015 info->crop_width + (xoffset % info->iMCU_sample_width);
1016 if (info->crop_height_set == JCROP_FORCE)
1017 info->output_height = info->crop_height;
1018 else
1019 info->output_height =
1020 info->crop_height + (yoffset % info->iMCU_sample_height);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001021 /* Save x/y offsets measured in iMCUs */
Guido Vollbeding989630f2010-01-10 00:00:00 +00001022 info->x_crop_offset = xoffset / info->iMCU_sample_width;
1023 info->y_crop_offset = yoffset / info->iMCU_sample_height;
Guido Vollbeding5996a252009-06-27 00:00:00 +00001024 } else {
1025 info->x_crop_offset = 0;
1026 info->y_crop_offset = 0;
1027 }
1028
1029 /* Figure out whether we need workspace arrays,
1030 * and if so whether they are transposed relative to the source.
1031 */
1032 need_workspace = FALSE;
1033 transpose_it = FALSE;
1034 switch (info->transform) {
1035 case JXFORM_NONE:
1036 if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
1037 need_workspace = TRUE;
1038 /* No workspace needed if neither cropping nor transforming */
1039 break;
1040 case JXFORM_FLIP_H:
1041 if (info->trim)
Guido Vollbeding989630f2010-01-10 00:00:00 +00001042 trim_right_edge(info, srcinfo->output_width);
DRCba5ea512011-03-04 03:20:34 +00001043 if (info->y_crop_offset != 0 || info->slow_hflip)
Guido Vollbeding5996a252009-06-27 00:00:00 +00001044 need_workspace = TRUE;
1045 /* do_flip_h_no_crop doesn't need a workspace array */
1046 break;
1047 case JXFORM_FLIP_V:
1048 if (info->trim)
Guido Vollbeding989630f2010-01-10 00:00:00 +00001049 trim_bottom_edge(info, srcinfo->output_height);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001050 /* Need workspace arrays having same dimensions as source image. */
1051 need_workspace = TRUE;
1052 break;
1053 case JXFORM_TRANSPOSE:
1054 /* transpose does NOT have to trim anything */
1055 /* Need workspace arrays having transposed dimensions. */
1056 need_workspace = TRUE;
1057 transpose_it = TRUE;
1058 break;
1059 case JXFORM_TRANSVERSE:
1060 if (info->trim) {
Guido Vollbeding989630f2010-01-10 00:00:00 +00001061 trim_right_edge(info, srcinfo->output_height);
1062 trim_bottom_edge(info, srcinfo->output_width);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001063 }
1064 /* Need workspace arrays having transposed dimensions. */
1065 need_workspace = TRUE;
1066 transpose_it = TRUE;
1067 break;
1068 case JXFORM_ROT_90:
1069 if (info->trim)
Guido Vollbeding989630f2010-01-10 00:00:00 +00001070 trim_right_edge(info, srcinfo->output_height);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001071 /* Need workspace arrays having transposed dimensions. */
1072 need_workspace = TRUE;
1073 transpose_it = TRUE;
1074 break;
1075 case JXFORM_ROT_180:
1076 if (info->trim) {
Guido Vollbeding989630f2010-01-10 00:00:00 +00001077 trim_right_edge(info, srcinfo->output_width);
1078 trim_bottom_edge(info, srcinfo->output_height);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001079 }
1080 /* Need workspace arrays having same dimensions as source image. */
1081 need_workspace = TRUE;
1082 break;
1083 case JXFORM_ROT_270:
1084 if (info->trim)
Guido Vollbeding989630f2010-01-10 00:00:00 +00001085 trim_bottom_edge(info, srcinfo->output_width);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001086 /* Need workspace arrays having transposed dimensions. */
1087 need_workspace = TRUE;
1088 transpose_it = TRUE;
1089 break;
1090 }
1091
1092 /* Allocate workspace if needed.
1093 * Note that we allocate arrays padded out to the next iMCU boundary,
1094 * so that transform routines need not worry about missing edge blocks.
1095 */
1096 if (need_workspace) {
1097 coef_arrays = (jvirt_barray_ptr *)
Leon Scroggins III3993b372018-07-16 10:43:45 -04001098 (*srcinfo->mem->alloc_small) ((j_common_ptr)srcinfo, JPOOL_IMAGE,
DRC5de454b2014-05-18 19:04:03 +00001099 sizeof(jvirt_barray_ptr) * info->num_components);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001100 width_in_iMCUs = (JDIMENSION)
Leon Scroggins III3993b372018-07-16 10:43:45 -04001101 jdiv_round_up((long)info->output_width, (long)info->iMCU_sample_width);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001102 height_in_iMCUs = (JDIMENSION)
Leon Scroggins III3993b372018-07-16 10:43:45 -04001103 jdiv_round_up((long)info->output_height, (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)
Leon Scroggins III3993b372018-07-16 10:43:45 -04001119 ((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)
Leon Scroggins III3993b372018-07-16 10:43:45 -04001133transpose_critical_parameters(j_compress_ptr dstinfo)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001134{
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++) {
Leon Scroggins III3993b372018-07-16 10:43:45 -04001165 qtemp = qtblptr->quantval[i * DCTSIZE + j];
1166 qtblptr->quantval[i * DCTSIZE + j] =
1167 qtblptr->quantval[j * DCTSIZE + i];
1168 qtblptr->quantval[j * DCTSIZE + i] = qtemp;
DRCe5eaf372014-05-09 18:00:32 +00001169 }
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001170 }
1171 }
1172 }
1173}
1174
1175
Guido Vollbeding5996a252009-06-27 00:00:00 +00001176/* Adjust Exif image parameters.
1177 *
1178 * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible.
1179 */
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001180
1181LOCAL(void)
Leon Scroggins III3993b372018-07-16 10:43:45 -04001182adjust_exif_parameters(JOCTET *data, unsigned int length, JDIMENSION new_width,
1183 JDIMENSION new_height)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001184{
Guido Vollbeding5996a252009-06-27 00:00:00 +00001185 boolean is_motorola; /* Flag for byte order */
1186 unsigned int number_of_tags, tagnum;
1187 unsigned int firstoffset, offset;
1188 JDIMENSION new_value;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001189
Guido Vollbeding5996a252009-06-27 00:00:00 +00001190 if (length < 12) return; /* Length of an IFD entry */
1191
1192 /* Discover byte order */
1193 if (GETJOCTET(data[0]) == 0x49 && GETJOCTET(data[1]) == 0x49)
1194 is_motorola = FALSE;
1195 else if (GETJOCTET(data[0]) == 0x4D && GETJOCTET(data[1]) == 0x4D)
1196 is_motorola = TRUE;
1197 else
1198 return;
1199
1200 /* Check Tag Mark */
1201 if (is_motorola) {
1202 if (GETJOCTET(data[2]) != 0) return;
1203 if (GETJOCTET(data[3]) != 0x2A) return;
1204 } else {
1205 if (GETJOCTET(data[3]) != 0) return;
1206 if (GETJOCTET(data[2]) != 0x2A) return;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001207 }
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001208
Guido Vollbeding5996a252009-06-27 00:00:00 +00001209 /* Get first IFD offset (offset to IFD0) */
1210 if (is_motorola) {
1211 if (GETJOCTET(data[4]) != 0) return;
1212 if (GETJOCTET(data[5]) != 0) return;
1213 firstoffset = GETJOCTET(data[6]);
1214 firstoffset <<= 8;
1215 firstoffset += GETJOCTET(data[7]);
1216 } else {
1217 if (GETJOCTET(data[7]) != 0) return;
1218 if (GETJOCTET(data[6]) != 0) return;
1219 firstoffset = GETJOCTET(data[5]);
1220 firstoffset <<= 8;
1221 firstoffset += GETJOCTET(data[4]);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001222 }
Guido Vollbeding5996a252009-06-27 00:00:00 +00001223 if (firstoffset > length - 2) return; /* check end of data segment */
1224
1225 /* Get the number of directory entries contained in this IFD */
1226 if (is_motorola) {
1227 number_of_tags = GETJOCTET(data[firstoffset]);
1228 number_of_tags <<= 8;
Leon Scroggins III3993b372018-07-16 10:43:45 -04001229 number_of_tags += GETJOCTET(data[firstoffset + 1]);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001230 } else {
Leon Scroggins III3993b372018-07-16 10:43:45 -04001231 number_of_tags = GETJOCTET(data[firstoffset + 1]);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001232 number_of_tags <<= 8;
1233 number_of_tags += GETJOCTET(data[firstoffset]);
1234 }
1235 if (number_of_tags == 0) return;
1236 firstoffset += 2;
1237
1238 /* Search for ExifSubIFD offset Tag in IFD0 */
1239 for (;;) {
1240 if (firstoffset > length - 12) return; /* check end of data segment */
1241 /* Get Tag number */
1242 if (is_motorola) {
1243 tagnum = GETJOCTET(data[firstoffset]);
1244 tagnum <<= 8;
Leon Scroggins III3993b372018-07-16 10:43:45 -04001245 tagnum += GETJOCTET(data[firstoffset + 1]);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001246 } else {
Leon Scroggins III3993b372018-07-16 10:43:45 -04001247 tagnum = GETJOCTET(data[firstoffset + 1]);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001248 tagnum <<= 8;
1249 tagnum += GETJOCTET(data[firstoffset]);
1250 }
1251 if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */
1252 if (--number_of_tags == 0) return;
1253 firstoffset += 12;
1254 }
1255
1256 /* Get the ExifSubIFD offset */
1257 if (is_motorola) {
Leon Scroggins III3993b372018-07-16 10:43:45 -04001258 if (GETJOCTET(data[firstoffset + 8]) != 0) return;
1259 if (GETJOCTET(data[firstoffset + 9]) != 0) return;
1260 offset = GETJOCTET(data[firstoffset + 10]);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001261 offset <<= 8;
Leon Scroggins III3993b372018-07-16 10:43:45 -04001262 offset += GETJOCTET(data[firstoffset + 11]);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001263 } else {
Leon Scroggins III3993b372018-07-16 10:43:45 -04001264 if (GETJOCTET(data[firstoffset + 11]) != 0) return;
1265 if (GETJOCTET(data[firstoffset + 10]) != 0) return;
1266 offset = GETJOCTET(data[firstoffset + 9]);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001267 offset <<= 8;
Leon Scroggins III3993b372018-07-16 10:43:45 -04001268 offset += GETJOCTET(data[firstoffset + 8]);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001269 }
1270 if (offset > length - 2) return; /* check end of data segment */
1271
1272 /* Get the number of directory entries contained in this SubIFD */
1273 if (is_motorola) {
1274 number_of_tags = GETJOCTET(data[offset]);
1275 number_of_tags <<= 8;
Leon Scroggins III3993b372018-07-16 10:43:45 -04001276 number_of_tags += GETJOCTET(data[offset + 1]);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001277 } else {
Leon Scroggins III3993b372018-07-16 10:43:45 -04001278 number_of_tags = GETJOCTET(data[offset + 1]);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001279 number_of_tags <<= 8;
1280 number_of_tags += GETJOCTET(data[offset]);
1281 }
1282 if (number_of_tags < 2) return;
1283 offset += 2;
1284
1285 /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */
1286 do {
1287 if (offset > length - 12) return; /* check end of data segment */
1288 /* Get Tag number */
1289 if (is_motorola) {
1290 tagnum = GETJOCTET(data[offset]);
1291 tagnum <<= 8;
Leon Scroggins III3993b372018-07-16 10:43:45 -04001292 tagnum += GETJOCTET(data[offset + 1]);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001293 } else {
Leon Scroggins III3993b372018-07-16 10:43:45 -04001294 tagnum = GETJOCTET(data[offset + 1]);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001295 tagnum <<= 8;
1296 tagnum += GETJOCTET(data[offset]);
1297 }
1298 if (tagnum == 0xA002 || tagnum == 0xA003) {
1299 if (tagnum == 0xA002)
DRCe5eaf372014-05-09 18:00:32 +00001300 new_value = new_width; /* ExifImageWidth Tag */
Guido Vollbeding5996a252009-06-27 00:00:00 +00001301 else
DRCe5eaf372014-05-09 18:00:32 +00001302 new_value = new_height; /* ExifImageHeight Tag */
Guido Vollbeding5996a252009-06-27 00:00:00 +00001303 if (is_motorola) {
Leon Scroggins III3993b372018-07-16 10:43:45 -04001304 data[offset + 2] = 0; /* Format = unsigned long (4 octets) */
1305 data[offset + 3] = 4;
1306 data[offset + 4] = 0; /* Number Of Components = 1 */
1307 data[offset + 5] = 0;
1308 data[offset + 6] = 0;
1309 data[offset + 7] = 1;
1310 data[offset + 8] = 0;
1311 data[offset + 9] = 0;
1312 data[offset + 10] = (JOCTET)((new_value >> 8) & 0xFF);
1313 data[offset + 11] = (JOCTET)(new_value & 0xFF);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001314 } else {
Leon Scroggins III3993b372018-07-16 10:43:45 -04001315 data[offset + 2] = 4; /* Format = unsigned long (4 octets) */
1316 data[offset + 3] = 0;
1317 data[offset + 4] = 1; /* Number Of Components = 1 */
1318 data[offset + 5] = 0;
1319 data[offset + 6] = 0;
1320 data[offset + 7] = 0;
1321 data[offset + 8] = (JOCTET)(new_value & 0xFF);
1322 data[offset + 9] = (JOCTET)((new_value >> 8) & 0xFF);
1323 data[offset + 10] = 0;
1324 data[offset + 11] = 0;
Guido Vollbeding5996a252009-06-27 00:00:00 +00001325 }
1326 }
1327 offset += 12;
1328 } while (--number_of_tags);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001329}
1330
1331
1332/* Adjust output image parameters as needed.
1333 *
1334 * This must be called after jpeg_copy_critical_parameters()
1335 * and before jpeg_write_coefficients().
1336 *
1337 * The return value is the set of virtual coefficient arrays to be written
1338 * (either the ones allocated by jtransform_request_workspace, or the
1339 * original source data arrays). The caller will need to pass this value
1340 * to jpeg_write_coefficients().
1341 */
1342
1343GLOBAL(jvirt_barray_ptr *)
Leon Scroggins III3993b372018-07-16 10:43:45 -04001344jtransform_adjust_parameters(j_decompress_ptr srcinfo, 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 &&
Leon Scroggins III3993b372018-07-16 10:43:45 -04001412 srcinfo->marker_list->marker == JPEG_APP0 + 1 &&
Guido Vollbeding5996a252009-06-27 00:00:00 +00001413 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,
Leon Scroggins III3993b372018-07-16 10:43:45 -04001428 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,
Leon Scroggins III3993b372018-07-16 10:43:45 -04001435 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)
Leon Scroggins III3993b372018-07-16 10:43:45 -04001457jtransform_execute_transform(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
1458 jvirt_barray_ptr *src_coef_arrays,
1459 jpeg_transform_info *info)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001460{
1461 jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays;
1462
Guido Vollbeding5996a252009-06-27 00:00:00 +00001463 /* Note: conditions tested here should match those in switch statement
1464 * in jtransform_request_workspace()
1465 */
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001466 switch (info->transform) {
1467 case JXFORM_NONE:
Guido Vollbeding5996a252009-06-27 00:00:00 +00001468 if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
1469 do_crop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
DRCe5eaf372014-05-09 18:00:32 +00001470 src_coef_arrays, dst_coef_arrays);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001471 break;
1472 case JXFORM_FLIP_H:
DRCba5ea512011-03-04 03:20:34 +00001473 if (info->y_crop_offset != 0 || info->slow_hflip)
Guido Vollbeding5996a252009-06-27 00:00:00 +00001474 do_flip_h(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
DRCe5eaf372014-05-09 18:00:32 +00001475 src_coef_arrays, dst_coef_arrays);
Guido Vollbeding5996a252009-06-27 00:00:00 +00001476 else
1477 do_flip_h_no_crop(srcinfo, dstinfo, info->x_crop_offset,
DRCe5eaf372014-05-09 18:00:32 +00001478 src_coef_arrays);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001479 break;
1480 case JXFORM_FLIP_V:
Guido Vollbeding5996a252009-06-27 00:00:00 +00001481 do_flip_v(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
DRCe5eaf372014-05-09 18:00:32 +00001482 src_coef_arrays, dst_coef_arrays);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001483 break;
1484 case JXFORM_TRANSPOSE:
Guido Vollbeding5996a252009-06-27 00:00:00 +00001485 do_transpose(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
DRCe5eaf372014-05-09 18:00:32 +00001486 src_coef_arrays, dst_coef_arrays);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001487 break;
1488 case JXFORM_TRANSVERSE:
Guido Vollbeding5996a252009-06-27 00:00:00 +00001489 do_transverse(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
DRCe5eaf372014-05-09 18:00:32 +00001490 src_coef_arrays, dst_coef_arrays);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001491 break;
1492 case JXFORM_ROT_90:
Guido Vollbeding5996a252009-06-27 00:00:00 +00001493 do_rot_90(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
DRCe5eaf372014-05-09 18:00:32 +00001494 src_coef_arrays, dst_coef_arrays);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001495 break;
1496 case JXFORM_ROT_180:
Guido Vollbeding5996a252009-06-27 00:00:00 +00001497 do_rot_180(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
DRCe5eaf372014-05-09 18:00:32 +00001498 src_coef_arrays, dst_coef_arrays);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001499 break;
1500 case JXFORM_ROT_270:
Guido Vollbeding5996a252009-06-27 00:00:00 +00001501 do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
DRCe5eaf372014-05-09 18:00:32 +00001502 src_coef_arrays, dst_coef_arrays);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001503 break;
1504 }
1505}
1506
Guido Vollbeding5996a252009-06-27 00:00:00 +00001507/* jtransform_perfect_transform
1508 *
1509 * Determine whether lossless transformation is perfectly
1510 * possible for a specified image and transformation.
1511 *
1512 * Inputs:
1513 * image_width, image_height: source image dimensions.
1514 * MCU_width, MCU_height: pixel dimensions of MCU.
1515 * transform: transformation identifier.
1516 * Parameter sources from initialized jpeg_struct
1517 * (after reading source header):
1518 * image_width = cinfo.image_width
1519 * image_height = cinfo.image_height
Guido Vollbeding989630f2010-01-10 00:00:00 +00001520 * MCU_width = cinfo.max_h_samp_factor * cinfo.block_size
1521 * MCU_height = cinfo.max_v_samp_factor * cinfo.block_size
Guido Vollbeding5996a252009-06-27 00:00:00 +00001522 * Result:
1523 * TRUE = perfect transformation possible
1524 * FALSE = perfect transformation not possible
1525 * (may use custom action then)
1526 */
1527
1528GLOBAL(boolean)
1529jtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height,
DRCe5eaf372014-05-09 18:00:32 +00001530 int MCU_width, int MCU_height,
1531 JXFORM_CODE transform)
Guido Vollbeding5996a252009-06-27 00:00:00 +00001532{
1533 boolean result = TRUE; /* initialize TRUE */
1534
1535 switch (transform) {
1536 case JXFORM_FLIP_H:
1537 case JXFORM_ROT_270:
Leon Scroggins III3993b372018-07-16 10:43:45 -04001538 if (image_width % (JDIMENSION)MCU_width)
Guido Vollbeding5996a252009-06-27 00:00:00 +00001539 result = FALSE;
1540 break;
1541 case JXFORM_FLIP_V:
1542 case JXFORM_ROT_90:
Leon Scroggins III3993b372018-07-16 10:43:45 -04001543 if (image_height % (JDIMENSION)MCU_height)
Guido Vollbeding5996a252009-06-27 00:00:00 +00001544 result = FALSE;
1545 break;
1546 case JXFORM_TRANSVERSE:
1547 case JXFORM_ROT_180:
Leon Scroggins III3993b372018-07-16 10:43:45 -04001548 if (image_width % (JDIMENSION)MCU_width)
Guido Vollbeding5996a252009-06-27 00:00:00 +00001549 result = FALSE;
Leon Scroggins III3993b372018-07-16 10:43:45 -04001550 if (image_height % (JDIMENSION)MCU_height)
Guido Vollbeding5996a252009-06-27 00:00:00 +00001551 result = FALSE;
1552 break;
1553 default:
1554 break;
1555 }
1556
1557 return result;
1558}
1559
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001560#endif /* TRANSFORMS_SUPPORTED */
1561
1562
1563/* Setup decompression object to save desired markers in memory.
1564 * This must be called before jpeg_read_header() to have the desired effect.
1565 */
1566
1567GLOBAL(void)
Leon Scroggins III3993b372018-07-16 10:43:45 -04001568jcopy_markers_setup(j_decompress_ptr srcinfo, JCOPY_OPTION option)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001569{
1570#ifdef SAVE_MARKERS_SUPPORTED
1571 int m;
1572
1573 /* Save comments except under NONE option */
1574 if (option != JCOPYOPT_NONE) {
1575 jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF);
1576 }
1577 /* Save all types of APPn markers iff ALL option */
Leon Scroggins III3993b372018-07-16 10:43:45 -04001578 if (option == JCOPYOPT_ALL || option == JCOPYOPT_ALL_EXCEPT_ICC) {
1579 for (m = 0; m < 16; m++) {
1580 if (option == JCOPYOPT_ALL_EXCEPT_ICC && m == 2)
1581 continue;
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001582 jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF);
Leon Scroggins III3993b372018-07-16 10:43:45 -04001583 }
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001584 }
1585#endif /* SAVE_MARKERS_SUPPORTED */
1586}
1587
1588/* Copy markers saved in the given source object to the destination object.
1589 * This should be called just after jpeg_start_compress() or
1590 * jpeg_write_coefficients().
1591 * Note that those routines will have written the SOI, and also the
1592 * JFIF APP0 or Adobe APP14 markers if selected.
1593 */
1594
1595GLOBAL(void)
Leon Scroggins III3993b372018-07-16 10:43:45 -04001596jcopy_markers_execute(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
1597 JCOPY_OPTION option)
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001598{
1599 jpeg_saved_marker_ptr marker;
1600
1601 /* In the current implementation, we don't actually need to examine the
1602 * option flag here; we just copy everything that got saved.
1603 * But to avoid confusion, we do not output JFIF and Adobe APP14 markers
1604 * if the encoder library already wrote one.
1605 */
1606 for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) {
1607 if (dstinfo->write_JFIF_header &&
DRCe5eaf372014-05-09 18:00:32 +00001608 marker->marker == JPEG_APP0 &&
1609 marker->data_length >= 5 &&
1610 GETJOCTET(marker->data[0]) == 0x4A &&
1611 GETJOCTET(marker->data[1]) == 0x46 &&
1612 GETJOCTET(marker->data[2]) == 0x49 &&
1613 GETJOCTET(marker->data[3]) == 0x46 &&
1614 GETJOCTET(marker->data[4]) == 0)
1615 continue; /* reject duplicate JFIF */
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001616 if (dstinfo->write_Adobe_marker &&
Leon Scroggins III3993b372018-07-16 10:43:45 -04001617 marker->marker == JPEG_APP0 + 14 &&
DRCe5eaf372014-05-09 18:00:32 +00001618 marker->data_length >= 5 &&
1619 GETJOCTET(marker->data[0]) == 0x41 &&
1620 GETJOCTET(marker->data[1]) == 0x64 &&
1621 GETJOCTET(marker->data[2]) == 0x6F &&
1622 GETJOCTET(marker->data[3]) == 0x62 &&
1623 GETJOCTET(marker->data[4]) == 0x65)
1624 continue; /* reject duplicate Adobe */
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001625 jpeg_write_marker(dstinfo, marker->marker,
DRCe5eaf372014-05-09 18:00:32 +00001626 marker->data, marker->data_length);
Thomas G. Lane5ead57a1998-03-27 00:00:00 +00001627 }
1628}