Coverage Report

Created: 2025-09-29 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/jbig2dec/jbig2_refinement.c
Line
Count
Source
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
309k
    ((y) < -128 || (y) > 0 || (x) < -128 || ((y) < 0 && (x) > 127) || ((y) == 0 && (x) >= 0))
45
#define refpixel_outside_field(x, y) \
46
154k
    ((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
154k
{
53
154k
    const int GRW = image->width;
54
154k
    const int GRH = image->height;
55
154k
    Jbig2Image *ref = params->GRREFERENCE;
56
154k
    const int dx = params->GRREFERENCEDX;
57
154k
    const int dy = params->GRREFERENCEDY;
58
154k
    uint32_t CONTEXT;
59
154k
    int x, y;
60
154k
    int bit;
61
62
154k
    if (pixel_outside_field(params->grat[0], params->grat[1]) ||
63
154k
        refpixel_outside_field(params->grat[2], params->grat[3]))
64
18
        return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
65
18
                           "adaptive template pixel is out of field");
66
67
5.01M
    for (y = 0; y < GRH; y++) {
68
136M
        for (x = 0; x < GRW; x++) {
69
132M
            CONTEXT = 0;
70
132M
            CONTEXT |= jbig2_image_get_pixel(image, x - 1, y + 0) << 0;
71
132M
            CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 1;
72
132M
            CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 2;
73
132M
            CONTEXT |= jbig2_image_get_pixel(image, x + params->grat[0], y + params->grat[1]) << 3;
74
132M
            CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 1) << 4;
75
132M
            CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 1) << 5;
76
132M
            CONTEXT |= jbig2_image_get_pixel(ref, x - dx - 1, y - dy + 1) << 6;
77
132M
            CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 0) << 7;
78
132M
            CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 0) << 8;
79
132M
            CONTEXT |= jbig2_image_get_pixel(ref, x - dx - 1, y - dy + 0) << 9;
80
132M
            CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy - 1) << 10;
81
132M
            CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy - 1) << 11;
82
132M
            CONTEXT |= jbig2_image_get_pixel(ref, x - dx + params->grat[2], y - dy + params->grat[3]) << 12;
83
132M
            bit = jbig2_arith_decode(ctx, as, &GR_stats[CONTEXT]);
84
132M
            if (bit < 0)
85
0
                return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling refinement template0");
86
132M
            jbig2_image_set_pixel(image, x, y, bit);
87
132M
        }
88
4.86M
    }
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
154k
    return 0;
108
154k
}
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
2.04k
{
115
2.04k
    const int GRW = image->width;
116
2.04k
    const int GRH = image->height;
117
2.04k
    Jbig2Image *ref = params->GRREFERENCE;
118
2.04k
    const int dx = params->GRREFERENCEDX;
119
2.04k
    const int dy = params->GRREFERENCEDY;
120
2.04k
    uint32_t CONTEXT;
121
2.04k
    int x, y;
122
2.04k
    int bit;
123
124
26.0M
    for (y = 0; y < GRH; y++) {
125
203M
        for (x = 0; x < GRW; x++) {
126
177M
            CONTEXT = 0;
127
177M
            CONTEXT |= jbig2_image_get_pixel(image, x - 1, y + 0) << 0;
128
177M
            CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 1;
129
177M
            CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 2;
130
177M
            CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 3;
131
177M
            CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 1) << 4;
132
177M
            CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 1) << 5;
133
177M
            CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 0) << 6;
134
177M
            CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 0) << 7;
135
177M
            CONTEXT |= jbig2_image_get_pixel(ref, x - dx - 1, y - dy + 0) << 8;
136
177M
            CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy - 1) << 9;
137
177M
            bit = jbig2_arith_decode(ctx, as, &GR_stats[CONTEXT]);
138
177M
            if (bit < 0)
139
0
                return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling refinement template0");
140
177M
            jbig2_image_set_pixel(image, x, y, bit);
141
177M
        }
142
26.0M
    }
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
2.04k
    return 0;
162
2.04k
}
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
119M
{
242
119M
    Jbig2Image *ref = params->GRREFERENCE;
243
119M
    int i = x - params->GRREFERENCEDX;
244
119M
    int j = y - params->GRREFERENCEDY;
245
119M
    int m = jbig2_image_get_pixel(ref, i, j);
246
247
119M
    return ((jbig2_image_get_pixel(ref, i - 1, j - 1) == m) &&
248
119M
            (jbig2_image_get_pixel(ref, i, j - 1) == m) &&
249
119M
            (jbig2_image_get_pixel(ref, i + 1, j - 1) == m) &&
250
119M
            (jbig2_image_get_pixel(ref, i - 1, j) == m) &&
251
119M
            (jbig2_image_get_pixel(ref, i + 1, j) == m) &&
252
118M
            (jbig2_image_get_pixel(ref, i - 1, j + 1) == m) &&
253
118M
            (jbig2_image_get_pixel(ref, i, j + 1) == m) &&
254
118M
            (jbig2_image_get_pixel(ref, i + 1, j + 1) == m)
255
119M
           )? m : -1;
256
119M
}
257
258
static uint32_t
259
mkctx0(const Jbig2RefinementRegionParams *params, Jbig2Image *image, int x, int y)
260
66.3M
{
261
66.3M
    Jbig2Image *ref = params->GRREFERENCE;
262
66.3M
    const int dx = params->GRREFERENCEDX;
263
66.3M
    const int dy = params->GRREFERENCEDY;
264
66.3M
    uint32_t CONTEXT;
265
266
66.3M
    CONTEXT = jbig2_image_get_pixel(image, x - 1, y + 0);
267
66.3M
    CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 1;
268
66.3M
    CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 2;
269
66.3M
    CONTEXT |= jbig2_image_get_pixel(image, x + params->grat[0], y + params->grat[1]) << 3;
270
66.3M
    CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 1) << 4;
271
66.3M
    CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 1) << 5;
272
66.3M
    CONTEXT |= jbig2_image_get_pixel(ref, x - dx - 1, y - dy + 1) << 6;
273
66.3M
    CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 0) << 7;
274
66.3M
    CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 0) << 8;
275
66.3M
    CONTEXT |= jbig2_image_get_pixel(ref, x - dx - 1, y - dy + 0) << 9;
276
66.3M
    CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy - 1) << 10;
277
66.3M
    CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy - 1) << 11;
278
66.3M
    CONTEXT |= jbig2_image_get_pixel(ref, x - dx + params->grat[2], y - dy + params->grat[3]) << 12;
279
66.3M
    return CONTEXT;
280
66.3M
}
281
282
static uint32_t
283
mkctx1(const Jbig2RefinementRegionParams *params, Jbig2Image *image, int x, int y)
284
145M
{
285
145M
    Jbig2Image *ref = params->GRREFERENCE;
286
145M
    const int dx = params->GRREFERENCEDX;
287
145M
    const int dy = params->GRREFERENCEDY;
288
145M
    uint32_t CONTEXT;
289
290
145M
    CONTEXT = jbig2_image_get_pixel(image, x - 1, y + 0);
291
145M
    CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 1;
292
145M
    CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 2;
293
145M
    CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 3;
294
145M
    CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 1) << 4;
295
145M
    CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 1) << 5;
296
145M
    CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 0) << 6;
297
145M
    CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 0) << 7;
298
145M
    CONTEXT |= jbig2_image_get_pixel(ref, x - dx - 1, y - dy + 0) << 8;
299
145M
    CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy - 1) << 9;
300
145M
    return CONTEXT;
301
145M
}
302
303
static int
304
jbig2_decode_refinement_TPGRON(Jbig2Ctx *ctx, const Jbig2RefinementRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GR_stats)
305
445
{
306
445
    const int GRW = image->width;
307
445
    const int GRH = image->height;
308
445
    int x, y, iv, LTP = 0;
309
445
    uint32_t start_context = (params->GRTEMPLATE ? 0x40 : 0x100);
310
445
    ContextBuilder mkctx = (params->GRTEMPLATE ? mkctx1 : mkctx0);
311
312
445
    if (params->GRTEMPLATE == 0 &&
313
315
        (pixel_outside_field(params->grat[0], params->grat[1]) ||
314
309
        refpixel_outside_field(params->grat[2], params->grat[3])))
315
6
        return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER,
316
6
                           "adaptive template pixel is out of field");
317
318
11.8M
    for (y = 0; y < GRH; y++) {
319
11.8M
        int bit = jbig2_arith_decode(ctx, as, &GR_stats[start_context]);
320
11.8M
        if (bit < 0)
321
0
            return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to decode arithmetic code when handling refinement TPGRON1");
322
11.8M
        LTP ^= bit;
323
11.8M
        if (!LTP) {
324
217M
            for (x = 0; x < GRW; x++) {
325
211M
                bit = jbig2_arith_decode(ctx, as, &GR_stats[mkctx(params, image, x, y)]);
326
211M
                if (bit < 0)
327
0
                    return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to decode arithmetic code when handling refinement TPGRON1");
328
211M
                jbig2_image_set_pixel(image, x, y, bit);
329
211M
            }
330
6.54M
        } else {
331
124M
            for (x = 0; x < GRW; x++) {
332
119M
                iv = implicit_value(params, image, x, y);
333
119M
                if (iv < 0) {
334
838k
                    int bit = jbig2_arith_decode(ctx, as, &GR_stats[mkctx(params, image, x, y)]);
335
838k
                    if (bit < 0)
336
0
                        return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to decode arithmetic code when handling refinement TPGRON1");
337
838k
                    jbig2_image_set_pixel(image, x, y, bit);
338
838k
                } else
339
118M
                    jbig2_image_set_pixel(image, x, y, iv);
340
119M
            }
341
5.26M
        }
342
11.8M
    }
343
344
439
    return 0;
345
439
}
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
157k
{
369
157k
    jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
370
157k
                "decoding generic refinement region with offset %d,%x, GRTEMPLATE=%d, TPGRON=%d",
371
157k
                params->GRREFERENCEDX, params->GRREFERENCEDY, params->GRTEMPLATE, params->TPGRON);
372
373
157k
    if (params->TPGRON)
374
445
        return jbig2_decode_refinement_TPGRON(ctx, params, as, image, GR_stats);
375
376
156k
    if (params->GRTEMPLATE)
377
2.04k
        return jbig2_decode_refinement_template1_unopt(ctx, segment, params, as, image, GR_stats);
378
154k
    else
379
154k
        return jbig2_decode_refinement_template0_unopt(ctx, segment, params, as, image, GR_stats);
380
156k
}
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
90
{
389
90
    const int nsegments = segment->referred_to_segment_count;
390
90
    Jbig2Segment *rsegment;
391
90
    int index;
392
393
2.84k
    for (index = 0; index < nsegments; index++) {
394
2.81k
        rsegment = jbig2_find_segment(ctx, segment->referred_to_segments[index]);
395
2.81k
        if (rsegment == NULL) {
396
1.83k
            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to find referred to segment %d", segment->referred_to_segments[index]);
397
1.83k
            continue;
398
1.83k
        }
399
978
        switch (rsegment->flags & 63) {
400
303
        case 4:                /* intermediate text region */
401
303
        case 20:               /* intermediate halftone region */
402
303
        case 36:               /* intermediate generic region */
403
349
        case 40:               /* intermediate generic refinement region */
404
349
            if (rsegment->result)
405
56
                return rsegment;
406
293
            break;
407
629
        default:               /* keep looking */
408
629
            break;
409
978
        }
410
978
    }
411
    /* no appropriate reference was found. */
412
34
    return NULL;
413
90
}
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
1.14k
{
421
1.14k
    Jbig2RefinementRegionParams params;
422
1.14k
    Jbig2RegionSegmentInfo rsi;
423
1.14k
    int offset = 0;
424
1.14k
    byte seg_flags;
425
1.14k
    int code = 0;
426
427
    /* 7.4.7 */
428
1.14k
    if (segment->data_length < 18)
429
11
        return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short");
430
431
1.12k
    jbig2_get_region_segment_info(&rsi, segment_data);
432
1.12k
    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
1.12k
    seg_flags = segment_data[17];
436
1.12k
    params.GRTEMPLATE = seg_flags & 0x01;
437
1.12k
    params.TPGRON = seg_flags & 0x02 ? 1 : 0;
438
1.12k
    jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
439
1.12k
                "segment flags = %02x %s%s", seg_flags, params.GRTEMPLATE ? " GRTEMPLATE" : "", params.TPGRON ? " TPGRON" : "");
440
1.12k
    if (seg_flags & 0xFC)
441
832
        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "reserved segment flag bits are non-zero");
442
1.12k
    offset += 18;
443
444
    /* 7.4.7.3 */
445
1.12k
    if (!params.GRTEMPLATE) {
446
434
        if (segment->data_length < 22)
447
4
            return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short");
448
430
        params.grat[0] = segment_data[offset + 0];
449
430
        params.grat[1] = segment_data[offset + 1];
450
430
        params.grat[2] = segment_data[offset + 2];
451
430
        params.grat[3] = segment_data[offset + 3];
452
430
        jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
453
430
                    "grat1: (%d, %d) grat2: (%d, %d)", params.grat[0], params.grat[1], params.grat[2], params.grat[3]);
454
430
        offset += 4;
455
430
    }
456
457
    /* 7.4.7.4 - set up the reference image */
458
1.12k
    if (segment->referred_to_segment_count) {
459
90
        Jbig2Segment *ref;
460
461
90
        ref = jbig2_region_find_referred(ctx, segment);
462
90
        if (ref == NULL)
463
34
            return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to find reference bitmap");
464
56
        if (ref->result == NULL)
465
0
            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
56
        params.GRREFERENCE = jbig2_image_reference(ctx, (Jbig2Image *) ref->result);
472
56
        jbig2_image_release(ctx, (Jbig2Image *) ref->result);
473
56
        ref->result = NULL;
474
56
        jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "found reference bitmap in segment %d", ref->number);
475
1.03k
    } else {
476
        /* the reference is just (a subset of) the page buffer */
477
1.03k
        if (ctx->pages[ctx->current_page].image == NULL)
478
14
            return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "reference page bitmap has no decoded image");
479
1.02k
        params.GRREFERENCE = jbig2_image_reference(ctx, ctx->pages[ctx->current_page].image);
480
        /* TODO: subset the image if appropriate */
481
1.02k
    }
482
483
    /* 7.4.7.5 */
484
1.07k
    params.GRREFERENCEDX = 0;
485
1.07k
    params.GRREFERENCEDY = 0;
486
1.07k
    {
487
1.07k
        Jbig2WordStream *ws = NULL;
488
1.07k
        Jbig2ArithState *as = NULL;
489
1.07k
        Jbig2ArithCx *GR_stats = NULL;
490
1.07k
        int stats_size;
491
1.07k
        Jbig2Image *image = NULL;
492
493
1.07k
        image = jbig2_image_new(ctx, rsi.width, rsi.height);
494
1.07k
        if (image == NULL) {
495
13
            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate refinement image");
496
13
            goto cleanup;
497
13
        }
498
1.06k
        jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "allocated %d x %d image buffer for region decode results", rsi.width, rsi.height);
499
500
1.06k
        stats_size = params.GRTEMPLATE ? 1 << 10 : 1 << 13;
501
1.06k
        GR_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);
502
1.06k
        if (GR_stats == NULL) {
503
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate arithmetic decoder state for generic refinement regions");
504
1
            goto cleanup;
505
1
        }
506
1.06k
        memset(GR_stats, 0, stats_size);
507
508
1.06k
        ws = jbig2_word_stream_buf_new(ctx, segment_data + offset, segment->data_length - offset);
509
1.06k
        if (ws == NULL) {
510
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate word stream when handling refinement region");
511
1
            goto cleanup;
512
1
        }
513
514
1.06k
        as = jbig2_arith_new(ctx, ws);
515
1.06k
        if (as == NULL) {
516
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate arithmetic coding state when handling refinement region");
517
1
            goto cleanup;
518
1
        }
519
520
1.06k
        code = jbig2_decode_refinement_region(ctx, segment, &params, as, image, GR_stats);
521
1.06k
        if (code < 0) {
522
11
            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode refinement region");
523
11
            goto cleanup;
524
11
        }
525
526
1.05k
        if ((segment->flags & 63) == 40) {
527
            /* intermediate region. save the result for later */
528
94
            segment->result = jbig2_image_reference(ctx, image);
529
956
        } else {
530
            /* immediate region. composite onto the page */
531
956
            jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
532
956
                        "composing %dx%d decoded refinement region onto page at (%d, %d)", rsi.width, rsi.height, rsi.x, rsi.y);
533
956
            code = jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], image, rsi.x, rsi.y, rsi.op);
534
956
            if (code < 0) {
535
94
                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable to add refinement region to page");
536
94
                goto cleanup;
537
94
            }
538
956
        }
539
540
1.07k
cleanup:
541
1.07k
        jbig2_image_release(ctx, image);
542
1.07k
        jbig2_image_release(ctx, params.GRREFERENCE);
543
1.07k
        jbig2_free(ctx->allocator, as);
544
1.07k
        jbig2_word_stream_buf_free(ctx, ws);
545
1.07k
        jbig2_free(ctx->allocator, GR_stats);
546
1.07k
    }
547
548
0
    return code;
549
1.05k
}