1 /* Copyright (C) 2001-2012 Artifex Software, Inc.
4 This software is provided AS-IS with no warranty, either express or
7 This software is distributed under license and may not be copied,
8 modified or distributed except as expressly authorized under the terms
9 of the license contained in the file LICENSE in this distribution.
11 Refer to licensing information at http://www.artifex.com or contact
12 Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
13 CA 94903, U.S.A., +1(415)492-9861, for further information.
22 * Generic region handlers.
31 #include <string.h> /* memcpy(), memset() */
38 #include "jbig2_priv.h"
39 #include "jbig2_image.h"
40 #include "jbig2_arith.h"
41 #include "jbig2_generic.h"
42 #include "jbig2_mmr.h"
44 /* return the appropriate context size for the given template */
46 jbig2_generic_stats_size(Jbig2Ctx *ctx, int template)
48 int stats_size = template == 0 ? 1 << 16 :
49 template == 1 ? 1 << 1 << 13 : 1 << 10;
55 jbig2_decode_generic_template0(Jbig2Ctx *ctx,
56 Jbig2Segment *segment,
57 const Jbig2GenericRegionParams *params,
60 Jbig2ArithCx *GB_stats)
62 const int GBW = image->width;
63 const int GBH = image->height;
64 const int rowstride = image->stride;
66 byte *gbreg_line = (byte *)image->data;
68 /* todo: currently we only handle the nominal gbat location */
71 printf("P4\n%d %d\n", GBW, GBH);
77 for (y = 0; y < GBH; y++)
82 int padded_width = (GBW + 7) & -8;
84 line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0;
85 line_m2 = (y >= 2) ? gbreg_line[-(rowstride << 1)] << 6 : 0;
86 CONTEXT = (line_m1 & 0x7f0) | (line_m2 & 0xf800);
89 for (x = 0; x < padded_width; x += 8)
93 int minor_width = GBW - x > 8 ? 8 : GBW - x;
96 line_m1 = (line_m1 << 8) |
97 (x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0);
100 line_m2 = (line_m2 << 8) |
101 (x + 8 < GBW ? gbreg_line[-(rowstride << 1) + (x >> 3) + 1] << 6: 0);
103 /* This is the speed-critical inner loop. */
104 for (x_minor = 0; x_minor < minor_width; x_minor++)
108 bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
111 result |= bit << (7 - x_minor);
112 CONTEXT = ((CONTEXT & 0x7bf7) << 1) | bit |
113 ((line_m1 >> (7 - x_minor)) & 0x10) |
114 ((line_m2 >> (7 - x_minor)) & 0x800);
116 gbreg_line[x >> 3] = result;
119 fwrite(gbreg_line, 1, rowstride, stdout);
121 gbreg_line += rowstride;
128 jbig2_decode_generic_template0_unopt(Jbig2Ctx *ctx,
129 Jbig2Segment *segment,
130 const Jbig2GenericRegionParams *params,
133 Jbig2ArithCx *GB_stats)
135 const int GBW = image->width;
136 const int GBH = image->height;
141 /* this version is generic and easy to understand, but very slow */
143 for (y = 0; y < GBH; y++) {
144 for (x = 0; x < GBW; x++) {
146 CONTEXT |= jbig2_image_get_pixel(image, x - 1, y) << 0;
147 CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
148 CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
149 CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3;
150 CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0],
151 y + params->gbat[1]) << 4;
152 CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 1) << 5;
153 CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 6;
154 CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 7;
155 CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 8;
156 CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 9;
157 CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[2],
158 y + params->gbat[3]) << 10;
159 CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[4],
160 y + params->gbat[5]) << 11;
161 CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 12;
162 CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 2) << 13;
163 CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 14;
164 CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[6],
165 y + params->gbat[7]) << 15;
166 bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
169 jbig2_image_set_pixel(image, x, y, bit);
176 jbig2_decode_generic_template1(Jbig2Ctx *ctx,
177 Jbig2Segment *segment,
178 const Jbig2GenericRegionParams *params,
181 Jbig2ArithCx *GB_stats)
183 const int GBW = image->width;
184 const int GBH = image->height;
185 const int rowstride = image->stride;
187 byte *gbreg_line = (byte *)image->data;
189 /* todo: currently we only handle the nominal gbat location */
192 printf("P4\n%d %d\n", GBW, GBH);
198 for (y = 0; y < GBH; y++)
203 int padded_width = (GBW + 7) & -8;
205 line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0;
206 line_m2 = (y >= 2) ? gbreg_line[-(rowstride << 1)] << 5 : 0;
207 CONTEXT = ((line_m1 >> 1) & 0x1f8) | ((line_m2 >> 1) & 0x1e00);
210 for (x = 0; x < padded_width; x += 8)
214 int minor_width = GBW - x > 8 ? 8 : GBW - x;
217 line_m1 = (line_m1 << 8) |
218 (x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0);
221 line_m2 = (line_m2 << 8) |
222 (x + 8 < GBW ? gbreg_line[-(rowstride << 1) + (x >> 3) + 1] << 5: 0);
224 /* This is the speed-critical inner loop. */
225 for (x_minor = 0; x_minor < minor_width; x_minor++)
229 bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
232 result |= bit << (7 - x_minor);
233 CONTEXT = ((CONTEXT & 0xefb) << 1) | bit |
234 ((line_m1 >> (8 - x_minor)) & 0x8) |
235 ((line_m2 >> (8 - x_minor)) & 0x200);
237 gbreg_line[x >> 3] = result;
240 fwrite(gbreg_line, 1, rowstride, stdout);
242 gbreg_line += rowstride;
249 jbig2_decode_generic_template2(Jbig2Ctx *ctx,
250 Jbig2Segment *segment,
251 const Jbig2GenericRegionParams *params,
254 Jbig2ArithCx *GB_stats)
256 const int GBW = image->width;
257 const int GBH = image->height;
258 const int rowstride = image->stride;
260 byte *gbreg_line = (byte *)image->data;
262 /* todo: currently we only handle the nominal gbat location */
265 printf("P4\n%d %d\n", GBW, GBH);
271 for (y = 0; y < GBH; y++)
276 int padded_width = (GBW + 7) & -8;
278 line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0;
279 line_m2 = (y >= 2) ? gbreg_line[-(rowstride << 1)] << 4 : 0;
280 CONTEXT = ((line_m1 >> 3) & 0x7c) | ((line_m2 >> 3) & 0x380);
283 for (x = 0; x < padded_width; x += 8)
287 int minor_width = GBW - x > 8 ? 8 : GBW - x;
290 line_m1 = (line_m1 << 8) |
291 (x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0);
294 line_m2 = (line_m2 << 8) |
295 (x + 8 < GBW ? gbreg_line[-(rowstride << 1) + (x >> 3) + 1] << 4: 0);
297 /* This is the speed-critical inner loop. */
298 for (x_minor = 0; x_minor < minor_width; x_minor++)
302 bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
305 result |= bit << (7 - x_minor);
306 CONTEXT = ((CONTEXT & 0x1bd) << 1) | bit |
307 ((line_m1 >> (10 - x_minor)) & 0x4) |
308 ((line_m2 >> (10 - x_minor)) & 0x80);
310 gbreg_line[x >> 3] = result;
313 fwrite(gbreg_line, 1, rowstride, stdout);
315 gbreg_line += rowstride;
322 jbig2_decode_generic_template2a(Jbig2Ctx *ctx,
323 Jbig2Segment *segment,
324 const Jbig2GenericRegionParams *params,
327 Jbig2ArithCx *GB_stats)
329 const int GBW = image->width;
330 const int GBH = image->height;
331 const int rowstride = image->stride;
333 byte *gbreg_line = (byte *)image->data;
335 /* This is a special case for GBATX1 = 3, GBATY1 = -1 */
338 printf("P4\n%d %d\n", GBW, GBH);
344 for (y = 0; y < GBH; y++)
349 int padded_width = (GBW + 7) & -8;
351 line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0;
352 line_m2 = (y >= 2) ? gbreg_line[-(rowstride << 1)] << 4 : 0;
353 CONTEXT = ((line_m1 >> 3) & 0x78) | ((line_m1 >> 2) & 0x4) | ((line_m2 >> 3) & 0x380);
356 for (x = 0; x < padded_width; x += 8)
360 int minor_width = GBW - x > 8 ? 8 : GBW - x;
363 line_m1 = (line_m1 << 8) |
364 (x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0);
367 line_m2 = (line_m2 << 8) |
368 (x + 8 < GBW ? gbreg_line[-(rowstride << 1) + (x >> 3) + 1] << 4: 0);
370 /* This is the speed-critical inner loop. */
371 for (x_minor = 0; x_minor < minor_width; x_minor++)
375 bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
378 result |= bit << (7 - x_minor);
379 CONTEXT = ((CONTEXT & 0x1b9) << 1) | bit |
380 ((line_m1 >> (10 - x_minor)) & 0x8) |
381 ((line_m1 >> (9 - x_minor)) & 0x4) |
382 ((line_m2 >> (10 - x_minor)) & 0x80);
384 gbreg_line[x >> 3] = result;
387 fwrite(gbreg_line, 1, rowstride, stdout);
389 gbreg_line += rowstride;
396 jbig2_decode_generic_template3(Jbig2Ctx *ctx,
397 Jbig2Segment *segment,
398 const Jbig2GenericRegionParams *params,
401 Jbig2ArithCx *GB_stats)
403 const int GBW = image->width;
404 const int GBH = image->height;
405 const int rowstride = image->stride;
406 byte *gbreg_line = (byte *)image->data;
409 /* this routine only handles the nominal AT location */
412 printf("P4\n%d %d\n", GBW, GBH);
418 for (y = 0; y < GBH; y++)
422 int padded_width = (GBW + 7) & -8;
424 line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0;
425 CONTEXT = (line_m1 >> 1) & 0x3f0;
428 for (x = 0; x < padded_width; x += 8)
432 int minor_width = GBW - x > 8 ? 8 : GBW - x;
435 line_m1 = (line_m1 << 8) |
436 (x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0);
438 /* This is the speed-critical inner loop. */
439 for (x_minor = 0; x_minor < minor_width; x_minor++)
443 bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
446 result |= bit << (7 - x_minor);
447 CONTEXT = ((CONTEXT & 0x1f7) << 1) | bit |
448 ((line_m1 >> (10 - x_minor)) & 0x010);
450 gbreg_line[x >> 3] = result;
453 fwrite(gbreg_line, 1, rowstride, stdout);
455 gbreg_line += rowstride;
462 jbig2_decode_generic_template3_unopt(Jbig2Ctx *ctx,
463 Jbig2Segment *segment,
464 const Jbig2GenericRegionParams *params,
467 Jbig2ArithCx *GB_stats)
469 const int GBW = image->width;
470 const int GBH = image->height;
475 /* this version is generic and easy to understand, but very slow */
477 for (y = 0; y < GBH; y++) {
478 for (x = 0; x < GBW; x++) {
480 CONTEXT |= jbig2_image_get_pixel(image, x - 1, y) << 0;
481 CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
482 CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
483 CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3;
484 CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0],
485 y + params->gbat[1]) << 4;
486 CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 5;
487 CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 6;
488 CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7;
489 CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8;
490 CONTEXT |= jbig2_image_get_pixel(image, x - 3, y - 1) << 9;
491 bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
494 jbig2_image_set_pixel(image, x, y, bit);
501 copy_prev_row(Jbig2Image *image, int row)
504 /* no previous row */
505 memset( image->data, 0, image->stride );
507 /* duplicate data from the previous row */
508 uint8_t *src = image->data + (row - 1) * image->stride;
509 memcpy( src + image->stride, src, image->stride );
514 jbig2_decode_generic_template0_TPGDON(Jbig2Ctx *ctx,
515 Jbig2Segment *segment,
516 const Jbig2GenericRegionParams *params,
519 Jbig2ArithCx *GB_stats)
521 const int GBW = image->width;
522 const int GBH = image->height;
528 for (y = 0; y < GBH; y++)
530 bit = jbig2_arith_decode(as, &GB_stats[0x9B25]);
535 for (x = 0; x < GBW; x++) {
536 CONTEXT = jbig2_image_get_pixel(image, x - 1, y);
537 CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
538 CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
539 CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3;
540 CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0],
541 y + params->gbat[1]) << 4;
542 CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 1) << 5;
543 CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 6;
544 CONTEXT |= jbig2_image_get_pixel(image, x , y - 1) << 7;
545 CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 8;
546 CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 9;
547 CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[2],
548 y + params->gbat[3]) << 10;
549 CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[4],
550 y + params->gbat[5]) << 11;
551 CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 12;
552 CONTEXT |= jbig2_image_get_pixel(image, x , y - 2) << 13;
553 CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 14;
554 CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[6],
555 y + params->gbat[7]) << 15;
556 bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
559 jbig2_image_set_pixel(image, x, y, bit);
562 copy_prev_row(image, y);
570 jbig2_decode_generic_template1_TPGDON(Jbig2Ctx *ctx,
571 Jbig2Segment *segment,
572 const Jbig2GenericRegionParams *params,
575 Jbig2ArithCx *GB_stats)
577 const int GBW = image->width;
578 const int GBH = image->height;
584 for (y = 0; y < GBH; y++) {
585 bit = jbig2_arith_decode(as, &GB_stats[0x0795]);
590 for (x = 0; x < GBW; x++) {
591 CONTEXT = jbig2_image_get_pixel(image, x - 1, y);
592 CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
593 CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
594 CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0],
595 y + params->gbat[1]) << 3;
596 CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 1) << 4;
597 CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 5;
598 CONTEXT |= jbig2_image_get_pixel(image, x , y - 1) << 6;
599 CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7;
600 CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8;
601 CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 2) << 9;
602 CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 10;
603 CONTEXT |= jbig2_image_get_pixel(image, x , y - 2) << 11;
604 CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 12;
605 bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
608 jbig2_image_set_pixel(image, x, y, bit);
611 copy_prev_row(image, y);
619 jbig2_decode_generic_template2_TPGDON(Jbig2Ctx *ctx,
620 Jbig2Segment *segment,
621 const Jbig2GenericRegionParams *params,
624 Jbig2ArithCx *GB_stats)
626 const int GBW = image->width;
627 const int GBH = image->height;
633 for (y = 0; y < GBH; y++) {
634 bit = jbig2_arith_decode(as, &GB_stats[0xE5]);
639 for (x = 0; x < GBW; x++) {
640 CONTEXT = jbig2_image_get_pixel(image, x - 1, y);
641 CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
642 CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0],
643 y + params->gbat[1]) << 2;
644 CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 3;
645 CONTEXT |= jbig2_image_get_pixel(image, x , y - 1) << 4;
646 CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 5;
647 CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 6;
648 CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 7;
649 CONTEXT |= jbig2_image_get_pixel(image, x , y - 2) << 8;
650 CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 9;
651 bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
654 jbig2_image_set_pixel(image, x, y, bit);
657 copy_prev_row(image, y);
665 jbig2_decode_generic_template3_TPGDON(Jbig2Ctx *ctx,
666 Jbig2Segment *segment,
667 const Jbig2GenericRegionParams *params,
670 Jbig2ArithCx *GB_stats)
672 const int GBW = image->width;
673 const int GBH = image->height;
679 for (y = 0; y < GBH; y++) {
680 bit = jbig2_arith_decode(as, &GB_stats[0x0195]);
685 for (x = 0; x < GBW; x++) {
686 CONTEXT = jbig2_image_get_pixel(image, x - 1, y);
687 CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
688 CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
689 CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3;
690 CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0],
691 y + params->gbat[1]) << 4;
692 CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 5;
693 CONTEXT |= jbig2_image_get_pixel(image, x , y - 1) << 6;
694 CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7;
695 CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8;
696 CONTEXT |= jbig2_image_get_pixel(image, x - 3, y - 1) << 9;
697 bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
700 jbig2_image_set_pixel(image, x, y, bit);
703 copy_prev_row(image, y);
711 jbig2_decode_generic_region_TPGDON(Jbig2Ctx *ctx,
712 Jbig2Segment *segment,
713 const Jbig2GenericRegionParams *params,
716 Jbig2ArithCx *GB_stats)
718 switch (params->GBTEMPLATE) {
720 return jbig2_decode_generic_template0_TPGDON(ctx, segment,
721 params, as, image, GB_stats);
723 return jbig2_decode_generic_template1_TPGDON(ctx, segment,
724 params, as, image, GB_stats);
726 return jbig2_decode_generic_template2_TPGDON(ctx, segment,
727 params, as, image, GB_stats);
729 return jbig2_decode_generic_template3_TPGDON(ctx, segment,
730 params, as, image, GB_stats);
737 * jbig2_decode_generic_region: Decode a generic region.
738 * @ctx: The context for allocation and error reporting.
739 * @segment: A segment reference for error reporting.
740 * @params: Decoding parameter set.
741 * @as: Arithmetic decoder state.
742 * @image: Where to store the decoded data.
743 * @GB_stats: Arithmetic stats.
745 * Decodes a generic region, according to section 6.2. The caller should
746 * pass an already allocated Jbig2Image object for @image
748 * Because this API is based on an arithmetic decoding state, it is
749 * not suitable for MMR decoding.
751 * Return code: 0 on success.
754 jbig2_decode_generic_region(Jbig2Ctx *ctx,
755 Jbig2Segment *segment,
756 const Jbig2GenericRegionParams *params,
759 Jbig2ArithCx *GB_stats)
761 const int8_t *gbat = params->gbat;
763 if (image->stride * image->height > (1 << 24) && segment->data_length < image->stride * image->height / 256) {
764 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
765 "region is far larger than data provided (%d << %d), aborting to prevent DOS",
766 segment->data_length, image->stride * image->height);
769 if (!params->MMR && params->TPGDON)
770 return jbig2_decode_generic_region_TPGDON(ctx, segment, params,
771 as, image, GB_stats);
773 if (!params->MMR && params->GBTEMPLATE == 0) {
774 if (gbat[0] == +3 && gbat[1] == -1 &&
775 gbat[2] == -3 && gbat[3] == -1 &&
776 gbat[4] == +2 && gbat[5] == -2 &&
777 gbat[6] == -2 && gbat[7] == -2)
778 return jbig2_decode_generic_template0(ctx, segment, params,
779 as, image, GB_stats);
781 return jbig2_decode_generic_template0_unopt(ctx, segment, params,
782 as, image, GB_stats);
783 } else if (!params->MMR && params->GBTEMPLATE == 1)
784 return jbig2_decode_generic_template1(ctx, segment, params,
785 as, image, GB_stats);
786 else if (!params->MMR && params->GBTEMPLATE == 2)
788 if (gbat[0] == 3 && gbat[1] == -1)
789 return jbig2_decode_generic_template2a(ctx, segment, params,
790 as, image, GB_stats);
792 return jbig2_decode_generic_template2(ctx, segment, params,
793 as, image, GB_stats);
795 else if (!params->MMR && params->GBTEMPLATE == 3) {
796 if (gbat[0] == 2 && gbat[1] == -1)
797 return jbig2_decode_generic_template3_unopt(ctx, segment, params,
798 as, image, GB_stats);
800 return jbig2_decode_generic_template3_unopt(ctx, segment, params,
801 as, image, GB_stats);
806 for (i = 0; i < 8; i++)
807 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
808 "gbat[%d] = %d", i, params->gbat[i]);
810 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
811 "decode_generic_region: MMR=%d, GBTEMPLATE=%d NYI",
812 params->MMR, params->GBTEMPLATE);
817 * Handler for immediate generic region segments
820 jbig2_immediate_generic_region(Jbig2Ctx *ctx, Jbig2Segment *segment,
821 const byte *segment_data)
823 Jbig2RegionSegmentInfo rsi;
828 Jbig2GenericRegionParams params;
830 Jbig2Image *image = NULL;
831 Jbig2WordStream *ws = NULL;
832 Jbig2ArithState *as = NULL;
833 Jbig2ArithCx *GB_stats = NULL;
836 if (segment->data_length < 18)
837 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
838 "Segment too short");
840 jbig2_get_region_segment_info(&rsi, segment_data);
841 jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
842 "generic region: %d x %d @ (%d, %d), flags = %02x",
843 rsi.width, rsi.height, rsi.x, rsi.y, rsi.flags);
846 seg_flags = segment_data[17];
847 jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
848 "segment flags = %02x", seg_flags);
849 if ((seg_flags & 1) && (seg_flags & 6))
850 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
851 "MMR is 1, but GBTEMPLATE is not 0");
854 if (!(seg_flags & 1))
856 gbat_bytes = (seg_flags & 6) ? 2 : 8;
857 if (18 + gbat_bytes > segment->data_length)
858 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
859 "Segment too short");
860 memcpy(gbat, segment_data + 18, gbat_bytes);
861 jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
862 "gbat: %d, %d", gbat[0], gbat[1]);
865 offset = 18 + gbat_bytes;
868 params.MMR = seg_flags & 1;
869 params.GBTEMPLATE = (seg_flags & 6) >> 1;
870 params.TPGDON = (seg_flags & 8) >> 3;
872 memcpy (params.gbat, gbat, gbat_bytes);
874 image = jbig2_image_new(ctx, rsi.width, rsi.height);
876 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
877 "unable to allocate generic image");
878 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
879 "allocated %d x %d image buffer for region decode results",
880 rsi.width, rsi.height);
884 code = jbig2_decode_generic_mmr(ctx, segment, ¶ms,
885 segment_data + offset, segment->data_length - offset, image);
889 int stats_size = jbig2_generic_stats_size(ctx, params.GBTEMPLATE);
890 GB_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);
891 if (GB_stats == NULL)
893 code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
894 "unable to allocate GB_stats in jbig2_immediate_generic_region");
897 memset(GB_stats, 0, stats_size);
899 ws = jbig2_word_stream_buf_new(ctx, segment_data + offset,
900 segment->data_length - offset);
903 code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
904 "unable to allocate ws in jbig2_immediate_generic_region");
907 as = jbig2_arith_new(ctx, ws);
910 code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
911 "unable to allocate as in jbig2_immediate_generic_region");
914 code = jbig2_decode_generic_region(ctx, segment, ¶ms,
915 as, image, GB_stats);
919 jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page],
920 image, rsi.x, rsi.y, rsi.op);
922 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
923 "error while decoding immediate_generic_region");
926 jbig2_free(ctx->allocator, as);
927 jbig2_word_stream_buf_free(ctx, ws);
928 jbig2_free(ctx->allocator, GB_stats);
929 jbig2_image_release(ctx, image);