1/* Copyright (C) 2001-2019 Artifex Software, Inc.
2 All Rights Reserved.
3
4 This software is provided AS-IS with no warranty, either express or
5 implied.
6
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.
10
11 Refer to licensing information at http://www.artifex.com or contact
12 Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato,
13 CA 94945, U.S.A., +1(415)492-9861, for further information.
14*/
15
16/*
17 jbig2dec
18*/
19
20/**
21 * Generic Refinement region handlers.
22 **/
23
24#ifdef HAVE_CONFIG_H
25#include "config.h"
26#endif
27#include "os_types.h"
28
29#include <stddef.h>
30#include <string.h> /* memcpy(), memset() */
31
32#include <stdio.h>
33
34#include "jbig2.h"
35#include "jbig2_priv.h"
36#include "jbig2_arith.h"
37#include "jbig2_generic.h"
38#include "jbig2_image.h"
39#include "jbig2_page.h"
40#include "jbig2_refinement.h"
41#include "jbig2_segment.h"
42
43#define pixel_outside_field(x, y) \
44 ((y) < -128 || (y) > 0 || (x) < -128 || ((y) < 0 && (x) > 127) || ((y) == 0 && (x) >= 0))
45#define refpixel_outside_field(x, y) \
46 ((y) < -128 || (y) > 127 || (x) < -128 || (x) > 127)
47
48static int
49jbig2_decode_refinement_template0_unopt(Jbig2Ctx *ctx,
50 Jbig2Segment *segment,
51 const Jbig2RefinementRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GR_stats)
52{
53 const int GRW = image->width;
54 const int GRH = image->height;
55 Jbig2Image *ref = params->GRREFERENCE;
56 const int dx = params->GRREFERENCEDX;
57 const int dy = params->GRREFERENCEDY;
58 uint32_t CONTEXT;
59 int x, y;
60 bool bit;
61 int code = 0;
62
63 if (pixel_outside_field(params->grat[0], params->grat[1]) ||
64 refpixel_outside_field(params->grat[2], params->grat[3]))
65 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
66 "adaptive template pixel is out of field");
67
68 for (y = 0; y < GRH; y++) {
69 for (x = 0; x < GRW; x++) {
70 CONTEXT = 0;
71 CONTEXT |= jbig2_image_get_pixel(image, x - 1, y + 0) << 0;
72 CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 1;
73 CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 2;
74 CONTEXT |= jbig2_image_get_pixel(image, x + params->grat[0], y + params->grat[1]) << 3;
75 CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 1) << 4;
76 CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 1) << 5;
77 CONTEXT |= jbig2_image_get_pixel(ref, x - dx - 1, y - dy + 1) << 6;
78 CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 0) << 7;
79 CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 0) << 8;
80 CONTEXT |= jbig2_image_get_pixel(ref, x - dx - 1, y - dy + 0) << 9;
81 CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy - 1) << 10;
82 CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy - 1) << 11;
83 CONTEXT |= jbig2_image_get_pixel(ref, x - dx + params->grat[2], y - dy + params->grat[3]) << 12;
84 bit = jbig2_arith_decode(as, &GR_stats[CONTEXT], &code);
85 if (code)
86 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling refinement template0");
87 jbig2_image_set_pixel(image, x, y, bit);
88 }
89 }
90#ifdef JBIG2_DEBUG_DUMP
91 {
92 static count = 0;
93 char name[32];
94 int code;
95
96 snprintf(name, 32, "refin-%d.pbm", count);
97 code = jbig2_image_write_pbm_file(ref, name);
98 if (code < 0)
99 return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed write refinement input");
100 snprintf(name, 32, "refout-%d.pbm", count);
101 code = jbig2_image_write_pbm_file(image, name);
102 if (code < 0)
103 return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed write refinement output");
104 count++;
105 }
106#endif
107
108 return 0;
109}
110
111static int
112jbig2_decode_refinement_template1_unopt(Jbig2Ctx *ctx,
113 Jbig2Segment *segment,
114 const Jbig2RefinementRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GR_stats)
115{
116 const int GRW = image->width;
117 const int GRH = image->height;
118 Jbig2Image *ref = params->GRREFERENCE;
119 const int dx = params->GRREFERENCEDX;
120 const int dy = params->GRREFERENCEDY;
121 uint32_t CONTEXT;
122 int x, y;
123 bool bit;
124 int code = 0;
125
126 for (y = 0; y < GRH; y++) {
127 for (x = 0; x < GRW; x++) {
128 CONTEXT = 0;
129 CONTEXT |= jbig2_image_get_pixel(image, x - 1, y + 0) << 0;
130 CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 1;
131 CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 2;
132 CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 3;
133 CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 1) << 4;
134 CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 1) << 5;
135 CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 0) << 6;
136 CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 0) << 7;
137 CONTEXT |= jbig2_image_get_pixel(ref, x - dx - 1, y - dy + 0) << 8;
138 CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy - 1) << 9;
139 bit = jbig2_arith_decode(as, &GR_stats[CONTEXT], &code);
140 if (code)
141 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling refinement template0");
142 jbig2_image_set_pixel(image, x, y, bit);
143 }
144 }
145
146#ifdef JBIG2_DEBUG_DUMP
147 {
148 static count = 0;
149 char name[32];
150
151 snprintf(name, 32, "refin-%d.pbm", count);
152 code = jbig2_image_write_pbm_file(ref, name);
153 if (code < 0)
154 return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to write refinement input");
155 snprintf(name, 32, "refout-%d.pbm", count);
156 code = jbig2_image_write_pbm_file(image, name);
157 if (code < 0)
158 return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to write refinement output");
159 count++;
160 }
161#endif
162
163 return 0;
164}
165
166#if 0 /* currently not used */
167static int
168jbig2_decode_refinement_template1(Jbig2Ctx *ctx,
169 Jbig2Segment *segment,
170 const Jbig2RefinementRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GR_stats)
171{
172 const int GRW = image->width;
173 const int GRH = image->height;
174 const int stride = image->stride;
175 const int refstride = params->reference->stride;
176 const int dy = params->DY;
177 byte *grreg_line = (byte *) image->data;
178 byte *grref_line = (byte *) params->reference->data;
179 int x, y;
180 int code = 0;
181
182 for (y = 0; y < GRH; y++) {
183 const int padded_width = (GRW + 7) & -8;
184 uint32_t CONTEXT;
185 uint32_t refline_m1; /* previous line of the reference bitmap */
186 uint32_t refline_0; /* current line of the reference bitmap */
187 uint32_t refline_1; /* next line of the reference bitmap */
188 uint32_t line_m1; /* previous line of the decoded bitmap */
189
190 line_m1 = (y >= 1) ? grreg_line[-stride] : 0;
191 refline_m1 = ((y - dy) >= 1) ? grref_line[(-1 - dy) * stride] << 2 : 0;
192 refline_0 = (((y - dy) > 0) && ((y - dy) < GRH)) ? grref_line[(0 - dy) * stride] << 4 : 0;
193 refline_1 = (y < GRH - 1) ? grref_line[(+1 - dy) * stride] << 7 : 0;
194 CONTEXT = ((line_m1 >> 5) & 0x00e) | ((refline_1 >> 5) & 0x030) | ((refline_0 >> 5) & 0x1c0) | ((refline_m1 >> 5) & 0x200);
195
196 for (x = 0; x < padded_width; x += 8) {
197 byte result = 0;
198 int x_minor;
199 const int minor_width = GRW - x > 8 ? 8 : GRW - x;
200
201 if (y >= 1) {
202 line_m1 = (line_m1 << 8) | (x + 8 < GRW ? grreg_line[-stride + (x >> 3) + 1] : 0);
203 refline_m1 = (refline_m1 << 8) | (x + 8 < GRW ? grref_line[-refstride + (x >> 3) + 1] << 2 : 0);
204 }
205
206 refline_0 = (refline_0 << 8) | (x + 8 < GRW ? grref_line[(x >> 3) + 1] << 4 : 0);
207
208 if (y < GRH - 1)
209 refline_1 = (refline_1 << 8) | (x + 8 < GRW ? grref_line[+refstride + (x >> 3) + 1] << 7 : 0);
210 else
211 refline_1 = 0;
212
213 /* this is the speed critical inner-loop */
214 for (x_minor = 0; x_minor < minor_width; x_minor++) {
215 bool bit;
216
217 bit = jbig2_arith_decode(as, &GR_stats[CONTEXT], &code);
218 if (code)
219 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling refinement template1");
220 result |= bit << (7 - x_minor);
221 CONTEXT = ((CONTEXT & 0x0d6) << 1) | bit |
222 ((line_m1 >> (9 - x_minor)) & 0x002) |
223 ((refline_1 >> (9 - x_minor)) & 0x010) | ((refline_0 >> (9 - x_minor)) & 0x040) | ((refline_m1 >> (9 - x_minor)) & 0x200);
224 }
225
226 grreg_line[x >> 3] = result;
227
228 }
229
230 grreg_line += stride;
231 grref_line += refstride;
232
233 }
234
235 return 0;
236
237}
238#endif
239
240typedef uint32_t(*ContextBuilder)(const Jbig2RefinementRegionParams *, Jbig2Image *, int, int);
241
242static int
243implicit_value(const Jbig2RefinementRegionParams *params, Jbig2Image *image, int x, int y)
244{
245 Jbig2Image *ref = params->GRREFERENCE;
246 int i = x - params->GRREFERENCEDX;
247 int j = y - params->GRREFERENCEDY;
248 int m = jbig2_image_get_pixel(ref, i, j);
249
250 return ((jbig2_image_get_pixel(ref, i - 1, j - 1) == m) &&
251 (jbig2_image_get_pixel(ref, i, j - 1) == m) &&
252 (jbig2_image_get_pixel(ref, i + 1, j - 1) == m) &&
253 (jbig2_image_get_pixel(ref, i - 1, j) == m) &&
254 (jbig2_image_get_pixel(ref, i + 1, j) == m) &&
255 (jbig2_image_get_pixel(ref, i - 1, j + 1) == m) &&
256 (jbig2_image_get_pixel(ref, i, j + 1) == m) &&
257 (jbig2_image_get_pixel(ref, i + 1, j + 1) == m)
258 )? m : -1;
259}
260
261static uint32_t
262mkctx0(const Jbig2RefinementRegionParams *params, Jbig2Image *image, int x, int y)
263{
264 Jbig2Image *ref = params->GRREFERENCE;
265 const int dx = params->GRREFERENCEDX;
266 const int dy = params->GRREFERENCEDY;
267 uint32_t CONTEXT;
268
269 CONTEXT = jbig2_image_get_pixel(image, x - 1, y + 0);
270 CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 1;
271 CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 2;
272 CONTEXT |= jbig2_image_get_pixel(image, x + params->grat[0], y + params->grat[1]) << 3;
273 CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 1) << 4;
274 CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 1) << 5;
275 CONTEXT |= jbig2_image_get_pixel(ref, x - dx - 1, y - dy + 1) << 6;
276 CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 0) << 7;
277 CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 0) << 8;
278 CONTEXT |= jbig2_image_get_pixel(ref, x - dx - 1, y - dy + 0) << 9;
279 CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy - 1) << 10;
280 CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy - 1) << 11;
281 CONTEXT |= jbig2_image_get_pixel(ref, x - dx + params->grat[2], y - dy + params->grat[3]) << 12;
282 return CONTEXT;
283}
284
285static uint32_t
286mkctx1(const Jbig2RefinementRegionParams *params, Jbig2Image *image, int x, int y)
287{
288 Jbig2Image *ref = params->GRREFERENCE;
289 const int dx = params->GRREFERENCEDX;
290 const int dy = params->GRREFERENCEDY;
291 uint32_t CONTEXT;
292
293 CONTEXT = jbig2_image_get_pixel(image, x - 1, y + 0);
294 CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 1;
295 CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 2;
296 CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 3;
297 CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 1) << 4;
298 CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 1) << 5;
299 CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 0) << 6;
300 CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 0) << 7;
301 CONTEXT |= jbig2_image_get_pixel(ref, x - dx - 1, y - dy + 0) << 8;
302 CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy - 1) << 9;
303 return CONTEXT;
304}
305
306static int
307jbig2_decode_refinement_TPGRON(Jbig2Ctx *ctx, const Jbig2RefinementRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GR_stats)
308{
309 const int GRW = image->width;
310 const int GRH = image->height;
311 int x, y, iv, bit, LTP = 0;
312 uint32_t start_context = (params->GRTEMPLATE ? 0x40 : 0x100);
313 ContextBuilder mkctx = (params->GRTEMPLATE ? mkctx1 : mkctx0);
314 int code = 0;
315
316 if (params->GRTEMPLATE == 0 &&
317 (pixel_outside_field(params->grat[0], params->grat[1]) ||
318 refpixel_outside_field(params->grat[2], params->grat[3])))
319 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
320 "adaptive template pixel is out of field");
321
322 for (y = 0; y < GRH; y++) {
323 LTP ^= jbig2_arith_decode(as, &GR_stats[start_context], &code);
324 if (code)
325 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling refinement TPGRON1");
326 if (!LTP) {
327 for (x = 0; x < GRW; x++) {
328 bit = jbig2_arith_decode(as, &GR_stats[mkctx(params, image, x, y)], &code);
329 if (code)
330 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling refinement TPGRON1");
331 jbig2_image_set_pixel(image, x, y, bit);
332 }
333 } else {
334 for (x = 0; x < GRW; x++) {
335 iv = implicit_value(params, image, x, y);
336 if (iv < 0) {
337 bit = jbig2_arith_decode(as, &GR_stats[mkctx(params, image, x, y)], &code);
338 if (code)
339 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling refinement TPGRON1");
340 jbig2_image_set_pixel(image, x, y, bit);
341 } else
342 jbig2_image_set_pixel(image, x, y, iv);
343 }
344 }
345 }
346
347 return 0;
348}
349
350/**
351 * jbig2_decode_refinement_region: Decode a generic refinement region.
352 * @ctx: The context for allocation and error reporting.
353 * @segment: A segment reference for error reporting.
354 * @params: Decoding parameter set.
355 * @as: Arithmetic decoder state.
356 * @image: Where to store the decoded image.
357 * @GR_stats: Arithmetic stats.
358 *
359 * Decodes a generic refinement region, according to section 6.3.
360 * an already allocated Jbig2Image object in @image for the result.
361 *
362 * Because this API is based on an arithmetic decoding state, it is
363 * not suitable for MMR decoding.
364 *
365 * Return code: 0 on success.
366 **/
367int
368jbig2_decode_refinement_region(Jbig2Ctx *ctx,
369 Jbig2Segment *segment,
370 const Jbig2RefinementRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GR_stats)
371{
372 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
373 "decoding generic refinement region with offset %d,%x, GRTEMPLATE=%d, TPGRON=%d",
374 params->GRREFERENCEDX, params->GRREFERENCEDY, params->GRTEMPLATE, params->TPGRON);
375
376 if (params->TPGRON)
377 return jbig2_decode_refinement_TPGRON(ctx, params, as, image, GR_stats);
378
379 if (params->GRTEMPLATE)
380 return jbig2_decode_refinement_template1_unopt(ctx, segment, params, as, image, GR_stats);
381 else
382 return jbig2_decode_refinement_template0_unopt(ctx, segment, params, as, image, GR_stats);
383}
384
385/**
386 * Find the first referred-to intermediate region segment
387 * with a non-NULL result for use as a reference image
388 */
389static Jbig2Segment *
390jbig2_region_find_referred(Jbig2Ctx *ctx, Jbig2Segment *segment)
391{
392 const int nsegments = segment->referred_to_segment_count;
393 Jbig2Segment *rsegment;
394 int index;
395
396 for (index = 0; index < nsegments; index++) {
397 rsegment = jbig2_find_segment(ctx, segment->referred_to_segments[index]);
398 if (rsegment == NULL) {
399 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to find referred to segment %d", segment->referred_to_segments[index]);
400 continue;
401 }
402 switch (rsegment->flags & 63) {
403 case 4: /* intermediate text region */
404 case 20: /* intermediate halftone region */
405 case 36: /* intermediate generic region */
406 case 40: /* intermediate generic refinement region */
407 if (rsegment->result)
408 return rsegment;
409 break;
410 default: /* keep looking */
411 break;
412 }
413 }
414 /* no appropriate reference was found. */
415 return NULL;
416}
417
418/**
419 * Handler for generic refinement region segments
420 */
421int
422jbig2_refinement_region(Jbig2Ctx *ctx, Jbig2Segment *segment, const byte *segment_data)
423{
424 Jbig2RefinementRegionParams params;
425 Jbig2RegionSegmentInfo rsi;
426 int offset = 0;
427 byte seg_flags;
428 int code = 0;
429
430 /* 7.4.7 */
431 if (segment->data_length < 18)
432 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short");
433
434 jbig2_get_region_segment_info(&rsi, segment_data);
435 jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "generic region: %u x %u @ (%u, %u), flags = %02x", rsi.width, rsi.height, rsi.x, rsi.y, rsi.flags);
436
437 /* 7.4.7.2 */
438 seg_flags = segment_data[17];
439 params.GRTEMPLATE = seg_flags & 0x01;
440 params.TPGRON = seg_flags & 0x02 ? 1 : 0;
441 jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
442 "segment flags = %02x %s%s", seg_flags, params.GRTEMPLATE ? " GRTEMPLATE" : "", params.TPGRON ? " TPGRON" : "");
443 if (seg_flags & 0xFC)
444 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "reserved segment flag bits are non-zero");
445 offset += 18;
446
447 /* 7.4.7.3 */
448 if (!params.GRTEMPLATE) {
449 if (segment->data_length < 22)
450 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short");
451 params.grat[0] = segment_data[offset + 0];
452 params.grat[1] = segment_data[offset + 1];
453 params.grat[2] = segment_data[offset + 2];
454 params.grat[3] = segment_data[offset + 3];
455 jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
456 "grat1: (%d, %d) grat2: (%d, %d)", params.grat[0], params.grat[1], params.grat[2], params.grat[3]);
457 offset += 4;
458 }
459
460 /* 7.4.7.4 - set up the reference image */
461 if (segment->referred_to_segment_count) {
462 Jbig2Segment *ref;
463
464 ref = jbig2_region_find_referred(ctx, segment);
465 if (ref == NULL)
466 return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to find reference bitmap");
467 if (ref->result == NULL)
468 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "reference bitmap has no decoded image");
469 /* the reference bitmap is the result of a previous
470 intermediate region segment; the reference selection
471 rules say to use the first one available, and not to
472 reuse any intermediate result, so we simply take another
473 reference to it and free the original to keep track of this. */
474 params.GRREFERENCE = jbig2_image_reference(ctx, (Jbig2Image *) ref->result);
475 jbig2_image_release(ctx, (Jbig2Image *) ref->result);
476 ref->result = NULL;
477 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "found reference bitmap in segment %d", ref->number);
478 } else {
479 /* the reference is just (a subset of) the page buffer */
480 if (ctx->pages[ctx->current_page].image == NULL)
481 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "reference page bitmap has no decoded image");
482 params.GRREFERENCE = jbig2_image_reference(ctx, ctx->pages[ctx->current_page].image);
483 /* TODO: subset the image if appropriate */
484 }
485
486 /* 7.4.7.5 */
487 params.GRREFERENCEDX = 0;
488 params.GRREFERENCEDY = 0;
489 {
490 Jbig2WordStream *ws = NULL;
491 Jbig2ArithState *as = NULL;
492 Jbig2ArithCx *GR_stats = NULL;
493 int stats_size;
494 Jbig2Image *image = NULL;
495
496 image = jbig2_image_new(ctx, rsi.width, rsi.height);
497 if (image == NULL) {
498 code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate refinement image");
499 goto cleanup;
500 }
501 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "allocated %d x %d image buffer for region decode results", rsi.width, rsi.height);
502
503 stats_size = params.GRTEMPLATE ? 1 << 10 : 1 << 13;
504 GR_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);
505 if (GR_stats == NULL) {
506 code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate arithmetic decoder state for generic refinement regions");
507 goto cleanup;
508 }
509 memset(GR_stats, 0, stats_size);
510
511 ws = jbig2_word_stream_buf_new(ctx, segment_data + offset, segment->data_length - offset);
512 if (ws == NULL) {
513 code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate word stream when handling refinement region");
514 goto cleanup;
515 }
516
517 as = jbig2_arith_new(ctx, ws);
518 if (as == NULL) {
519 code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate arithmetic coding state when handling refinement region");
520 goto cleanup;
521 }
522
523 code = jbig2_decode_refinement_region(ctx, segment, &params, as, image, GR_stats);
524 if (code < 0) {
525 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode refinement region");
526 goto cleanup;
527 }
528
529 if ((segment->flags & 63) == 40) {
530 /* intermediate region. save the result for later */
531 segment->result = jbig2_image_reference(ctx, image);
532 } else {
533 /* immediate region. composite onto the page */
534 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
535 "composing %dx%d decoded refinement region onto page at (%d, %d)", rsi.width, rsi.height, rsi.x, rsi.y);
536 code = jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], image, rsi.x, rsi.y, rsi.op);
537 if (code < 0) {
538 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable to add refinement region to page");
539 goto cleanup;
540 }
541 }
542
543cleanup:
544 jbig2_image_release(ctx, image);
545 jbig2_image_release(ctx, params.GRREFERENCE);
546 jbig2_free(ctx->allocator, as);
547 jbig2_word_stream_buf_free(ctx, ws);
548 jbig2_free(ctx->allocator, GR_stats);
549 }
550
551 return code;
552}
553