comparison mupdf-source/thirdparty/jbig2dec/jbig2_refinement.c @ 2:b50eed0cc0ef upstream

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