Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/jbig2dec/jbig2_image.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 /* Copyright (C) 2001-2023 Artifex Software, Inc. | |
| 2 All Rights Reserved. | |
| 3 | |
| 4 This software is provided AS-IS with no warranty, either express or | |
| 5 implied. | |
| 6 | |
| 7 This software is distributed under license and may not be copied, | |
| 8 modified or distributed except as expressly authorized under the terms | |
| 9 of the license contained in the file LICENSE in this distribution. | |
| 10 | |
| 11 Refer to licensing information at http://www.artifex.com or contact | |
| 12 Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, | |
| 13 CA 94129, USA, for further information. | |
| 14 */ | |
| 15 | |
| 16 /* | |
| 17 jbig2dec | |
| 18 */ | |
| 19 | |
| 20 #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 { | |
| 37 Jbig2Image *image; | |
| 38 uint32_t stride; | |
| 39 | |
| 40 if (width == 0 || height == 0) { | |
| 41 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to create zero sized image"); | |
| 42 return NULL; | |
| 43 } | |
| 44 | |
| 45 image = jbig2_new(ctx, Jbig2Image, 1); | |
| 46 if (image == NULL) { | |
| 47 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to allocate image"); | |
| 48 return NULL; | |
| 49 } | |
| 50 | |
| 51 stride = ((width - 1) >> 3) + 1; /* generate a byte-aligned stride */ | |
| 52 | |
| 53 /* check for integer multiplication overflow */ | |
| 54 if (height > (INT32_MAX / stride)) { | |
| 55 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "integer multiplication overflow (stride=%u, height=%u)", stride, height); | |
| 56 jbig2_free(ctx->allocator, image); | |
| 57 return NULL; | |
| 58 } | |
| 59 image->data = jbig2_new(ctx, uint8_t, (size_t) height * stride); | |
| 60 if (image->data == NULL) { | |
| 61 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to allocate image data buffer (stride=%u, height=%u)", stride, height); | |
| 62 jbig2_free(ctx->allocator, image); | |
| 63 return NULL; | |
| 64 } | |
| 65 | |
| 66 image->width = width; | |
| 67 image->height = height; | |
| 68 image->stride = stride; | |
| 69 image->refcount = 1; | |
| 70 | |
| 71 return image; | |
| 72 } | |
| 73 | |
| 74 /* bump the reference count for an image pointer */ | |
| 75 Jbig2Image * | |
| 76 jbig2_image_reference(Jbig2Ctx *ctx, Jbig2Image *image) | |
| 77 { | |
| 78 if (image) | |
| 79 image->refcount++; | |
| 80 return image; | |
| 81 } | |
| 82 | |
| 83 /* release an image pointer, freeing it it appropriate */ | |
| 84 void | |
| 85 jbig2_image_release(Jbig2Ctx *ctx, Jbig2Image *image) | |
| 86 { | |
| 87 if (image == NULL) | |
| 88 return; | |
| 89 image->refcount--; | |
| 90 if (image->refcount == 0) | |
| 91 jbig2_image_free(ctx, image); | |
| 92 } | |
| 93 | |
| 94 /* free a Jbig2Image structure and its associated memory */ | |
| 95 void | |
| 96 jbig2_image_free(Jbig2Ctx *ctx, Jbig2Image *image) | |
| 97 { | |
| 98 if (image != NULL) { | |
| 99 jbig2_free(ctx->allocator, image->data); | |
| 100 jbig2_free(ctx->allocator, image); | |
| 101 } | |
| 102 } | |
| 103 | |
| 104 /* resize a Jbig2Image */ | |
| 105 Jbig2Image * | |
| 106 jbig2_image_resize(Jbig2Ctx *ctx, Jbig2Image *image, uint32_t width, uint32_t height, int value) | |
| 107 { | |
| 108 if (width == image->width) { | |
| 109 uint8_t *data; | |
| 110 | |
| 111 /* check for integer multiplication overflow */ | |
| 112 if (image->height > (INT32_MAX / image->stride)) { | |
| 113 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "integer multiplication overflow during resize (stride=%u, height=%u)", image->stride, height); | |
| 114 return NULL; | |
| 115 } | |
| 116 /* use the same stride, just change the length */ | |
| 117 data = jbig2_renew(ctx, image->data, uint8_t, (size_t) height * image->stride); | |
| 118 if (data == NULL) { | |
| 119 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to reallocate image"); | |
| 120 return NULL; | |
| 121 } | |
| 122 image->data = data; | |
| 123 if (height > image->height) { | |
| 124 const uint8_t fill = value ? 0xFF : 0x00; | |
| 125 memset(image->data + (size_t) image->height * image->stride, fill, ((size_t) height - image->height) * image->stride); | |
| 126 } | |
| 127 image->height = height; | |
| 128 | |
| 129 } else { | |
| 130 Jbig2Image *newimage; | |
| 131 int code; | |
| 132 | |
| 133 /* Unoptimized implementation, but it works. */ | |
| 134 | |
| 135 newimage = jbig2_image_new(ctx, width, height); | |
| 136 if (newimage == NULL) { | |
| 137 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to allocate resized image"); | |
| 138 return NULL; | |
| 139 } | |
| 140 jbig2_image_clear(ctx, newimage, value); | |
| 141 | |
| 142 code = jbig2_image_compose(ctx, newimage, image, 0, 0, JBIG2_COMPOSE_REPLACE); | |
| 143 if (code < 0) { | |
| 144 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to compose image buffers when resizing"); | |
| 145 jbig2_image_release(ctx, newimage); | |
| 146 return NULL; | |
| 147 } | |
| 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 jbig2_free(ctx->allocator, image->data); | |
| 153 image->width = newimage->width; | |
| 154 image->height = newimage->height; | |
| 155 image->stride = newimage->stride; | |
| 156 image->data = newimage->data; | |
| 157 jbig2_free(ctx->allocator, newimage); | |
| 158 } | |
| 159 | |
| 160 return image; | |
| 161 } | |
| 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 { | |
| 166 int i; | |
| 167 uint32_t j; | |
| 168 int bytewidth = (int)bytewidth_; | |
| 169 | |
| 170 if (bytewidth == 1) { | |
| 171 for (j = 0; j < h; j++) { | |
| 172 /* Only 1 byte! */ | |
| 173 uint8_t v = (((early ? 0 : ss[0]<<8) | (late ? 0 : ss[1]))>>shift); | |
| 174 if (op == JBIG2_COMPOSE_OR) | |
| 175 *dd |= v & leftmask; | |
| 176 else if (op == JBIG2_COMPOSE_AND) | |
| 177 *dd &= (v & leftmask) | ~leftmask; | |
| 178 else if (op == JBIG2_COMPOSE_XOR) | |
| 179 *dd ^= v & leftmask; | |
| 180 else if (op == JBIG2_COMPOSE_XNOR) | |
| 181 *dd ^= (~v) & leftmask; | |
| 182 else /* Replace */ | |
| 183 *dd = (v & leftmask) | (*dd & ~leftmask); | |
| 184 dd += dstride; | |
| 185 ss += sstride; | |
| 186 } | |
| 187 return; | |
| 188 } | |
| 189 bytewidth -= 2; | |
| 190 if (shift == 0) { | |
| 191 ss++; | |
| 192 for (j = 0; j < h; j++) { | |
| 193 /* Left byte */ | |
| 194 const uint8_t * JBIG2_RESTRICT s = ss; | |
| 195 uint8_t * JBIG2_RESTRICT d = dd; | |
| 196 if (op == JBIG2_COMPOSE_OR) | |
| 197 *d++ |= *s++ & leftmask; | |
| 198 else if (op == JBIG2_COMPOSE_AND) | |
| 199 *d++ &= (*s++ & leftmask) | ~leftmask; | |
| 200 else if (op == JBIG2_COMPOSE_XOR) | |
| 201 *d++ ^= *s++ & leftmask; | |
| 202 else if (op == JBIG2_COMPOSE_XNOR) | |
| 203 *d++ ^= (~*s++) & leftmask; | |
| 204 else /* Replace */ | |
| 205 *d = (*s++ & leftmask) | (*d & ~leftmask), d++; | |
| 206 /* Central run */ | |
| 207 for (i = bytewidth; i != 0; i--) { | |
| 208 if (op == JBIG2_COMPOSE_OR) | |
| 209 *d++ |= *s++; | |
| 210 else if (op == JBIG2_COMPOSE_AND) | |
| 211 *d++ &= *s++; | |
| 212 else if (op == JBIG2_COMPOSE_XOR) | |
| 213 *d++ ^= *s++; | |
| 214 else if (op == JBIG2_COMPOSE_XNOR) | |
| 215 *d++ ^= ~*s++; | |
| 216 else /* Replace */ | |
| 217 *d++ = *s++; | |
| 218 } | |
| 219 /* Right byte */ | |
| 220 if (op == JBIG2_COMPOSE_OR) | |
| 221 *d |= *s & rightmask; | |
| 222 else if (op == JBIG2_COMPOSE_AND) | |
| 223 *d &= (*s & rightmask) | ~rightmask; | |
| 224 else if (op == JBIG2_COMPOSE_XOR) | |
| 225 *d ^= *s & rightmask; | |
| 226 else if (op == JBIG2_COMPOSE_XNOR) | |
| 227 *d ^= (~*s) & rightmask; | |
| 228 else /* Replace */ | |
| 229 *d = (*s & rightmask) | (*d & ~rightmask); | |
| 230 dd += dstride; | |
| 231 ss += sstride; | |
| 232 } | |
| 233 } else { | |
| 234 for (j = 0; j < h; j++) { | |
| 235 /* Left byte */ | |
| 236 const uint8_t * JBIG2_RESTRICT s = ss; | |
| 237 uint8_t * JBIG2_RESTRICT d = dd; | |
| 238 uint8_t s0, s1, v; | |
| 239 s0 = early ? 0 : *s; | |
| 240 s++; | |
| 241 s1 = *s++; | |
| 242 v = ((s0<<8) | s1)>>shift; | |
| 243 if (op == JBIG2_COMPOSE_OR) | |
| 244 *d++ |= v & leftmask; | |
| 245 else if (op == JBIG2_COMPOSE_AND) | |
| 246 *d++ &= (v & leftmask) | ~leftmask; | |
| 247 else if (op == JBIG2_COMPOSE_XOR) | |
| 248 *d++ ^= v & leftmask; | |
| 249 else if (op == JBIG2_COMPOSE_XNOR) | |
| 250 *d++ ^= (~v) & leftmask; | |
| 251 else /* Replace */ | |
| 252 *d = (v & leftmask) | (*d & ~leftmask), d++; | |
| 253 /* Central run */ | |
| 254 for (i = bytewidth; i > 0; i--) { | |
| 255 s0 = s1; s1 = *s++; | |
| 256 v = ((s0<<8) | s1)>>shift; | |
| 257 if (op == JBIG2_COMPOSE_OR) | |
| 258 *d++ |= v; | |
| 259 else if (op == JBIG2_COMPOSE_AND) | |
| 260 *d++ &= v; | |
| 261 else if (op == JBIG2_COMPOSE_XOR) | |
| 262 *d++ ^= v; | |
| 263 else if (op == JBIG2_COMPOSE_XNOR) | |
| 264 *d++ ^= ~v; | |
| 265 else /* Replace */ | |
| 266 *d++ = v; | |
| 267 } | |
| 268 /* Right byte */ | |
| 269 s0 = s1; s1 = (late ? 0 : *s); | |
| 270 v = (((s0<<8) | s1)>>shift); | |
| 271 if (op == JBIG2_COMPOSE_OR) | |
| 272 *d |= v & rightmask; | |
| 273 else if (op == JBIG2_COMPOSE_AND) | |
| 274 *d &= (v & rightmask) | ~rightmask; | |
| 275 else if (op == JBIG2_COMPOSE_XOR) | |
| 276 *d ^= v & rightmask; | |
| 277 else if (op == JBIG2_COMPOSE_XNOR) | |
| 278 *d ^= ~v & rightmask; | |
| 279 else /* Replace */ | |
| 280 *d = (v & rightmask) | (*d & ~rightmask); | |
| 281 dd += dstride; | |
| 282 ss += sstride; | |
| 283 } | |
| 284 } | |
| 285 } | |
| 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 { | |
| 290 if (early || late) | |
| 291 template_image_compose_opt(s, d, early, late, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_OR); | |
| 292 else | |
| 293 template_image_compose_opt(s, d, 0, 0, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_OR); | |
| 294 } | |
| 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 { | |
| 299 if (early || late) | |
| 300 template_image_compose_opt(s, d, early, late, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_AND); | |
| 301 else | |
| 302 template_image_compose_opt(s, d, 0, 0, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_AND); | |
| 303 } | |
| 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 { | |
| 308 if (early || late) | |
| 309 template_image_compose_opt(s, d, early, late, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_XOR); | |
| 310 else | |
| 311 template_image_compose_opt(s, d, 0, 0, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_XOR); | |
| 312 } | |
| 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 { | |
| 317 if (early || late) | |
| 318 template_image_compose_opt(s, d, early, late, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_XNOR); | |
| 319 else | |
| 320 template_image_compose_opt(s, d, 0, 0, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_XNOR); | |
| 321 } | |
| 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 { | |
| 326 if (early || late) | |
| 327 template_image_compose_opt(s, d, early, late, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_REPLACE); | |
| 328 else | |
| 329 template_image_compose_opt(s, d, 0, 0, mask, rightmask, bytewidth, h, shift, dstride, sstride, JBIG2_COMPOSE_REPLACE); | |
| 330 } | |
| 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 { | |
| 336 uint32_t w, h; | |
| 337 uint32_t shift; | |
| 338 uint32_t leftbyte; | |
| 339 uint8_t *ss; | |
| 340 uint8_t *dd; | |
| 341 uint8_t leftmask, rightmask; | |
| 342 int early = x >= 0; | |
| 343 int late; | |
| 344 uint32_t bytewidth; | |
| 345 uint32_t syoffset = 0; | |
| 346 | |
| 347 if (src == NULL) | |
| 348 return 0; | |
| 349 | |
| 350 if ((UINT32_MAX - src->width < (uint32_t) (x > 0 ? x : -x)) || | |
| 351 (UINT32_MAX - src->height < (uint32_t) (y > 0 ? y : -y))) | |
| 352 { | |
| 353 #ifdef JBIG2_DEBUG | |
| 354 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, JBIG2_UNKNOWN_SEGMENT_NUMBER, "overflow in compose_image"); | |
| 355 #endif | |
| 356 return 0; | |
| 357 } | |
| 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 w = src->width; | |
| 379 h = src->height; | |
| 380 shift = (x & 7); | |
| 381 ss = src->data - early; | |
| 382 | |
| 383 if (x < 0) { | |
| 384 if (w < (uint32_t) -x) | |
| 385 w = 0; | |
| 386 else | |
| 387 w += x; | |
| 388 ss += (-x-1)>>3; | |
| 389 x = 0; | |
| 390 } | |
| 391 if (y < 0) { | |
| 392 if (h < (uint32_t) -y) | |
| 393 h = 0; | |
| 394 else | |
| 395 h += y; | |
| 396 syoffset = -y * src->stride; | |
| 397 y = 0; | |
| 398 } | |
| 399 if ((uint32_t)x + w > dst->width) | |
| 400 { | |
| 401 if (dst->width < (uint32_t)x) | |
| 402 w = 0; | |
| 403 else | |
| 404 w = dst->width - x; | |
| 405 } | |
| 406 if ((uint32_t)y + h > dst->height) | |
| 407 { | |
| 408 if (dst->height < (uint32_t)y) | |
| 409 h = 0; | |
| 410 else | |
| 411 h = dst->height - y; | |
| 412 } | |
| 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 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 return 0; | |
| 423 } | |
| 424 | |
| 425 leftbyte = (uint32_t) x >> 3; | |
| 426 dd = dst->data + y * dst->stride + leftbyte; | |
| 427 bytewidth = (((uint32_t) x + w - 1) >> 3) - leftbyte + 1; | |
| 428 leftmask = 255>>(x&7); | |
| 429 rightmask = (((x+w)&7) == 0) ? 255 : ~(255>>((x+w)&7)); | |
| 430 if (bytewidth == 1) | |
| 431 leftmask &= rightmask; | |
| 432 late = (ss + bytewidth >= src->data + ((src->width+7)>>3)); | |
| 433 ss += syoffset; | |
| 434 | |
| 435 switch(op) | |
| 436 { | |
| 437 case JBIG2_COMPOSE_OR: | |
| 438 jbig2_image_compose_opt_OR(ss, dd, early, late, leftmask, rightmask, bytewidth, h, shift, dst->stride, src->stride); | |
| 439 break; | |
| 440 case JBIG2_COMPOSE_AND: | |
| 441 jbig2_image_compose_opt_AND(ss, dd, early, late, leftmask, rightmask, bytewidth, h, shift, dst->stride, src->stride); | |
| 442 break; | |
| 443 case JBIG2_COMPOSE_XOR: | |
| 444 jbig2_image_compose_opt_XOR(ss, dd, early, late, leftmask, rightmask, bytewidth, h, shift, dst->stride, src->stride); | |
| 445 break; | |
| 446 case JBIG2_COMPOSE_XNOR: | |
| 447 jbig2_image_compose_opt_XNOR(ss, dd, early, late, leftmask, rightmask, bytewidth, h, shift, dst->stride, src->stride); | |
| 448 break; | |
| 449 case JBIG2_COMPOSE_REPLACE: | |
| 450 jbig2_image_compose_opt_REPLACE(ss, dd, early, late, leftmask, rightmask, bytewidth, h, shift, dst->stride, src->stride); | |
| 451 break; | |
| 452 } | |
| 453 | |
| 454 return 0; | |
| 455 } | |
| 456 | |
| 457 /* initialize an image bitmap to a constant value */ | |
| 458 void | |
| 459 jbig2_image_clear(Jbig2Ctx *ctx, Jbig2Image *image, int value) | |
| 460 { | |
| 461 const uint8_t fill = value ? 0xFF : 0x00; | |
| 462 | |
| 463 memset(image->data, fill, image->stride * image->height); | |
| 464 } | |
| 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 { | |
| 473 const int w = image->width; | |
| 474 const int h = image->height; | |
| 475 const int byte = (x >> 3) + y * image->stride; | |
| 476 const int bit = 7 - (x & 7); | |
| 477 | |
| 478 if ((x < 0) || (x >= w)) | |
| 479 return 0; | |
| 480 if ((y < 0) || (y >= h)) | |
| 481 return 0; | |
| 482 | |
| 483 return ((image->data[byte] >> bit) & 1); | |
| 484 } | |
| 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 { | |
| 490 const int w = image->width; | |
| 491 const int h = image->height; | |
| 492 int scratch, mask; | |
| 493 int bit, byte; | |
| 494 | |
| 495 if ((x < 0) || (x >= w)) | |
| 496 return; | |
| 497 if ((y < 0) || (y >= h)) | |
| 498 return; | |
| 499 | |
| 500 byte = (x >> 3) + y * image->stride; | |
| 501 bit = 7 - (x & 7); | |
| 502 mask = (1 << bit) ^ 0xff; | |
| 503 | |
| 504 scratch = image->data[byte] & mask; | |
| 505 image->data[byte] = scratch | (value << bit); | |
| 506 } |
