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