Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
8619 | maxcodehac | 1 | /* |
2 | jbig2dec |
||
3 | |||
4 | Copyright (C) 2002-2005 Artifex Software, Inc. |
||
5 | |||
6 | This software is provided AS-IS with no warranty, |
||
7 | either express or implied. |
||
8 | |||
9 | This software is distributed under license and may not |
||
10 | be copied, modified or distributed except as expressly |
||
11 | authorized under the terms of the license contained in |
||
12 | the file LICENSE in this distribution. |
||
13 | |||
14 | For further licensing information refer to http://artifex.com/ or |
||
15 | contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, |
||
16 | San Rafael, CA 94903, U.S.A., +1(415)492-9861. |
||
17 | */ |
||
18 | |||
19 | /** |
||
20 | * Generic region handlers. |
||
21 | **/ |
||
22 | |||
23 | #ifdef HAVE_CONFIG_H |
||
24 | #include "config.h" |
||
25 | #endif |
||
26 | #include "os_types.h" |
||
27 | |||
28 | #include |
||
29 | #include |
||
30 | |||
31 | #ifdef OUTPUT_PBM |
||
32 | #include |
||
33 | #endif |
||
34 | |||
35 | #include "jbig2.h" |
||
36 | #include "jbig2_priv.h" |
||
37 | #include "jbig2_image.h" |
||
38 | #include "jbig2_arith.h" |
||
39 | #include "jbig2_generic.h" |
||
40 | #include "jbig2_mmr.h" |
||
41 | |||
42 | /* return the appropriate context size for the given template */ |
||
43 | int |
||
44 | jbig2_generic_stats_size(Jbig2Ctx *ctx, int template) |
||
45 | { |
||
46 | int stats_size = template == 0 ? 1 << 16 : |
||
47 | template == 1 ? 1 << 1 << 13 : 1 << 10; |
||
48 | return stats_size; |
||
49 | } |
||
50 | |||
51 | |||
52 | static int |
||
53 | jbig2_decode_generic_template0(Jbig2Ctx *ctx, |
||
54 | Jbig2Segment *segment, |
||
55 | const Jbig2GenericRegionParams *params, |
||
56 | Jbig2ArithState *as, |
||
57 | Jbig2Image *image, |
||
58 | Jbig2ArithCx *GB_stats) |
||
59 | { |
||
60 | const int GBW = image->width; |
||
61 | const int GBH = image->height; |
||
62 | const int rowstride = image->stride; |
||
63 | int x, y; |
||
64 | byte *gbreg_line = (byte *)image->data; |
||
65 | |||
66 | /* todo: currently we only handle the nominal gbat location */ |
||
67 | |||
68 | #ifdef OUTPUT_PBM |
||
69 | printf("P4\n%d %d\n", GBW, GBH); |
||
70 | #endif |
||
71 | |||
72 | for (y = 0; y < GBH; y++) |
||
73 | { |
||
74 | uint32_t CONTEXT; |
||
75 | uint32_t line_m1; |
||
76 | uint32_t line_m2; |
||
77 | int padded_width = (GBW + 7) & -8; |
||
78 | |||
79 | line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0; |
||
80 | line_m2 = (y >= 2) ? gbreg_line[-(rowstride << 1)] << 6 : 0; |
||
81 | CONTEXT = (line_m1 & 0x7f0) | (line_m2 & 0xf800); |
||
82 | |||
83 | /* 6.2.5.7 3d */ |
||
84 | for (x = 0; x < padded_width; x += 8) |
||
85 | { |
||
86 | byte result = 0; |
||
87 | int x_minor; |
||
88 | int minor_width = GBW - x > 8 ? 8 : GBW - x; |
||
89 | |||
90 | if (y >= 1) |
||
91 | line_m1 = (line_m1 << 8) | |
||
92 | (x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0); |
||
93 | |||
94 | if (y >= 2) |
||
95 | line_m2 = (line_m2 << 8) | |
||
96 | (x + 8 < GBW ? gbreg_line[-(rowstride << 1) + (x >> 3) + 1] << 6: 0); |
||
97 | |||
98 | /* This is the speed-critical inner loop. */ |
||
99 | for (x_minor = 0; x_minor < minor_width; x_minor++) |
||
100 | { |
||
101 | bool bit; |
||
102 | |||
103 | bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]); |
||
104 | result |= bit << (7 - x_minor); |
||
105 | CONTEXT = ((CONTEXT & 0x7bf7) << 1) | bit | |
||
106 | ((line_m1 >> (7 - x_minor)) & 0x10) | |
||
107 | ((line_m2 >> (7 - x_minor)) & 0x800); |
||
108 | } |
||
109 | gbreg_line[x >> 3] = result; |
||
110 | } |
||
111 | #ifdef OUTPUT_PBM |
||
112 | fwrite(gbreg_line, 1, rowstride, stdout); |
||
113 | #endif |
||
114 | gbreg_line += rowstride; |
||
115 | } |
||
116 | |||
117 | return 0; |
||
118 | } |
||
119 | |||
120 | static int |
||
121 | jbig2_decode_generic_template0_unopt(Jbig2Ctx *ctx, |
||
122 | Jbig2Segment *segment, |
||
123 | const Jbig2GenericRegionParams *params, |
||
124 | Jbig2ArithState *as, |
||
125 | Jbig2Image *image, |
||
126 | Jbig2ArithCx *GB_stats) |
||
127 | { |
||
128 | const int GBW = image->width; |
||
129 | const int GBH = image->height; |
||
130 | uint32_t CONTEXT; |
||
131 | int x,y; |
||
132 | bool bit; |
||
133 | |||
134 | /* this version is generic and easy to understand, but very slow */ |
||
135 | |||
136 | for (y = 0; y < GBH; y++) { |
||
137 | for (x = 0; x < GBW; x++) { |
||
138 | CONTEXT = 0; |
||
139 | CONTEXT |= jbig2_image_get_pixel(image, x - 1, y) << 0; |
||
140 | CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1; |
||
141 | CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2; |
||
142 | CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3; |
||
143 | CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], |
||
144 | y + params->gbat[1]) << 4; |
||
145 | CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 1) << 5; |
||
146 | CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 6; |
||
147 | CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 7; |
||
148 | CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 8; |
||
149 | CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 9; |
||
150 | CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[2], |
||
151 | y + params->gbat[3]) << 10; |
||
152 | CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[4], |
||
153 | y + params->gbat[5]) << 11; |
||
154 | CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 12; |
||
155 | CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 2) << 13; |
||
156 | CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 14; |
||
157 | CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[6], |
||
158 | y + params->gbat[7]) << 15; |
||
159 | bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]); |
||
160 | jbig2_image_set_pixel(image, x, y, bit); |
||
161 | } |
||
162 | } |
||
163 | return 0; |
||
164 | } |
||
165 | |||
166 | static int |
||
167 | jbig2_decode_generic_template1(Jbig2Ctx *ctx, |
||
168 | Jbig2Segment *segment, |
||
169 | const Jbig2GenericRegionParams *params, |
||
170 | Jbig2ArithState *as, |
||
171 | Jbig2Image *image, |
||
172 | Jbig2ArithCx *GB_stats) |
||
173 | { |
||
174 | const int GBW = image->width; |
||
175 | const int GBH = image->height; |
||
176 | const int rowstride = image->stride; |
||
177 | int x, y; |
||
178 | byte *gbreg_line = (byte *)image->data; |
||
179 | |||
180 | /* todo: currently we only handle the nominal gbat location */ |
||
181 | |||
182 | #ifdef OUTPUT_PBM |
||
183 | printf("P4\n%d %d\n", GBW, GBH); |
||
184 | #endif |
||
185 | |||
186 | for (y = 0; y < GBH; y++) |
||
187 | { |
||
188 | uint32_t CONTEXT; |
||
189 | uint32_t line_m1; |
||
190 | uint32_t line_m2; |
||
191 | int padded_width = (GBW + 7) & -8; |
||
192 | |||
193 | line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0; |
||
194 | line_m2 = (y >= 2) ? gbreg_line[-(rowstride << 1)] << 5 : 0; |
||
195 | CONTEXT = ((line_m1 >> 1) & 0x1f8) | ((line_m2 >> 1) & 0x1e00); |
||
196 | |||
197 | /* 6.2.5.7 3d */ |
||
198 | for (x = 0; x < padded_width; x += 8) |
||
199 | { |
||
200 | byte result = 0; |
||
201 | int x_minor; |
||
202 | int minor_width = GBW - x > 8 ? 8 : GBW - x; |
||
203 | |||
204 | if (y >= 1) |
||
205 | line_m1 = (line_m1 << 8) | |
||
206 | (x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0); |
||
207 | |||
208 | if (y >= 2) |
||
209 | line_m2 = (line_m2 << 8) | |
||
210 | (x + 8 < GBW ? gbreg_line[-(rowstride << 1) + (x >> 3) + 1] << 5: 0); |
||
211 | |||
212 | /* This is the speed-critical inner loop. */ |
||
213 | for (x_minor = 0; x_minor < minor_width; x_minor++) |
||
214 | { |
||
215 | bool bit; |
||
216 | |||
217 | bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]); |
||
218 | result |= bit << (7 - x_minor); |
||
219 | CONTEXT = ((CONTEXT & 0xefb) << 1) | bit | |
||
220 | ((line_m1 >> (8 - x_minor)) & 0x8) | |
||
221 | ((line_m2 >> (8 - x_minor)) & 0x200); |
||
222 | } |
||
223 | gbreg_line[x >> 3] = result; |
||
224 | } |
||
225 | #ifdef OUTPUT_PBM |
||
226 | fwrite(gbreg_line, 1, rowstride, stdout); |
||
227 | #endif |
||
228 | gbreg_line += rowstride; |
||
229 | } |
||
230 | |||
231 | return 0; |
||
232 | } |
||
233 | |||
234 | static int |
||
235 | jbig2_decode_generic_template2(Jbig2Ctx *ctx, |
||
236 | Jbig2Segment *segment, |
||
237 | const Jbig2GenericRegionParams *params, |
||
238 | Jbig2ArithState *as, |
||
239 | Jbig2Image *image, |
||
240 | Jbig2ArithCx *GB_stats) |
||
241 | { |
||
242 | const int GBW = image->width; |
||
243 | const int GBH = image->height; |
||
244 | const int rowstride = image->stride; |
||
245 | int x, y; |
||
246 | byte *gbreg_line = (byte *)image->data; |
||
247 | |||
248 | /* todo: currently we only handle the nominal gbat location */ |
||
249 | |||
250 | #ifdef OUTPUT_PBM |
||
251 | printf("P4\n%d %d\n", GBW, GBH); |
||
252 | #endif |
||
253 | |||
254 | for (y = 0; y < GBH; y++) |
||
255 | { |
||
256 | uint32_t CONTEXT; |
||
257 | uint32_t line_m1; |
||
258 | uint32_t line_m2; |
||
259 | int padded_width = (GBW + 7) & -8; |
||
260 | |||
261 | line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0; |
||
262 | line_m2 = (y >= 2) ? gbreg_line[-(rowstride << 1)] << 4 : 0; |
||
263 | CONTEXT = ((line_m1 >> 3) & 0x7c) | ((line_m2 >> 3) & 0x380); |
||
264 | |||
265 | /* 6.2.5.7 3d */ |
||
266 | for (x = 0; x < padded_width; x += 8) |
||
267 | { |
||
268 | byte result = 0; |
||
269 | int x_minor; |
||
270 | int minor_width = GBW - x > 8 ? 8 : GBW - x; |
||
271 | |||
272 | if (y >= 1) |
||
273 | line_m1 = (line_m1 << 8) | |
||
274 | (x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0); |
||
275 | |||
276 | if (y >= 2) |
||
277 | line_m2 = (line_m2 << 8) | |
||
278 | (x + 8 < GBW ? gbreg_line[-(rowstride << 1) + (x >> 3) + 1] << 4: 0); |
||
279 | |||
280 | /* This is the speed-critical inner loop. */ |
||
281 | for (x_minor = 0; x_minor < minor_width; x_minor++) |
||
282 | { |
||
283 | bool bit; |
||
284 | |||
285 | bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]); |
||
286 | result |= bit << (7 - x_minor); |
||
287 | CONTEXT = ((CONTEXT & 0x1bd) << 1) | bit | |
||
288 | ((line_m1 >> (10 - x_minor)) & 0x4) | |
||
289 | ((line_m2 >> (10 - x_minor)) & 0x80); |
||
290 | } |
||
291 | gbreg_line[x >> 3] = result; |
||
292 | } |
||
293 | #ifdef OUTPUT_PBM |
||
294 | fwrite(gbreg_line, 1, rowstride, stdout); |
||
295 | #endif |
||
296 | gbreg_line += rowstride; |
||
297 | } |
||
298 | |||
299 | return 0; |
||
300 | } |
||
301 | |||
302 | static int |
||
303 | jbig2_decode_generic_template2a(Jbig2Ctx *ctx, |
||
304 | Jbig2Segment *segment, |
||
305 | const Jbig2GenericRegionParams *params, |
||
306 | Jbig2ArithState *as, |
||
307 | Jbig2Image *image, |
||
308 | Jbig2ArithCx *GB_stats) |
||
309 | { |
||
310 | const int GBW = image->width; |
||
311 | const int GBH = image->height; |
||
312 | const int rowstride = image->stride; |
||
313 | int x, y; |
||
314 | byte *gbreg_line = (byte *)image->data; |
||
315 | |||
316 | /* This is a special case for GBATX1 = 3, GBATY1 = -1 */ |
||
317 | |||
318 | #ifdef OUTPUT_PBM |
||
319 | printf("P4\n%d %d\n", GBW, GBH); |
||
320 | #endif |
||
321 | |||
322 | for (y = 0; y < GBH; y++) |
||
323 | { |
||
324 | uint32_t CONTEXT; |
||
325 | uint32_t line_m1; |
||
326 | uint32_t line_m2; |
||
327 | int padded_width = (GBW + 7) & -8; |
||
328 | |||
329 | line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0; |
||
330 | line_m2 = (y >= 2) ? gbreg_line[-(rowstride << 1)] << 4 : 0; |
||
331 | CONTEXT = ((line_m1 >> 3) & 0x78) | ((line_m1 >> 2) & 0x4) | ((line_m2 >> 3) & 0x380); |
||
332 | |||
333 | /* 6.2.5.7 3d */ |
||
334 | for (x = 0; x < padded_width; x += 8) |
||
335 | { |
||
336 | byte result = 0; |
||
337 | int x_minor; |
||
338 | int minor_width = GBW - x > 8 ? 8 : GBW - x; |
||
339 | |||
340 | if (y >= 1) |
||
341 | line_m1 = (line_m1 << 8) | |
||
342 | (x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0); |
||
343 | |||
344 | if (y >= 2) |
||
345 | line_m2 = (line_m2 << 8) | |
||
346 | (x + 8 < GBW ? gbreg_line[-(rowstride << 1) + (x >> 3) + 1] << 4: 0); |
||
347 | |||
348 | /* This is the speed-critical inner loop. */ |
||
349 | for (x_minor = 0; x_minor < minor_width; x_minor++) |
||
350 | { |
||
351 | bool bit; |
||
352 | |||
353 | bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]); |
||
354 | result |= bit << (7 - x_minor); |
||
355 | CONTEXT = ((CONTEXT & 0x1b9) << 1) | bit | |
||
356 | ((line_m1 >> (10 - x_minor)) & 0x8) | |
||
357 | ((line_m1 >> (9 - x_minor)) & 0x4) | |
||
358 | ((line_m2 >> (10 - x_minor)) & 0x80); |
||
359 | } |
||
360 | gbreg_line[x >> 3] = result; |
||
361 | } |
||
362 | #ifdef OUTPUT_PBM |
||
363 | fwrite(gbreg_line, 1, rowstride, stdout); |
||
364 | #endif |
||
365 | gbreg_line += rowstride; |
||
366 | } |
||
367 | |||
368 | return 0; |
||
369 | } |
||
370 | |||
371 | static int |
||
372 | jbig2_decode_generic_template3(Jbig2Ctx *ctx, |
||
373 | Jbig2Segment *segment, |
||
374 | const Jbig2GenericRegionParams *params, |
||
375 | Jbig2ArithState *as, |
||
376 | Jbig2Image *image, |
||
377 | Jbig2ArithCx *GB_stats) |
||
378 | { |
||
379 | const int GBW = image->width; |
||
380 | const int GBH = image->height; |
||
381 | const int rowstride = image->stride; |
||
382 | byte *gbreg_line = (byte *)image->data; |
||
383 | int x, y; |
||
384 | |||
385 | /* this routine only handles the nominal AT location */ |
||
386 | |||
387 | #ifdef OUTPUT_PBM |
||
388 | printf("P4\n%d %d\n", GBW, GBH); |
||
389 | #endif |
||
390 | |||
391 | for (y = 0; y < GBH; y++) |
||
392 | { |
||
393 | uint32_t CONTEXT; |
||
394 | uint32_t line_m1; |
||
395 | int padded_width = (GBW + 7) & -8; |
||
396 | |||
397 | line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0; |
||
398 | CONTEXT = (line_m1 >> 1) & 0x3f0; |
||
399 | |||
400 | /* 6.2.5.7 3d */ |
||
401 | for (x = 0; x < padded_width; x += 8) |
||
402 | { |
||
403 | byte result = 0; |
||
404 | int x_minor; |
||
405 | int minor_width = GBW - x > 8 ? 8 : GBW - x; |
||
406 | |||
407 | if (y >= 1) |
||
408 | line_m1 = (line_m1 << 8) | |
||
409 | (x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0); |
||
410 | |||
411 | /* This is the speed-critical inner loop. */ |
||
412 | for (x_minor = 0; x_minor < minor_width; x_minor++) |
||
413 | { |
||
414 | bool bit; |
||
415 | |||
416 | bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]); |
||
417 | result |= bit << (7 - x_minor); |
||
418 | CONTEXT = ((CONTEXT & 0x1f7) << 1) | bit | |
||
419 | ((line_m1 >> (10 - x_minor)) & 0x010); |
||
420 | } |
||
421 | gbreg_line[x >> 3] = result; |
||
422 | } |
||
423 | #ifdef OUTPUT_PBM |
||
424 | fwrite(gbreg_line, 1, rowstride, stdout); |
||
425 | #endif |
||
426 | gbreg_line += rowstride; |
||
427 | } |
||
428 | |||
429 | return 0; |
||
430 | } |
||
431 | |||
432 | static int |
||
433 | jbig2_decode_generic_template3_unopt(Jbig2Ctx *ctx, |
||
434 | Jbig2Segment *segment, |
||
435 | const Jbig2GenericRegionParams *params, |
||
436 | Jbig2ArithState *as, |
||
437 | Jbig2Image *image, |
||
438 | Jbig2ArithCx *GB_stats) |
||
439 | { |
||
440 | const int GBW = image->width; |
||
441 | const int GBH = image->height; |
||
442 | uint32_t CONTEXT; |
||
443 | int x,y; |
||
444 | bool bit; |
||
445 | |||
446 | /* this version is generic and easy to understand, but very slow */ |
||
447 | |||
448 | for (y = 0; y < GBH; y++) { |
||
449 | for (x = 0; x < GBW; x++) { |
||
450 | CONTEXT = 0; |
||
451 | CONTEXT |= jbig2_image_get_pixel(image, x - 1, y) << 0; |
||
452 | CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1; |
||
453 | CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2; |
||
454 | CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3; |
||
455 | CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], |
||
456 | y + params->gbat[1]) << 4; |
||
457 | CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 5; |
||
458 | CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 6; |
||
459 | CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7; |
||
460 | CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8; |
||
461 | CONTEXT |= jbig2_image_get_pixel(image, x - 3, y - 1) << 9; |
||
462 | bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]); |
||
463 | jbig2_image_set_pixel(image, x, y, bit); |
||
464 | } |
||
465 | } |
||
466 | return 0; |
||
467 | } |
||
468 | |||
469 | static void |
||
470 | copy_prev_row(Jbig2Image *image, int row) |
||
471 | { |
||
472 | if (!row) { |
||
473 | /* no previous row */ |
||
474 | memset( image->data, 0, image->stride ); |
||
475 | } else { |
||
476 | /* duplicate data from the previous row */ |
||
477 | uint8_t *src = image->data + (row - 1) * image->stride; |
||
478 | memcpy( src + image->stride, src, image->stride ); |
||
479 | } |
||
480 | } |
||
481 | |||
482 | static int |
||
483 | jbig2_decode_generic_template0_TPGDON(Jbig2Ctx *ctx, |
||
484 | Jbig2Segment *segment, |
||
485 | const Jbig2GenericRegionParams *params, |
||
486 | Jbig2ArithState *as, |
||
487 | Jbig2Image *image, |
||
488 | Jbig2ArithCx *GB_stats) |
||
489 | { |
||
490 | const int GBW = image->width; |
||
491 | const int GBH = image->height; |
||
492 | uint32_t CONTEXT; |
||
493 | int x, y; |
||
494 | bool bit; |
||
495 | int LTP = 0; |
||
496 | |||
497 | for (y = 0; y < GBH; y++) |
||
498 | { |
||
499 | LTP ^= jbig2_arith_decode(as, &GB_stats[0x9B25]); |
||
500 | if (!LTP) { |
||
501 | for (x = 0; x < GBW; x++) { |
||
502 | CONTEXT = jbig2_image_get_pixel(image, x - 1, y); |
||
503 | CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1; |
||
504 | CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2; |
||
505 | CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3; |
||
506 | CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], |
||
507 | y + params->gbat[1]) << 4; |
||
508 | CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 1) << 5; |
||
509 | CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 6; |
||
510 | CONTEXT |= jbig2_image_get_pixel(image, x , y - 1) << 7; |
||
511 | CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 8; |
||
512 | CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 9; |
||
513 | CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[2], |
||
514 | y + params->gbat[3]) << 10; |
||
515 | CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[4], |
||
516 | y + params->gbat[5]) << 11; |
||
517 | CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 12; |
||
518 | CONTEXT |= jbig2_image_get_pixel(image, x , y - 2) << 13; |
||
519 | CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 14; |
||
520 | CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[6], |
||
521 | y + params->gbat[7]) << 15; |
||
522 | bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]); |
||
523 | jbig2_image_set_pixel(image, x, y, bit); |
||
524 | } |
||
525 | } else { |
||
526 | copy_prev_row(image, y); |
||
527 | } |
||
528 | } |
||
529 | |||
530 | return 0; |
||
531 | } |
||
532 | |||
533 | static int |
||
534 | jbig2_decode_generic_template1_TPGDON(Jbig2Ctx *ctx, |
||
535 | Jbig2Segment *segment, |
||
536 | const Jbig2GenericRegionParams *params, |
||
537 | Jbig2ArithState *as, |
||
538 | Jbig2Image *image, |
||
539 | Jbig2ArithCx *GB_stats) |
||
540 | { |
||
541 | const int GBW = image->width; |
||
542 | const int GBH = image->height; |
||
543 | uint32_t CONTEXT; |
||
544 | int x, y; |
||
545 | bool bit; |
||
546 | int LTP = 0; |
||
547 | |||
548 | for (y = 0; y < GBH; y++) { |
||
549 | LTP ^= jbig2_arith_decode(as, &GB_stats[0x0795]); |
||
550 | if (!LTP) { |
||
551 | for (x = 0; x < GBW; x++) { |
||
552 | CONTEXT = jbig2_image_get_pixel(image, x - 1, y); |
||
553 | CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1; |
||
554 | CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2; |
||
555 | CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], |
||
556 | y + params->gbat[1]) << 3; |
||
557 | CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 1) << 4; |
||
558 | CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 5; |
||
559 | CONTEXT |= jbig2_image_get_pixel(image, x , y - 1) << 6; |
||
560 | CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7; |
||
561 | CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8; |
||
562 | CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 2) << 9; |
||
563 | CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 10; |
||
564 | CONTEXT |= jbig2_image_get_pixel(image, x , y - 2) << 11; |
||
565 | CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 12; |
||
566 | bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]); |
||
567 | jbig2_image_set_pixel(image, x, y, bit); |
||
568 | } |
||
569 | } else { |
||
570 | copy_prev_row(image, y); |
||
571 | } |
||
572 | } |
||
573 | |||
574 | return 0; |
||
575 | } |
||
576 | |||
577 | static int |
||
578 | jbig2_decode_generic_template2_TPGDON(Jbig2Ctx *ctx, |
||
579 | Jbig2Segment *segment, |
||
580 | const Jbig2GenericRegionParams *params, |
||
581 | Jbig2ArithState *as, |
||
582 | Jbig2Image *image, |
||
583 | Jbig2ArithCx *GB_stats) |
||
584 | { |
||
585 | const int GBW = image->width; |
||
586 | const int GBH = image->height; |
||
587 | uint32_t CONTEXT; |
||
588 | int x, y; |
||
589 | bool bit; |
||
590 | int LTP = 0; |
||
591 | |||
592 | for (y = 0; y < GBH; y++) { |
||
593 | LTP ^= jbig2_arith_decode(as, &GB_stats[0xE5]); |
||
594 | if (!LTP) { |
||
595 | for (x = 0; x < GBW; x++) { |
||
596 | CONTEXT = jbig2_image_get_pixel(image, x - 1, y); |
||
597 | CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1; |
||
598 | CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], |
||
599 | y + params->gbat[1]) << 2; |
||
600 | CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 3; |
||
601 | CONTEXT |= jbig2_image_get_pixel(image, x , y - 1) << 4; |
||
602 | CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 5; |
||
603 | CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 6; |
||
604 | CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 7; |
||
605 | CONTEXT |= jbig2_image_get_pixel(image, x , y - 2) << 8; |
||
606 | CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 9; |
||
607 | bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]); |
||
608 | jbig2_image_set_pixel(image, x, y, bit); |
||
609 | } |
||
610 | } else { |
||
611 | copy_prev_row(image, y); |
||
612 | } |
||
613 | } |
||
614 | |||
615 | return 0; |
||
616 | } |
||
617 | |||
618 | static int |
||
619 | jbig2_decode_generic_template3_TPGDON(Jbig2Ctx *ctx, |
||
620 | Jbig2Segment *segment, |
||
621 | const Jbig2GenericRegionParams *params, |
||
622 | Jbig2ArithState *as, |
||
623 | Jbig2Image *image, |
||
624 | Jbig2ArithCx *GB_stats) |
||
625 | { |
||
626 | const int GBW = image->width; |
||
627 | const int GBH = image->height; |
||
628 | uint32_t CONTEXT; |
||
629 | int x, y; |
||
630 | bool bit; |
||
631 | int LTP = 0; |
||
632 | |||
633 | for (y = 0; y < GBH; y++) { |
||
634 | LTP ^= jbig2_arith_decode(as, &GB_stats[0x0195]); |
||
635 | if (!LTP) { |
||
636 | for (x = 0; x < GBW; x++) { |
||
637 | CONTEXT = jbig2_image_get_pixel(image, x - 1, y); |
||
638 | CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1; |
||
639 | CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2; |
||
640 | CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3; |
||
641 | CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], |
||
642 | y + params->gbat[1]) << 4; |
||
643 | CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 5; |
||
644 | CONTEXT |= jbig2_image_get_pixel(image, x , y - 1) << 6; |
||
645 | CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7; |
||
646 | CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8; |
||
647 | CONTEXT |= jbig2_image_get_pixel(image, x - 3, y - 1) << 9; |
||
648 | bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]); |
||
649 | jbig2_image_set_pixel(image, x, y, bit); |
||
650 | } |
||
651 | } else { |
||
652 | copy_prev_row(image, y); |
||
653 | } |
||
654 | } |
||
655 | |||
656 | return 0; |
||
657 | } |
||
658 | |||
659 | static int |
||
660 | jbig2_decode_generic_region_TPGDON(Jbig2Ctx *ctx, |
||
661 | Jbig2Segment *segment, |
||
662 | const Jbig2GenericRegionParams *params, |
||
663 | Jbig2ArithState *as, |
||
664 | Jbig2Image *image, |
||
665 | Jbig2ArithCx *GB_stats) |
||
666 | { |
||
667 | switch (params->GBTEMPLATE) { |
||
668 | case 0: |
||
669 | return jbig2_decode_generic_template0_TPGDON(ctx, segment, |
||
670 | params, as, image, GB_stats); |
||
671 | case 1: |
||
672 | return jbig2_decode_generic_template1_TPGDON(ctx, segment, |
||
673 | params, as, image, GB_stats); |
||
674 | case 2: |
||
675 | return jbig2_decode_generic_template2_TPGDON(ctx, segment, |
||
676 | params, as, image, GB_stats); |
||
677 | case 3: |
||
678 | return jbig2_decode_generic_template3_TPGDON(ctx, segment, |
||
679 | params, as, image, GB_stats); |
||
680 | } |
||
681 | |||
682 | return -1; |
||
683 | } |
||
684 | |||
685 | /** |
||
686 | * jbig2_decode_generic_region: Decode a generic region. |
||
687 | * @ctx: The context for allocation and error reporting. |
||
688 | * @segment: A segment reference for error reporting. |
||
689 | * @params: Decoding parameter set. |
||
690 | * @as: Arithmetic decoder state. |
||
691 | * @image: Where to store the decoded data. |
||
692 | * @GB_stats: Arithmetic stats. |
||
693 | * |
||
694 | * Decodes a generic region, according to section 6.2. The caller should |
||
695 | * pass an already allocated Jbig2Image object for @image |
||
696 | * |
||
697 | * Because this API is based on an arithmetic decoding state, it is |
||
698 | * not suitable for MMR decoding. |
||
699 | * |
||
700 | * Return code: 0 on success. |
||
701 | **/ |
||
702 | int |
||
703 | jbig2_decode_generic_region(Jbig2Ctx *ctx, |
||
704 | Jbig2Segment *segment, |
||
705 | const Jbig2GenericRegionParams *params, |
||
706 | Jbig2ArithState *as, |
||
707 | Jbig2Image *image, |
||
708 | Jbig2ArithCx *GB_stats) |
||
709 | { |
||
710 | const int8_t *gbat = params->gbat; |
||
711 | |||
712 | if (!params->MMR && params->TPGDON) |
||
713 | return jbig2_decode_generic_region_TPGDON(ctx, segment, params, |
||
714 | as, image, GB_stats); |
||
715 | |||
716 | if (!params->MMR && params->GBTEMPLATE == 0) { |
||
717 | if (gbat[0] == +3 && gbat[1] == -1 && |
||
718 | gbat[2] == -3 && gbat[3] == -1 && |
||
719 | gbat[4] == +2 && gbat[5] == -2 && |
||
720 | gbat[6] == -2 && gbat[7] == -2) |
||
721 | return jbig2_decode_generic_template0(ctx, segment, params, |
||
722 | as, image, GB_stats); |
||
723 | else |
||
724 | return jbig2_decode_generic_template0_unopt(ctx, segment, params, |
||
725 | as, image, GB_stats); |
||
726 | } else if (!params->MMR && params->GBTEMPLATE == 1) |
||
727 | return jbig2_decode_generic_template1(ctx, segment, params, |
||
728 | as, image, GB_stats); |
||
729 | else if (!params->MMR && params->GBTEMPLATE == 2) |
||
730 | { |
||
731 | if (gbat[0] == 3 && gbat[1] == -1) |
||
732 | return jbig2_decode_generic_template2a(ctx, segment, params, |
||
733 | as, image, GB_stats); |
||
734 | else |
||
735 | return jbig2_decode_generic_template2(ctx, segment, params, |
||
736 | as, image, GB_stats); |
||
737 | } |
||
738 | else if (!params->MMR && params->GBTEMPLATE == 3) { |
||
739 | if (gbat[0] == 2 && gbat[1] == -1) |
||
740 | return jbig2_decode_generic_template3_unopt(ctx, segment, params, |
||
741 | as, image, GB_stats); |
||
742 | else |
||
743 | return jbig2_decode_generic_template3_unopt(ctx, segment, params, |
||
744 | as, image, GB_stats); |
||
745 | } |
||
746 | |||
747 | { |
||
748 | int i; |
||
749 | for (i = 0; i < 8; i++) |
||
750 | jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
||
751 | "gbat[%d] = %d", i, params->gbat[i]); |
||
752 | } |
||
753 | jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
||
754 | "decode_generic_region: MMR=%d, GBTEMPLATE=%d NYI", |
||
755 | params->MMR, params->GBTEMPLATE); |
||
756 | return -1; |
||
757 | } |
||
758 | |||
759 | /** |
||
760 | * Handler for immediate generic region segments |
||
761 | */ |
||
762 | int |
||
763 | jbig2_immediate_generic_region(Jbig2Ctx *ctx, Jbig2Segment *segment, |
||
764 | const byte *segment_data) |
||
765 | { |
||
766 | Jbig2RegionSegmentInfo rsi; |
||
767 | byte seg_flags; |
||
768 | int8_t gbat[8]; |
||
769 | int offset; |
||
770 | int gbat_bytes = 0; |
||
771 | Jbig2GenericRegionParams params; |
||
772 | int code; |
||
773 | Jbig2Image *image; |
||
774 | Jbig2WordStream *ws; |
||
775 | Jbig2ArithState *as; |
||
776 | Jbig2ArithCx *GB_stats = NULL; |
||
777 | |||
778 | /* 7.4.6 */ |
||
779 | if (segment->data_length < 18) |
||
780 | return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
||
781 | "Segment too short"); |
||
782 | |||
783 | jbig2_get_region_segment_info(&rsi, segment_data); |
||
784 | jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
||
785 | "generic region: %d x %d @ (%d, %d), flags = %02x", |
||
786 | rsi.width, rsi.height, rsi.x, rsi.y, rsi.flags); |
||
787 | |||
788 | /* 7.4.6.2 */ |
||
789 | seg_flags = segment_data[17]; |
||
790 | jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
||
791 | "segment flags = %02x", seg_flags); |
||
792 | if ((seg_flags & 1) && (seg_flags & 6)) |
||
793 | jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, |
||
794 | "MMR is 1, but GBTEMPLATE is not 0"); |
||
795 | |||
796 | /* 7.4.6.3 */ |
||
797 | if (!(seg_flags & 1)) |
||
798 | { |
||
799 | gbat_bytes = (seg_flags & 6) ? 2 : 8; |
||
800 | if (18 + gbat_bytes > segment->data_length) |
||
801 | return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
||
802 | "Segment too short"); |
||
803 | memcpy(gbat, segment_data + 18, gbat_bytes); |
||
804 | jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
||
805 | "gbat: %d, %d", gbat[0], gbat[1]); |
||
806 | } |
||
807 | |||
808 | offset = 18 + gbat_bytes; |
||
809 | |||
810 | /* Table 34 */ |
||
811 | params.MMR = seg_flags & 1; |
||
812 | params.GBTEMPLATE = (seg_flags & 6) >> 1; |
||
813 | params.TPGDON = (seg_flags & 8) >> 3; |
||
814 | params.USESKIP = 0; |
||
815 | memcpy (params.gbat, gbat, gbat_bytes); |
||
816 | |||
817 | image = jbig2_image_new(ctx, rsi.width, rsi.height); |
||
818 | if (image == NULL) |
||
819 | return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, |
||
820 | "unable to allocate generic image"); |
||
821 | jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, |
||
822 | "allocated %d x %d image buffer for region decode results", |
||
823 | rsi.width, rsi.height); |
||
824 | |||
825 | if (params.MMR) |
||
826 | { |
||
827 | code = jbig2_decode_generic_mmr(ctx, segment, ¶ms, |
||
828 | segment_data + offset, segment->data_length - offset, |
||
829 | image); |
||
830 | } |
||
831 | else |
||
832 | { |
||
833 | int stats_size = jbig2_generic_stats_size(ctx, params.GBTEMPLATE); |
||
834 | GB_stats = jbig2_alloc(ctx->allocator, stats_size); |
||
835 | memset(GB_stats, 0, stats_size); |
||
836 | |||
837 | ws = jbig2_word_stream_buf_new(ctx, |
||
838 | segment_data + offset, |
||
839 | segment->data_length - offset); |
||
840 | as = jbig2_arith_new(ctx, ws); |
||
841 | code = jbig2_decode_generic_region(ctx, segment, ¶ms, |
||
842 | as, image, GB_stats); |
||
843 | jbig2_free(ctx->allocator, as); |
||
844 | jbig2_word_stream_buf_free(ctx, ws); |
||
845 | |||
846 | jbig2_free(ctx->allocator, GB_stats); |
||
847 | } |
||
848 | |||
849 | jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], |
||
850 | image, rsi.x, rsi.y, JBIG2_COMPOSE_OR); |
||
851 | jbig2_image_release(ctx, image); |
||
852 | |||
853 | return code; |
||
854 | }>>><>><>><>><>><>><>><>><>><>>>><>><>><>><>><>><>><>><>><>>>><>><>><>><>><>><>><>><>><>><>><>><>>>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>>>><>><>><>><>><>><>><>><>><>><>>>><>><>>>><>>>><>><>>><>><>>><>>><>>><>><>>><>><>>><>><>>><>>><>>><>><>>><>><>>><>><>>><>>><>>><>><>>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>>>><>><>>><>><>>><>>><>>><>><>>><>><>><>><> |