1 /*
2 * transupp.c
3 *
4 * This file was part of the Independent JPEG Group's software:
5 * Copyright (C) 1997-2019, Thomas G. Lane, Guido Vollbeding.
6 * libjpeg-turbo Modifications:
7 * Copyright (C) 2010, 2017, 2021-2022, D. R. Commander.
8 * For conditions of distribution and use, see the accompanying README.ijg
9 * file.
10 *
11 * This file contains image transformation routines and other utility code
12 * used by the jpegtran sample application. These are NOT part of the core
13 * JPEG library. But we keep these routines separate from jpegtran.c to
14 * ease the task of maintaining jpegtran-like programs that have other user
15 * interfaces.
16 */
17
18 /* Although this file really shouldn't have access to the library internals,
19 * it's helpful to let it call jround_up() and jcopy_block_row().
20 */
21 #define JPEG_INTERNALS
22
23 #include "jinclude.h"
24 #include "jpeglib.h"
25 #include "transupp.h" /* My own external interface */
26 #include "jpegcomp.h"
27 #include <ctype.h> /* to declare isdigit() */
28
29
30 #if JPEG_LIB_VERSION >= 70
31 #define dstinfo_min_DCT_h_scaled_size dstinfo->min_DCT_h_scaled_size
32 #define dstinfo_min_DCT_v_scaled_size dstinfo->min_DCT_v_scaled_size
33 #else
34 #define dstinfo_min_DCT_h_scaled_size DCTSIZE
35 #define dstinfo_min_DCT_v_scaled_size DCTSIZE
36 #endif
37
38
39 #if TRANSFORMS_SUPPORTED
40
41 /*
42 * Lossless image transformation routines. These routines work on DCT
43 * coefficient arrays and thus do not require any lossy decompression
44 * or recompression of the image.
45 * Thanks to Guido Vollbeding for the initial design and code of this feature,
46 * and to Ben Jackson for introducing the cropping feature.
47 *
48 * Horizontal flipping is done in-place, using a single top-to-bottom
49 * pass through the virtual source array. It will thus be much the
50 * fastest option for images larger than main memory.
51 *
52 * The other routines require a set of destination virtual arrays, so they
53 * need twice as much memory as jpegtran normally does. The destination
54 * arrays are always written in normal scan order (top to bottom) because
55 * the virtual array manager expects this. The source arrays will be scanned
56 * in the corresponding order, which means multiple passes through the source
57 * arrays for most of the transforms. That could result in much thrashing
58 * if the image is larger than main memory.
59 *
60 * If cropping or trimming is involved, the destination arrays may be smaller
61 * than the source arrays. Note it is not possible to do horizontal flip
62 * in-place when a nonzero Y crop offset is specified, since we'd have to move
63 * data from one block row to another but the virtual array manager doesn't
64 * guarantee we can touch more than one row at a time. So in that case,
65 * we have to use a separate destination array.
66 *
67 * Some notes about the operating environment of the individual transform
68 * routines:
69 * 1. Both the source and destination virtual arrays are allocated from the
70 * source JPEG object, and therefore should be manipulated by calling the
71 * source's memory manager.
72 * 2. The destination's component count should be used. It may be smaller
73 * than the source's when forcing to grayscale.
74 * 3. Likewise the destination's sampling factors should be used. When
75 * forcing to grayscale the destination's sampling factors will be all 1,
76 * and we may as well take that as the effective iMCU size.
77 * 4. When "trim" is in effect, the destination's dimensions will be the
78 * trimmed values but the source's will be untrimmed.
79 * 5. When "crop" is in effect, the destination's dimensions will be the
80 * cropped values but the source's will be uncropped. Each transform
81 * routine is responsible for picking up source data starting at the
82 * correct X and Y offset for the crop region. (The X and Y offsets
83 * passed to the transform routines are measured in iMCU blocks of the
84 * destination.)
85 * 6. All the routines assume that the source and destination buffers are
86 * padded out to a full iMCU boundary. This is true, although for the
87 * source buffer it is an undocumented property of jdcoefct.c.
88 */
89
90
91 LOCAL(void)
dequant_comp(j_decompress_ptr cinfo,jpeg_component_info * compptr,jvirt_barray_ptr coef_array,JQUANT_TBL * qtblptr1)92 dequant_comp(j_decompress_ptr cinfo, jpeg_component_info *compptr,
93 jvirt_barray_ptr coef_array, JQUANT_TBL *qtblptr1)
94 {
95 JDIMENSION blk_x, blk_y;
96 int offset_y, k;
97 JQUANT_TBL *qtblptr;
98 JBLOCKARRAY buffer;
99 JBLOCKROW block;
100 JCOEFPTR ptr;
101
102 qtblptr = compptr->quant_table;
103 for (blk_y = 0; blk_y < compptr->height_in_blocks;
104 blk_y += compptr->v_samp_factor) {
105 buffer = (*cinfo->mem->access_virt_barray)
106 ((j_common_ptr)cinfo, coef_array, blk_y,
107 (JDIMENSION)compptr->v_samp_factor, TRUE);
108 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
109 block = buffer[offset_y];
110 for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
111 ptr = block[blk_x];
112 for (k = 0; k < DCTSIZE2; k++)
113 if (qtblptr->quantval[k] != qtblptr1->quantval[k])
114 ptr[k] *= qtblptr->quantval[k] / qtblptr1->quantval[k];
115 }
116 }
117 }
118 }
119
120
121 LOCAL(void)
requant_comp(j_decompress_ptr cinfo,jpeg_component_info * compptr,jvirt_barray_ptr coef_array,JQUANT_TBL * qtblptr1)122 requant_comp(j_decompress_ptr cinfo, jpeg_component_info *compptr,
123 jvirt_barray_ptr coef_array, JQUANT_TBL *qtblptr1)
124 {
125 JDIMENSION blk_x, blk_y;
126 int offset_y, k;
127 JQUANT_TBL *qtblptr;
128 JBLOCKARRAY buffer;
129 JBLOCKROW block;
130 JCOEFPTR ptr;
131 JCOEF temp, qval;
132
133 qtblptr = compptr->quant_table;
134 for (blk_y = 0; blk_y < compptr->height_in_blocks;
135 blk_y += compptr->v_samp_factor) {
136 buffer = (*cinfo->mem->access_virt_barray)
137 ((j_common_ptr)cinfo, coef_array, blk_y,
138 (JDIMENSION)compptr->v_samp_factor, TRUE);
139 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
140 block = buffer[offset_y];
141 for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
142 ptr = block[blk_x];
143 for (k = 0; k < DCTSIZE2; k++) {
144 temp = qtblptr->quantval[k];
145 qval = qtblptr1->quantval[k];
146 if (temp != qval && qval != 0) {
147 temp *= ptr[k];
148 /* The following quantization code is copied from jcdctmgr.c */
149 #ifdef FAST_DIVIDE
150 #define DIVIDE_BY(a, b) a /= b
151 #else
152 #define DIVIDE_BY(a, b) if (a >= b) a /= b; else a = 0
153 #endif
154 if (temp < 0) {
155 temp = -temp;
156 temp += qval >> 1; /* for rounding */
157 DIVIDE_BY(temp, qval);
158 temp = -temp;
159 } else {
160 temp += qval >> 1; /* for rounding */
161 DIVIDE_BY(temp, qval);
162 }
163 ptr[k] = temp;
164 }
165 }
166 }
167 }
168 }
169 }
170
171
172 /*
173 * Calculate largest common denominator using Euclid's algorithm.
174 */
175 LOCAL(JCOEF)
largest_common_denominator(JCOEF a,JCOEF b)176 largest_common_denominator(JCOEF a, JCOEF b)
177 {
178 JCOEF c;
179
180 do {
181 c = a % b;
182 a = b;
183 b = c;
184 } while (c);
185
186 return a;
187 }
188
189
190 LOCAL(void)
adjust_quant(j_decompress_ptr srcinfo,jvirt_barray_ptr * src_coef_arrays,j_decompress_ptr dropinfo,jvirt_barray_ptr * drop_coef_arrays,boolean trim,j_compress_ptr dstinfo)191 adjust_quant(j_decompress_ptr srcinfo, jvirt_barray_ptr *src_coef_arrays,
192 j_decompress_ptr dropinfo, jvirt_barray_ptr *drop_coef_arrays,
193 boolean trim, j_compress_ptr dstinfo)
194 {
195 jpeg_component_info *compptr1, *compptr2;
196 JQUANT_TBL *qtblptr1, *qtblptr2, *qtblptr3;
197 int ci, k;
198
199 for (ci = 0; ci < dstinfo->num_components && ci < dropinfo->num_components;
200 ci++) {
201 compptr1 = srcinfo->comp_info + ci;
202 compptr2 = dropinfo->comp_info + ci;
203 qtblptr1 = compptr1->quant_table;
204 qtblptr2 = compptr2->quant_table;
205 for (k = 0; k < DCTSIZE2; k++) {
206 if (qtblptr1->quantval[k] != qtblptr2->quantval[k]) {
207 if (trim)
208 requant_comp(dropinfo, compptr2, drop_coef_arrays[ci], qtblptr1);
209 else {
210 qtblptr3 = dstinfo->quant_tbl_ptrs[compptr1->quant_tbl_no];
211 for (k = 0; k < DCTSIZE2; k++)
212 if (qtblptr1->quantval[k] != qtblptr2->quantval[k])
213 qtblptr3->quantval[k] =
214 largest_common_denominator(qtblptr1->quantval[k],
215 qtblptr2->quantval[k]);
216 dequant_comp(srcinfo, compptr1, src_coef_arrays[ci], qtblptr3);
217 dequant_comp(dropinfo, compptr2, drop_coef_arrays[ci], qtblptr3);
218 }
219 break;
220 }
221 }
222 }
223 }
224
225
226 LOCAL(void)
do_drop(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,j_decompress_ptr dropinfo,jvirt_barray_ptr * drop_coef_arrays,JDIMENSION drop_width,JDIMENSION drop_height)227 do_drop(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
228 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
229 jvirt_barray_ptr *src_coef_arrays,
230 j_decompress_ptr dropinfo, jvirt_barray_ptr *drop_coef_arrays,
231 JDIMENSION drop_width, JDIMENSION drop_height)
232 /* Drop (insert) the contents of another image into the source image. If the
233 * number of components in the drop image is smaller than the number of
234 * components in the destination image, then we fill in the remaining
235 * components with zero. This allows for dropping the contents of grayscale
236 * images into (arbitrarily sampled) color images.
237 */
238 {
239 JDIMENSION comp_width, comp_height;
240 JDIMENSION blk_y, x_drop_blocks, y_drop_blocks;
241 int ci, offset_y;
242 JBLOCKARRAY src_buffer, dst_buffer;
243 jpeg_component_info *compptr;
244
245 for (ci = 0; ci < dstinfo->num_components; ci++) {
246 compptr = dstinfo->comp_info + ci;
247 comp_width = drop_width * compptr->h_samp_factor;
248 comp_height = drop_height * compptr->v_samp_factor;
249 x_drop_blocks = x_crop_offset * compptr->h_samp_factor;
250 y_drop_blocks = y_crop_offset * compptr->v_samp_factor;
251 for (blk_y = 0; blk_y < comp_height; blk_y += compptr->v_samp_factor) {
252 dst_buffer = (*srcinfo->mem->access_virt_barray)
253 ((j_common_ptr)srcinfo, src_coef_arrays[ci], blk_y + y_drop_blocks,
254 (JDIMENSION)compptr->v_samp_factor, TRUE);
255 if (ci < dropinfo->num_components) {
256 src_buffer = (*dropinfo->mem->access_virt_barray)
257 ((j_common_ptr)dropinfo, drop_coef_arrays[ci], blk_y,
258 (JDIMENSION)compptr->v_samp_factor, FALSE);
259 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
260 jcopy_block_row(src_buffer[offset_y],
261 dst_buffer[offset_y] + x_drop_blocks, comp_width);
262 }
263 } else {
264 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
265 memset(dst_buffer[offset_y] + x_drop_blocks, 0,
266 comp_width * sizeof(JBLOCK));
267 }
268 }
269 }
270 }
271 }
272
273
274 LOCAL(void)
do_crop(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,jvirt_barray_ptr * dst_coef_arrays)275 do_crop(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
276 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
277 jvirt_barray_ptr *src_coef_arrays,
278 jvirt_barray_ptr *dst_coef_arrays)
279 /* Crop. This is only used when no rotate/flip is requested with the crop. */
280 {
281 JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks;
282 int ci, offset_y;
283 JBLOCKARRAY src_buffer, dst_buffer;
284 jpeg_component_info *compptr;
285
286 /* We simply have to copy the right amount of data (the destination's
287 * image size) starting at the given X and Y offsets in the source.
288 */
289 for (ci = 0; ci < dstinfo->num_components; ci++) {
290 compptr = dstinfo->comp_info + ci;
291 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
292 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
293 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
294 dst_blk_y += compptr->v_samp_factor) {
295 dst_buffer = (*srcinfo->mem->access_virt_barray)
296 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
297 (JDIMENSION)compptr->v_samp_factor, TRUE);
298 src_buffer = (*srcinfo->mem->access_virt_barray)
299 ((j_common_ptr)srcinfo, src_coef_arrays[ci], dst_blk_y + y_crop_blocks,
300 (JDIMENSION)compptr->v_samp_factor, FALSE);
301 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
302 jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
303 dst_buffer[offset_y], compptr->width_in_blocks);
304 }
305 }
306 }
307 }
308
309
310 LOCAL(void)
do_crop_ext_zero(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,jvirt_barray_ptr * dst_coef_arrays)311 do_crop_ext_zero(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
312 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
313 jvirt_barray_ptr *src_coef_arrays,
314 jvirt_barray_ptr *dst_coef_arrays)
315 /* Crop. This is only used when no rotate/flip is requested with the crop.
316 * Extension: If the destination size is larger than the source, we fill in the
317 * expanded region with zero (neutral gray). Note that we also have to zero
318 * partial iMCUs at the right and bottom edge of the source image area in this
319 * case.
320 */
321 {
322 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height;
323 JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks;
324 int ci, offset_y;
325 JBLOCKARRAY src_buffer, dst_buffer;
326 jpeg_component_info *compptr;
327
328 MCU_cols = srcinfo->output_width /
329 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
330 MCU_rows = srcinfo->output_height /
331 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
332
333 for (ci = 0; ci < dstinfo->num_components; ci++) {
334 compptr = dstinfo->comp_info + ci;
335 comp_width = MCU_cols * compptr->h_samp_factor;
336 comp_height = MCU_rows * compptr->v_samp_factor;
337 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
338 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
339 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
340 dst_blk_y += compptr->v_samp_factor) {
341 dst_buffer = (*srcinfo->mem->access_virt_barray)
342 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
343 (JDIMENSION)compptr->v_samp_factor, TRUE);
344 if (dstinfo->_jpeg_height > srcinfo->output_height) {
345 if (dst_blk_y < y_crop_blocks ||
346 dst_blk_y >= y_crop_blocks + comp_height) {
347 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
348 memset(dst_buffer[offset_y], 0,
349 compptr->width_in_blocks * sizeof(JBLOCK));
350 }
351 continue;
352 }
353 src_buffer = (*srcinfo->mem->access_virt_barray)
354 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
355 dst_blk_y - y_crop_blocks, (JDIMENSION)compptr->v_samp_factor,
356 FALSE);
357 } else {
358 src_buffer = (*srcinfo->mem->access_virt_barray)
359 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
360 dst_blk_y + y_crop_blocks, (JDIMENSION)compptr->v_samp_factor,
361 FALSE);
362 }
363 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
364 if (dstinfo->_jpeg_width > srcinfo->output_width) {
365 if (x_crop_blocks > 0) {
366 memset(dst_buffer[offset_y], 0, x_crop_blocks * sizeof(JBLOCK));
367 }
368 jcopy_block_row(src_buffer[offset_y],
369 dst_buffer[offset_y] + x_crop_blocks, comp_width);
370 if (compptr->width_in_blocks > x_crop_blocks + comp_width) {
371 memset(dst_buffer[offset_y] + x_crop_blocks + comp_width, 0,
372 (compptr->width_in_blocks - x_crop_blocks - comp_width) *
373 sizeof(JBLOCK));
374 }
375 } else {
376 jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
377 dst_buffer[offset_y], compptr->width_in_blocks);
378 }
379 }
380 }
381 }
382 }
383
384
385 LOCAL(void)
do_crop_ext_flat(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,jvirt_barray_ptr * dst_coef_arrays)386 do_crop_ext_flat(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)
390 /* Crop. This is only used when no rotate/flip is requested with the crop.
391 * Extension: The destination width is larger than the source, and we fill in
392 * the expanded region with the DC coefficient of the adjacent block. Note
393 * that we also have to fill partial iMCUs at the right and bottom edge of the
394 * source image area in this case.
395 */
396 {
397 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height;
398 JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks;
399 int ci, offset_y;
400 JCOEF dc;
401 JBLOCKARRAY src_buffer, dst_buffer;
402 jpeg_component_info *compptr;
403
404 MCU_cols = srcinfo->output_width /
405 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
406 MCU_rows = srcinfo->output_height /
407 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
408
409 for (ci = 0; ci < dstinfo->num_components; ci++) {
410 compptr = dstinfo->comp_info + ci;
411 comp_width = MCU_cols * compptr->h_samp_factor;
412 comp_height = MCU_rows * compptr->v_samp_factor;
413 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
414 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
415 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
416 dst_blk_y += compptr->v_samp_factor) {
417 dst_buffer = (*srcinfo->mem->access_virt_barray)
418 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
419 (JDIMENSION)compptr->v_samp_factor, TRUE);
420 if (dstinfo->_jpeg_height > srcinfo->output_height) {
421 if (dst_blk_y < y_crop_blocks ||
422 dst_blk_y >= y_crop_blocks + comp_height) {
423 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
424 memset(dst_buffer[offset_y], 0,
425 compptr->width_in_blocks * sizeof(JBLOCK));
426 }
427 continue;
428 }
429 src_buffer = (*srcinfo->mem->access_virt_barray)
430 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
431 dst_blk_y - y_crop_blocks, (JDIMENSION)compptr->v_samp_factor,
432 FALSE);
433 } else {
434 src_buffer = (*srcinfo->mem->access_virt_barray)
435 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
436 dst_blk_y + y_crop_blocks, (JDIMENSION)compptr->v_samp_factor,
437 FALSE);
438 }
439 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
440 if (x_crop_blocks > 0) {
441 memset(dst_buffer[offset_y], 0, x_crop_blocks * sizeof(JBLOCK));
442 dc = src_buffer[offset_y][0][0];
443 for (dst_blk_x = 0; dst_blk_x < x_crop_blocks; dst_blk_x++) {
444 dst_buffer[offset_y][dst_blk_x][0] = dc;
445 }
446 }
447 jcopy_block_row(src_buffer[offset_y],
448 dst_buffer[offset_y] + x_crop_blocks, comp_width);
449 if (compptr->width_in_blocks > x_crop_blocks + comp_width) {
450 memset(dst_buffer[offset_y] + x_crop_blocks + comp_width, 0,
451 (compptr->width_in_blocks - x_crop_blocks - comp_width) *
452 sizeof(JBLOCK));
453 dc = src_buffer[offset_y][comp_width - 1][0];
454 for (dst_blk_x = x_crop_blocks + comp_width;
455 dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
456 dst_buffer[offset_y][dst_blk_x][0] = dc;
457 }
458 }
459 }
460 }
461 }
462 }
463
464
465 LOCAL(void)
do_crop_ext_reflect(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,jvirt_barray_ptr * dst_coef_arrays)466 do_crop_ext_reflect(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
467 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
468 jvirt_barray_ptr *src_coef_arrays,
469 jvirt_barray_ptr *dst_coef_arrays)
470 /* Crop. This is only used when no rotate/flip is requested with the crop.
471 * Extension: The destination width is larger than the source, and we fill in
472 * the expanded region with repeated reflections of the source image. Note
473 * that we also have to fill partial iMCUs at the right and bottom edge of the
474 * source image area in this case.
475 */
476 {
477 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, src_blk_x;
478 JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks;
479 int ci, k, offset_y;
480 JBLOCKARRAY src_buffer, dst_buffer;
481 JBLOCKROW src_row_ptr, dst_row_ptr;
482 JCOEFPTR src_ptr, dst_ptr;
483 jpeg_component_info *compptr;
484
485 MCU_cols = srcinfo->output_width /
486 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
487 MCU_rows = srcinfo->output_height /
488 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
489
490 for (ci = 0; ci < dstinfo->num_components; ci++) {
491 compptr = dstinfo->comp_info + ci;
492 comp_width = MCU_cols * compptr->h_samp_factor;
493 comp_height = MCU_rows * compptr->v_samp_factor;
494 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
495 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
496 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
497 dst_blk_y += compptr->v_samp_factor) {
498 dst_buffer = (*srcinfo->mem->access_virt_barray)
499 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
500 (JDIMENSION)compptr->v_samp_factor, TRUE);
501 if (dstinfo->_jpeg_height > srcinfo->output_height) {
502 if (dst_blk_y < y_crop_blocks ||
503 dst_blk_y >= y_crop_blocks + comp_height) {
504 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
505 memset(dst_buffer[offset_y], 0,
506 compptr->width_in_blocks * sizeof(JBLOCK));
507 }
508 continue;
509 }
510 src_buffer = (*srcinfo->mem->access_virt_barray)
511 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
512 dst_blk_y - y_crop_blocks, (JDIMENSION)compptr->v_samp_factor,
513 FALSE);
514 } else {
515 src_buffer = (*srcinfo->mem->access_virt_barray)
516 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
517 dst_blk_y + y_crop_blocks, (JDIMENSION)compptr->v_samp_factor,
518 FALSE);
519 }
520 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
521 /* Copy source region */
522 jcopy_block_row(src_buffer[offset_y],
523 dst_buffer[offset_y] + x_crop_blocks, comp_width);
524 if (x_crop_blocks > 0) {
525 /* Reflect to left */
526 dst_row_ptr = dst_buffer[offset_y] + x_crop_blocks;
527 for (dst_blk_x = x_crop_blocks; dst_blk_x > 0;) {
528 src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */
529 for (src_blk_x = comp_width; src_blk_x > 0 && dst_blk_x > 0;
530 src_blk_x--, dst_blk_x--) {
531 dst_ptr = *(--dst_row_ptr); /* destination goes left */
532 src_ptr = *src_row_ptr++; /* source goes right */
533 /* This unrolled loop doesn't need to know which row it's on. */
534 for (k = 0; k < DCTSIZE2; k += 2) {
535 *dst_ptr++ = *src_ptr++; /* copy even column */
536 *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign
537 change */
538 }
539 }
540 }
541 }
542 if (compptr->width_in_blocks > x_crop_blocks + comp_width) {
543 /* Reflect to right */
544 dst_row_ptr = dst_buffer[offset_y] + x_crop_blocks + comp_width;
545 for (dst_blk_x = compptr->width_in_blocks - x_crop_blocks - comp_width;
546 dst_blk_x > 0;) {
547 src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */
548 for (src_blk_x = comp_width; src_blk_x > 0 && dst_blk_x > 0;
549 src_blk_x--, dst_blk_x--) {
550 dst_ptr = *dst_row_ptr++; /* destination goes right */
551 src_ptr = *(--src_row_ptr); /* source goes left */
552 /* This unrolled loop doesn't need to know which row it's on. */
553 for (k = 0; k < DCTSIZE2; k += 2) {
554 *dst_ptr++ = *src_ptr++; /* copy even column */
555 *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign
556 change */
557 }
558 }
559 }
560 }
561 }
562 }
563 }
564 }
565
566
567 LOCAL(void)
do_wipe(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,JDIMENSION drop_width,JDIMENSION drop_height)568 do_wipe(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
569 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
570 jvirt_barray_ptr *src_coef_arrays,
571 JDIMENSION drop_width, JDIMENSION drop_height)
572 /* Wipe - discard image contents of specified region and fill with zero
573 * (neutral gray)
574 */
575 {
576 JDIMENSION x_wipe_blocks, wipe_width;
577 JDIMENSION y_wipe_blocks, wipe_bottom;
578 int ci, offset_y;
579 JBLOCKARRAY buffer;
580 jpeg_component_info *compptr;
581
582 for (ci = 0; ci < dstinfo->num_components; ci++) {
583 compptr = dstinfo->comp_info + ci;
584 x_wipe_blocks = x_crop_offset * compptr->h_samp_factor;
585 wipe_width = drop_width * compptr->h_samp_factor;
586 y_wipe_blocks = y_crop_offset * compptr->v_samp_factor;
587 wipe_bottom = drop_height * compptr->v_samp_factor + y_wipe_blocks;
588 for (; y_wipe_blocks < wipe_bottom;
589 y_wipe_blocks += compptr->v_samp_factor) {
590 buffer = (*srcinfo->mem->access_virt_barray)
591 ((j_common_ptr)srcinfo, src_coef_arrays[ci], y_wipe_blocks,
592 (JDIMENSION)compptr->v_samp_factor, TRUE);
593 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
594 memset(buffer[offset_y] + x_wipe_blocks, 0,
595 wipe_width * sizeof(JBLOCK));
596 }
597 }
598 }
599 }
600
601
602 LOCAL(void)
do_flatten(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,JDIMENSION drop_width,JDIMENSION drop_height)603 do_flatten(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
604 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
605 jvirt_barray_ptr *src_coef_arrays,
606 JDIMENSION drop_width, JDIMENSION drop_height)
607 /* Flatten - discard image contents of specified region, similarly to wipe,
608 * but fill with the average of adjacent blocks instead of zero.
609 */
610 {
611 JDIMENSION x_wipe_blocks, wipe_width, wipe_right;
612 JDIMENSION y_wipe_blocks, wipe_bottom, blk_x;
613 int ci, offset_y, dc_left_value, dc_right_value, average;
614 JBLOCKARRAY buffer;
615 jpeg_component_info *compptr;
616
617 for (ci = 0; ci < dstinfo->num_components; ci++) {
618 compptr = dstinfo->comp_info + ci;
619 x_wipe_blocks = x_crop_offset * compptr->h_samp_factor;
620 wipe_width = drop_width * compptr->h_samp_factor;
621 wipe_right = wipe_width + x_wipe_blocks;
622 y_wipe_blocks = y_crop_offset * compptr->v_samp_factor;
623 wipe_bottom = drop_height * compptr->v_samp_factor + y_wipe_blocks;
624 for (; y_wipe_blocks < wipe_bottom;
625 y_wipe_blocks += compptr->v_samp_factor) {
626 buffer = (*srcinfo->mem->access_virt_barray)
627 ((j_common_ptr)srcinfo, src_coef_arrays[ci], y_wipe_blocks,
628 (JDIMENSION)compptr->v_samp_factor, TRUE);
629 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
630 memset(buffer[offset_y] + x_wipe_blocks, 0,
631 wipe_width * sizeof(JBLOCK));
632 if (x_wipe_blocks > 0) {
633 dc_left_value = buffer[offset_y][x_wipe_blocks - 1][0];
634 if (wipe_right < compptr->width_in_blocks) {
635 dc_right_value = buffer[offset_y][wipe_right][0];
636 average = (dc_left_value + dc_right_value) >> 1;
637 } else {
638 average = dc_left_value;
639 }
640 } else if (wipe_right < compptr->width_in_blocks) {
641 average = buffer[offset_y][wipe_right][0];
642 } else continue;
643 for (blk_x = x_wipe_blocks; blk_x < wipe_right; blk_x++) {
644 buffer[offset_y][blk_x][0] = (JCOEF)average;
645 }
646 }
647 }
648 }
649 }
650
651
652 LOCAL(void)
do_reflect(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,jvirt_barray_ptr * src_coef_arrays,JDIMENSION drop_width,JDIMENSION drop_height)653 do_reflect(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
654 JDIMENSION x_crop_offset, jvirt_barray_ptr *src_coef_arrays,
655 JDIMENSION drop_width, JDIMENSION drop_height)
656 /* Reflect - discard image contents of specified region, similarly to wipe,
657 * but fill with repeated reflections of the outside region instead of zero.
658 * NB: y_crop_offset is assumed to be zero.
659 */
660 {
661 JDIMENSION x_wipe_blocks, wipe_width;
662 JDIMENSION y_wipe_blocks, wipe_bottom;
663 JDIMENSION src_blk_x, dst_blk_x;
664 int ci, k, offset_y;
665 JBLOCKARRAY buffer;
666 JBLOCKROW src_row_ptr, dst_row_ptr;
667 JCOEFPTR src_ptr, dst_ptr;
668 jpeg_component_info *compptr;
669
670 for (ci = 0; ci < dstinfo->num_components; ci++) {
671 compptr = dstinfo->comp_info + ci;
672 x_wipe_blocks = x_crop_offset * compptr->h_samp_factor;
673 wipe_width = drop_width * compptr->h_samp_factor;
674 wipe_bottom = drop_height * compptr->v_samp_factor;
675 for (y_wipe_blocks = 0; y_wipe_blocks < wipe_bottom;
676 y_wipe_blocks += compptr->v_samp_factor) {
677 buffer = (*srcinfo->mem->access_virt_barray)
678 ((j_common_ptr)srcinfo, src_coef_arrays[ci], y_wipe_blocks,
679 (JDIMENSION)compptr->v_samp_factor, TRUE);
680 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
681 if (x_wipe_blocks > 0) {
682 /* Reflect from left */
683 dst_row_ptr = buffer[offset_y] + x_wipe_blocks;
684 for (dst_blk_x = wipe_width; dst_blk_x > 0;) {
685 src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */
686 for (src_blk_x = x_wipe_blocks;
687 src_blk_x > 0 && dst_blk_x > 0; src_blk_x--, dst_blk_x--) {
688 dst_ptr = *dst_row_ptr++; /* destination goes right */
689 src_ptr = *(--src_row_ptr); /* source goes left */
690 /* this unrolled loop doesn't need to know which row it's on... */
691 for (k = 0; k < DCTSIZE2; k += 2) {
692 *dst_ptr++ = *src_ptr++; /* copy even column */
693 *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign change */
694 }
695 }
696 }
697 } else if (compptr->width_in_blocks > x_wipe_blocks + wipe_width) {
698 /* Reflect from right */
699 dst_row_ptr = buffer[offset_y] + x_wipe_blocks + wipe_width;
700 for (dst_blk_x = wipe_width; dst_blk_x > 0;) {
701 src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */
702 src_blk_x = compptr->width_in_blocks - x_wipe_blocks - wipe_width;
703 for (; src_blk_x > 0 && dst_blk_x > 0; src_blk_x--, dst_blk_x--) {
704 dst_ptr = *(--dst_row_ptr); /* destination goes left */
705 src_ptr = *src_row_ptr++; /* source goes right */
706 /* this unrolled loop doesn't need to know which row it's on... */
707 for (k = 0; k < DCTSIZE2; k += 2) {
708 *dst_ptr++ = *src_ptr++; /* copy even column */
709 *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign change */
710 }
711 }
712 }
713 } else {
714 memset(buffer[offset_y] + x_wipe_blocks, 0,
715 wipe_width * sizeof(JBLOCK));
716 }
717 }
718 }
719 }
720 }
721
722
723 LOCAL(void)
do_flip_h_no_crop(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,jvirt_barray_ptr * src_coef_arrays)724 do_flip_h_no_crop(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
725 JDIMENSION x_crop_offset, jvirt_barray_ptr *src_coef_arrays)
726 /* Horizontal flip; done in-place, so no separate dest array is required.
727 * NB: this only works when y_crop_offset is zero.
728 */
729 {
730 JDIMENSION MCU_cols, comp_width, blk_x, blk_y, x_crop_blocks;
731 int ci, k, offset_y;
732 JBLOCKARRAY buffer;
733 JCOEFPTR ptr1, ptr2;
734 JCOEF temp1, temp2;
735 jpeg_component_info *compptr;
736
737 /* Horizontal mirroring of DCT blocks is accomplished by swapping
738 * pairs of blocks in-place. Within a DCT block, we perform horizontal
739 * mirroring by changing the signs of odd-numbered columns.
740 * Partial iMCUs at the right edge are left untouched.
741 */
742 MCU_cols = srcinfo->output_width /
743 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
744
745 for (ci = 0; ci < dstinfo->num_components; ci++) {
746 compptr = dstinfo->comp_info + ci;
747 comp_width = MCU_cols * compptr->h_samp_factor;
748 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
749 for (blk_y = 0; blk_y < compptr->height_in_blocks;
750 blk_y += compptr->v_samp_factor) {
751 buffer = (*srcinfo->mem->access_virt_barray)
752 ((j_common_ptr)srcinfo, src_coef_arrays[ci], blk_y,
753 (JDIMENSION)compptr->v_samp_factor, TRUE);
754 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
755 /* Do the mirroring */
756 for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) {
757 ptr1 = buffer[offset_y][blk_x];
758 ptr2 = buffer[offset_y][comp_width - blk_x - 1];
759 /* this unrolled loop doesn't need to know which row it's on... */
760 for (k = 0; k < DCTSIZE2; k += 2) {
761 temp1 = *ptr1; /* swap even column */
762 temp2 = *ptr2;
763 *ptr1++ = temp2;
764 *ptr2++ = temp1;
765 temp1 = *ptr1; /* swap odd column with sign change */
766 temp2 = *ptr2;
767 *ptr1++ = -temp2;
768 *ptr2++ = -temp1;
769 }
770 }
771 if (x_crop_blocks > 0) {
772 /* Now left-justify the portion of the data to be kept.
773 * We can't use a single jcopy_block_row() call because that routine
774 * depends on memcpy(), whose behavior is unspecified for overlapping
775 * source and destination areas. Sigh.
776 */
777 for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
778 jcopy_block_row(buffer[offset_y] + blk_x + x_crop_blocks,
779 buffer[offset_y] + blk_x, (JDIMENSION)1);
780 }
781 }
782 }
783 }
784 }
785 }
786
787
788 LOCAL(void)
do_flip_h(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,jvirt_barray_ptr * dst_coef_arrays)789 do_flip_h(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
790 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
791 jvirt_barray_ptr *src_coef_arrays,
792 jvirt_barray_ptr *dst_coef_arrays)
793 /* Horizontal flip in general cropping case */
794 {
795 JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
796 JDIMENSION x_crop_blocks, y_crop_blocks;
797 int ci, k, offset_y;
798 JBLOCKARRAY src_buffer, dst_buffer;
799 JBLOCKROW src_row_ptr, dst_row_ptr;
800 JCOEFPTR src_ptr, dst_ptr;
801 jpeg_component_info *compptr;
802
803 /* Here we must output into a separate array because we can't touch
804 * different rows of a single virtual array simultaneously. Otherwise,
805 * this is essentially the same as the routine above.
806 */
807 MCU_cols = srcinfo->output_width /
808 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
809
810 for (ci = 0; ci < dstinfo->num_components; ci++) {
811 compptr = dstinfo->comp_info + ci;
812 comp_width = MCU_cols * compptr->h_samp_factor;
813 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
814 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
815 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
816 dst_blk_y += compptr->v_samp_factor) {
817 dst_buffer = (*srcinfo->mem->access_virt_barray)
818 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
819 (JDIMENSION)compptr->v_samp_factor, TRUE);
820 src_buffer = (*srcinfo->mem->access_virt_barray)
821 ((j_common_ptr)srcinfo, src_coef_arrays[ci], dst_blk_y + y_crop_blocks,
822 (JDIMENSION)compptr->v_samp_factor, FALSE);
823 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
824 dst_row_ptr = dst_buffer[offset_y];
825 src_row_ptr = src_buffer[offset_y];
826 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
827 dst_blk_x++) {
828 if (x_crop_blocks + dst_blk_x < comp_width) {
829 /* Do the mirrorable blocks */
830 dst_ptr = dst_row_ptr[dst_blk_x];
831 src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
832 /* this unrolled loop doesn't need to know which row it's on... */
833 for (k = 0; k < DCTSIZE2; k += 2) {
834 *dst_ptr++ = *src_ptr++; /* copy even column */
835 *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign
836 change */
837 }
838 } else {
839 /* Copy last partial block(s) verbatim */
840 jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
841 dst_row_ptr + dst_blk_x, (JDIMENSION)1);
842 }
843 }
844 }
845 }
846 }
847 }
848
849
850 LOCAL(void)
do_flip_v(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,jvirt_barray_ptr * dst_coef_arrays)851 do_flip_v(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
852 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
853 jvirt_barray_ptr *src_coef_arrays,
854 jvirt_barray_ptr *dst_coef_arrays)
855 /* Vertical flip */
856 {
857 JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
858 JDIMENSION x_crop_blocks, y_crop_blocks;
859 int ci, i, j, offset_y;
860 JBLOCKARRAY src_buffer, dst_buffer;
861 JBLOCKROW src_row_ptr, dst_row_ptr;
862 JCOEFPTR src_ptr, dst_ptr;
863 jpeg_component_info *compptr;
864
865 /* We output into a separate array because we can't touch different
866 * rows of the source virtual array simultaneously. Otherwise, this
867 * is a pretty straightforward analog of horizontal flip.
868 * Within a DCT block, vertical mirroring is done by changing the signs
869 * of odd-numbered rows.
870 * Partial iMCUs at the bottom edge are copied verbatim.
871 */
872 MCU_rows = srcinfo->output_height /
873 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
874
875 for (ci = 0; ci < dstinfo->num_components; ci++) {
876 compptr = dstinfo->comp_info + ci;
877 comp_height = MCU_rows * compptr->v_samp_factor;
878 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
879 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
880 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
881 dst_blk_y += compptr->v_samp_factor) {
882 dst_buffer = (*srcinfo->mem->access_virt_barray)
883 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
884 (JDIMENSION)compptr->v_samp_factor, TRUE);
885 if (y_crop_blocks + dst_blk_y < comp_height) {
886 /* Row is within the mirrorable area. */
887 src_buffer = (*srcinfo->mem->access_virt_barray)
888 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
889 comp_height - y_crop_blocks - dst_blk_y -
890 (JDIMENSION)compptr->v_samp_factor,
891 (JDIMENSION)compptr->v_samp_factor, FALSE);
892 } else {
893 /* Bottom-edge blocks will be copied verbatim. */
894 src_buffer = (*srcinfo->mem->access_virt_barray)
895 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
896 dst_blk_y + y_crop_blocks,
897 (JDIMENSION)compptr->v_samp_factor, FALSE);
898 }
899 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
900 if (y_crop_blocks + dst_blk_y < comp_height) {
901 /* Row is within the mirrorable area. */
902 dst_row_ptr = dst_buffer[offset_y];
903 src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
904 src_row_ptr += x_crop_blocks;
905 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
906 dst_blk_x++) {
907 dst_ptr = dst_row_ptr[dst_blk_x];
908 src_ptr = src_row_ptr[dst_blk_x];
909 for (i = 0; i < DCTSIZE; i += 2) {
910 /* copy even row */
911 for (j = 0; j < DCTSIZE; j++)
912 *dst_ptr++ = *src_ptr++;
913 /* copy odd row with sign change */
914 for (j = 0; j < DCTSIZE; j++)
915 *dst_ptr++ = -(*src_ptr++);
916 }
917 }
918 } else {
919 /* Just copy row verbatim. */
920 jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
921 dst_buffer[offset_y], compptr->width_in_blocks);
922 }
923 }
924 }
925 }
926 }
927
928
929 LOCAL(void)
do_transpose(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,jvirt_barray_ptr * dst_coef_arrays)930 do_transpose(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
931 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
932 jvirt_barray_ptr *src_coef_arrays,
933 jvirt_barray_ptr *dst_coef_arrays)
934 /* Transpose source into destination */
935 {
936 JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks;
937 int ci, i, j, offset_x, offset_y;
938 JBLOCKARRAY src_buffer, dst_buffer;
939 JCOEFPTR src_ptr, dst_ptr;
940 jpeg_component_info *compptr;
941
942 /* Transposing pixels within a block just requires transposing the
943 * DCT coefficients.
944 * Partial iMCUs at the edges require no special treatment; we simply
945 * process all the available DCT blocks for every component.
946 */
947 for (ci = 0; ci < dstinfo->num_components; ci++) {
948 compptr = dstinfo->comp_info + ci;
949 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
950 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
951 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
952 dst_blk_y += compptr->v_samp_factor) {
953 dst_buffer = (*srcinfo->mem->access_virt_barray)
954 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
955 (JDIMENSION)compptr->v_samp_factor, TRUE);
956 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
957 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
958 dst_blk_x += compptr->h_samp_factor) {
959 src_buffer = (*srcinfo->mem->access_virt_barray)
960 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
961 dst_blk_x + x_crop_blocks,
962 (JDIMENSION)compptr->h_samp_factor, FALSE);
963 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
964 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
965 src_ptr =
966 src_buffer[offset_x][dst_blk_y + offset_y + y_crop_blocks];
967 for (i = 0; i < DCTSIZE; i++)
968 for (j = 0; j < DCTSIZE; j++)
969 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
970 }
971 }
972 }
973 }
974 }
975 }
976
977
978 LOCAL(void)
do_rot_90(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,jvirt_barray_ptr * dst_coef_arrays)979 do_rot_90(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
980 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
981 jvirt_barray_ptr *src_coef_arrays,
982 jvirt_barray_ptr *dst_coef_arrays)
983 /* 90 degree rotation is equivalent to
984 * 1. Transposing the image;
985 * 2. Horizontal mirroring.
986 * These two steps are merged into a single processing routine.
987 */
988 {
989 JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
990 JDIMENSION x_crop_blocks, y_crop_blocks;
991 int ci, i, j, offset_x, offset_y;
992 JBLOCKARRAY src_buffer, dst_buffer;
993 JCOEFPTR src_ptr, dst_ptr;
994 jpeg_component_info *compptr;
995
996 /* Because of the horizontal mirror step, we can't process partial iMCUs
997 * at the (output) right edge properly. They just get transposed and
998 * not mirrored.
999 */
1000 MCU_cols = srcinfo->output_height /
1001 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
1002
1003 for (ci = 0; ci < dstinfo->num_components; ci++) {
1004 compptr = dstinfo->comp_info + ci;
1005 comp_width = MCU_cols * compptr->h_samp_factor;
1006 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
1007 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
1008 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
1009 dst_blk_y += compptr->v_samp_factor) {
1010 dst_buffer = (*srcinfo->mem->access_virt_barray)
1011 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
1012 (JDIMENSION)compptr->v_samp_factor, TRUE);
1013 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
1014 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
1015 dst_blk_x += compptr->h_samp_factor) {
1016 if (x_crop_blocks + dst_blk_x < comp_width) {
1017 /* Block is within the mirrorable area. */
1018 src_buffer = (*srcinfo->mem->access_virt_barray)
1019 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1020 comp_width - x_crop_blocks - dst_blk_x -
1021 (JDIMENSION)compptr->h_samp_factor,
1022 (JDIMENSION)compptr->h_samp_factor, FALSE);
1023 } else {
1024 /* Edge blocks are transposed but not mirrored. */
1025 src_buffer = (*srcinfo->mem->access_virt_barray)
1026 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1027 dst_blk_x + x_crop_blocks,
1028 (JDIMENSION)compptr->h_samp_factor, FALSE);
1029 }
1030 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
1031 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
1032 if (x_crop_blocks + dst_blk_x < comp_width) {
1033 /* Block is within the mirrorable area. */
1034 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
1035 [dst_blk_y + offset_y + y_crop_blocks];
1036 for (i = 0; i < DCTSIZE; i++) {
1037 for (j = 0; j < DCTSIZE; j++)
1038 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1039 i++;
1040 for (j = 0; j < DCTSIZE; j++)
1041 dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
1042 }
1043 } else {
1044 /* Edge blocks are transposed but not mirrored. */
1045 src_ptr = src_buffer[offset_x]
1046 [dst_blk_y + offset_y + y_crop_blocks];
1047 for (i = 0; i < DCTSIZE; i++)
1048 for (j = 0; j < DCTSIZE; j++)
1049 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1050 }
1051 }
1052 }
1053 }
1054 }
1055 }
1056 }
1057
1058
1059 LOCAL(void)
do_rot_270(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,jvirt_barray_ptr * dst_coef_arrays)1060 do_rot_270(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
1061 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
1062 jvirt_barray_ptr *src_coef_arrays,
1063 jvirt_barray_ptr *dst_coef_arrays)
1064 /* 270 degree rotation is equivalent to
1065 * 1. Horizontal mirroring;
1066 * 2. Transposing the image.
1067 * These two steps are merged into a single processing routine.
1068 */
1069 {
1070 JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
1071 JDIMENSION x_crop_blocks, y_crop_blocks;
1072 int ci, i, j, offset_x, offset_y;
1073 JBLOCKARRAY src_buffer, dst_buffer;
1074 JCOEFPTR src_ptr, dst_ptr;
1075 jpeg_component_info *compptr;
1076
1077 /* Because of the horizontal mirror step, we can't process partial iMCUs
1078 * at the (output) bottom edge properly. They just get transposed and
1079 * not mirrored.
1080 */
1081 MCU_rows = srcinfo->output_width /
1082 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
1083
1084 for (ci = 0; ci < dstinfo->num_components; ci++) {
1085 compptr = dstinfo->comp_info + ci;
1086 comp_height = MCU_rows * compptr->v_samp_factor;
1087 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
1088 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
1089 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
1090 dst_blk_y += compptr->v_samp_factor) {
1091 dst_buffer = (*srcinfo->mem->access_virt_barray)
1092 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
1093 (JDIMENSION)compptr->v_samp_factor, TRUE);
1094 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
1095 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
1096 dst_blk_x += compptr->h_samp_factor) {
1097 src_buffer = (*srcinfo->mem->access_virt_barray)
1098 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1099 dst_blk_x + x_crop_blocks,
1100 (JDIMENSION)compptr->h_samp_factor, FALSE);
1101 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
1102 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
1103 if (y_crop_blocks + dst_blk_y < comp_height) {
1104 /* Block is within the mirrorable area. */
1105 src_ptr = src_buffer[offset_x]
1106 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
1107 for (i = 0; i < DCTSIZE; i++) {
1108 for (j = 0; j < DCTSIZE; j++) {
1109 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1110 j++;
1111 dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
1112 }
1113 }
1114 } else {
1115 /* Edge blocks are transposed but not mirrored. */
1116 src_ptr = src_buffer[offset_x]
1117 [dst_blk_y + offset_y + y_crop_blocks];
1118 for (i = 0; i < DCTSIZE; i++)
1119 for (j = 0; j < DCTSIZE; j++)
1120 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1121 }
1122 }
1123 }
1124 }
1125 }
1126 }
1127 }
1128
1129
1130 LOCAL(void)
do_rot_180(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,jvirt_barray_ptr * dst_coef_arrays)1131 do_rot_180(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
1132 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
1133 jvirt_barray_ptr *src_coef_arrays,
1134 jvirt_barray_ptr *dst_coef_arrays)
1135 /* 180 degree rotation is equivalent to
1136 * 1. Vertical mirroring;
1137 * 2. Horizontal mirroring.
1138 * These two steps are merged into a single processing routine.
1139 */
1140 {
1141 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
1142 JDIMENSION x_crop_blocks, y_crop_blocks;
1143 int ci, i, j, offset_y;
1144 JBLOCKARRAY src_buffer, dst_buffer;
1145 JBLOCKROW src_row_ptr, dst_row_ptr;
1146 JCOEFPTR src_ptr, dst_ptr;
1147 jpeg_component_info *compptr;
1148
1149 MCU_cols = srcinfo->output_width /
1150 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
1151 MCU_rows = srcinfo->output_height /
1152 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
1153
1154 for (ci = 0; ci < dstinfo->num_components; ci++) {
1155 compptr = dstinfo->comp_info + ci;
1156 comp_width = MCU_cols * compptr->h_samp_factor;
1157 comp_height = MCU_rows * compptr->v_samp_factor;
1158 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
1159 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
1160 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
1161 dst_blk_y += compptr->v_samp_factor) {
1162 dst_buffer = (*srcinfo->mem->access_virt_barray)
1163 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
1164 (JDIMENSION)compptr->v_samp_factor, TRUE);
1165 if (y_crop_blocks + dst_blk_y < comp_height) {
1166 /* Row is within the vertically mirrorable area. */
1167 src_buffer = (*srcinfo->mem->access_virt_barray)
1168 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1169 comp_height - y_crop_blocks - dst_blk_y -
1170 (JDIMENSION)compptr->v_samp_factor,
1171 (JDIMENSION)compptr->v_samp_factor, FALSE);
1172 } else {
1173 /* Bottom-edge rows are only mirrored horizontally. */
1174 src_buffer = (*srcinfo->mem->access_virt_barray)
1175 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1176 dst_blk_y + y_crop_blocks,
1177 (JDIMENSION)compptr->v_samp_factor, FALSE);
1178 }
1179 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
1180 dst_row_ptr = dst_buffer[offset_y];
1181 if (y_crop_blocks + dst_blk_y < comp_height) {
1182 /* Row is within the mirrorable area. */
1183 src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
1184 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
1185 dst_blk_x++) {
1186 dst_ptr = dst_row_ptr[dst_blk_x];
1187 if (x_crop_blocks + dst_blk_x < comp_width) {
1188 /* Process the blocks that can be mirrored both ways. */
1189 src_ptr =
1190 src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
1191 for (i = 0; i < DCTSIZE; i += 2) {
1192 /* For even row, negate every odd column. */
1193 for (j = 0; j < DCTSIZE; j += 2) {
1194 *dst_ptr++ = *src_ptr++;
1195 *dst_ptr++ = -(*src_ptr++);
1196 }
1197 /* For odd row, negate every even column. */
1198 for (j = 0; j < DCTSIZE; j += 2) {
1199 *dst_ptr++ = -(*src_ptr++);
1200 *dst_ptr++ = *src_ptr++;
1201 }
1202 }
1203 } else {
1204 /* Any remaining right-edge blocks are only mirrored vertically. */
1205 src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x];
1206 for (i = 0; i < DCTSIZE; i += 2) {
1207 for (j = 0; j < DCTSIZE; j++)
1208 *dst_ptr++ = *src_ptr++;
1209 for (j = 0; j < DCTSIZE; j++)
1210 *dst_ptr++ = -(*src_ptr++);
1211 }
1212 }
1213 }
1214 } else {
1215 /* Remaining rows are just mirrored horizontally. */
1216 src_row_ptr = src_buffer[offset_y];
1217 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
1218 dst_blk_x++) {
1219 if (x_crop_blocks + dst_blk_x < comp_width) {
1220 /* Process the blocks that can be mirrored. */
1221 dst_ptr = dst_row_ptr[dst_blk_x];
1222 src_ptr =
1223 src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
1224 for (i = 0; i < DCTSIZE2; i += 2) {
1225 *dst_ptr++ = *src_ptr++;
1226 *dst_ptr++ = -(*src_ptr++);
1227 }
1228 } else {
1229 /* Any remaining right-edge blocks are only copied. */
1230 jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
1231 dst_row_ptr + dst_blk_x, (JDIMENSION)1);
1232 }
1233 }
1234 }
1235 }
1236 }
1237 }
1238 }
1239
1240
1241 LOCAL(void)
do_transverse(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,jvirt_barray_ptr * dst_coef_arrays)1242 do_transverse(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
1243 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
1244 jvirt_barray_ptr *src_coef_arrays,
1245 jvirt_barray_ptr *dst_coef_arrays)
1246 /* Transverse transpose is equivalent to
1247 * 1. 180 degree rotation;
1248 * 2. Transposition;
1249 * or
1250 * 1. Horizontal mirroring;
1251 * 2. Transposition;
1252 * 3. Horizontal mirroring.
1253 * These steps are merged into a single processing routine.
1254 */
1255 {
1256 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
1257 JDIMENSION x_crop_blocks, y_crop_blocks;
1258 int ci, i, j, offset_x, offset_y;
1259 JBLOCKARRAY src_buffer, dst_buffer;
1260 JCOEFPTR src_ptr, dst_ptr;
1261 jpeg_component_info *compptr;
1262
1263 MCU_cols = srcinfo->output_height /
1264 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
1265 MCU_rows = srcinfo->output_width /
1266 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
1267
1268 for (ci = 0; ci < dstinfo->num_components; ci++) {
1269 compptr = dstinfo->comp_info + ci;
1270 comp_width = MCU_cols * compptr->h_samp_factor;
1271 comp_height = MCU_rows * compptr->v_samp_factor;
1272 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
1273 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
1274 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
1275 dst_blk_y += compptr->v_samp_factor) {
1276 dst_buffer = (*srcinfo->mem->access_virt_barray)
1277 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
1278 (JDIMENSION)compptr->v_samp_factor, TRUE);
1279 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
1280 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
1281 dst_blk_x += compptr->h_samp_factor) {
1282 if (x_crop_blocks + dst_blk_x < comp_width) {
1283 /* Block is within the mirrorable area. */
1284 src_buffer = (*srcinfo->mem->access_virt_barray)
1285 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1286 comp_width - x_crop_blocks - dst_blk_x -
1287 (JDIMENSION)compptr->h_samp_factor,
1288 (JDIMENSION)compptr->h_samp_factor, FALSE);
1289 } else {
1290 src_buffer = (*srcinfo->mem->access_virt_barray)
1291 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1292 dst_blk_x + x_crop_blocks,
1293 (JDIMENSION)compptr->h_samp_factor, FALSE);
1294 }
1295 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
1296 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
1297 if (y_crop_blocks + dst_blk_y < comp_height) {
1298 if (x_crop_blocks + dst_blk_x < comp_width) {
1299 /* Block is within the mirrorable area. */
1300 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
1301 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
1302 for (i = 0; i < DCTSIZE; i++) {
1303 for (j = 0; j < DCTSIZE; j++) {
1304 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1305 j++;
1306 dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
1307 }
1308 i++;
1309 for (j = 0; j < DCTSIZE; j++) {
1310 dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
1311 j++;
1312 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1313 }
1314 }
1315 } else {
1316 /* Right-edge blocks are mirrored in y only */
1317 src_ptr = src_buffer[offset_x]
1318 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
1319 for (i = 0; i < DCTSIZE; i++) {
1320 for (j = 0; j < DCTSIZE; j++) {
1321 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1322 j++;
1323 dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
1324 }
1325 }
1326 }
1327 } else {
1328 if (x_crop_blocks + dst_blk_x < comp_width) {
1329 /* Bottom-edge blocks are mirrored in x only */
1330 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
1331 [dst_blk_y + offset_y + y_crop_blocks];
1332 for (i = 0; i < DCTSIZE; i++) {
1333 for (j = 0; j < DCTSIZE; j++)
1334 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1335 i++;
1336 for (j = 0; j < DCTSIZE; j++)
1337 dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
1338 }
1339 } else {
1340 /* At lower right corner, just transpose, no mirroring */
1341 src_ptr = src_buffer[offset_x]
1342 [dst_blk_y + offset_y + y_crop_blocks];
1343 for (i = 0; i < DCTSIZE; i++)
1344 for (j = 0; j < DCTSIZE; j++)
1345 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1346 }
1347 }
1348 }
1349 }
1350 }
1351 }
1352 }
1353 }
1354
1355
1356 /* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec.
1357 * Returns TRUE if valid integer found, FALSE if not.
1358 * *strptr is advanced over the digit string, and *result is set to its value.
1359 */
1360
1361 LOCAL(boolean)
jt_read_integer(const char ** strptr,JDIMENSION * result)1362 jt_read_integer(const char **strptr, JDIMENSION *result)
1363 {
1364 const char *ptr = *strptr;
1365 JDIMENSION val = 0;
1366
1367 for (; isdigit(*ptr); ptr++) {
1368 val = val * 10 + (JDIMENSION)(*ptr - '0');
1369 }
1370 *result = val;
1371 if (ptr == *strptr)
1372 return FALSE; /* oops, no digits */
1373 *strptr = ptr;
1374 return TRUE;
1375 }
1376
1377
1378 /* Parse a crop specification (written in X11 geometry style).
1379 * The routine returns TRUE if the spec string is valid, FALSE if not.
1380 *
1381 * The crop spec string should have the format
1382 * <width>[{fr}]x<height>[{fr}]{+-}<xoffset>{+-}<yoffset>
1383 * where width, height, xoffset, and yoffset are unsigned integers.
1384 * Each of the elements can be omitted to indicate a default value.
1385 * (A weakness of this style is that it is not possible to omit xoffset
1386 * while specifying yoffset, since they look alike.)
1387 *
1388 * This code is loosely based on XParseGeometry from the X11 distribution.
1389 */
1390
1391 GLOBAL(boolean)
jtransform_parse_crop_spec(jpeg_transform_info * info,const char * spec)1392 jtransform_parse_crop_spec(jpeg_transform_info *info, const char *spec)
1393 {
1394 info->crop = FALSE;
1395 info->crop_width_set = JCROP_UNSET;
1396 info->crop_height_set = JCROP_UNSET;
1397 info->crop_xoffset_set = JCROP_UNSET;
1398 info->crop_yoffset_set = JCROP_UNSET;
1399
1400 if (isdigit(*spec)) {
1401 /* fetch width */
1402 if (!jt_read_integer(&spec, &info->crop_width))
1403 return FALSE;
1404 if (*spec == 'f' || *spec == 'F') {
1405 spec++;
1406 info->crop_width_set = JCROP_FORCE;
1407 } else if (*spec == 'r' || *spec == 'R') {
1408 spec++;
1409 info->crop_width_set = JCROP_REFLECT;
1410 } else
1411 info->crop_width_set = JCROP_POS;
1412 }
1413 if (*spec == 'x' || *spec == 'X') {
1414 /* fetch height */
1415 spec++;
1416 if (!jt_read_integer(&spec, &info->crop_height))
1417 return FALSE;
1418 if (*spec == 'f' || *spec == 'F') {
1419 spec++;
1420 info->crop_height_set = JCROP_FORCE;
1421 } else if (*spec == 'r' || *spec == 'R') {
1422 spec++;
1423 info->crop_height_set = JCROP_REFLECT;
1424 } else
1425 info->crop_height_set = JCROP_POS;
1426 }
1427 if (*spec == '+' || *spec == '-') {
1428 /* fetch xoffset */
1429 info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
1430 spec++;
1431 if (!jt_read_integer(&spec, &info->crop_xoffset))
1432 return FALSE;
1433 }
1434 if (*spec == '+' || *spec == '-') {
1435 /* fetch yoffset */
1436 info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
1437 spec++;
1438 if (!jt_read_integer(&spec, &info->crop_yoffset))
1439 return FALSE;
1440 }
1441 /* We had better have gotten to the end of the string. */
1442 if (*spec != '\0')
1443 return FALSE;
1444 info->crop = TRUE;
1445 return TRUE;
1446 }
1447
1448
1449 /* Trim off any partial iMCUs on the indicated destination edge */
1450
1451 LOCAL(void)
trim_right_edge(jpeg_transform_info * info,JDIMENSION full_width)1452 trim_right_edge(jpeg_transform_info *info, JDIMENSION full_width)
1453 {
1454 JDIMENSION MCU_cols;
1455
1456 MCU_cols = info->output_width / info->iMCU_sample_width;
1457 if (MCU_cols > 0 && info->x_crop_offset + MCU_cols ==
1458 full_width / info->iMCU_sample_width)
1459 info->output_width = MCU_cols * info->iMCU_sample_width;
1460 }
1461
1462 LOCAL(void)
trim_bottom_edge(jpeg_transform_info * info,JDIMENSION full_height)1463 trim_bottom_edge(jpeg_transform_info *info, JDIMENSION full_height)
1464 {
1465 JDIMENSION MCU_rows;
1466
1467 MCU_rows = info->output_height / info->iMCU_sample_height;
1468 if (MCU_rows > 0 && info->y_crop_offset + MCU_rows ==
1469 full_height / info->iMCU_sample_height)
1470 info->output_height = MCU_rows * info->iMCU_sample_height;
1471 }
1472
1473
1474 /* Request any required workspace.
1475 *
1476 * This routine figures out the size that the output image will be
1477 * (which implies that all the transform parameters must be set before
1478 * it is called).
1479 *
1480 * We allocate the workspace virtual arrays from the source decompression
1481 * object, so that all the arrays (both the original data and the workspace)
1482 * will be taken into account while making memory management decisions.
1483 * Hence, this routine must be called after jpeg_read_header (which reads
1484 * the image dimensions) and before jpeg_read_coefficients (which realizes
1485 * the source's virtual arrays).
1486 *
1487 * This function returns FALSE right away if -perfect is given
1488 * and transformation is not perfect. Otherwise returns TRUE.
1489 */
1490
1491 GLOBAL(boolean)
jtransform_request_workspace(j_decompress_ptr srcinfo,jpeg_transform_info * info)1492 jtransform_request_workspace(j_decompress_ptr srcinfo,
1493 jpeg_transform_info *info)
1494 {
1495 jvirt_barray_ptr *coef_arrays;
1496 boolean need_workspace, transpose_it;
1497 jpeg_component_info *compptr;
1498 JDIMENSION xoffset, yoffset, dtemp;
1499 JDIMENSION width_in_iMCUs, height_in_iMCUs;
1500 JDIMENSION width_in_blocks, height_in_blocks;
1501 int itemp, ci, h_samp_factor, v_samp_factor;
1502
1503 /* Determine number of components in output image */
1504 if (info->force_grayscale &&
1505 srcinfo->jpeg_color_space == JCS_YCbCr &&
1506 srcinfo->num_components == 3)
1507 /* We'll only process the first component */
1508 info->num_components = 1;
1509 else
1510 /* Process all the components */
1511 info->num_components = srcinfo->num_components;
1512
1513 /* Compute output image dimensions and related values. */
1514 #if JPEG_LIB_VERSION >= 80
1515 jpeg_core_output_dimensions(srcinfo);
1516 #else
1517 srcinfo->output_width = srcinfo->image_width;
1518 srcinfo->output_height = srcinfo->image_height;
1519 #endif
1520
1521 /* Return right away if -perfect is given and transformation is not perfect.
1522 */
1523 if (info->perfect) {
1524 if (info->num_components == 1) {
1525 if (!jtransform_perfect_transform(srcinfo->output_width,
1526 srcinfo->output_height,
1527 srcinfo->_min_DCT_h_scaled_size,
1528 srcinfo->_min_DCT_v_scaled_size,
1529 info->transform))
1530 return FALSE;
1531 } else {
1532 if (!jtransform_perfect_transform(srcinfo->output_width,
1533 srcinfo->output_height,
1534 srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size,
1535 srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size,
1536 info->transform))
1537 return FALSE;
1538 }
1539 }
1540
1541 /* If there is only one output component, force the iMCU size to be 1;
1542 * else use the source iMCU size. (This allows us to do the right thing
1543 * when reducing color to grayscale, and also provides a handy way of
1544 * cleaning up "funny" grayscale images whose sampling factors are not 1x1.)
1545 */
1546 switch (info->transform) {
1547 case JXFORM_TRANSPOSE:
1548 case JXFORM_TRANSVERSE:
1549 case JXFORM_ROT_90:
1550 case JXFORM_ROT_270:
1551 info->output_width = srcinfo->output_height;
1552 info->output_height = srcinfo->output_width;
1553 if (info->num_components == 1) {
1554 info->iMCU_sample_width = srcinfo->_min_DCT_v_scaled_size;
1555 info->iMCU_sample_height = srcinfo->_min_DCT_h_scaled_size;
1556 } else {
1557 info->iMCU_sample_width =
1558 srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size;
1559 info->iMCU_sample_height =
1560 srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size;
1561 }
1562 break;
1563 default:
1564 info->output_width = srcinfo->output_width;
1565 info->output_height = srcinfo->output_height;
1566 if (info->num_components == 1) {
1567 info->iMCU_sample_width = srcinfo->_min_DCT_h_scaled_size;
1568 info->iMCU_sample_height = srcinfo->_min_DCT_v_scaled_size;
1569 } else {
1570 info->iMCU_sample_width =
1571 srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size;
1572 info->iMCU_sample_height =
1573 srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size;
1574 }
1575 break;
1576 }
1577
1578 /* If cropping has been requested, compute the crop area's position and
1579 * dimensions, ensuring that its upper left corner falls at an iMCU boundary.
1580 */
1581 if (info->crop) {
1582 /* Insert default values for unset crop parameters */
1583 if (info->crop_xoffset_set == JCROP_UNSET)
1584 info->crop_xoffset = 0; /* default to +0 */
1585 if (info->crop_yoffset_set == JCROP_UNSET)
1586 info->crop_yoffset = 0; /* default to +0 */
1587 if (info->crop_width_set == JCROP_UNSET) {
1588 if (info->crop_xoffset >= info->output_width)
1589 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1590 info->crop_width = info->output_width - info->crop_xoffset;
1591 } else {
1592 /* Check for crop extension */
1593 if (info->crop_width > info->output_width) {
1594 /* Crop extension does not work when transforming! */
1595 if (info->transform != JXFORM_NONE ||
1596 info->crop_xoffset >= info->crop_width ||
1597 info->crop_xoffset > info->crop_width - info->output_width)
1598 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1599 } else {
1600 if (info->crop_xoffset >= info->output_width ||
1601 info->crop_width <= 0 ||
1602 info->crop_xoffset > info->output_width - info->crop_width)
1603 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1604 }
1605 }
1606 if (info->crop_height_set == JCROP_UNSET) {
1607 if (info->crop_yoffset >= info->output_height)
1608 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1609 info->crop_height = info->output_height - info->crop_yoffset;
1610 } else {
1611 /* Check for crop extension */
1612 if (info->crop_height > info->output_height) {
1613 /* Crop extension does not work when transforming! */
1614 if (info->transform != JXFORM_NONE ||
1615 info->crop_yoffset >= info->crop_height ||
1616 info->crop_yoffset > info->crop_height - info->output_height)
1617 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1618 } else {
1619 if (info->crop_yoffset >= info->output_height ||
1620 info->crop_height <= 0 ||
1621 info->crop_yoffset > info->output_height - info->crop_height)
1622 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1623 }
1624 }
1625 /* Convert negative crop offsets into regular offsets */
1626 if (info->crop_xoffset_set != JCROP_NEG)
1627 xoffset = info->crop_xoffset;
1628 else if (info->crop_width > info->output_width) /* crop extension */
1629 xoffset = info->crop_width - info->output_width - info->crop_xoffset;
1630 else
1631 xoffset = info->output_width - info->crop_width - info->crop_xoffset;
1632 if (info->crop_yoffset_set != JCROP_NEG)
1633 yoffset = info->crop_yoffset;
1634 else if (info->crop_height > info->output_height) /* crop extension */
1635 yoffset = info->crop_height - info->output_height - info->crop_yoffset;
1636 else
1637 yoffset = info->output_height - info->crop_height - info->crop_yoffset;
1638 /* Now adjust so that upper left corner falls at an iMCU boundary */
1639 switch (info->transform) {
1640 case JXFORM_DROP:
1641 /* Ensure the effective drop region will not exceed the requested */
1642 itemp = info->iMCU_sample_width;
1643 dtemp = itemp - 1 - ((xoffset + itemp - 1) % itemp);
1644 xoffset += dtemp;
1645 if (info->crop_width <= dtemp)
1646 info->drop_width = 0;
1647 else if (xoffset + info->crop_width - dtemp == info->output_width)
1648 /* Matching right edge: include partial iMCU */
1649 info->drop_width = (info->crop_width - dtemp + itemp - 1) / itemp;
1650 else
1651 info->drop_width = (info->crop_width - dtemp) / itemp;
1652 itemp = info->iMCU_sample_height;
1653 dtemp = itemp - 1 - ((yoffset + itemp - 1) % itemp);
1654 yoffset += dtemp;
1655 if (info->crop_height <= dtemp)
1656 info->drop_height = 0;
1657 else if (yoffset + info->crop_height - dtemp == info->output_height)
1658 /* Matching bottom edge: include partial iMCU */
1659 info->drop_height = (info->crop_height - dtemp + itemp - 1) / itemp;
1660 else
1661 info->drop_height = (info->crop_height - dtemp) / itemp;
1662 /* Check if sampling factors match for dropping */
1663 if (info->drop_width != 0 && info->drop_height != 0)
1664 for (ci = 0; ci < info->num_components &&
1665 ci < info->drop_ptr->num_components; ci++) {
1666 if (info->drop_ptr->comp_info[ci].h_samp_factor *
1667 srcinfo->max_h_samp_factor !=
1668 srcinfo->comp_info[ci].h_samp_factor *
1669 info->drop_ptr->max_h_samp_factor)
1670 ERREXIT6(srcinfo, JERR_BAD_DROP_SAMPLING, ci,
1671 info->drop_ptr->comp_info[ci].h_samp_factor,
1672 info->drop_ptr->max_h_samp_factor,
1673 srcinfo->comp_info[ci].h_samp_factor,
1674 srcinfo->max_h_samp_factor, 'h');
1675 if (info->drop_ptr->comp_info[ci].v_samp_factor *
1676 srcinfo->max_v_samp_factor !=
1677 srcinfo->comp_info[ci].v_samp_factor *
1678 info->drop_ptr->max_v_samp_factor)
1679 ERREXIT6(srcinfo, JERR_BAD_DROP_SAMPLING, ci,
1680 info->drop_ptr->comp_info[ci].v_samp_factor,
1681 info->drop_ptr->max_v_samp_factor,
1682 srcinfo->comp_info[ci].v_samp_factor,
1683 srcinfo->max_v_samp_factor, 'v');
1684 }
1685 break;
1686 case JXFORM_WIPE:
1687 /* Ensure the effective wipe region will cover the requested */
1688 info->drop_width = (JDIMENSION)jdiv_round_up
1689 ((long)(info->crop_width + (xoffset % info->iMCU_sample_width)),
1690 (long)info->iMCU_sample_width);
1691 info->drop_height = (JDIMENSION)jdiv_round_up
1692 ((long)(info->crop_height + (yoffset % info->iMCU_sample_height)),
1693 (long)info->iMCU_sample_height);
1694 break;
1695 default:
1696 /* Ensure the effective crop region will cover the requested */
1697 if (info->crop_width_set == JCROP_FORCE ||
1698 info->crop_width > info->output_width)
1699 info->output_width = info->crop_width;
1700 else
1701 info->output_width =
1702 info->crop_width + (xoffset % info->iMCU_sample_width);
1703 if (info->crop_height_set == JCROP_FORCE ||
1704 info->crop_height > info->output_height)
1705 info->output_height = info->crop_height;
1706 else
1707 info->output_height =
1708 info->crop_height + (yoffset % info->iMCU_sample_height);
1709 }
1710 /* Save x/y offsets measured in iMCUs */
1711 info->x_crop_offset = xoffset / info->iMCU_sample_width;
1712 info->y_crop_offset = yoffset / info->iMCU_sample_height;
1713 } else {
1714 info->x_crop_offset = 0;
1715 info->y_crop_offset = 0;
1716 }
1717
1718 /* Figure out whether we need workspace arrays,
1719 * and if so whether they are transposed relative to the source.
1720 */
1721 need_workspace = FALSE;
1722 transpose_it = FALSE;
1723 switch (info->transform) {
1724 case JXFORM_NONE:
1725 if (info->x_crop_offset != 0 || info->y_crop_offset != 0 ||
1726 info->output_width > srcinfo->output_width ||
1727 info->output_height > srcinfo->output_height)
1728 need_workspace = TRUE;
1729 /* No workspace needed if neither cropping nor transforming */
1730 break;
1731 case JXFORM_FLIP_H:
1732 if (info->trim)
1733 trim_right_edge(info, srcinfo->output_width);
1734 if (info->y_crop_offset != 0 || info->slow_hflip)
1735 need_workspace = TRUE;
1736 /* do_flip_h_no_crop doesn't need a workspace array */
1737 break;
1738 case JXFORM_FLIP_V:
1739 if (info->trim)
1740 trim_bottom_edge(info, srcinfo->output_height);
1741 /* Need workspace arrays having same dimensions as source image. */
1742 need_workspace = TRUE;
1743 break;
1744 case JXFORM_TRANSPOSE:
1745 /* transpose does NOT have to trim anything */
1746 /* Need workspace arrays having transposed dimensions. */
1747 need_workspace = TRUE;
1748 transpose_it = TRUE;
1749 break;
1750 case JXFORM_TRANSVERSE:
1751 if (info->trim) {
1752 trim_right_edge(info, srcinfo->output_height);
1753 trim_bottom_edge(info, srcinfo->output_width);
1754 }
1755 /* Need workspace arrays having transposed dimensions. */
1756 need_workspace = TRUE;
1757 transpose_it = TRUE;
1758 break;
1759 case JXFORM_ROT_90:
1760 if (info->trim)
1761 trim_right_edge(info, srcinfo->output_height);
1762 /* Need workspace arrays having transposed dimensions. */
1763 need_workspace = TRUE;
1764 transpose_it = TRUE;
1765 break;
1766 case JXFORM_ROT_180:
1767 if (info->trim) {
1768 trim_right_edge(info, srcinfo->output_width);
1769 trim_bottom_edge(info, srcinfo->output_height);
1770 }
1771 /* Need workspace arrays having same dimensions as source image. */
1772 need_workspace = TRUE;
1773 break;
1774 case JXFORM_ROT_270:
1775 if (info->trim)
1776 trim_bottom_edge(info, srcinfo->output_width);
1777 /* Need workspace arrays having transposed dimensions. */
1778 need_workspace = TRUE;
1779 transpose_it = TRUE;
1780 break;
1781 case JXFORM_WIPE:
1782 break;
1783 case JXFORM_DROP:
1784 break;
1785 }
1786
1787 /* Allocate workspace if needed.
1788 * Note that we allocate arrays padded out to the next iMCU boundary,
1789 * so that transform routines need not worry about missing edge blocks.
1790 */
1791 if (need_workspace) {
1792 coef_arrays = (jvirt_barray_ptr *)
1793 (*srcinfo->mem->alloc_small) ((j_common_ptr)srcinfo, JPOOL_IMAGE,
1794 sizeof(jvirt_barray_ptr) * info->num_components);
1795 width_in_iMCUs = (JDIMENSION)
1796 jdiv_round_up((long)info->output_width, (long)info->iMCU_sample_width);
1797 height_in_iMCUs = (JDIMENSION)
1798 jdiv_round_up((long)info->output_height, (long)info->iMCU_sample_height);
1799 for (ci = 0; ci < info->num_components; ci++) {
1800 compptr = srcinfo->comp_info + ci;
1801 if (info->num_components == 1) {
1802 /* we're going to force samp factors to 1x1 in this case */
1803 h_samp_factor = v_samp_factor = 1;
1804 } else if (transpose_it) {
1805 h_samp_factor = compptr->v_samp_factor;
1806 v_samp_factor = compptr->h_samp_factor;
1807 } else {
1808 h_samp_factor = compptr->h_samp_factor;
1809 v_samp_factor = compptr->v_samp_factor;
1810 }
1811 width_in_blocks = width_in_iMCUs * h_samp_factor;
1812 height_in_blocks = height_in_iMCUs * v_samp_factor;
1813 coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
1814 ((j_common_ptr)srcinfo, JPOOL_IMAGE, FALSE,
1815 width_in_blocks, height_in_blocks, (JDIMENSION)v_samp_factor);
1816 }
1817 info->workspace_coef_arrays = coef_arrays;
1818 } else
1819 info->workspace_coef_arrays = NULL;
1820
1821 return TRUE;
1822 }
1823
1824
1825 /* Transpose destination image parameters */
1826
1827 LOCAL(void)
transpose_critical_parameters(j_compress_ptr dstinfo)1828 transpose_critical_parameters(j_compress_ptr dstinfo)
1829 {
1830 int tblno, i, j, ci, itemp;
1831 jpeg_component_info *compptr;
1832 JQUANT_TBL *qtblptr;
1833 JDIMENSION jtemp;
1834 UINT16 qtemp;
1835
1836 /* Transpose image dimensions */
1837 jtemp = dstinfo->image_width;
1838 dstinfo->image_width = dstinfo->image_height;
1839 dstinfo->image_height = jtemp;
1840 #if JPEG_LIB_VERSION >= 70
1841 itemp = dstinfo->min_DCT_h_scaled_size;
1842 dstinfo->min_DCT_h_scaled_size = dstinfo->min_DCT_v_scaled_size;
1843 dstinfo->min_DCT_v_scaled_size = itemp;
1844 #endif
1845
1846 /* Transpose sampling factors */
1847 for (ci = 0; ci < dstinfo->num_components; ci++) {
1848 compptr = dstinfo->comp_info + ci;
1849 itemp = compptr->h_samp_factor;
1850 compptr->h_samp_factor = compptr->v_samp_factor;
1851 compptr->v_samp_factor = itemp;
1852 }
1853
1854 /* Transpose quantization tables */
1855 for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
1856 qtblptr = dstinfo->quant_tbl_ptrs[tblno];
1857 if (qtblptr != NULL) {
1858 for (i = 0; i < DCTSIZE; i++) {
1859 for (j = 0; j < i; j++) {
1860 qtemp = qtblptr->quantval[i * DCTSIZE + j];
1861 qtblptr->quantval[i * DCTSIZE + j] =
1862 qtblptr->quantval[j * DCTSIZE + i];
1863 qtblptr->quantval[j * DCTSIZE + i] = qtemp;
1864 }
1865 }
1866 }
1867 }
1868 }
1869
1870
1871 /* Adjust Exif image parameters.
1872 *
1873 * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible.
1874 */
1875
1876 LOCAL(void)
adjust_exif_parameters(JOCTET * data,unsigned int length,JDIMENSION new_width,JDIMENSION new_height)1877 adjust_exif_parameters(JOCTET *data, unsigned int length, JDIMENSION new_width,
1878 JDIMENSION new_height)
1879 {
1880 boolean is_motorola; /* Flag for byte order */
1881 unsigned int number_of_tags, tagnum;
1882 unsigned int firstoffset, offset;
1883 JDIMENSION new_value;
1884
1885 if (length < 12) return; /* Length of an IFD entry */
1886
1887 /* Discover byte order */
1888 if (data[0] == 0x49 && data[1] == 0x49)
1889 is_motorola = FALSE;
1890 else if (data[0] == 0x4D && data[1] == 0x4D)
1891 is_motorola = TRUE;
1892 else
1893 return;
1894
1895 /* Check Tag Mark */
1896 if (is_motorola) {
1897 if (data[2] != 0) return;
1898 if (data[3] != 0x2A) return;
1899 } else {
1900 if (data[3] != 0) return;
1901 if (data[2] != 0x2A) return;
1902 }
1903
1904 /* Get first IFD offset (offset to IFD0) */
1905 if (is_motorola) {
1906 if (data[4] != 0) return;
1907 if (data[5] != 0) return;
1908 firstoffset = data[6];
1909 firstoffset <<= 8;
1910 firstoffset += data[7];
1911 } else {
1912 if (data[7] != 0) return;
1913 if (data[6] != 0) return;
1914 firstoffset = data[5];
1915 firstoffset <<= 8;
1916 firstoffset += data[4];
1917 }
1918 if (firstoffset > length - 2) return; /* check end of data segment */
1919
1920 /* Get the number of directory entries contained in this IFD */
1921 if (is_motorola) {
1922 number_of_tags = data[firstoffset];
1923 number_of_tags <<= 8;
1924 number_of_tags += data[firstoffset + 1];
1925 } else {
1926 number_of_tags = data[firstoffset + 1];
1927 number_of_tags <<= 8;
1928 number_of_tags += data[firstoffset];
1929 }
1930 if (number_of_tags == 0) return;
1931 firstoffset += 2;
1932
1933 /* Search for ExifSubIFD offset Tag in IFD0 */
1934 for (;;) {
1935 if (firstoffset > length - 12) return; /* check end of data segment */
1936 /* Get Tag number */
1937 if (is_motorola) {
1938 tagnum = data[firstoffset];
1939 tagnum <<= 8;
1940 tagnum += data[firstoffset + 1];
1941 } else {
1942 tagnum = data[firstoffset + 1];
1943 tagnum <<= 8;
1944 tagnum += data[firstoffset];
1945 }
1946 if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */
1947 if (--number_of_tags == 0) return;
1948 firstoffset += 12;
1949 }
1950
1951 /* Get the ExifSubIFD offset */
1952 if (is_motorola) {
1953 if (data[firstoffset + 8] != 0) return;
1954 if (data[firstoffset + 9] != 0) return;
1955 offset = data[firstoffset + 10];
1956 offset <<= 8;
1957 offset += data[firstoffset + 11];
1958 } else {
1959 if (data[firstoffset + 11] != 0) return;
1960 if (data[firstoffset + 10] != 0) return;
1961 offset = data[firstoffset + 9];
1962 offset <<= 8;
1963 offset += data[firstoffset + 8];
1964 }
1965 if (offset > length - 2) return; /* check end of data segment */
1966
1967 /* Get the number of directory entries contained in this SubIFD */
1968 if (is_motorola) {
1969 number_of_tags = data[offset];
1970 number_of_tags <<= 8;
1971 number_of_tags += data[offset + 1];
1972 } else {
1973 number_of_tags = data[offset + 1];
1974 number_of_tags <<= 8;
1975 number_of_tags += data[offset];
1976 }
1977 if (number_of_tags < 2) return;
1978 offset += 2;
1979
1980 /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */
1981 do {
1982 if (offset > length - 12) return; /* check end of data segment */
1983 /* Get Tag number */
1984 if (is_motorola) {
1985 tagnum = data[offset];
1986 tagnum <<= 8;
1987 tagnum += data[offset + 1];
1988 } else {
1989 tagnum = data[offset + 1];
1990 tagnum <<= 8;
1991 tagnum += data[offset];
1992 }
1993 if (tagnum == 0xA002 || tagnum == 0xA003) {
1994 if (tagnum == 0xA002)
1995 new_value = new_width; /* ExifImageWidth Tag */
1996 else
1997 new_value = new_height; /* ExifImageHeight Tag */
1998 if (is_motorola) {
1999 data[offset + 2] = 0; /* Format = unsigned long (4 octets) */
2000 data[offset + 3] = 4;
2001 data[offset + 4] = 0; /* Number Of Components = 1 */
2002 data[offset + 5] = 0;
2003 data[offset + 6] = 0;
2004 data[offset + 7] = 1;
2005 data[offset + 8] = 0;
2006 data[offset + 9] = 0;
2007 data[offset + 10] = (JOCTET)((new_value >> 8) & 0xFF);
2008 data[offset + 11] = (JOCTET)(new_value & 0xFF);
2009 } else {
2010 data[offset + 2] = 4; /* Format = unsigned long (4 octets) */
2011 data[offset + 3] = 0;
2012 data[offset + 4] = 1; /* Number Of Components = 1 */
2013 data[offset + 5] = 0;
2014 data[offset + 6] = 0;
2015 data[offset + 7] = 0;
2016 data[offset + 8] = (JOCTET)(new_value & 0xFF);
2017 data[offset + 9] = (JOCTET)((new_value >> 8) & 0xFF);
2018 data[offset + 10] = 0;
2019 data[offset + 11] = 0;
2020 }
2021 }
2022 offset += 12;
2023 } while (--number_of_tags);
2024 }
2025
2026
2027 /* Adjust output image parameters as needed.
2028 *
2029 * This must be called after jpeg_copy_critical_parameters()
2030 * and before jpeg_write_coefficients().
2031 *
2032 * The return value is the set of virtual coefficient arrays to be written
2033 * (either the ones allocated by jtransform_request_workspace, or the
2034 * original source data arrays). The caller will need to pass this value
2035 * to jpeg_write_coefficients().
2036 */
2037
2038 GLOBAL(jvirt_barray_ptr *)
jtransform_adjust_parameters(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,jvirt_barray_ptr * src_coef_arrays,jpeg_transform_info * info)2039 jtransform_adjust_parameters(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
2040 jvirt_barray_ptr *src_coef_arrays,
2041 jpeg_transform_info *info)
2042 {
2043 /* If force-to-grayscale is requested, adjust destination parameters */
2044 if (info->force_grayscale) {
2045 /* First, ensure we have YCbCr or grayscale data, and that the source's
2046 * Y channel is full resolution. (No reasonable person would make Y
2047 * be less than full resolution, so actually coping with that case
2048 * isn't worth extra code space. But we check it to avoid crashing.)
2049 */
2050 if (((dstinfo->jpeg_color_space == JCS_YCbCr &&
2051 dstinfo->num_components == 3) ||
2052 (dstinfo->jpeg_color_space == JCS_GRAYSCALE &&
2053 dstinfo->num_components == 1)) &&
2054 srcinfo->comp_info[0].h_samp_factor == srcinfo->max_h_samp_factor &&
2055 srcinfo->comp_info[0].v_samp_factor == srcinfo->max_v_samp_factor) {
2056 /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
2057 * properly. Among other things, it sets the target h_samp_factor &
2058 * v_samp_factor to 1, which typically won't match the source.
2059 * We have to preserve the source's quantization table number, however.
2060 */
2061 int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no;
2062 jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE);
2063 dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no;
2064 } else {
2065 /* Sorry, can't do it */
2066 ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL);
2067 }
2068 } else if (info->num_components == 1) {
2069 /* For a single-component source, we force the destination sampling factors
2070 * to 1x1, with or without force_grayscale. This is useful because some
2071 * decoders choke on grayscale images with other sampling factors.
2072 */
2073 dstinfo->comp_info[0].h_samp_factor = 1;
2074 dstinfo->comp_info[0].v_samp_factor = 1;
2075 }
2076
2077 /* Correct the destination's image dimensions as necessary
2078 * for rotate/flip, resize, and crop operations.
2079 */
2080 #if JPEG_LIB_VERSION >= 80
2081 dstinfo->jpeg_width = info->output_width;
2082 dstinfo->jpeg_height = info->output_height;
2083 #endif
2084
2085 /* Transpose destination image parameters, adjust quantization */
2086 switch (info->transform) {
2087 case JXFORM_TRANSPOSE:
2088 case JXFORM_TRANSVERSE:
2089 case JXFORM_ROT_90:
2090 case JXFORM_ROT_270:
2091 #if JPEG_LIB_VERSION < 80
2092 dstinfo->image_width = info->output_height;
2093 dstinfo->image_height = info->output_width;
2094 #endif
2095 transpose_critical_parameters(dstinfo);
2096 break;
2097 case JXFORM_DROP:
2098 if (info->drop_width != 0 && info->drop_height != 0)
2099 adjust_quant(srcinfo, src_coef_arrays,
2100 info->drop_ptr, info->drop_coef_arrays,
2101 info->trim, dstinfo);
2102 break;
2103 default:
2104 #if JPEG_LIB_VERSION < 80
2105 dstinfo->image_width = info->output_width;
2106 dstinfo->image_height = info->output_height;
2107 #endif
2108 break;
2109 }
2110
2111 /* Adjust Exif properties */
2112 if (srcinfo->marker_list != NULL &&
2113 srcinfo->marker_list->marker == JPEG_APP0 + 1 &&
2114 srcinfo->marker_list->data_length >= 6 &&
2115 srcinfo->marker_list->data[0] == 0x45 &&
2116 srcinfo->marker_list->data[1] == 0x78 &&
2117 srcinfo->marker_list->data[2] == 0x69 &&
2118 srcinfo->marker_list->data[3] == 0x66 &&
2119 srcinfo->marker_list->data[4] == 0 &&
2120 srcinfo->marker_list->data[5] == 0) {
2121 /* Suppress output of JFIF marker */
2122 dstinfo->write_JFIF_header = FALSE;
2123 /* Adjust Exif image parameters */
2124 #if JPEG_LIB_VERSION >= 80
2125 if (dstinfo->jpeg_width != srcinfo->image_width ||
2126 dstinfo->jpeg_height != srcinfo->image_height)
2127 /* Align data segment to start of TIFF structure for parsing */
2128 adjust_exif_parameters(srcinfo->marker_list->data + 6,
2129 srcinfo->marker_list->data_length - 6,
2130 dstinfo->jpeg_width, dstinfo->jpeg_height);
2131 #else
2132 if (dstinfo->image_width != srcinfo->image_width ||
2133 dstinfo->image_height != srcinfo->image_height)
2134 /* Align data segment to start of TIFF structure for parsing */
2135 adjust_exif_parameters(srcinfo->marker_list->data + 6,
2136 srcinfo->marker_list->data_length - 6,
2137 dstinfo->image_width, dstinfo->image_height);
2138 #endif
2139 }
2140
2141 /* Return the appropriate output data set */
2142 if (info->workspace_coef_arrays != NULL)
2143 return info->workspace_coef_arrays;
2144 return src_coef_arrays;
2145 }
2146
2147
2148 /* Execute the actual transformation, if any.
2149 *
2150 * This must be called *after* jpeg_write_coefficients, because it depends
2151 * on jpeg_write_coefficients to have computed subsidiary values such as
2152 * the per-component width and height fields in the destination object.
2153 *
2154 * Note that some transformations will modify the source data arrays!
2155 */
2156
2157 GLOBAL(void)
jtransform_execute_transform(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,jvirt_barray_ptr * src_coef_arrays,jpeg_transform_info * info)2158 jtransform_execute_transform(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
2159 jvirt_barray_ptr *src_coef_arrays,
2160 jpeg_transform_info *info)
2161 {
2162 jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays;
2163
2164 /* Note: conditions tested here should match those in switch statement
2165 * in jtransform_request_workspace()
2166 */
2167 switch (info->transform) {
2168 case JXFORM_NONE:
2169 if (info->output_width > srcinfo->output_width ||
2170 info->output_height > srcinfo->output_height) {
2171 if (info->output_width > srcinfo->output_width &&
2172 info->crop_width_set == JCROP_REFLECT)
2173 do_crop_ext_reflect(srcinfo, dstinfo,
2174 info->x_crop_offset, info->y_crop_offset,
2175 src_coef_arrays, dst_coef_arrays);
2176 else if (info->output_width > srcinfo->output_width &&
2177 info->crop_width_set == JCROP_FORCE)
2178 do_crop_ext_flat(srcinfo, dstinfo,
2179 info->x_crop_offset, info->y_crop_offset,
2180 src_coef_arrays, dst_coef_arrays);
2181 else
2182 do_crop_ext_zero(srcinfo, dstinfo,
2183 info->x_crop_offset, info->y_crop_offset,
2184 src_coef_arrays, dst_coef_arrays);
2185 } else if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
2186 do_crop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2187 src_coef_arrays, dst_coef_arrays);
2188 break;
2189 case JXFORM_FLIP_H:
2190 if (info->y_crop_offset != 0 || info->slow_hflip)
2191 do_flip_h(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2192 src_coef_arrays, dst_coef_arrays);
2193 else
2194 do_flip_h_no_crop(srcinfo, dstinfo, info->x_crop_offset,
2195 src_coef_arrays);
2196 break;
2197 case JXFORM_FLIP_V:
2198 do_flip_v(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2199 src_coef_arrays, dst_coef_arrays);
2200 break;
2201 case JXFORM_TRANSPOSE:
2202 do_transpose(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2203 src_coef_arrays, dst_coef_arrays);
2204 break;
2205 case JXFORM_TRANSVERSE:
2206 do_transverse(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2207 src_coef_arrays, dst_coef_arrays);
2208 break;
2209 case JXFORM_ROT_90:
2210 do_rot_90(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2211 src_coef_arrays, dst_coef_arrays);
2212 break;
2213 case JXFORM_ROT_180:
2214 do_rot_180(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2215 src_coef_arrays, dst_coef_arrays);
2216 break;
2217 case JXFORM_ROT_270:
2218 do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2219 src_coef_arrays, dst_coef_arrays);
2220 break;
2221 case JXFORM_WIPE:
2222 if (info->crop_width_set == JCROP_REFLECT &&
2223 info->y_crop_offset == 0 && info->drop_height ==
2224 (JDIMENSION)jdiv_round_up
2225 ((long)info->output_height, (long)info->iMCU_sample_height) &&
2226 (info->x_crop_offset == 0 ||
2227 info->x_crop_offset + info->drop_width ==
2228 (JDIMENSION)jdiv_round_up
2229 ((long)info->output_width, (long)info->iMCU_sample_width)))
2230 do_reflect(srcinfo, dstinfo, info->x_crop_offset,
2231 src_coef_arrays, info->drop_width, info->drop_height);
2232 else if (info->crop_width_set == JCROP_FORCE)
2233 do_flatten(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2234 src_coef_arrays, info->drop_width, info->drop_height);
2235 else
2236 do_wipe(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2237 src_coef_arrays, info->drop_width, info->drop_height);
2238 break;
2239 case JXFORM_DROP:
2240 if (info->drop_width != 0 && info->drop_height != 0)
2241 do_drop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2242 src_coef_arrays, info->drop_ptr, info->drop_coef_arrays,
2243 info->drop_width, info->drop_height);
2244 break;
2245 }
2246 }
2247
2248 /* jtransform_perfect_transform
2249 *
2250 * Determine whether lossless transformation is perfectly
2251 * possible for a specified image and transformation.
2252 *
2253 * Inputs:
2254 * image_width, image_height: source image dimensions.
2255 * MCU_width, MCU_height: pixel dimensions of MCU.
2256 * transform: transformation identifier.
2257 * Parameter sources from initialized jpeg_struct
2258 * (after reading source header):
2259 * image_width = cinfo.image_width
2260 * image_height = cinfo.image_height
2261 * MCU_width = cinfo.max_h_samp_factor * cinfo.block_size
2262 * MCU_height = cinfo.max_v_samp_factor * cinfo.block_size
2263 * Result:
2264 * TRUE = perfect transformation possible
2265 * FALSE = perfect transformation not possible
2266 * (may use custom action then)
2267 */
2268
2269 GLOBAL(boolean)
jtransform_perfect_transform(JDIMENSION image_width,JDIMENSION image_height,int MCU_width,int MCU_height,JXFORM_CODE transform)2270 jtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height,
2271 int MCU_width, int MCU_height,
2272 JXFORM_CODE transform)
2273 {
2274 boolean result = TRUE; /* initialize TRUE */
2275
2276 switch (transform) {
2277 case JXFORM_FLIP_H:
2278 case JXFORM_ROT_270:
2279 if (image_width % (JDIMENSION)MCU_width)
2280 result = FALSE;
2281 break;
2282 case JXFORM_FLIP_V:
2283 case JXFORM_ROT_90:
2284 if (image_height % (JDIMENSION)MCU_height)
2285 result = FALSE;
2286 break;
2287 case JXFORM_TRANSVERSE:
2288 case JXFORM_ROT_180:
2289 if (image_width % (JDIMENSION)MCU_width)
2290 result = FALSE;
2291 if (image_height % (JDIMENSION)MCU_height)
2292 result = FALSE;
2293 break;
2294 default:
2295 break;
2296 }
2297
2298 return result;
2299 }
2300
2301 #endif /* TRANSFORMS_SUPPORTED */
2302
2303
2304 /* Setup decompression object to save desired markers in memory.
2305 * This must be called before jpeg_read_header() to have the desired effect.
2306 */
2307
2308 GLOBAL(void)
jcopy_markers_setup(j_decompress_ptr srcinfo,JCOPY_OPTION option)2309 jcopy_markers_setup(j_decompress_ptr srcinfo, JCOPY_OPTION option)
2310 {
2311 #ifdef SAVE_MARKERS_SUPPORTED
2312 int m;
2313
2314 /* Save comments except under NONE option */
2315 if (option != JCOPYOPT_NONE && option != JCOPYOPT_ICC) {
2316 jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF);
2317 }
2318 /* Save all types of APPn markers iff ALL option */
2319 if (option == JCOPYOPT_ALL || option == JCOPYOPT_ALL_EXCEPT_ICC) {
2320 for (m = 0; m < 16; m++) {
2321 if (option == JCOPYOPT_ALL_EXCEPT_ICC && m == 2)
2322 continue;
2323 jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF);
2324 }
2325 }
2326 /* Save only APP2 markers if ICC option selected */
2327 if (option == JCOPYOPT_ICC) {
2328 jpeg_save_markers(srcinfo, JPEG_APP0 + 2, 0xFFFF);
2329 }
2330 #endif /* SAVE_MARKERS_SUPPORTED */
2331 }
2332
2333 /* Copy markers saved in the given source object to the destination object.
2334 * This should be called just after jpeg_start_compress() or
2335 * jpeg_write_coefficients().
2336 * Note that those routines will have written the SOI, and also the
2337 * JFIF APP0 or Adobe APP14 markers if selected.
2338 */
2339
2340 GLOBAL(void)
jcopy_markers_execute(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JCOPY_OPTION option)2341 jcopy_markers_execute(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
2342 JCOPY_OPTION option)
2343 {
2344 jpeg_saved_marker_ptr marker;
2345
2346 /* In the current implementation, we don't actually need to examine the
2347 * option flag here; we just copy everything that got saved.
2348 * But to avoid confusion, we do not output JFIF and Adobe APP14 markers
2349 * if the encoder library already wrote one.
2350 */
2351 for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) {
2352 if (dstinfo->write_JFIF_header &&
2353 marker->marker == JPEG_APP0 &&
2354 marker->data_length >= 5 &&
2355 marker->data[0] == 0x4A &&
2356 marker->data[1] == 0x46 &&
2357 marker->data[2] == 0x49 &&
2358 marker->data[3] == 0x46 &&
2359 marker->data[4] == 0)
2360 continue; /* reject duplicate JFIF */
2361 if (dstinfo->write_Adobe_marker &&
2362 marker->marker == JPEG_APP0 + 14 &&
2363 marker->data_length >= 5 &&
2364 marker->data[0] == 0x41 &&
2365 marker->data[1] == 0x64 &&
2366 marker->data[2] == 0x6F &&
2367 marker->data[3] == 0x62 &&
2368 marker->data[4] == 0x65)
2369 continue; /* reject duplicate Adobe */
2370 jpeg_write_marker(dstinfo, marker->marker,
2371 marker->data, marker->data_length);
2372 }
2373 }
2374