Coverage Report

Created: 2025-07-11 06:20

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