Coverage Report

Created: 2026-08-31 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/jbig2dec/jbig2_image.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
#ifdef HAVE_CONFIG_H
21
#include "config.h"
22
#endif
23
#include "os_types.h"
24
25
#include <stdio.h>
26
#include <stdlib.h>
27
#include <string.h>             /* memcpy() */
28
29
#include "jbig2.h"
30
#include "jbig2_priv.h"
31
#include "jbig2_image.h"
32
33
/* allocate a Jbig2Image structure and its associated bitmap */
34
Jbig2Image *
35
jbig2_image_new(Jbig2Ctx *ctx, uint32_t width, uint32_t height)
36
15.1M
{
37
15.1M
    Jbig2Image *image;
38
15.1M
    uint32_t stride;
39
40
15.1M
    if (width == 0 || height == 0) {
41
106
        jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to create zero sized image");
42
106
        return NULL;
43
106
    }
44
45
15.1M
    image = jbig2_new(ctx, Jbig2Image, 1);
46
15.1M
    if (image == NULL) {
47
35
        jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to allocate image");
48
35
        return NULL;
49
35
    }
50
51
15.1M
    stride = ((width - 1) >> 3) + 1;    /* generate a byte-aligned stride */
52
53
    /* check for integer multiplication overflow */
54
15.1M
    if (height > (INT32_MAX / stride)) {
55
236
        jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "integer multiplication overflow (stride=%u, height=%u)", stride, height);
56
236
        jbig2_free(ctx->allocator, image);
57
236
        return NULL;
58
236
    }
59
15.1M
    image->data = jbig2_new(ctx, uint8_t, (size_t) height * stride);
60
15.1M
    if (image->data == NULL) {
61
180
        jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to allocate image data buffer (stride=%u, height=%u)", stride, height);
62
180
        jbig2_free(ctx->allocator, image);
63
180
        return NULL;
64
180
    }
65
66
15.1M
    image->width = width;
67
15.1M
    image->height = height;
68
15.1M
    image->stride = stride;
69
15.1M
    image->refcount = 1;
70
71
15.1M
    return image;
72
15.1M
}
73
74
/* bump the reference count for an image pointer */
75
Jbig2Image *
76
jbig2_image_reference(Jbig2Ctx *ctx, Jbig2Image *image)
77
44.9M
{
78
44.9M
    (void) ctx;
79
44.9M
    if (image)
80
13.4M
        image->refcount++;
81
44.9M
    return image;
82
44.9M
}
83
84
/* release an image pointer, freeing it it appropriate */
85
void
86
jbig2_image_release(Jbig2Ctx *ctx, Jbig2Image *image)
87
444M
{
88
444M
    if (image == NULL)
89
415M
        return;
90
28.5M
    image->refcount--;
91
28.5M
    if (image->refcount == 0)
92
15.1M
        jbig2_image_free(ctx, image);
93
28.5M
}
94
95
/* free a Jbig2Image structure and its associated memory */
96
void
97
jbig2_image_free(Jbig2Ctx *ctx, Jbig2Image *image)
98
15.1M
{
99
15.1M
    if (image != NULL) {
100
15.1M
        jbig2_free(ctx->allocator, image->data);
101
15.1M
        jbig2_free(ctx->allocator, image);
102
15.1M
    }
103
15.1M
}
104
105
/* resize a Jbig2Image */
106
Jbig2Image *
107
jbig2_image_resize(Jbig2Ctx *ctx, Jbig2Image *image, uint32_t width, uint32_t height, int value)
108
2.36k
{
109
2.36k
    if (width == image->width) {
110
2.36k
        uint8_t *data;
111
112
        /* check for integer multiplication overflow */
113
2.36k
        if (image->height > (INT32_MAX / image->stride)) {
114
0
            jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "integer multiplication overflow during resize (stride=%u, height=%u)", image->stride, height);
115
0
            return NULL;
116
0
        }
117
        /* use the same stride, just change the length */
118
2.36k
        data = jbig2_renew(ctx, image->data, uint8_t, (size_t) height * image->stride);
119
2.36k
        if (data == NULL) {
120
56
            jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to reallocate image");
121
56
            return NULL;
122
56
        }
123
2.31k
        image->data = data;
124
2.31k
        if (height > image->height) {
125
2.31k
            const uint8_t fill = value ? 0xFF : 0x00;
126
2.31k
            memset(image->data + (size_t) image->height * image->stride, fill, ((size_t) height - image->height) * image->stride);
127
2.31k
        }
128
2.31k
        image->height = height;
129
130
2.31k
    } else {
131
0
        Jbig2Image *newimage;
132
0
        int code;
133
134
        /* Unoptimized implementation, but it works. */
135
136
0
        newimage = jbig2_image_new(ctx, width, height);
137
0
        if (newimage == NULL) {
138
0
            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to allocate resized image");
139
0
            return NULL;
140
0
        }
141
0
        jbig2_image_clear(ctx, newimage, value);
142
143
0
        code = jbig2_image_compose(ctx, newimage, image, 0, 0, JBIG2_COMPOSE_REPLACE);
144
0
        if (code < 0) {
145
0
            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to compose image buffers when resizing");
146
0
            jbig2_image_release(ctx, newimage);
147
0
            return NULL;
148
0
        }
149
150
        /* if refcount > 1 the original image, its pointer must
151
        be kept, so simply replaces its innards, and throw away
152
        the empty new image shell. */
153
0
        jbig2_free(ctx->allocator, image->data);
154
0
        image->width = newimage->width;
155
0
        image->height = newimage->height;
156
0
        image->stride = newimage->stride;
157
0
        image->data = newimage->data;
158
0
        jbig2_free(ctx->allocator, newimage);
159
0
    }
160
161
2.31k
    return image;
162
2.36k
}
163
164
static inline void
165
template_image_compose_opt(const uint8_t * JBIG2_RESTRICT ss, uint8_t * JBIG2_RESTRICT dd, int early, int late, uint8_t leftmask, uint8_t rightmask, uint32_t bytewidth_, uint32_t h, uint32_t shift, uint32_t dstride, uint32_t sstride, Jbig2ComposeOp op)
166
17.7M
{
167
17.7M
    int i;
168
17.7M
    uint32_t j;
169
17.7M
    int bytewidth = (int)bytewidth_;
170
171
17.7M
    if (bytewidth == 1) {
172
131M
        for (j = 0; j < h; j++) {
173
            /* Only 1 byte! */
174
121M
            uint8_t v = (((early ? 0 : ss[0]<<8) | (late ? 0 : ss[1]))>>shift);
175
121M
            if (op == JBIG2_COMPOSE_OR)
176
40.0M
                *dd |= v & leftmask;
177
81.9M
            else if (op == JBIG2_COMPOSE_AND)
178
12.4k
                *dd &= (v & leftmask) | ~leftmask;
179
81.9M
            else if (op == JBIG2_COMPOSE_XOR)
180
153k
                *dd ^= v & leftmask;
181
81.7M
            else if (op == JBIG2_COMPOSE_XNOR)
182
113k
                *dd ^= (~v) & leftmask;
183
81.6M
            else /* Replace */
184
81.6M
                *dd = (v & leftmask) | (*dd & ~leftmask);
185
121M
            dd += dstride;
186
121M
            ss += sstride;
187
121M
        }
188
9.44M
        return;
189
9.44M
    }
190
8.33M
    bytewidth -= 2;
191
8.33M
    if (shift == 0) {
192
2.53M
        ss++;
193
44.9M
        for (j = 0; j < h; j++) {
194
            /* Left byte */
195
42.3M
            const uint8_t * JBIG2_RESTRICT s = ss;
196
42.3M
            uint8_t * JBIG2_RESTRICT d = dd;
197
42.3M
            if (op == JBIG2_COMPOSE_OR)
198
1.48M
                *d++ |= *s++ & leftmask;
199
40.9M
            else if (op == JBIG2_COMPOSE_AND)
200
46.8k
                *d++ &= (*s++ & leftmask) | ~leftmask;
201
40.8M
            else if (op == JBIG2_COMPOSE_XOR)
202
34.8k
                *d++ ^= *s++ & leftmask;
203
40.8M
            else if (op == JBIG2_COMPOSE_XNOR)
204
66.3k
                *d++ ^= (~*s++) & leftmask;
205
40.7M
            else /* Replace */
206
40.7M
                *d = (*s++ & leftmask) | (*d & ~leftmask), d++;
207
            /* Central run */
208
1.53G
            for (i = bytewidth; i != 0; i--) {
209
1.49G
                if (op == JBIG2_COMPOSE_OR)
210
1.15G
                    *d++ |= *s++;
211
336M
                else if (op == JBIG2_COMPOSE_AND)
212
90.9k
                    *d++ &= *s++;
213
335M
                else if (op == JBIG2_COMPOSE_XOR)
214
224k
                    *d++ ^= *s++;
215
335M
                else if (op == JBIG2_COMPOSE_XNOR)
216
69.8k
                    *d++ ^= ~*s++;
217
335M
                else /* Replace */
218
335M
                    *d++ = *s++;
219
1.49G
            }
220
            /* Right byte */
221
42.3M
            if (op == JBIG2_COMPOSE_OR)
222
1.48M
                *d |= *s & rightmask;
223
40.9M
            else if (op == JBIG2_COMPOSE_AND)
224
46.8k
                *d &= (*s & rightmask) | ~rightmask;
225
40.8M
            else if (op == JBIG2_COMPOSE_XOR)
226
34.8k
                *d ^= *s & rightmask;
227
40.8M
            else if (op == JBIG2_COMPOSE_XNOR)
228
66.3k
                *d ^= (~*s) & rightmask;
229
40.7M
            else /* Replace */
230
40.7M
                *d = (*s & rightmask) | (*d & ~rightmask);
231
42.3M
            dd += dstride;
232
42.3M
            ss += sstride;
233
42.3M
        }
234
5.80M
    } else {
235
89.3M
        for (j = 0; j < h; j++) {
236
            /* Left byte */
237
83.5M
            const uint8_t * JBIG2_RESTRICT s = ss;
238
83.5M
            uint8_t * JBIG2_RESTRICT d = dd;
239
83.5M
            uint8_t s0, s1, v;
240
83.5M
            s0 = early ? 0 : *s;
241
83.5M
            s++;
242
83.5M
            s1 = *s++;
243
83.5M
            v = ((s0<<8) | s1)>>shift;
244
83.5M
            if (op == JBIG2_COMPOSE_OR)
245
7.09M
                *d++ |= v & leftmask;
246
76.4M
            else if (op == JBIG2_COMPOSE_AND)
247
42.4k
                *d++ &= (v & leftmask) | ~leftmask;
248
76.4M
            else if (op == JBIG2_COMPOSE_XOR)
249
140k
                *d++ ^= v & leftmask;
250
76.2M
            else if (op == JBIG2_COMPOSE_XNOR)
251
14.4k
                *d++ ^= (~v) & leftmask;
252
76.2M
            else /* Replace */
253
76.2M
                *d = (v & leftmask) | (*d & ~leftmask), d++;
254
            /* Central run */
255
1.10G
            for (i = bytewidth; i > 0; i--) {
256
1.01G
                s0 = s1; s1 = *s++;
257
1.01G
                v = ((s0<<8) | s1)>>shift;
258
1.01G
                if (op == JBIG2_COMPOSE_OR)
259
290M
                    *d++ |= v;
260
726M
                else if (op == JBIG2_COMPOSE_AND)
261
425k
                    *d++ &= v;
262
726M
                else if (op == JBIG2_COMPOSE_XOR)
263
923k
                    *d++ ^= v;
264
725M
                else if (op == JBIG2_COMPOSE_XNOR)
265
864k
                    *d++ ^= ~v;
266
724M
                else /* Replace */
267
724M
                    *d++ = v;
268
1.01G
            }
269
            /* Right byte */
270
83.5M
            s0 = s1; s1 = (late ? 0 : *s);
271
83.5M
            v = (((s0<<8) | s1)>>shift);
272
83.5M
            if (op == JBIG2_COMPOSE_OR)
273
7.09M
                *d |= v & rightmask;
274
76.4M
            else if (op == JBIG2_COMPOSE_AND)
275
42.4k
                *d &= (v & rightmask) | ~rightmask;
276
76.4M
            else if (op == JBIG2_COMPOSE_XOR)
277
140k
                *d ^= v & rightmask;
278
76.2M
            else if (op == JBIG2_COMPOSE_XNOR)
279
14.4k
                *d ^= ~v & rightmask;
280
76.2M
            else /* Replace */
281
76.2M
                *d = (v & rightmask) | (*d & ~rightmask);
282
83.5M
            dd += dstride;
283
83.5M
            ss += sstride;
284
83.5M
        }
285
5.80M
    }
286
8.33M
}
287
288
static void
289
jbig2_image_compose_opt_OR(const uint8_t *s, uint8_t *d, int early, int late, uint8_t mask, uint8_t rightmask, uint32_t bytewidth, uint32_t h, uint32_t shift, uint32_t dstride, uint32_t sstride)
290
2.90M
{
291
2.90M
    if (early || late)
292
2.90M
        template_image_compose_opt(s, d, early, late, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_OR);
293
1.11k
    else
294
1.11k
        template_image_compose_opt(s, d, 0, 0, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_OR);
295
2.90M
}
296
297
static void
298
jbig2_image_compose_opt_AND(const uint8_t *s, uint8_t *d, int early, int late, uint8_t mask, uint8_t rightmask, uint32_t bytewidth, uint32_t h, uint32_t shift, uint32_t dstride, uint32_t sstride)
299
1.75k
{
300
1.75k
    if (early || late)
301
1.27k
        template_image_compose_opt(s, d, early, late, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_AND);
302
479
    else
303
479
        template_image_compose_opt(s, d, 0, 0, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_AND);
304
1.75k
}
305
306
static void
307
jbig2_image_compose_opt_XOR(const uint8_t *s, uint8_t *d, int early, int late, uint8_t mask, uint8_t rightmask, uint32_t bytewidth, uint32_t h, uint32_t shift, uint32_t dstride, uint32_t sstride)
308
5.29k
{
309
5.29k
    if (early || late)
310
3.08k
        template_image_compose_opt(s, d, early, late, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_XOR);
311
2.21k
    else
312
2.21k
        template_image_compose_opt(s, d, 0, 0, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_XOR);
313
5.29k
}
314
315
static void
316
jbig2_image_compose_opt_XNOR(const uint8_t *s, uint8_t *d, int early, int late, uint8_t mask, uint8_t rightmask, uint32_t bytewidth, uint32_t h, uint32_t shift, uint32_t dstride, uint32_t sstride)
317
1.84k
{
318
1.84k
    if (early || late)
319
1.29k
        template_image_compose_opt(s, d, early, late, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_XNOR);
320
548
    else
321
548
        template_image_compose_opt(s, d, 0, 0, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_XNOR);
322
1.84k
}
323
324
static void
325
jbig2_image_compose_opt_REPLACE(const uint8_t *s, uint8_t *d, int early, int late, uint8_t mask, uint8_t rightmask, uint32_t bytewidth, uint32_t h, uint32_t shift, uint32_t dstride, uint32_t sstride)
326
14.8M
{
327
14.8M
    if (early || late)
328
16.7k
        template_image_compose_opt(s, d, early, late, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_REPLACE);
329
14.8M
    else
330
14.8M
        template_image_compose_opt(s, d, 0, 0, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_REPLACE);
331
14.8M
}
332
333
/* composite one jbig2_image onto another */
334
int
335
jbig2_image_compose(Jbig2Ctx *ctx, Jbig2Image *dst, Jbig2Image *src, int64_t x, int64_t y, Jbig2ComposeOp op)
336
134M
{
337
134M
    uint32_t w, h;
338
134M
    uint32_t shift;
339
134M
    uint32_t leftbyte;
340
134M
    uint8_t *ss;
341
134M
    uint8_t *dd;
342
134M
    uint8_t leftmask, rightmask;
343
134M
    int early = x >= 0;
344
134M
    int late;
345
134M
    uint32_t bytewidth;
346
134M
    uint32_t syoffset = 0;
347
348
134M
    (void) ctx;
349
350
134M
    if (src == NULL)
351
11.8M
        return 0;
352
353
    /* Detect if src image has no overlap with the dst image.
354
     * Because the widths/heights are of type uint32_t their theoretical
355
     * maximum size is UINT32_MAX. Therefore this check also rejects any
356
     * x/y values outside the range [-UINT32_MAX + 1, UINT32_MAX - 1].
357
     * And after this if-statement x/y must necessarily fall within this
358
     * closed range.
359
     */
360
122M
    if (
361
122M
            (x <= -((int64_t) src->width)) || (x >= (int64_t) dst->width) ||
362
31.0M
            (y <= -((int64_t) src->height)) || (y >= (int64_t) dst->height))
363
104M
    {
364
104M
        jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, JBIG2_UNKNOWN_SEGMENT_NUMBER, "src image entirely outside dst image in compose_image");
365
104M
        return 0;
366
104M
    }
367
368
    /* This code takes a src image and combines it onto dst at offset (x,y), with operation op. */
369
370
    /* Data is packed msb first within a byte, so with bits numbered: 01234567.
371
     * Second byte is: 89abcdef. So to combine into a run, we use:
372
     *       (s[0]<<8) | s[1] == 0123456789abcdef.
373
     * To read from src into dst at offset 3, we need to read:
374
     *    read:      0123456789abcdef...
375
     *    write:  0123456798abcdef...
376
     * In general, to read from src and write into dst at offset x, we need to shift
377
     * down by (x&7) bits to allow for bit alignment. So shift = x&7.
378
     * So the 'central' part of our runs will see us doing:
379
     *   *d++ op= ((s[0]<<8)|s[1])>>shift;
380
     * with special cases on the left and right edges of the run to mask.
381
     * With the left hand edge, we have to be careful not to 'underread' the start of
382
     * the src image; this is what the early flag is about. Similarly we have to be
383
     * careful not to read off the right hand edge; this is what the late flag is for.
384
     */
385
386
17.7M
    w = src->width;
387
17.7M
    h = src->height;
388
17.7M
    shift = (uint32_t) (x & 7);
389
17.7M
    ss = src->data - early;
390
391
    /* Since we know that x/y are now limited to [-UINT32_MAX + 1, UINT32_MAX - 1],
392
     * we know that we can't accidentally negate an INT64_MIN. Moreover, we know
393
     * that their negated values fit within an uint32_t, so casting to uint32_t is
394
     * safe.
395
     */
396
397
    /* clip left/top */
398
17.7M
    if (x < 0) {
399
14.8M
        uint32_t negx = (uint32_t) (-x);
400
14.8M
        w -= negx;
401
14.8M
        ss += (negx-1)>>3;
402
14.8M
        x = 0;
403
14.8M
    }
404
17.7M
    if (y < 0) {
405
7.90k
        uint32_t negy = (uint32_t) (-y);
406
7.90k
        h -= negy;
407
7.90k
        syoffset = negy * src->stride;
408
7.90k
        y = 0;
409
7.90k
    }
410
411
    /* clip right/bottom */
412
17.7M
    if ((uint32_t)x + w > dst->width)
413
14.8M
        w = dst->width - ((uint32_t) x);
414
17.7M
    if ((uint32_t)y + h > dst->height)
415
11.4k
        h = dst->height - ((uint32_t) y);
416
#ifdef JBIG2_DEBUG
417
    jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, JBIG2_UNKNOWN_SEGMENT_NUMBER, "compositing %ux%u at (%u, %u) after clipping",
418
        w, h, (uint32_t) x, (uint32_t) y);
419
#endif
420
421
    /* check for zero clipping region */
422
17.7M
    if ((w <= 0) || (h <= 0)) {
423
#ifdef JBIG2_DEBUG
424
        jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, JBIG2_UNKNOWN_SEGMENT_NUMBER, "zero clipping region");
425
#endif
426
0
        return 0;
427
0
    }
428
429
17.7M
    leftbyte = (uint32_t) x >> 3;
430
17.7M
    dd = dst->data + y * dst->stride + leftbyte;
431
17.7M
    bytewidth = (((uint32_t) x + w - 1) >> 3) - leftbyte + 1;
432
17.7M
    leftmask = 255>>(x&7);
433
17.7M
    rightmask = (((x+w)&7) == 0) ? 255 : ~(255>>((x+w)&7));
434
17.7M
    if (bytewidth == 1)
435
9.45M
        leftmask &= rightmask;
436
17.7M
    late = (ss + bytewidth >= src->data + ((src->width+7)>>3));
437
17.7M
    ss += syoffset;
438
439
17.7M
    switch(op)
440
17.7M
    {
441
2.90M
    case JBIG2_COMPOSE_OR:
442
2.90M
        jbig2_image_compose_opt_OR(ss, dd, early, late, leftmask, rightmask, bytewidth, h, shift, dst->stride, src->stride);
443
2.90M
        break;
444
1.75k
    case JBIG2_COMPOSE_AND:
445
1.75k
        jbig2_image_compose_opt_AND(ss, dd, early, late, leftmask, rightmask, bytewidth, h, shift, dst->stride, src->stride);
446
1.75k
        break;
447
5.29k
    case JBIG2_COMPOSE_XOR:
448
5.29k
        jbig2_image_compose_opt_XOR(ss, dd, early, late, leftmask, rightmask, bytewidth, h, shift, dst->stride, src->stride);
449
5.29k
        break;
450
1.84k
    case JBIG2_COMPOSE_XNOR:
451
1.84k
        jbig2_image_compose_opt_XNOR(ss, dd, early, late, leftmask, rightmask, bytewidth, h, shift, dst->stride, src->stride);
452
1.84k
        break;
453
14.8M
    case JBIG2_COMPOSE_REPLACE:
454
14.8M
        jbig2_image_compose_opt_REPLACE(ss, dd, early, late, leftmask, rightmask, bytewidth, h, shift, dst->stride, src->stride);
455
14.8M
        break;
456
17.7M
    }
457
458
17.7M
    return 0;
459
17.7M
}
460
461
/* initialize an image bitmap to a constant value */
462
void
463
jbig2_image_clear(Jbig2Ctx *ctx, Jbig2Image *image, int value)
464
116k
{
465
116k
    const uint8_t fill = value ? 0xFF : 0x00;
466
467
116k
    (void) ctx;
468
469
116k
    memset(image->data, fill, image->stride * image->height);
470
116k
}
471
472
/* look up a pixel value in an image.
473
   returns 0 outside the image frame for the convenience of
474
   the template code
475
*/
476
int
477
jbig2_image_get_pixel(Jbig2Image *image, int64_t x, int64_t y)
478
13.2G
{
479
13.2G
    const int64_t w = image->width;
480
13.2G
    const int64_t h = image->height;
481
13.2G
    size_t sx, sy;
482
13.2G
    size_t byte;
483
13.2G
    int bit;
484
485
13.2G
    if ((x < 0) || (x >= w))
486
3.67G
        return 0;
487
9.52G
    if ((y < 0) || (y >= h))
488
3.28G
        return 0;
489
490
6.24G
    sx = (size_t) x;
491
6.24G
    sy = (size_t) y;
492
493
6.24G
    byte = (sx >> 3) + sy * image->stride;
494
6.24G
    bit = 7 - ((int) (sx & 7));
495
496
6.24G
    return ((image->data[byte] >> bit) & 1);
497
9.52G
}
498
499
/* set an individual pixel value in an image */
500
void
501
jbig2_image_set_pixel(Jbig2Image *image, int64_t x, int64_t y, bool value)
502
1.47G
{
503
1.47G
    const int64_t w = image->width;
504
1.47G
    const int64_t h = image->height;
505
1.47G
    uint8_t scratch, mask;
506
1.47G
    size_t sx, sy;
507
1.47G
    size_t byte;
508
1.47G
    int bit;
509
510
1.47G
    if ((x < 0) || (x >= w))
511
0
        return;
512
1.47G
    if ((y < 0) || (y >= h))
513
0
        return;
514
515
1.47G
    sx = (size_t) x;
516
1.47G
    sy = (size_t) y;
517
518
1.47G
    byte = (sx >> 3) + sy * image->stride;
519
1.47G
    bit = 7 - ((int) (sx & 7));
520
1.47G
    mask = (uint8_t) ((1 << bit) ^ 0xff);
521
522
1.47G
    scratch = image->data[byte] & mask;
523
1.47G
    image->data[byte] = scratch | (value << bit);
524
1.47G
}