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, 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) {
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 MEMZERO(dst_buffer[offset_y] + x_drop_blocks,
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 MEMZERO(dst_buffer[offset_y],
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 MEMZERO(dst_buffer[offset_y], 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 MEMZERO(dst_buffer[offset_y] + x_crop_blocks + comp_width,
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 MEMZERO(dst_buffer[offset_y],
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 MEMZERO(dst_buffer[offset_y], 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 MEMZERO(dst_buffer[offset_y] + x_crop_blocks + comp_width,
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 MEMZERO(dst_buffer[offset_y],
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 MEMZERO(buffer[offset_y] + x_wipe_blocks, wipe_width * sizeof(JBLOCK));
595 }
596 }
597 }
598 }
599
600
601 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)602 do_flatten(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
603 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
604 jvirt_barray_ptr *src_coef_arrays,
605 JDIMENSION drop_width, JDIMENSION drop_height)
606 /* Flatten - discard image contents of specified region, similarly to wipe,
607 * but fill with the average of adjacent blocks instead of zero.
608 */
609 {
610 JDIMENSION x_wipe_blocks, wipe_width, wipe_right;
611 JDIMENSION y_wipe_blocks, wipe_bottom, blk_x;
612 int ci, offset_y, dc_left_value, dc_right_value, average;
613 JBLOCKARRAY buffer;
614 jpeg_component_info *compptr;
615
616 for (ci = 0; ci < dstinfo->num_components; ci++) {
617 compptr = dstinfo->comp_info + ci;
618 x_wipe_blocks = x_crop_offset * compptr->h_samp_factor;
619 wipe_width = drop_width * compptr->h_samp_factor;
620 wipe_right = wipe_width + x_wipe_blocks;
621 y_wipe_blocks = y_crop_offset * compptr->v_samp_factor;
622 wipe_bottom = drop_height * compptr->v_samp_factor + y_wipe_blocks;
623 for (; y_wipe_blocks < wipe_bottom;
624 y_wipe_blocks += compptr->v_samp_factor) {
625 buffer = (*srcinfo->mem->access_virt_barray)
626 ((j_common_ptr)srcinfo, src_coef_arrays[ci], y_wipe_blocks,
627 (JDIMENSION)compptr->v_samp_factor, TRUE);
628 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
629 MEMZERO(buffer[offset_y] + x_wipe_blocks, wipe_width * sizeof(JBLOCK));
630 if (x_wipe_blocks > 0) {
631 dc_left_value = buffer[offset_y][x_wipe_blocks - 1][0];
632 if (wipe_right < compptr->width_in_blocks) {
633 dc_right_value = buffer[offset_y][wipe_right][0];
634 average = (dc_left_value + dc_right_value) >> 1;
635 } else {
636 average = dc_left_value;
637 }
638 } else if (wipe_right < compptr->width_in_blocks) {
639 average = buffer[offset_y][wipe_right][0];
640 } else continue;
641 for (blk_x = x_wipe_blocks; blk_x < wipe_right; blk_x++) {
642 buffer[offset_y][blk_x][0] = (JCOEF)average;
643 }
644 }
645 }
646 }
647 }
648
649
650 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)651 do_reflect(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
652 JDIMENSION x_crop_offset, jvirt_barray_ptr *src_coef_arrays,
653 JDIMENSION drop_width, JDIMENSION drop_height)
654 /* Reflect - discard image contents of specified region, similarly to wipe,
655 * but fill with repeated reflections of the outside region instead of zero.
656 * NB: y_crop_offset is assumed to be zero.
657 */
658 {
659 JDIMENSION x_wipe_blocks, wipe_width;
660 JDIMENSION y_wipe_blocks, wipe_bottom;
661 JDIMENSION src_blk_x, dst_blk_x;
662 int ci, k, offset_y;
663 JBLOCKARRAY buffer;
664 JBLOCKROW src_row_ptr, dst_row_ptr;
665 JCOEFPTR src_ptr, dst_ptr;
666 jpeg_component_info *compptr;
667
668 for (ci = 0; ci < dstinfo->num_components; ci++) {
669 compptr = dstinfo->comp_info + ci;
670 x_wipe_blocks = x_crop_offset * compptr->h_samp_factor;
671 wipe_width = drop_width * compptr->h_samp_factor;
672 wipe_bottom = drop_height * compptr->v_samp_factor;
673 for (y_wipe_blocks = 0; y_wipe_blocks < wipe_bottom;
674 y_wipe_blocks += compptr->v_samp_factor) {
675 buffer = (*srcinfo->mem->access_virt_barray)
676 ((j_common_ptr)srcinfo, src_coef_arrays[ci], y_wipe_blocks,
677 (JDIMENSION)compptr->v_samp_factor, TRUE);
678 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
679 if (x_wipe_blocks > 0) {
680 /* Reflect from left */
681 dst_row_ptr = buffer[offset_y] + x_wipe_blocks;
682 for (dst_blk_x = wipe_width; dst_blk_x > 0;) {
683 src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */
684 for (src_blk_x = x_wipe_blocks;
685 src_blk_x > 0 && dst_blk_x > 0; src_blk_x--, dst_blk_x--) {
686 dst_ptr = *dst_row_ptr++; /* destination goes right */
687 src_ptr = *(--src_row_ptr); /* source goes left */
688 /* this unrolled loop doesn't need to know which row it's on... */
689 for (k = 0; k < DCTSIZE2; k += 2) {
690 *dst_ptr++ = *src_ptr++; /* copy even column */
691 *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign change */
692 }
693 }
694 }
695 } else if (compptr->width_in_blocks > x_wipe_blocks + wipe_width) {
696 /* Reflect from right */
697 dst_row_ptr = buffer[offset_y] + x_wipe_blocks + wipe_width;
698 for (dst_blk_x = wipe_width; dst_blk_x > 0;) {
699 src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */
700 src_blk_x = compptr->width_in_blocks - x_wipe_blocks - wipe_width;
701 for (; src_blk_x > 0 && dst_blk_x > 0; src_blk_x--, dst_blk_x--) {
702 dst_ptr = *(--dst_row_ptr); /* destination goes left */
703 src_ptr = *src_row_ptr++; /* source goes right */
704 /* this unrolled loop doesn't need to know which row it's on... */
705 for (k = 0; k < DCTSIZE2; k += 2) {
706 *dst_ptr++ = *src_ptr++; /* copy even column */
707 *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign change */
708 }
709 }
710 }
711 } else {
712 MEMZERO(buffer[offset_y] + x_wipe_blocks,
713 wipe_width * sizeof(JBLOCK));
714 }
715 }
716 }
717 }
718 }
719
720
721 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)722 do_flip_h_no_crop(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
723 JDIMENSION x_crop_offset, jvirt_barray_ptr *src_coef_arrays)
724 /* Horizontal flip; done in-place, so no separate dest array is required.
725 * NB: this only works when y_crop_offset is zero.
726 */
727 {
728 JDIMENSION MCU_cols, comp_width, blk_x, blk_y, x_crop_blocks;
729 int ci, k, offset_y;
730 JBLOCKARRAY buffer;
731 JCOEFPTR ptr1, ptr2;
732 JCOEF temp1, temp2;
733 jpeg_component_info *compptr;
734
735 /* Horizontal mirroring of DCT blocks is accomplished by swapping
736 * pairs of blocks in-place. Within a DCT block, we perform horizontal
737 * mirroring by changing the signs of odd-numbered columns.
738 * Partial iMCUs at the right edge are left untouched.
739 */
740 MCU_cols = srcinfo->output_width /
741 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
742
743 for (ci = 0; ci < dstinfo->num_components; ci++) {
744 compptr = dstinfo->comp_info + ci;
745 comp_width = MCU_cols * compptr->h_samp_factor;
746 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
747 for (blk_y = 0; blk_y < compptr->height_in_blocks;
748 blk_y += compptr->v_samp_factor) {
749 buffer = (*srcinfo->mem->access_virt_barray)
750 ((j_common_ptr)srcinfo, src_coef_arrays[ci], blk_y,
751 (JDIMENSION)compptr->v_samp_factor, TRUE);
752 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
753 /* Do the mirroring */
754 for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) {
755 ptr1 = buffer[offset_y][blk_x];
756 ptr2 = buffer[offset_y][comp_width - blk_x - 1];
757 /* this unrolled loop doesn't need to know which row it's on... */
758 for (k = 0; k < DCTSIZE2; k += 2) {
759 temp1 = *ptr1; /* swap even column */
760 temp2 = *ptr2;
761 *ptr1++ = temp2;
762 *ptr2++ = temp1;
763 temp1 = *ptr1; /* swap odd column with sign change */
764 temp2 = *ptr2;
765 *ptr1++ = -temp2;
766 *ptr2++ = -temp1;
767 }
768 }
769 if (x_crop_blocks > 0) {
770 /* Now left-justify the portion of the data to be kept.
771 * We can't use a single jcopy_block_row() call because that routine
772 * depends on memcpy(), whose behavior is unspecified for overlapping
773 * source and destination areas. Sigh.
774 */
775 for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
776 jcopy_block_row(buffer[offset_y] + blk_x + x_crop_blocks,
777 buffer[offset_y] + blk_x, (JDIMENSION)1);
778 }
779 }
780 }
781 }
782 }
783 }
784
785
786 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)787 do_flip_h(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
788 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
789 jvirt_barray_ptr *src_coef_arrays,
790 jvirt_barray_ptr *dst_coef_arrays)
791 /* Horizontal flip in general cropping case */
792 {
793 JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
794 JDIMENSION x_crop_blocks, y_crop_blocks;
795 int ci, k, offset_y;
796 JBLOCKARRAY src_buffer, dst_buffer;
797 JBLOCKROW src_row_ptr, dst_row_ptr;
798 JCOEFPTR src_ptr, dst_ptr;
799 jpeg_component_info *compptr;
800
801 /* Here we must output into a separate array because we can't touch
802 * different rows of a single virtual array simultaneously. Otherwise,
803 * this is essentially the same as the routine above.
804 */
805 MCU_cols = srcinfo->output_width /
806 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
807
808 for (ci = 0; ci < dstinfo->num_components; ci++) {
809 compptr = dstinfo->comp_info + ci;
810 comp_width = MCU_cols * compptr->h_samp_factor;
811 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
812 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
813 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
814 dst_blk_y += compptr->v_samp_factor) {
815 dst_buffer = (*srcinfo->mem->access_virt_barray)
816 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
817 (JDIMENSION)compptr->v_samp_factor, TRUE);
818 src_buffer = (*srcinfo->mem->access_virt_barray)
819 ((j_common_ptr)srcinfo, src_coef_arrays[ci], dst_blk_y + y_crop_blocks,
820 (JDIMENSION)compptr->v_samp_factor, FALSE);
821 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
822 dst_row_ptr = dst_buffer[offset_y];
823 src_row_ptr = src_buffer[offset_y];
824 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
825 dst_blk_x++) {
826 if (x_crop_blocks + dst_blk_x < comp_width) {
827 /* Do the mirrorable blocks */
828 dst_ptr = dst_row_ptr[dst_blk_x];
829 src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
830 /* this unrolled loop doesn't need to know which row it's on... */
831 for (k = 0; k < DCTSIZE2; k += 2) {
832 *dst_ptr++ = *src_ptr++; /* copy even column */
833 *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign
834 change */
835 }
836 } else {
837 /* Copy last partial block(s) verbatim */
838 jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
839 dst_row_ptr + dst_blk_x, (JDIMENSION)1);
840 }
841 }
842 }
843 }
844 }
845 }
846
847
848 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)849 do_flip_v(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
850 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
851 jvirt_barray_ptr *src_coef_arrays,
852 jvirt_barray_ptr *dst_coef_arrays)
853 /* Vertical flip */
854 {
855 JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
856 JDIMENSION x_crop_blocks, y_crop_blocks;
857 int ci, i, j, offset_y;
858 JBLOCKARRAY src_buffer, dst_buffer;
859 JBLOCKROW src_row_ptr, dst_row_ptr;
860 JCOEFPTR src_ptr, dst_ptr;
861 jpeg_component_info *compptr;
862
863 /* We output into a separate array because we can't touch different
864 * rows of the source virtual array simultaneously. Otherwise, this
865 * is a pretty straightforward analog of horizontal flip.
866 * Within a DCT block, vertical mirroring is done by changing the signs
867 * of odd-numbered rows.
868 * Partial iMCUs at the bottom edge are copied verbatim.
869 */
870 MCU_rows = srcinfo->output_height /
871 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
872
873 for (ci = 0; ci < dstinfo->num_components; ci++) {
874 compptr = dstinfo->comp_info + ci;
875 comp_height = MCU_rows * compptr->v_samp_factor;
876 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
877 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
878 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
879 dst_blk_y += compptr->v_samp_factor) {
880 dst_buffer = (*srcinfo->mem->access_virt_barray)
881 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
882 (JDIMENSION)compptr->v_samp_factor, TRUE);
883 if (y_crop_blocks + dst_blk_y < comp_height) {
884 /* Row is within the mirrorable area. */
885 src_buffer = (*srcinfo->mem->access_virt_barray)
886 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
887 comp_height - y_crop_blocks - dst_blk_y -
888 (JDIMENSION)compptr->v_samp_factor,
889 (JDIMENSION)compptr->v_samp_factor, FALSE);
890 } else {
891 /* Bottom-edge blocks will be copied verbatim. */
892 src_buffer = (*srcinfo->mem->access_virt_barray)
893 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
894 dst_blk_y + y_crop_blocks,
895 (JDIMENSION)compptr->v_samp_factor, FALSE);
896 }
897 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
898 if (y_crop_blocks + dst_blk_y < comp_height) {
899 /* Row is within the mirrorable area. */
900 dst_row_ptr = dst_buffer[offset_y];
901 src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
902 src_row_ptr += x_crop_blocks;
903 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
904 dst_blk_x++) {
905 dst_ptr = dst_row_ptr[dst_blk_x];
906 src_ptr = src_row_ptr[dst_blk_x];
907 for (i = 0; i < DCTSIZE; i += 2) {
908 /* copy even row */
909 for (j = 0; j < DCTSIZE; j++)
910 *dst_ptr++ = *src_ptr++;
911 /* copy odd row with sign change */
912 for (j = 0; j < DCTSIZE; j++)
913 *dst_ptr++ = -(*src_ptr++);
914 }
915 }
916 } else {
917 /* Just copy row verbatim. */
918 jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
919 dst_buffer[offset_y], compptr->width_in_blocks);
920 }
921 }
922 }
923 }
924 }
925
926
927 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)928 do_transpose(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
929 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
930 jvirt_barray_ptr *src_coef_arrays,
931 jvirt_barray_ptr *dst_coef_arrays)
932 /* Transpose source into destination */
933 {
934 JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks;
935 int ci, i, j, offset_x, offset_y;
936 JBLOCKARRAY src_buffer, dst_buffer;
937 JCOEFPTR src_ptr, dst_ptr;
938 jpeg_component_info *compptr;
939
940 /* Transposing pixels within a block just requires transposing the
941 * DCT coefficients.
942 * Partial iMCUs at the edges require no special treatment; we simply
943 * process all the available DCT blocks for every component.
944 */
945 for (ci = 0; ci < dstinfo->num_components; ci++) {
946 compptr = dstinfo->comp_info + ci;
947 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
948 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
949 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
950 dst_blk_y += compptr->v_samp_factor) {
951 dst_buffer = (*srcinfo->mem->access_virt_barray)
952 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
953 (JDIMENSION)compptr->v_samp_factor, TRUE);
954 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
955 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
956 dst_blk_x += compptr->h_samp_factor) {
957 src_buffer = (*srcinfo->mem->access_virt_barray)
958 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
959 dst_blk_x + x_crop_blocks,
960 (JDIMENSION)compptr->h_samp_factor, FALSE);
961 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
962 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
963 src_ptr =
964 src_buffer[offset_x][dst_blk_y + offset_y + y_crop_blocks];
965 for (i = 0; i < DCTSIZE; i++)
966 for (j = 0; j < DCTSIZE; j++)
967 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
968 }
969 }
970 }
971 }
972 }
973 }
974
975
976 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)977 do_rot_90(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
978 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
979 jvirt_barray_ptr *src_coef_arrays,
980 jvirt_barray_ptr *dst_coef_arrays)
981 /* 90 degree rotation is equivalent to
982 * 1. Transposing the image;
983 * 2. Horizontal mirroring.
984 * These two steps are merged into a single processing routine.
985 */
986 {
987 JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
988 JDIMENSION x_crop_blocks, y_crop_blocks;
989 int ci, i, j, offset_x, offset_y;
990 JBLOCKARRAY src_buffer, dst_buffer;
991 JCOEFPTR src_ptr, dst_ptr;
992 jpeg_component_info *compptr;
993
994 /* Because of the horizontal mirror step, we can't process partial iMCUs
995 * at the (output) right edge properly. They just get transposed and
996 * not mirrored.
997 */
998 MCU_cols = srcinfo->output_height /
999 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
1000
1001 for (ci = 0; ci < dstinfo->num_components; ci++) {
1002 compptr = dstinfo->comp_info + ci;
1003 comp_width = MCU_cols * compptr->h_samp_factor;
1004 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
1005 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
1006 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
1007 dst_blk_y += compptr->v_samp_factor) {
1008 dst_buffer = (*srcinfo->mem->access_virt_barray)
1009 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
1010 (JDIMENSION)compptr->v_samp_factor, TRUE);
1011 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
1012 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
1013 dst_blk_x += compptr->h_samp_factor) {
1014 if (x_crop_blocks + dst_blk_x < comp_width) {
1015 /* Block is within the mirrorable area. */
1016 src_buffer = (*srcinfo->mem->access_virt_barray)
1017 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1018 comp_width - x_crop_blocks - dst_blk_x -
1019 (JDIMENSION)compptr->h_samp_factor,
1020 (JDIMENSION)compptr->h_samp_factor, FALSE);
1021 } else {
1022 /* Edge blocks are transposed but not mirrored. */
1023 src_buffer = (*srcinfo->mem->access_virt_barray)
1024 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1025 dst_blk_x + x_crop_blocks,
1026 (JDIMENSION)compptr->h_samp_factor, FALSE);
1027 }
1028 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
1029 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
1030 if (x_crop_blocks + dst_blk_x < comp_width) {
1031 /* Block is within the mirrorable area. */
1032 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
1033 [dst_blk_y + offset_y + y_crop_blocks];
1034 for (i = 0; i < DCTSIZE; i++) {
1035 for (j = 0; j < DCTSIZE; j++)
1036 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1037 i++;
1038 for (j = 0; j < DCTSIZE; j++)
1039 dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
1040 }
1041 } else {
1042 /* Edge blocks are transposed but not mirrored. */
1043 src_ptr = src_buffer[offset_x]
1044 [dst_blk_y + offset_y + y_crop_blocks];
1045 for (i = 0; i < DCTSIZE; i++)
1046 for (j = 0; j < DCTSIZE; j++)
1047 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1048 }
1049 }
1050 }
1051 }
1052 }
1053 }
1054 }
1055
1056
1057 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)1058 do_rot_270(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
1059 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
1060 jvirt_barray_ptr *src_coef_arrays,
1061 jvirt_barray_ptr *dst_coef_arrays)
1062 /* 270 degree rotation is equivalent to
1063 * 1. Horizontal mirroring;
1064 * 2. Transposing the image.
1065 * These two steps are merged into a single processing routine.
1066 */
1067 {
1068 JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
1069 JDIMENSION x_crop_blocks, y_crop_blocks;
1070 int ci, i, j, offset_x, offset_y;
1071 JBLOCKARRAY src_buffer, dst_buffer;
1072 JCOEFPTR src_ptr, dst_ptr;
1073 jpeg_component_info *compptr;
1074
1075 /* Because of the horizontal mirror step, we can't process partial iMCUs
1076 * at the (output) bottom edge properly. They just get transposed and
1077 * not mirrored.
1078 */
1079 MCU_rows = srcinfo->output_width /
1080 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
1081
1082 for (ci = 0; ci < dstinfo->num_components; ci++) {
1083 compptr = dstinfo->comp_info + ci;
1084 comp_height = MCU_rows * compptr->v_samp_factor;
1085 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
1086 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
1087 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
1088 dst_blk_y += compptr->v_samp_factor) {
1089 dst_buffer = (*srcinfo->mem->access_virt_barray)
1090 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
1091 (JDIMENSION)compptr->v_samp_factor, TRUE);
1092 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
1093 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
1094 dst_blk_x += compptr->h_samp_factor) {
1095 src_buffer = (*srcinfo->mem->access_virt_barray)
1096 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1097 dst_blk_x + x_crop_blocks,
1098 (JDIMENSION)compptr->h_samp_factor, FALSE);
1099 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
1100 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
1101 if (y_crop_blocks + dst_blk_y < comp_height) {
1102 /* Block is within the mirrorable area. */
1103 src_ptr = src_buffer[offset_x]
1104 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
1105 for (i = 0; i < DCTSIZE; i++) {
1106 for (j = 0; j < DCTSIZE; j++) {
1107 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1108 j++;
1109 dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
1110 }
1111 }
1112 } else {
1113 /* Edge blocks are transposed but not mirrored. */
1114 src_ptr = src_buffer[offset_x]
1115 [dst_blk_y + offset_y + y_crop_blocks];
1116 for (i = 0; i < DCTSIZE; i++)
1117 for (j = 0; j < DCTSIZE; j++)
1118 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1119 }
1120 }
1121 }
1122 }
1123 }
1124 }
1125 }
1126
1127
1128 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)1129 do_rot_180(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
1130 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
1131 jvirt_barray_ptr *src_coef_arrays,
1132 jvirt_barray_ptr *dst_coef_arrays)
1133 /* 180 degree rotation is equivalent to
1134 * 1. Vertical mirroring;
1135 * 2. Horizontal mirroring.
1136 * These two steps are merged into a single processing routine.
1137 */
1138 {
1139 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
1140 JDIMENSION x_crop_blocks, y_crop_blocks;
1141 int ci, i, j, offset_y;
1142 JBLOCKARRAY src_buffer, dst_buffer;
1143 JBLOCKROW src_row_ptr, dst_row_ptr;
1144 JCOEFPTR src_ptr, dst_ptr;
1145 jpeg_component_info *compptr;
1146
1147 MCU_cols = srcinfo->output_width /
1148 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
1149 MCU_rows = srcinfo->output_height /
1150 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
1151
1152 for (ci = 0; ci < dstinfo->num_components; ci++) {
1153 compptr = dstinfo->comp_info + ci;
1154 comp_width = MCU_cols * compptr->h_samp_factor;
1155 comp_height = MCU_rows * compptr->v_samp_factor;
1156 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
1157 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
1158 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
1159 dst_blk_y += compptr->v_samp_factor) {
1160 dst_buffer = (*srcinfo->mem->access_virt_barray)
1161 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
1162 (JDIMENSION)compptr->v_samp_factor, TRUE);
1163 if (y_crop_blocks + dst_blk_y < comp_height) {
1164 /* Row is within the vertically mirrorable area. */
1165 src_buffer = (*srcinfo->mem->access_virt_barray)
1166 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1167 comp_height - y_crop_blocks - dst_blk_y -
1168 (JDIMENSION)compptr->v_samp_factor,
1169 (JDIMENSION)compptr->v_samp_factor, FALSE);
1170 } else {
1171 /* Bottom-edge rows are only mirrored horizontally. */
1172 src_buffer = (*srcinfo->mem->access_virt_barray)
1173 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1174 dst_blk_y + y_crop_blocks,
1175 (JDIMENSION)compptr->v_samp_factor, FALSE);
1176 }
1177 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
1178 dst_row_ptr = dst_buffer[offset_y];
1179 if (y_crop_blocks + dst_blk_y < comp_height) {
1180 /* Row is within the mirrorable area. */
1181 src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
1182 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
1183 dst_blk_x++) {
1184 dst_ptr = dst_row_ptr[dst_blk_x];
1185 if (x_crop_blocks + dst_blk_x < comp_width) {
1186 /* Process the blocks that can be mirrored both ways. */
1187 src_ptr =
1188 src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
1189 for (i = 0; i < DCTSIZE; i += 2) {
1190 /* For even row, negate every odd column. */
1191 for (j = 0; j < DCTSIZE; j += 2) {
1192 *dst_ptr++ = *src_ptr++;
1193 *dst_ptr++ = -(*src_ptr++);
1194 }
1195 /* For odd row, negate every even column. */
1196 for (j = 0; j < DCTSIZE; j += 2) {
1197 *dst_ptr++ = -(*src_ptr++);
1198 *dst_ptr++ = *src_ptr++;
1199 }
1200 }
1201 } else {
1202 /* Any remaining right-edge blocks are only mirrored vertically. */
1203 src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x];
1204 for (i = 0; i < DCTSIZE; i += 2) {
1205 for (j = 0; j < DCTSIZE; j++)
1206 *dst_ptr++ = *src_ptr++;
1207 for (j = 0; j < DCTSIZE; j++)
1208 *dst_ptr++ = -(*src_ptr++);
1209 }
1210 }
1211 }
1212 } else {
1213 /* Remaining rows are just mirrored horizontally. */
1214 src_row_ptr = src_buffer[offset_y];
1215 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
1216 dst_blk_x++) {
1217 if (x_crop_blocks + dst_blk_x < comp_width) {
1218 /* Process the blocks that can be mirrored. */
1219 dst_ptr = dst_row_ptr[dst_blk_x];
1220 src_ptr =
1221 src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
1222 for (i = 0; i < DCTSIZE2; i += 2) {
1223 *dst_ptr++ = *src_ptr++;
1224 *dst_ptr++ = -(*src_ptr++);
1225 }
1226 } else {
1227 /* Any remaining right-edge blocks are only copied. */
1228 jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
1229 dst_row_ptr + dst_blk_x, (JDIMENSION)1);
1230 }
1231 }
1232 }
1233 }
1234 }
1235 }
1236 }
1237
1238
1239 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)1240 do_transverse(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
1241 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
1242 jvirt_barray_ptr *src_coef_arrays,
1243 jvirt_barray_ptr *dst_coef_arrays)
1244 /* Transverse transpose is equivalent to
1245 * 1. 180 degree rotation;
1246 * 2. Transposition;
1247 * or
1248 * 1. Horizontal mirroring;
1249 * 2. Transposition;
1250 * 3. Horizontal mirroring.
1251 * These steps are merged into a single processing routine.
1252 */
1253 {
1254 JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
1255 JDIMENSION x_crop_blocks, y_crop_blocks;
1256 int ci, i, j, offset_x, offset_y;
1257 JBLOCKARRAY src_buffer, dst_buffer;
1258 JCOEFPTR src_ptr, dst_ptr;
1259 jpeg_component_info *compptr;
1260
1261 MCU_cols = srcinfo->output_height /
1262 (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
1263 MCU_rows = srcinfo->output_width /
1264 (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
1265
1266 for (ci = 0; ci < dstinfo->num_components; ci++) {
1267 compptr = dstinfo->comp_info + ci;
1268 comp_width = MCU_cols * compptr->h_samp_factor;
1269 comp_height = MCU_rows * compptr->v_samp_factor;
1270 x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
1271 y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
1272 for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
1273 dst_blk_y += compptr->v_samp_factor) {
1274 dst_buffer = (*srcinfo->mem->access_virt_barray)
1275 ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
1276 (JDIMENSION)compptr->v_samp_factor, TRUE);
1277 for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
1278 for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
1279 dst_blk_x += compptr->h_samp_factor) {
1280 if (x_crop_blocks + dst_blk_x < comp_width) {
1281 /* Block is within the mirrorable area. */
1282 src_buffer = (*srcinfo->mem->access_virt_barray)
1283 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1284 comp_width - x_crop_blocks - dst_blk_x -
1285 (JDIMENSION)compptr->h_samp_factor,
1286 (JDIMENSION)compptr->h_samp_factor, FALSE);
1287 } else {
1288 src_buffer = (*srcinfo->mem->access_virt_barray)
1289 ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1290 dst_blk_x + x_crop_blocks,
1291 (JDIMENSION)compptr->h_samp_factor, FALSE);
1292 }
1293 for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
1294 dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
1295 if (y_crop_blocks + dst_blk_y < comp_height) {
1296 if (x_crop_blocks + dst_blk_x < comp_width) {
1297 /* Block is within the mirrorable area. */
1298 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
1299 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
1300 for (i = 0; i < DCTSIZE; i++) {
1301 for (j = 0; j < DCTSIZE; j++) {
1302 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1303 j++;
1304 dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
1305 }
1306 i++;
1307 for (j = 0; j < DCTSIZE; j++) {
1308 dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
1309 j++;
1310 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1311 }
1312 }
1313 } else {
1314 /* Right-edge blocks are mirrored in y only */
1315 src_ptr = src_buffer[offset_x]
1316 [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
1317 for (i = 0; i < DCTSIZE; i++) {
1318 for (j = 0; j < DCTSIZE; j++) {
1319 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1320 j++;
1321 dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
1322 }
1323 }
1324 }
1325 } else {
1326 if (x_crop_blocks + dst_blk_x < comp_width) {
1327 /* Bottom-edge blocks are mirrored in x only */
1328 src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
1329 [dst_blk_y + offset_y + y_crop_blocks];
1330 for (i = 0; i < DCTSIZE; i++) {
1331 for (j = 0; j < DCTSIZE; j++)
1332 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1333 i++;
1334 for (j = 0; j < DCTSIZE; j++)
1335 dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
1336 }
1337 } else {
1338 /* At lower right corner, just transpose, no mirroring */
1339 src_ptr = src_buffer[offset_x]
1340 [dst_blk_y + offset_y + y_crop_blocks];
1341 for (i = 0; i < DCTSIZE; i++)
1342 for (j = 0; j < DCTSIZE; j++)
1343 dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1344 }
1345 }
1346 }
1347 }
1348 }
1349 }
1350 }
1351 }
1352
1353
1354 /* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec.
1355 * Returns TRUE if valid integer found, FALSE if not.
1356 * *strptr is advanced over the digit string, and *result is set to its value.
1357 */
1358
1359 LOCAL(boolean)
jt_read_integer(const char ** strptr,JDIMENSION * result)1360 jt_read_integer(const char **strptr, JDIMENSION *result)
1361 {
1362 const char *ptr = *strptr;
1363 JDIMENSION val = 0;
1364
1365 for (; isdigit(*ptr); ptr++) {
1366 val = val * 10 + (JDIMENSION)(*ptr - '0');
1367 }
1368 *result = val;
1369 if (ptr == *strptr)
1370 return FALSE; /* oops, no digits */
1371 *strptr = ptr;
1372 return TRUE;
1373 }
1374
1375
1376 /* Parse a crop specification (written in X11 geometry style).
1377 * The routine returns TRUE if the spec string is valid, FALSE if not.
1378 *
1379 * The crop spec string should have the format
1380 * <width>[{fr}]x<height>[{fr}]{+-}<xoffset>{+-}<yoffset>
1381 * where width, height, xoffset, and yoffset are unsigned integers.
1382 * Each of the elements can be omitted to indicate a default value.
1383 * (A weakness of this style is that it is not possible to omit xoffset
1384 * while specifying yoffset, since they look alike.)
1385 *
1386 * This code is loosely based on XParseGeometry from the X11 distribution.
1387 */
1388
1389 GLOBAL(boolean)
jtransform_parse_crop_spec(jpeg_transform_info * info,const char * spec)1390 jtransform_parse_crop_spec(jpeg_transform_info *info, const char *spec)
1391 {
1392 info->crop = FALSE;
1393 info->crop_width_set = JCROP_UNSET;
1394 info->crop_height_set = JCROP_UNSET;
1395 info->crop_xoffset_set = JCROP_UNSET;
1396 info->crop_yoffset_set = JCROP_UNSET;
1397
1398 if (isdigit(*spec)) {
1399 /* fetch width */
1400 if (!jt_read_integer(&spec, &info->crop_width))
1401 return FALSE;
1402 if (*spec == 'f' || *spec == 'F') {
1403 spec++;
1404 info->crop_width_set = JCROP_FORCE;
1405 } else if (*spec == 'r' || *spec == 'R') {
1406 spec++;
1407 info->crop_width_set = JCROP_REFLECT;
1408 } else
1409 info->crop_width_set = JCROP_POS;
1410 }
1411 if (*spec == 'x' || *spec == 'X') {
1412 /* fetch height */
1413 spec++;
1414 if (!jt_read_integer(&spec, &info->crop_height))
1415 return FALSE;
1416 if (*spec == 'f' || *spec == 'F') {
1417 spec++;
1418 info->crop_height_set = JCROP_FORCE;
1419 } else if (*spec == 'r' || *spec == 'R') {
1420 spec++;
1421 info->crop_height_set = JCROP_REFLECT;
1422 } else
1423 info->crop_height_set = JCROP_POS;
1424 }
1425 if (*spec == '+' || *spec == '-') {
1426 /* fetch xoffset */
1427 info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
1428 spec++;
1429 if (!jt_read_integer(&spec, &info->crop_xoffset))
1430 return FALSE;
1431 }
1432 if (*spec == '+' || *spec == '-') {
1433 /* fetch yoffset */
1434 info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
1435 spec++;
1436 if (!jt_read_integer(&spec, &info->crop_yoffset))
1437 return FALSE;
1438 }
1439 /* We had better have gotten to the end of the string. */
1440 if (*spec != '\0')
1441 return FALSE;
1442 info->crop = TRUE;
1443 return TRUE;
1444 }
1445
1446
1447 /* Trim off any partial iMCUs on the indicated destination edge */
1448
1449 LOCAL(void)
trim_right_edge(jpeg_transform_info * info,JDIMENSION full_width)1450 trim_right_edge(jpeg_transform_info *info, JDIMENSION full_width)
1451 {
1452 JDIMENSION MCU_cols;
1453
1454 MCU_cols = info->output_width / info->iMCU_sample_width;
1455 if (MCU_cols > 0 && info->x_crop_offset + MCU_cols ==
1456 full_width / info->iMCU_sample_width)
1457 info->output_width = MCU_cols * info->iMCU_sample_width;
1458 }
1459
1460 LOCAL(void)
trim_bottom_edge(jpeg_transform_info * info,JDIMENSION full_height)1461 trim_bottom_edge(jpeg_transform_info *info, JDIMENSION full_height)
1462 {
1463 JDIMENSION MCU_rows;
1464
1465 MCU_rows = info->output_height / info->iMCU_sample_height;
1466 if (MCU_rows > 0 && info->y_crop_offset + MCU_rows ==
1467 full_height / info->iMCU_sample_height)
1468 info->output_height = MCU_rows * info->iMCU_sample_height;
1469 }
1470
1471
1472 /* Request any required workspace.
1473 *
1474 * This routine figures out the size that the output image will be
1475 * (which implies that all the transform parameters must be set before
1476 * it is called).
1477 *
1478 * We allocate the workspace virtual arrays from the source decompression
1479 * object, so that all the arrays (both the original data and the workspace)
1480 * will be taken into account while making memory management decisions.
1481 * Hence, this routine must be called after jpeg_read_header (which reads
1482 * the image dimensions) and before jpeg_read_coefficients (which realizes
1483 * the source's virtual arrays).
1484 *
1485 * This function returns FALSE right away if -perfect is given
1486 * and transformation is not perfect. Otherwise returns TRUE.
1487 */
1488
1489 GLOBAL(boolean)
jtransform_request_workspace(j_decompress_ptr srcinfo,jpeg_transform_info * info)1490 jtransform_request_workspace(j_decompress_ptr srcinfo,
1491 jpeg_transform_info *info)
1492 {
1493 jvirt_barray_ptr *coef_arrays;
1494 boolean need_workspace, transpose_it;
1495 jpeg_component_info *compptr;
1496 JDIMENSION xoffset, yoffset, dtemp;
1497 JDIMENSION width_in_iMCUs, height_in_iMCUs;
1498 JDIMENSION width_in_blocks, height_in_blocks;
1499 int itemp, ci, h_samp_factor, v_samp_factor;
1500
1501 /* Determine number of components in output image */
1502 if (info->force_grayscale &&
1503 srcinfo->jpeg_color_space == JCS_YCbCr &&
1504 srcinfo->num_components == 3)
1505 /* We'll only process the first component */
1506 info->num_components = 1;
1507 else
1508 /* Process all the components */
1509 info->num_components = srcinfo->num_components;
1510
1511 /* Compute output image dimensions and related values. */
1512 #if JPEG_LIB_VERSION >= 80
1513 jpeg_core_output_dimensions(srcinfo);
1514 #else
1515 srcinfo->output_width = srcinfo->image_width;
1516 srcinfo->output_height = srcinfo->image_height;
1517 #endif
1518
1519 /* Return right away if -perfect is given and transformation is not perfect.
1520 */
1521 if (info->perfect) {
1522 if (info->num_components == 1) {
1523 if (!jtransform_perfect_transform(srcinfo->output_width,
1524 srcinfo->output_height,
1525 srcinfo->_min_DCT_h_scaled_size,
1526 srcinfo->_min_DCT_v_scaled_size,
1527 info->transform))
1528 return FALSE;
1529 } else {
1530 if (!jtransform_perfect_transform(srcinfo->output_width,
1531 srcinfo->output_height,
1532 srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size,
1533 srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size,
1534 info->transform))
1535 return FALSE;
1536 }
1537 }
1538
1539 /* If there is only one output component, force the iMCU size to be 1;
1540 * else use the source iMCU size. (This allows us to do the right thing
1541 * when reducing color to grayscale, and also provides a handy way of
1542 * cleaning up "funny" grayscale images whose sampling factors are not 1x1.)
1543 */
1544 switch (info->transform) {
1545 case JXFORM_TRANSPOSE:
1546 case JXFORM_TRANSVERSE:
1547 case JXFORM_ROT_90:
1548 case JXFORM_ROT_270:
1549 info->output_width = srcinfo->output_height;
1550 info->output_height = srcinfo->output_width;
1551 if (info->num_components == 1) {
1552 info->iMCU_sample_width = srcinfo->_min_DCT_v_scaled_size;
1553 info->iMCU_sample_height = srcinfo->_min_DCT_h_scaled_size;
1554 } else {
1555 info->iMCU_sample_width =
1556 srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size;
1557 info->iMCU_sample_height =
1558 srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size;
1559 }
1560 break;
1561 default:
1562 info->output_width = srcinfo->output_width;
1563 info->output_height = srcinfo->output_height;
1564 if (info->num_components == 1) {
1565 info->iMCU_sample_width = srcinfo->_min_DCT_h_scaled_size;
1566 info->iMCU_sample_height = srcinfo->_min_DCT_v_scaled_size;
1567 } else {
1568 info->iMCU_sample_width =
1569 srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size;
1570 info->iMCU_sample_height =
1571 srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size;
1572 }
1573 break;
1574 }
1575
1576 /* If cropping has been requested, compute the crop area's position and
1577 * dimensions, ensuring that its upper left corner falls at an iMCU boundary.
1578 */
1579 if (info->crop) {
1580 /* Insert default values for unset crop parameters */
1581 if (info->crop_xoffset_set == JCROP_UNSET)
1582 info->crop_xoffset = 0; /* default to +0 */
1583 if (info->crop_yoffset_set == JCROP_UNSET)
1584 info->crop_yoffset = 0; /* default to +0 */
1585 if (info->crop_width_set == JCROP_UNSET) {
1586 if (info->crop_xoffset >= info->output_width)
1587 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1588 info->crop_width = info->output_width - info->crop_xoffset;
1589 } else {
1590 /* Check for crop extension */
1591 if (info->crop_width > info->output_width) {
1592 /* Crop extension does not work when transforming! */
1593 if (info->transform != JXFORM_NONE ||
1594 info->crop_xoffset >= info->crop_width ||
1595 info->crop_xoffset > info->crop_width - info->output_width)
1596 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1597 } else {
1598 if (info->crop_xoffset >= info->output_width ||
1599 info->crop_width <= 0 ||
1600 info->crop_xoffset > info->output_width - info->crop_width)
1601 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1602 }
1603 }
1604 if (info->crop_height_set == JCROP_UNSET) {
1605 if (info->crop_yoffset >= info->output_height)
1606 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1607 info->crop_height = info->output_height - info->crop_yoffset;
1608 } else {
1609 /* Check for crop extension */
1610 if (info->crop_height > info->output_height) {
1611 /* Crop extension does not work when transforming! */
1612 if (info->transform != JXFORM_NONE ||
1613 info->crop_yoffset >= info->crop_height ||
1614 info->crop_yoffset > info->crop_height - info->output_height)
1615 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1616 } else {
1617 if (info->crop_yoffset >= info->output_height ||
1618 info->crop_height <= 0 ||
1619 info->crop_yoffset > info->output_height - info->crop_height)
1620 ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1621 }
1622 }
1623 /* Convert negative crop offsets into regular offsets */
1624 if (info->crop_xoffset_set != JCROP_NEG)
1625 xoffset = info->crop_xoffset;
1626 else if (info->crop_width > info->output_width) /* crop extension */
1627 xoffset = info->crop_width - info->output_width - info->crop_xoffset;
1628 else
1629 xoffset = info->output_width - info->crop_width - info->crop_xoffset;
1630 if (info->crop_yoffset_set != JCROP_NEG)
1631 yoffset = info->crop_yoffset;
1632 else if (info->crop_height > info->output_height) /* crop extension */
1633 yoffset = info->crop_height - info->output_height - info->crop_yoffset;
1634 else
1635 yoffset = info->output_height - info->crop_height - info->crop_yoffset;
1636 /* Now adjust so that upper left corner falls at an iMCU boundary */
1637 switch (info->transform) {
1638 case JXFORM_DROP:
1639 /* Ensure the effective drop region will not exceed the requested */
1640 itemp = info->iMCU_sample_width;
1641 dtemp = itemp - 1 - ((xoffset + itemp - 1) % itemp);
1642 xoffset += dtemp;
1643 if (info->crop_width <= dtemp)
1644 info->drop_width = 0;
1645 else if (xoffset + info->crop_width - dtemp == info->output_width)
1646 /* Matching right edge: include partial iMCU */
1647 info->drop_width = (info->crop_width - dtemp + itemp - 1) / itemp;
1648 else
1649 info->drop_width = (info->crop_width - dtemp) / itemp;
1650 itemp = info->iMCU_sample_height;
1651 dtemp = itemp - 1 - ((yoffset + itemp - 1) % itemp);
1652 yoffset += dtemp;
1653 if (info->crop_height <= dtemp)
1654 info->drop_height = 0;
1655 else if (yoffset + info->crop_height - dtemp == info->output_height)
1656 /* Matching bottom edge: include partial iMCU */
1657 info->drop_height = (info->crop_height - dtemp + itemp - 1) / itemp;
1658 else
1659 info->drop_height = (info->crop_height - dtemp) / itemp;
1660 /* Check if sampling factors match for dropping */
1661 if (info->drop_width != 0 && info->drop_height != 0)
1662 for (ci = 0; ci < info->num_components &&
1663 ci < info->drop_ptr->num_components; ci++) {
1664 if (info->drop_ptr->comp_info[ci].h_samp_factor *
1665 srcinfo->max_h_samp_factor !=
1666 srcinfo->comp_info[ci].h_samp_factor *
1667 info->drop_ptr->max_h_samp_factor)
1668 ERREXIT6(srcinfo, JERR_BAD_DROP_SAMPLING, ci,
1669 info->drop_ptr->comp_info[ci].h_samp_factor,
1670 info->drop_ptr->max_h_samp_factor,
1671 srcinfo->comp_info[ci].h_samp_factor,
1672 srcinfo->max_h_samp_factor, 'h');
1673 if (info->drop_ptr->comp_info[ci].v_samp_factor *
1674 srcinfo->max_v_samp_factor !=
1675 srcinfo->comp_info[ci].v_samp_factor *
1676 info->drop_ptr->max_v_samp_factor)
1677 ERREXIT6(srcinfo, JERR_BAD_DROP_SAMPLING, ci,
1678 info->drop_ptr->comp_info[ci].v_samp_factor,
1679 info->drop_ptr->max_v_samp_factor,
1680 srcinfo->comp_info[ci].v_samp_factor,
1681 srcinfo->max_v_samp_factor, 'v');
1682 }
1683 break;
1684 case JXFORM_WIPE:
1685 /* Ensure the effective wipe region will cover the requested */
1686 info->drop_width = (JDIMENSION)jdiv_round_up
1687 ((long)(info->crop_width + (xoffset % info->iMCU_sample_width)),
1688 (long)info->iMCU_sample_width);
1689 info->drop_height = (JDIMENSION)jdiv_round_up
1690 ((long)(info->crop_height + (yoffset % info->iMCU_sample_height)),
1691 (long)info->iMCU_sample_height);
1692 break;
1693 default:
1694 /* Ensure the effective crop region will cover the requested */
1695 if (info->crop_width_set == JCROP_FORCE ||
1696 info->crop_width > info->output_width)
1697 info->output_width = info->crop_width;
1698 else
1699 info->output_width =
1700 info->crop_width + (xoffset % info->iMCU_sample_width);
1701 if (info->crop_height_set == JCROP_FORCE ||
1702 info->crop_height > info->output_height)
1703 info->output_height = info->crop_height;
1704 else
1705 info->output_height =
1706 info->crop_height + (yoffset % info->iMCU_sample_height);
1707 }
1708 /* Save x/y offsets measured in iMCUs */
1709 info->x_crop_offset = xoffset / info->iMCU_sample_width;
1710 info->y_crop_offset = yoffset / info->iMCU_sample_height;
1711 } else {
1712 info->x_crop_offset = 0;
1713 info->y_crop_offset = 0;
1714 }
1715
1716 /* Figure out whether we need workspace arrays,
1717 * and if so whether they are transposed relative to the source.
1718 */
1719 need_workspace = FALSE;
1720 transpose_it = FALSE;
1721 switch (info->transform) {
1722 case JXFORM_NONE:
1723 if (info->x_crop_offset != 0 || info->y_crop_offset != 0 ||
1724 info->output_width > srcinfo->output_width ||
1725 info->output_height > srcinfo->output_height)
1726 need_workspace = TRUE;
1727 /* No workspace needed if neither cropping nor transforming */
1728 break;
1729 case JXFORM_FLIP_H:
1730 if (info->trim)
1731 trim_right_edge(info, srcinfo->output_width);
1732 if (info->y_crop_offset != 0 || info->slow_hflip)
1733 need_workspace = TRUE;
1734 /* do_flip_h_no_crop doesn't need a workspace array */
1735 break;
1736 case JXFORM_FLIP_V:
1737 if (info->trim)
1738 trim_bottom_edge(info, srcinfo->output_height);
1739 /* Need workspace arrays having same dimensions as source image. */
1740 need_workspace = TRUE;
1741 break;
1742 case JXFORM_TRANSPOSE:
1743 /* transpose does NOT have to trim anything */
1744 /* Need workspace arrays having transposed dimensions. */
1745 need_workspace = TRUE;
1746 transpose_it = TRUE;
1747 break;
1748 case JXFORM_TRANSVERSE:
1749 if (info->trim) {
1750 trim_right_edge(info, srcinfo->output_height);
1751 trim_bottom_edge(info, srcinfo->output_width);
1752 }
1753 /* Need workspace arrays having transposed dimensions. */
1754 need_workspace = TRUE;
1755 transpose_it = TRUE;
1756 break;
1757 case JXFORM_ROT_90:
1758 if (info->trim)
1759 trim_right_edge(info, srcinfo->output_height);
1760 /* Need workspace arrays having transposed dimensions. */
1761 need_workspace = TRUE;
1762 transpose_it = TRUE;
1763 break;
1764 case JXFORM_ROT_180:
1765 if (info->trim) {
1766 trim_right_edge(info, srcinfo->output_width);
1767 trim_bottom_edge(info, srcinfo->output_height);
1768 }
1769 /* Need workspace arrays having same dimensions as source image. */
1770 need_workspace = TRUE;
1771 break;
1772 case JXFORM_ROT_270:
1773 if (info->trim)
1774 trim_bottom_edge(info, srcinfo->output_width);
1775 /* Need workspace arrays having transposed dimensions. */
1776 need_workspace = TRUE;
1777 transpose_it = TRUE;
1778 break;
1779 case JXFORM_WIPE:
1780 break;
1781 case JXFORM_DROP:
1782 break;
1783 }
1784
1785 /* Allocate workspace if needed.
1786 * Note that we allocate arrays padded out to the next iMCU boundary,
1787 * so that transform routines need not worry about missing edge blocks.
1788 */
1789 if (need_workspace) {
1790 coef_arrays = (jvirt_barray_ptr *)
1791 (*srcinfo->mem->alloc_small) ((j_common_ptr)srcinfo, JPOOL_IMAGE,
1792 sizeof(jvirt_barray_ptr) * info->num_components);
1793 width_in_iMCUs = (JDIMENSION)
1794 jdiv_round_up((long)info->output_width, (long)info->iMCU_sample_width);
1795 height_in_iMCUs = (JDIMENSION)
1796 jdiv_round_up((long)info->output_height, (long)info->iMCU_sample_height);
1797 for (ci = 0; ci < info->num_components; ci++) {
1798 compptr = srcinfo->comp_info + ci;
1799 if (info->num_components == 1) {
1800 /* we're going to force samp factors to 1x1 in this case */
1801 h_samp_factor = v_samp_factor = 1;
1802 } else if (transpose_it) {
1803 h_samp_factor = compptr->v_samp_factor;
1804 v_samp_factor = compptr->h_samp_factor;
1805 } else {
1806 h_samp_factor = compptr->h_samp_factor;
1807 v_samp_factor = compptr->v_samp_factor;
1808 }
1809 width_in_blocks = width_in_iMCUs * h_samp_factor;
1810 height_in_blocks = height_in_iMCUs * v_samp_factor;
1811 coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
1812 ((j_common_ptr)srcinfo, JPOOL_IMAGE, FALSE,
1813 width_in_blocks, height_in_blocks, (JDIMENSION)v_samp_factor);
1814 }
1815 info->workspace_coef_arrays = coef_arrays;
1816 } else
1817 info->workspace_coef_arrays = NULL;
1818
1819 return TRUE;
1820 }
1821
1822
1823 /* Transpose destination image parameters */
1824
1825 LOCAL(void)
transpose_critical_parameters(j_compress_ptr dstinfo)1826 transpose_critical_parameters(j_compress_ptr dstinfo)
1827 {
1828 int tblno, i, j, ci, itemp;
1829 jpeg_component_info *compptr;
1830 JQUANT_TBL *qtblptr;
1831 JDIMENSION jtemp;
1832 UINT16 qtemp;
1833
1834 /* Transpose image dimensions */
1835 jtemp = dstinfo->image_width;
1836 dstinfo->image_width = dstinfo->image_height;
1837 dstinfo->image_height = jtemp;
1838 #if JPEG_LIB_VERSION >= 70
1839 itemp = dstinfo->min_DCT_h_scaled_size;
1840 dstinfo->min_DCT_h_scaled_size = dstinfo->min_DCT_v_scaled_size;
1841 dstinfo->min_DCT_v_scaled_size = itemp;
1842 #endif
1843
1844 /* Transpose sampling factors */
1845 for (ci = 0; ci < dstinfo->num_components; ci++) {
1846 compptr = dstinfo->comp_info + ci;
1847 itemp = compptr->h_samp_factor;
1848 compptr->h_samp_factor = compptr->v_samp_factor;
1849 compptr->v_samp_factor = itemp;
1850 }
1851
1852 /* Transpose quantization tables */
1853 for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
1854 qtblptr = dstinfo->quant_tbl_ptrs[tblno];
1855 if (qtblptr != NULL) {
1856 for (i = 0; i < DCTSIZE; i++) {
1857 for (j = 0; j < i; j++) {
1858 qtemp = qtblptr->quantval[i * DCTSIZE + j];
1859 qtblptr->quantval[i * DCTSIZE + j] =
1860 qtblptr->quantval[j * DCTSIZE + i];
1861 qtblptr->quantval[j * DCTSIZE + i] = qtemp;
1862 }
1863 }
1864 }
1865 }
1866 }
1867
1868
1869 /* Adjust Exif image parameters.
1870 *
1871 * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible.
1872 */
1873
1874 LOCAL(void)
adjust_exif_parameters(JOCTET * data,unsigned int length,JDIMENSION new_width,JDIMENSION new_height)1875 adjust_exif_parameters(JOCTET *data, unsigned int length, JDIMENSION new_width,
1876 JDIMENSION new_height)
1877 {
1878 boolean is_motorola; /* Flag for byte order */
1879 unsigned int number_of_tags, tagnum;
1880 unsigned int firstoffset, offset;
1881 JDIMENSION new_value;
1882
1883 if (length < 12) return; /* Length of an IFD entry */
1884
1885 /* Discover byte order */
1886 if (data[0] == 0x49 && data[1] == 0x49)
1887 is_motorola = FALSE;
1888 else if (data[0] == 0x4D && data[1] == 0x4D)
1889 is_motorola = TRUE;
1890 else
1891 return;
1892
1893 /* Check Tag Mark */
1894 if (is_motorola) {
1895 if (data[2] != 0) return;
1896 if (data[3] != 0x2A) return;
1897 } else {
1898 if (data[3] != 0) return;
1899 if (data[2] != 0x2A) return;
1900 }
1901
1902 /* Get first IFD offset (offset to IFD0) */
1903 if (is_motorola) {
1904 if (data[4] != 0) return;
1905 if (data[5] != 0) return;
1906 firstoffset = data[6];
1907 firstoffset <<= 8;
1908 firstoffset += data[7];
1909 } else {
1910 if (data[7] != 0) return;
1911 if (data[6] != 0) return;
1912 firstoffset = data[5];
1913 firstoffset <<= 8;
1914 firstoffset += data[4];
1915 }
1916 if (firstoffset > length - 2) return; /* check end of data segment */
1917
1918 /* Get the number of directory entries contained in this IFD */
1919 if (is_motorola) {
1920 number_of_tags = data[firstoffset];
1921 number_of_tags <<= 8;
1922 number_of_tags += data[firstoffset + 1];
1923 } else {
1924 number_of_tags = data[firstoffset + 1];
1925 number_of_tags <<= 8;
1926 number_of_tags += data[firstoffset];
1927 }
1928 if (number_of_tags == 0) return;
1929 firstoffset += 2;
1930
1931 /* Search for ExifSubIFD offset Tag in IFD0 */
1932 for (;;) {
1933 if (firstoffset > length - 12) return; /* check end of data segment */
1934 /* Get Tag number */
1935 if (is_motorola) {
1936 tagnum = data[firstoffset];
1937 tagnum <<= 8;
1938 tagnum += data[firstoffset + 1];
1939 } else {
1940 tagnum = data[firstoffset + 1];
1941 tagnum <<= 8;
1942 tagnum += data[firstoffset];
1943 }
1944 if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */
1945 if (--number_of_tags == 0) return;
1946 firstoffset += 12;
1947 }
1948
1949 /* Get the ExifSubIFD offset */
1950 if (is_motorola) {
1951 if (data[firstoffset + 8] != 0) return;
1952 if (data[firstoffset + 9] != 0) return;
1953 offset = data[firstoffset + 10];
1954 offset <<= 8;
1955 offset += data[firstoffset + 11];
1956 } else {
1957 if (data[firstoffset + 11] != 0) return;
1958 if (data[firstoffset + 10] != 0) return;
1959 offset = data[firstoffset + 9];
1960 offset <<= 8;
1961 offset += data[firstoffset + 8];
1962 }
1963 if (offset > length - 2) return; /* check end of data segment */
1964
1965 /* Get the number of directory entries contained in this SubIFD */
1966 if (is_motorola) {
1967 number_of_tags = data[offset];
1968 number_of_tags <<= 8;
1969 number_of_tags += data[offset + 1];
1970 } else {
1971 number_of_tags = data[offset + 1];
1972 number_of_tags <<= 8;
1973 number_of_tags += data[offset];
1974 }
1975 if (number_of_tags < 2) return;
1976 offset += 2;
1977
1978 /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */
1979 do {
1980 if (offset > length - 12) return; /* check end of data segment */
1981 /* Get Tag number */
1982 if (is_motorola) {
1983 tagnum = data[offset];
1984 tagnum <<= 8;
1985 tagnum += data[offset + 1];
1986 } else {
1987 tagnum = data[offset + 1];
1988 tagnum <<= 8;
1989 tagnum += data[offset];
1990 }
1991 if (tagnum == 0xA002 || tagnum == 0xA003) {
1992 if (tagnum == 0xA002)
1993 new_value = new_width; /* ExifImageWidth Tag */
1994 else
1995 new_value = new_height; /* ExifImageHeight Tag */
1996 if (is_motorola) {
1997 data[offset + 2] = 0; /* Format = unsigned long (4 octets) */
1998 data[offset + 3] = 4;
1999 data[offset + 4] = 0; /* Number Of Components = 1 */
2000 data[offset + 5] = 0;
2001 data[offset + 6] = 0;
2002 data[offset + 7] = 1;
2003 data[offset + 8] = 0;
2004 data[offset + 9] = 0;
2005 data[offset + 10] = (JOCTET)((new_value >> 8) & 0xFF);
2006 data[offset + 11] = (JOCTET)(new_value & 0xFF);
2007 } else {
2008 data[offset + 2] = 4; /* Format = unsigned long (4 octets) */
2009 data[offset + 3] = 0;
2010 data[offset + 4] = 1; /* Number Of Components = 1 */
2011 data[offset + 5] = 0;
2012 data[offset + 6] = 0;
2013 data[offset + 7] = 0;
2014 data[offset + 8] = (JOCTET)(new_value & 0xFF);
2015 data[offset + 9] = (JOCTET)((new_value >> 8) & 0xFF);
2016 data[offset + 10] = 0;
2017 data[offset + 11] = 0;
2018 }
2019 }
2020 offset += 12;
2021 } while (--number_of_tags);
2022 }
2023
2024
2025 /* Adjust output image parameters as needed.
2026 *
2027 * This must be called after jpeg_copy_critical_parameters()
2028 * and before jpeg_write_coefficients().
2029 *
2030 * The return value is the set of virtual coefficient arrays to be written
2031 * (either the ones allocated by jtransform_request_workspace, or the
2032 * original source data arrays). The caller will need to pass this value
2033 * to jpeg_write_coefficients().
2034 */
2035
2036 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)2037 jtransform_adjust_parameters(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
2038 jvirt_barray_ptr *src_coef_arrays,
2039 jpeg_transform_info *info)
2040 {
2041 /* If force-to-grayscale is requested, adjust destination parameters */
2042 if (info->force_grayscale) {
2043 /* First, ensure we have YCbCr or grayscale data, and that the source's
2044 * Y channel is full resolution. (No reasonable person would make Y
2045 * be less than full resolution, so actually coping with that case
2046 * isn't worth extra code space. But we check it to avoid crashing.)
2047 */
2048 if (((dstinfo->jpeg_color_space == JCS_YCbCr &&
2049 dstinfo->num_components == 3) ||
2050 (dstinfo->jpeg_color_space == JCS_GRAYSCALE &&
2051 dstinfo->num_components == 1)) &&
2052 srcinfo->comp_info[0].h_samp_factor == srcinfo->max_h_samp_factor &&
2053 srcinfo->comp_info[0].v_samp_factor == srcinfo->max_v_samp_factor) {
2054 /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
2055 * properly. Among other things, it sets the target h_samp_factor &
2056 * v_samp_factor to 1, which typically won't match the source.
2057 * We have to preserve the source's quantization table number, however.
2058 */
2059 int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no;
2060 jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE);
2061 dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no;
2062 } else {
2063 /* Sorry, can't do it */
2064 ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL);
2065 }
2066 } else if (info->num_components == 1) {
2067 /* For a single-component source, we force the destination sampling factors
2068 * to 1x1, with or without force_grayscale. This is useful because some
2069 * decoders choke on grayscale images with other sampling factors.
2070 */
2071 dstinfo->comp_info[0].h_samp_factor = 1;
2072 dstinfo->comp_info[0].v_samp_factor = 1;
2073 }
2074
2075 /* Correct the destination's image dimensions as necessary
2076 * for rotate/flip, resize, and crop operations.
2077 */
2078 #if JPEG_LIB_VERSION >= 80
2079 dstinfo->jpeg_width = info->output_width;
2080 dstinfo->jpeg_height = info->output_height;
2081 #endif
2082
2083 /* Transpose destination image parameters, adjust quantization */
2084 switch (info->transform) {
2085 case JXFORM_TRANSPOSE:
2086 case JXFORM_TRANSVERSE:
2087 case JXFORM_ROT_90:
2088 case JXFORM_ROT_270:
2089 #if JPEG_LIB_VERSION < 80
2090 dstinfo->image_width = info->output_height;
2091 dstinfo->image_height = info->output_width;
2092 #endif
2093 transpose_critical_parameters(dstinfo);
2094 break;
2095 case JXFORM_DROP:
2096 if (info->drop_width != 0 && info->drop_height != 0)
2097 adjust_quant(srcinfo, src_coef_arrays,
2098 info->drop_ptr, info->drop_coef_arrays,
2099 info->trim, dstinfo);
2100 break;
2101 default:
2102 #if JPEG_LIB_VERSION < 80
2103 dstinfo->image_width = info->output_width;
2104 dstinfo->image_height = info->output_height;
2105 #endif
2106 break;
2107 }
2108
2109 /* Adjust Exif properties */
2110 if (srcinfo->marker_list != NULL &&
2111 srcinfo->marker_list->marker == JPEG_APP0 + 1 &&
2112 srcinfo->marker_list->data_length >= 6 &&
2113 srcinfo->marker_list->data[0] == 0x45 &&
2114 srcinfo->marker_list->data[1] == 0x78 &&
2115 srcinfo->marker_list->data[2] == 0x69 &&
2116 srcinfo->marker_list->data[3] == 0x66 &&
2117 srcinfo->marker_list->data[4] == 0 &&
2118 srcinfo->marker_list->data[5] == 0) {
2119 /* Suppress output of JFIF marker */
2120 dstinfo->write_JFIF_header = FALSE;
2121 /* Adjust Exif image parameters */
2122 #if JPEG_LIB_VERSION >= 80
2123 if (dstinfo->jpeg_width != srcinfo->image_width ||
2124 dstinfo->jpeg_height != srcinfo->image_height)
2125 /* Align data segment to start of TIFF structure for parsing */
2126 adjust_exif_parameters(srcinfo->marker_list->data + 6,
2127 srcinfo->marker_list->data_length - 6,
2128 dstinfo->jpeg_width, dstinfo->jpeg_height);
2129 #else
2130 if (dstinfo->image_width != srcinfo->image_width ||
2131 dstinfo->image_height != srcinfo->image_height)
2132 /* Align data segment to start of TIFF structure for parsing */
2133 adjust_exif_parameters(srcinfo->marker_list->data + 6,
2134 srcinfo->marker_list->data_length - 6,
2135 dstinfo->image_width, dstinfo->image_height);
2136 #endif
2137 }
2138
2139 /* Return the appropriate output data set */
2140 if (info->workspace_coef_arrays != NULL)
2141 return info->workspace_coef_arrays;
2142 return src_coef_arrays;
2143 }
2144
2145
2146 /* Execute the actual transformation, if any.
2147 *
2148 * This must be called *after* jpeg_write_coefficients, because it depends
2149 * on jpeg_write_coefficients to have computed subsidiary values such as
2150 * the per-component width and height fields in the destination object.
2151 *
2152 * Note that some transformations will modify the source data arrays!
2153 */
2154
2155 GLOBAL(void)
jtransform_execute_transform(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,jvirt_barray_ptr * src_coef_arrays,jpeg_transform_info * info)2156 jtransform_execute_transform(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
2157 jvirt_barray_ptr *src_coef_arrays,
2158 jpeg_transform_info *info)
2159 {
2160 jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays;
2161
2162 /* Note: conditions tested here should match those in switch statement
2163 * in jtransform_request_workspace()
2164 */
2165 switch (info->transform) {
2166 case JXFORM_NONE:
2167 if (info->output_width > srcinfo->output_width ||
2168 info->output_height > srcinfo->output_height) {
2169 if (info->output_width > srcinfo->output_width &&
2170 info->crop_width_set == JCROP_REFLECT)
2171 do_crop_ext_reflect(srcinfo, dstinfo,
2172 info->x_crop_offset, info->y_crop_offset,
2173 src_coef_arrays, dst_coef_arrays);
2174 else if (info->output_width > srcinfo->output_width &&
2175 info->crop_width_set == JCROP_FORCE)
2176 do_crop_ext_flat(srcinfo, dstinfo,
2177 info->x_crop_offset, info->y_crop_offset,
2178 src_coef_arrays, dst_coef_arrays);
2179 else
2180 do_crop_ext_zero(srcinfo, dstinfo,
2181 info->x_crop_offset, info->y_crop_offset,
2182 src_coef_arrays, dst_coef_arrays);
2183 } else if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
2184 do_crop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2185 src_coef_arrays, dst_coef_arrays);
2186 break;
2187 case JXFORM_FLIP_H:
2188 if (info->y_crop_offset != 0 || info->slow_hflip)
2189 do_flip_h(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2190 src_coef_arrays, dst_coef_arrays);
2191 else
2192 do_flip_h_no_crop(srcinfo, dstinfo, info->x_crop_offset,
2193 src_coef_arrays);
2194 break;
2195 case JXFORM_FLIP_V:
2196 do_flip_v(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2197 src_coef_arrays, dst_coef_arrays);
2198 break;
2199 case JXFORM_TRANSPOSE:
2200 do_transpose(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2201 src_coef_arrays, dst_coef_arrays);
2202 break;
2203 case JXFORM_TRANSVERSE:
2204 do_transverse(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2205 src_coef_arrays, dst_coef_arrays);
2206 break;
2207 case JXFORM_ROT_90:
2208 do_rot_90(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2209 src_coef_arrays, dst_coef_arrays);
2210 break;
2211 case JXFORM_ROT_180:
2212 do_rot_180(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2213 src_coef_arrays, dst_coef_arrays);
2214 break;
2215 case JXFORM_ROT_270:
2216 do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2217 src_coef_arrays, dst_coef_arrays);
2218 break;
2219 case JXFORM_WIPE:
2220 if (info->crop_width_set == JCROP_REFLECT &&
2221 info->y_crop_offset == 0 && info->drop_height ==
2222 (JDIMENSION)jdiv_round_up
2223 ((long)info->output_height, (long)info->iMCU_sample_height) &&
2224 (info->x_crop_offset == 0 ||
2225 info->x_crop_offset + info->drop_width ==
2226 (JDIMENSION)jdiv_round_up
2227 ((long)info->output_width, (long)info->iMCU_sample_width)))
2228 do_reflect(srcinfo, dstinfo, info->x_crop_offset,
2229 src_coef_arrays, info->drop_width, info->drop_height);
2230 else if (info->crop_width_set == JCROP_FORCE)
2231 do_flatten(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2232 src_coef_arrays, info->drop_width, info->drop_height);
2233 else
2234 do_wipe(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2235 src_coef_arrays, info->drop_width, info->drop_height);
2236 break;
2237 case JXFORM_DROP:
2238 if (info->drop_width != 0 && info->drop_height != 0)
2239 do_drop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2240 src_coef_arrays, info->drop_ptr, info->drop_coef_arrays,
2241 info->drop_width, info->drop_height);
2242 break;
2243 }
2244 }
2245
2246 /* jtransform_perfect_transform
2247 *
2248 * Determine whether lossless transformation is perfectly
2249 * possible for a specified image and transformation.
2250 *
2251 * Inputs:
2252 * image_width, image_height: source image dimensions.
2253 * MCU_width, MCU_height: pixel dimensions of MCU.
2254 * transform: transformation identifier.
2255 * Parameter sources from initialized jpeg_struct
2256 * (after reading source header):
2257 * image_width = cinfo.image_width
2258 * image_height = cinfo.image_height
2259 * MCU_width = cinfo.max_h_samp_factor * cinfo.block_size
2260 * MCU_height = cinfo.max_v_samp_factor * cinfo.block_size
2261 * Result:
2262 * TRUE = perfect transformation possible
2263 * FALSE = perfect transformation not possible
2264 * (may use custom action then)
2265 */
2266
2267 GLOBAL(boolean)
jtransform_perfect_transform(JDIMENSION image_width,JDIMENSION image_height,int MCU_width,int MCU_height,JXFORM_CODE transform)2268 jtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height,
2269 int MCU_width, int MCU_height,
2270 JXFORM_CODE transform)
2271 {
2272 boolean result = TRUE; /* initialize TRUE */
2273
2274 switch (transform) {
2275 case JXFORM_FLIP_H:
2276 case JXFORM_ROT_270:
2277 if (image_width % (JDIMENSION)MCU_width)
2278 result = FALSE;
2279 break;
2280 case JXFORM_FLIP_V:
2281 case JXFORM_ROT_90:
2282 if (image_height % (JDIMENSION)MCU_height)
2283 result = FALSE;
2284 break;
2285 case JXFORM_TRANSVERSE:
2286 case JXFORM_ROT_180:
2287 if (image_width % (JDIMENSION)MCU_width)
2288 result = FALSE;
2289 if (image_height % (JDIMENSION)MCU_height)
2290 result = FALSE;
2291 break;
2292 default:
2293 break;
2294 }
2295
2296 return result;
2297 }
2298
2299 #endif /* TRANSFORMS_SUPPORTED */
2300
2301
2302 /* Setup decompression object to save desired markers in memory.
2303 * This must be called before jpeg_read_header() to have the desired effect.
2304 */
2305
2306 GLOBAL(void)
jcopy_markers_setup(j_decompress_ptr srcinfo,JCOPY_OPTION option)2307 jcopy_markers_setup(j_decompress_ptr srcinfo, JCOPY_OPTION option)
2308 {
2309 #ifdef SAVE_MARKERS_SUPPORTED
2310 int m;
2311
2312 /* Save comments except under NONE option */
2313 if (option != JCOPYOPT_NONE) {
2314 jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF);
2315 }
2316 /* Save all types of APPn markers iff ALL option */
2317 if (option == JCOPYOPT_ALL || option == JCOPYOPT_ALL_EXCEPT_ICC) {
2318 for (m = 0; m < 16; m++) {
2319 if (option == JCOPYOPT_ALL_EXCEPT_ICC && m == 2)
2320 continue;
2321 jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF);
2322 }
2323 }
2324 #endif /* SAVE_MARKERS_SUPPORTED */
2325 }
2326
2327 /* Copy markers saved in the given source object to the destination object.
2328 * This should be called just after jpeg_start_compress() or
2329 * jpeg_write_coefficients().
2330 * Note that those routines will have written the SOI, and also the
2331 * JFIF APP0 or Adobe APP14 markers if selected.
2332 */
2333
2334 GLOBAL(void)
jcopy_markers_execute(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JCOPY_OPTION option)2335 jcopy_markers_execute(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
2336 JCOPY_OPTION option)
2337 {
2338 jpeg_saved_marker_ptr marker;
2339
2340 /* In the current implementation, we don't actually need to examine the
2341 * option flag here; we just copy everything that got saved.
2342 * But to avoid confusion, we do not output JFIF and Adobe APP14 markers
2343 * if the encoder library already wrote one.
2344 */
2345 for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) {
2346 if (dstinfo->write_JFIF_header &&
2347 marker->marker == JPEG_APP0 &&
2348 marker->data_length >= 5 &&
2349 marker->data[0] == 0x4A &&
2350 marker->data[1] == 0x46 &&
2351 marker->data[2] == 0x49 &&
2352 marker->data[3] == 0x46 &&
2353 marker->data[4] == 0)
2354 continue; /* reject duplicate JFIF */
2355 if (dstinfo->write_Adobe_marker &&
2356 marker->marker == JPEG_APP0 + 14 &&
2357 marker->data_length >= 5 &&
2358 marker->data[0] == 0x41 &&
2359 marker->data[1] == 0x64 &&
2360 marker->data[2] == 0x6F &&
2361 marker->data[3] == 0x62 &&
2362 marker->data[4] == 0x65)
2363 continue; /* reject duplicate Adobe */
2364 jpeg_write_marker(dstinfo, marker->marker,
2365 marker->data, marker->data_length);
2366 }
2367 }
2368