Coverage Report

Created: 2025-12-11 07:00

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
10.0M
{
37
10.0M
    Jbig2Image *image;
38
10.0M
    uint32_t stride;
39
40
10.0M
    if (width == 0 || height == 0) {
41
54
        jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to create zero sized image");
42
54
        return NULL;
43
54
    }
44
45
10.0M
    image = jbig2_new(ctx, Jbig2Image, 1);
46
10.0M
    if (image == NULL) {
47
16
        jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to allocate image");
48
16
        return NULL;
49
16
    }
50
51
10.0M
    stride = ((width - 1) >> 3) + 1;    /* generate a byte-aligned stride */
52
53
    /* check for integer multiplication overflow */
54
10.0M
    if (height > (INT32_MAX / stride)) {
55
94
        jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "integer multiplication overflow (stride=%u, height=%u)", stride, height);
56
94
        jbig2_free(ctx->allocator, image);
57
94
        return NULL;
58
94
    }
59
10.0M
    image->data = jbig2_new(ctx, uint8_t, (size_t) height * stride);
60
10.0M
    if (image->data == NULL) {
61
123
        jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to allocate image data buffer (stride=%u, height=%u)", stride, height);
62
123
        jbig2_free(ctx->allocator, image);
63
123
        return NULL;
64
123
    }
65
66
10.0M
    image->width = width;
67
10.0M
    image->height = height;
68
10.0M
    image->stride = stride;
69
10.0M
    image->refcount = 1;
70
71
10.0M
    return image;
72
10.0M
}
73
74
/* bump the reference count for an image pointer */
75
Jbig2Image *
76
jbig2_image_reference(Jbig2Ctx *ctx, Jbig2Image *image)
77
37.3M
{
78
37.3M
    if (image)
79
31.1M
        image->refcount++;
80
37.3M
    return image;
81
37.3M
}
82
83
/* release an image pointer, freeing it it appropriate */
84
void
85
jbig2_image_release(Jbig2Ctx *ctx, Jbig2Image *image)
86
283M
{
87
283M
    if (image == NULL)
88
242M
        return;
89
41.2M
    image->refcount--;
90
41.2M
    if (image->refcount == 0)
91
10.0M
        jbig2_image_free(ctx, image);
92
41.2M
}
93
94
/* free a Jbig2Image structure and its associated memory */
95
void
96
jbig2_image_free(Jbig2Ctx *ctx, Jbig2Image *image)
97
10.0M
{
98
10.0M
    if (image != NULL) {
99
10.0M
        jbig2_free(ctx->allocator, image->data);
100
10.0M
        jbig2_free(ctx->allocator, image);
101
10.0M
    }
102
10.0M
}
103
104
/* resize a Jbig2Image */
105
Jbig2Image *
106
jbig2_image_resize(Jbig2Ctx *ctx, Jbig2Image *image, uint32_t width, uint32_t height, int value)
107
1.49k
{
108
1.49k
    if (width == image->width) {
109
1.49k
        uint8_t *data;
110
111
        /* check for integer multiplication overflow */
112
1.49k
        if (image->height > (INT32_MAX / image->stride)) {
113
0
            jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "integer multiplication overflow during resize (stride=%u, height=%u)", image->stride, height);
114
0
            return NULL;
115
0
        }
116
        /* use the same stride, just change the length */
117
1.49k
        data = jbig2_renew(ctx, image->data, uint8_t, (size_t) height * image->stride);
118
1.49k
        if (data == NULL) {
119
23
            jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to reallocate image");
120
23
            return NULL;
121
23
        }
122
1.47k
        image->data = data;
123
1.47k
        if (height > image->height) {
124
1.47k
            const uint8_t fill = value ? 0xFF : 0x00;
125
1.47k
            memset(image->data + (size_t) image->height * image->stride, fill, ((size_t) height - image->height) * image->stride);
126
1.47k
        }
127
1.47k
        image->height = height;
128
129
1.47k
    } else {
130
0
        Jbig2Image *newimage;
131
0
        int code;
132
133
        /* Unoptimized implementation, but it works. */
134
135
0
        newimage = jbig2_image_new(ctx, width, height);
136
0
        if (newimage == NULL) {
137
0
            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to allocate resized image");
138
0
            return NULL;
139
0
        }
140
0
        jbig2_image_clear(ctx, newimage, value);
141
142
0
        code = jbig2_image_compose(ctx, newimage, image, 0, 0, JBIG2_COMPOSE_REPLACE);
143
0
        if (code < 0) {
144
0
            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to compose image buffers when resizing");
145
0
            jbig2_image_release(ctx, newimage);
146
0
            return NULL;
147
0
        }
148
149
        /* if refcount > 1 the original image, its pointer must
150
        be kept, so simply replaces its innards, and throw away
151
        the empty new image shell. */
152
0
        jbig2_free(ctx->allocator, image->data);
153
0
        image->width = newimage->width;
154
0
        image->height = newimage->height;
155
0
        image->stride = newimage->stride;
156
0
        image->data = newimage->data;
157
0
        jbig2_free(ctx->allocator, newimage);
158
0
    }
159
160
1.47k
    return image;
161
1.49k
}
162
163
static inline void
164
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)
165
15.8M
{
166
15.8M
    int i;
167
15.8M
    uint32_t j;
168
15.8M
    int bytewidth = (int)bytewidth_;
169
170
15.8M
    if (bytewidth == 1) {
171
173M
        for (j = 0; j < h; j++) {
172
            /* Only 1 byte! */
173
166M
            uint8_t v = (((early ? 0 : ss[0]<<8) | (late ? 0 : ss[1]))>>shift);
174
166M
            if (op == JBIG2_COMPOSE_OR)
175
45.1M
                *dd |= v & leftmask;
176
121M
            else if (op == JBIG2_COMPOSE_AND)
177
1.84k
                *dd &= (v & leftmask) | ~leftmask;
178
121M
            else if (op == JBIG2_COMPOSE_XOR)
179
55.6k
                *dd ^= v & leftmask;
180
121M
            else if (op == JBIG2_COMPOSE_XNOR)
181
6.67k
                *dd ^= (~v) & leftmask;
182
121M
            else /* Replace */
183
121M
                *dd = (v & leftmask) | (*dd & ~leftmask);
184
166M
            dd += dstride;
185
166M
            ss += sstride;
186
166M
        }
187
7.09M
        return;
188
7.09M
    }
189
8.74M
    bytewidth -= 2;
190
8.74M
    if (shift == 0) {
191
2.18M
        ss++;
192
30.4M
        for (j = 0; j < h; j++) {
193
            /* Left byte */
194
28.2M
            const uint8_t * JBIG2_RESTRICT s = ss;
195
28.2M
            uint8_t * JBIG2_RESTRICT d = dd;
196
28.2M
            if (op == JBIG2_COMPOSE_OR)
197
1.85M
                *d++ |= *s++ & leftmask;
198
26.4M
            else if (op == JBIG2_COMPOSE_AND)
199
103k
                *d++ &= (*s++ & leftmask) | ~leftmask;
200
26.3M
            else if (op == JBIG2_COMPOSE_XOR)
201
1.39k
                *d++ ^= *s++ & leftmask;
202
26.3M
            else if (op == JBIG2_COMPOSE_XNOR)
203
4.39k
                *d++ ^= (~*s++) & leftmask;
204
26.3M
            else /* Replace */
205
26.3M
                *d = (*s++ & leftmask) | (*d & ~leftmask), d++;
206
            /* Central run */
207
732M
            for (i = bytewidth; i != 0; i--) {
208
703M
                if (op == JBIG2_COMPOSE_OR)
209
502M
                    *d++ |= *s++;
210
201M
                else if (op == JBIG2_COMPOSE_AND)
211
177k
                    *d++ &= *s++;
212
201M
                else if (op == JBIG2_COMPOSE_XOR)
213
87.2k
                    *d++ ^= *s++;
214
201M
                else if (op == JBIG2_COMPOSE_XNOR)
215
530k
                    *d++ ^= ~*s++;
216
200M
                else /* Replace */
217
200M
                    *d++ = *s++;
218
703M
            }
219
            /* Right byte */
220
28.2M
            if (op == JBIG2_COMPOSE_OR)
221
1.85M
                *d |= *s & rightmask;
222
26.4M
            else if (op == JBIG2_COMPOSE_AND)
223
103k
                *d &= (*s & rightmask) | ~rightmask;
224
26.3M
            else if (op == JBIG2_COMPOSE_XOR)
225
1.39k
                *d ^= *s & rightmask;
226
26.3M
            else if (op == JBIG2_COMPOSE_XNOR)
227
4.39k
                *d ^= (~*s) & rightmask;
228
26.3M
            else /* Replace */
229
26.3M
                *d = (*s & rightmask) | (*d & ~rightmask);
230
28.2M
            dd += dstride;
231
28.2M
            ss += sstride;
232
28.2M
        }
233
6.55M
    } else {
234
85.3M
        for (j = 0; j < h; j++) {
235
            /* Left byte */
236
78.8M
            const uint8_t * JBIG2_RESTRICT s = ss;
237
78.8M
            uint8_t * JBIG2_RESTRICT d = dd;
238
78.8M
            uint8_t s0, s1, v;
239
78.8M
            s0 = early ? 0 : *s;
240
78.8M
            s++;
241
78.8M
            s1 = *s++;
242
78.8M
            v = ((s0<<8) | s1)>>shift;
243
78.8M
            if (op == JBIG2_COMPOSE_OR)
244
18.4M
                *d++ |= v & leftmask;
245
60.3M
            else if (op == JBIG2_COMPOSE_AND)
246
87.8k
                *d++ &= (v & leftmask) | ~leftmask;
247
60.3M
            else if (op == JBIG2_COMPOSE_XOR)
248
103k
                *d++ ^= v & leftmask;
249
60.2M
            else if (op == JBIG2_COMPOSE_XNOR)
250
15.0k
                *d++ ^= (~v) & leftmask;
251
60.1M
            else /* Replace */
252
60.1M
                *d = (v & leftmask) | (*d & ~leftmask), d++;
253
            /* Central run */
254
770M
            for (i = bytewidth; i > 0; i--) {
255
691M
                s0 = s1; s1 = *s++;
256
691M
                v = ((s0<<8) | s1)>>shift;
257
691M
                if (op == JBIG2_COMPOSE_OR)
258
204M
                    *d++ |= v;
259
487M
                else if (op == JBIG2_COMPOSE_AND)
260
598k
                    *d++ &= v;
261
486M
                else if (op == JBIG2_COMPOSE_XOR)
262
719k
                    *d++ ^= v;
263
486M
                else if (op == JBIG2_COMPOSE_XNOR)
264
200k
                    *d++ ^= ~v;
265
485M
                else /* Replace */
266
485M
                    *d++ = v;
267
691M
            }
268
            /* Right byte */
269
78.8M
            s0 = s1; s1 = (late ? 0 : *s);
270
78.8M
            v = (((s0<<8) | s1)>>shift);
271
78.8M
            if (op == JBIG2_COMPOSE_OR)
272
18.4M
                *d |= v & rightmask;
273
60.3M
            else if (op == JBIG2_COMPOSE_AND)
274
87.8k
                *d &= (v & rightmask) | ~rightmask;
275
60.3M
            else if (op == JBIG2_COMPOSE_XOR)
276
103k
                *d ^= v & rightmask;
277
60.2M
            else if (op == JBIG2_COMPOSE_XNOR)
278
15.0k
                *d ^= ~v & rightmask;
279
60.1M
            else /* Replace */
280
60.1M
                *d = (v & rightmask) | (*d & ~rightmask);
281
78.8M
            dd += dstride;
282
78.8M
            ss += sstride;
283
78.8M
        }
284
6.55M
    }
285
8.74M
}
286
287
static void
288
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)
289
5.92M
{
290
5.92M
    if (early || late)
291
5.92M
        template_image_compose_opt(s, d, early, late, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_OR);
292
1.70k
    else
293
1.70k
        template_image_compose_opt(s, d, 0, 0, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_OR);
294
5.92M
}
295
296
static void
297
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)
298
8.22k
{
299
8.22k
    if (early || late)
300
7.50k
        template_image_compose_opt(s, d, early, late, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_AND);
301
720
    else
302
720
        template_image_compose_opt(s, d, 0, 0, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_AND);
303
8.22k
}
304
305
static void
306
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)
307
3.09k
{
308
3.09k
    if (early || late)
309
1.38k
        template_image_compose_opt(s, d, early, late, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_XOR);
310
1.70k
    else
311
1.70k
        template_image_compose_opt(s, d, 0, 0, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_XOR);
312
3.09k
}
313
314
static void
315
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)
316
5.18k
{
317
5.18k
    if (early || late)
318
4.53k
        template_image_compose_opt(s, d, early, late, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_XNOR);
319
644
    else
320
644
        template_image_compose_opt(s, d, 0, 0, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_XNOR);
321
5.18k
}
322
323
static void
324
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)
325
9.89M
{
326
9.89M
    if (early || late)
327
9.76k
        template_image_compose_opt(s, d, early, late, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_REPLACE);
328
9.88M
    else
329
9.88M
        template_image_compose_opt(s, d, 0, 0, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_REPLACE);
330
9.89M
}
331
332
/* composite one jbig2_image onto another */
333
int
334
jbig2_image_compose(Jbig2Ctx *ctx, Jbig2Image *dst, Jbig2Image *src, int x, int y, Jbig2ComposeOp op)
335
128M
{
336
128M
    uint32_t w, h;
337
128M
    uint32_t shift;
338
128M
    uint32_t leftbyte;
339
128M
    uint8_t *ss;
340
128M
    uint8_t *dd;
341
128M
    uint8_t leftmask, rightmask;
342
128M
    int early = x >= 0;
343
128M
    int late;
344
128M
    uint32_t bytewidth;
345
128M
    uint32_t syoffset = 0;
346
347
128M
    if (src == NULL)
348
7.68M
        return 0;
349
350
120M
    if ((UINT32_MAX - src->width  < (uint32_t) (x > 0 ? x : -x)) ||
351
120M
        (UINT32_MAX - src->height < (uint32_t) (y > 0 ? y : -y)))
352
0
    {
353
#ifdef JBIG2_DEBUG
354
        jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, JBIG2_UNKNOWN_SEGMENT_NUMBER, "overflow in compose_image");
355
#endif
356
0
        return 0;
357
0
    }
358
359
    /* This code takes a src image and combines it onto dst at offset (x,y), with operation op. */
360
361
    /* Data is packed msb first within a byte, so with bits numbered: 01234567.
362
     * Second byte is: 89abcdef. So to combine into a run, we use:
363
     *       (s[0]<<8) | s[1] == 0123456789abcdef.
364
     * To read from src into dst at offset 3, we need to read:
365
     *    read:      0123456789abcdef...
366
     *    write:  0123456798abcdef...
367
     * In general, to read from src and write into dst at offset x, we need to shift
368
     * down by (x&7) bits to allow for bit alignment. So shift = x&7.
369
     * So the 'central' part of our runs will see us doing:
370
     *   *d++ op= ((s[0]<<8)|s[1])>>shift;
371
     * with special cases on the left and right edges of the run to mask.
372
     * With the left hand edge, we have to be careful not to 'underread' the start of
373
     * the src image; this is what the early flag is about. Similarly we have to be
374
     * careful not to read off the right hand edge; this is what the late flag is for.
375
     */
376
377
    /* clip */
378
120M
    w = src->width;
379
120M
    h = src->height;
380
120M
    shift = (x & 7);
381
120M
    ss = src->data - early;
382
383
120M
    if (x < 0) {
384
33.3M
        if (w < (uint32_t) -x)
385
21.9M
            w = 0;
386
11.3M
        else
387
11.3M
            w += x;
388
33.3M
        ss += (-x-1)>>3;
389
33.3M
        x = 0;
390
33.3M
    }
391
120M
    if (y < 0) {
392
48.0M
        if (h < (uint32_t) -y)
393
42.4M
            h = 0;
394
5.68M
        else
395
5.68M
            h += y;
396
48.0M
        syoffset = -y * src->stride;
397
48.0M
        y = 0;
398
48.0M
    }
399
120M
    if ((uint32_t)x + w > dst->width)
400
78.9M
    {
401
78.9M
        if (dst->width < (uint32_t)x)
402
68.2M
            w = 0;
403
10.7M
        else
404
10.7M
            w = dst->width - x;
405
78.9M
    }
406
120M
    if ((uint32_t)y + h > dst->height)
407
42.2M
    {
408
42.2M
        if (dst->height < (uint32_t)y)
409
39.6M
            h = 0;
410
2.66M
        else
411
2.66M
            h = dst->height - y;
412
42.2M
    }
413
#ifdef JBIG2_DEBUG
414
    jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, JBIG2_UNKNOWN_SEGMENT_NUMBER, "compositing %dx%d at (%d, %d) after clipping", w, h, x, y);
415
#endif
416
417
    /* check for zero clipping region */
418
120M
    if ((w <= 0) || (h <= 0)) {
419
#ifdef JBIG2_DEBUG
420
        jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, JBIG2_UNKNOWN_SEGMENT_NUMBER, "zero clipping region");
421
#endif
422
105M
        return 0;
423
105M
    }
424
425
15.8M
    leftbyte = (uint32_t) x >> 3;
426
15.8M
    dd = dst->data + y * dst->stride + leftbyte;
427
15.8M
    bytewidth = (((uint32_t) x + w - 1) >> 3) - leftbyte + 1;
428
15.8M
    leftmask = 255>>(x&7);
429
15.8M
    rightmask = (((x+w)&7) == 0) ? 255 : ~(255>>((x+w)&7));
430
15.8M
    if (bytewidth == 1)
431
7.09M
        leftmask &= rightmask;
432
15.8M
    late = (ss + bytewidth >= src->data + ((src->width+7)>>3));
433
15.8M
    ss += syoffset;
434
435
15.8M
    switch(op)
436
15.8M
    {
437
5.92M
    case JBIG2_COMPOSE_OR:
438
5.92M
        jbig2_image_compose_opt_OR(ss, dd, early, late, leftmask, rightmask, bytewidth, h, shift, dst->stride, src->stride);
439
5.92M
        break;
440
8.22k
    case JBIG2_COMPOSE_AND:
441
8.22k
        jbig2_image_compose_opt_AND(ss, dd, early, late, leftmask, rightmask, bytewidth, h, shift, dst->stride, src->stride);
442
8.22k
        break;
443
3.09k
    case JBIG2_COMPOSE_XOR:
444
3.09k
        jbig2_image_compose_opt_XOR(ss, dd, early, late, leftmask, rightmask, bytewidth, h, shift, dst->stride, src->stride);
445
3.09k
        break;
446
5.18k
    case JBIG2_COMPOSE_XNOR:
447
5.18k
        jbig2_image_compose_opt_XNOR(ss, dd, early, late, leftmask, rightmask, bytewidth, h, shift, dst->stride, src->stride);
448
5.18k
        break;
449
9.89M
    case JBIG2_COMPOSE_REPLACE:
450
9.89M
        jbig2_image_compose_opt_REPLACE(ss, dd, early, late, leftmask, rightmask, bytewidth, h, shift, dst->stride, src->stride);
451
9.89M
        break;
452
15.8M
    }
453
454
15.8M
    return 0;
455
15.8M
}
456
457
/* initialize an image bitmap to a constant value */
458
void
459
jbig2_image_clear(Jbig2Ctx *ctx, Jbig2Image *image, int value)
460
82.9k
{
461
82.9k
    const uint8_t fill = value ? 0xFF : 0x00;
462
463
82.9k
    memset(image->data, fill, image->stride * image->height);
464
82.9k
}
465
466
/* look up a pixel value in an image.
467
   returns 0 outside the image frame for the convenience of
468
   the template code
469
*/
470
int
471
jbig2_image_get_pixel(Jbig2Image *image, int x, int y)
472
8.83G
{
473
8.83G
    const int w = image->width;
474
8.83G
    const int h = image->height;
475
8.83G
    const int byte = (x >> 3) + y * image->stride;
476
8.83G
    const int bit = 7 - (x & 7);
477
478
8.83G
    if ((x < 0) || (x >= w))
479
2.59G
        return 0;
480
6.24G
    if ((y < 0) || (y >= h))
481
2.04G
        return 0;
482
483
4.19G
    return ((image->data[byte] >> bit) & 1);
484
6.24G
}
485
486
/* set an individual pixel value in an image */
487
void
488
jbig2_image_set_pixel(Jbig2Image *image, int x, int y, bool value)
489
1.03G
{
490
1.03G
    const int w = image->width;
491
1.03G
    const int h = image->height;
492
1.03G
    int scratch, mask;
493
1.03G
    int bit, byte;
494
495
1.03G
    if ((x < 0) || (x >= w))
496
0
        return;
497
1.03G
    if ((y < 0) || (y >= h))
498
0
        return;
499
500
1.03G
    byte = (x >> 3) + y * image->stride;
501
1.03G
    bit = 7 - (x & 7);
502
1.03G
    mask = (1 << bit) ^ 0xff;
503
504
1.03G
    scratch = image->data[byte] & mask;
505
1.03G
    image->data[byte] = scratch | (value << bit);
506
1.03G
}