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