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