summaryrefslogtreecommitdiff
path: root/jbig2dec
diff options
context:
space:
mode:
authorRobin Watts <Robin.Watts@artifex.com>2020-01-29 15:34:58 +0000
committerRobin Watts <Robin.Watts@artifex.com>2020-01-30 17:14:09 +0000
commit1c5a25063d6041902442334f633840bd8660451e (patch)
tree871d4b09874c75ae757f82441667ff5598a8fdb2 /jbig2dec
parent0e84a5f7ca660af4de1afb5bce79f6262b44ebd1 (diff)
downloadghostpdl-1c5a25063d6041902442334f633840bd8660451e.tar.gz
Further optimisations to jbig2_decode_generic functions.
Carry 'window' of pixel data across scanlines, and read samples from it. Write pixel data back in whole bytes rather than single bits. Sadly, for cases where the adaptive pixels are non-standard we need to write back after every pixel in case the adaptive pixels read from it. Profiling shows the time spent in the hotspot with jbig2_042_08.pdf drops from 56% to 43% with this optimisation. Particular thanks to Sebastian for spotting various issues with this.
Diffstat (limited to 'jbig2dec')
-rw-r--r--jbig2dec/jbig2_generic.c605
1 files changed, 362 insertions, 243 deletions
diff --git a/jbig2dec/jbig2_generic.c b/jbig2dec/jbig2_generic.c
index fc00f62b0..3f1b41b57 100644
--- a/jbig2dec/jbig2_generic.c
+++ b/jbig2dec/jbig2_generic.c
@@ -356,36 +356,6 @@ jbig2_image_get_pixel_fast(Jbig2Image *image, int x, int y)
return ((image->data[byte] >> bit) & 1);
}
-/* Get a run of up to 9 bits. This reads into the next byte, so the caller
- * must ensure that we are always safe to read at least 9 pixels, even if
- * it only wants less than that. */
-static inline int
-jbig2_image_get_pixels_fast(Jbig2Image *image, int x, int y, int bits)
-{
- const int byte = (x >> 3) + y * image->stride;
- const int bit = 7 - (x & 7);
- int v = ((image->data[byte]<<8) | (image->data[byte+1]))>>(bit+9-bits);
-
- return v & ((1<<bits)-1);
-}
-
-/* set an individual pixel value in an image - no bounds checking */
-static inline void
-jbig2_image_set_pixel_fast(Jbig2Image *image, int x, int y, bool value)
-{
- int scratch, mask;
- int bit, byte;
-
- byte = (x >> 3) + y * image->stride;
- bit = 7 - (x & 7);
- mask = (1 << bit) ^ 0xff;
-
- scratch = image->data[byte] & mask;
- image->data[byte] = scratch | (value << bit);
-}
-
-
-
/* return the appropriate context size for the given template */
int
jbig2_generic_stats_size(Jbig2Ctx *ctx, int template)
@@ -484,36 +454,56 @@ jbig2_decode_generic_template0_unopt(Jbig2Ctx *ctx,
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"adaptive template pixel is out of field");
- /* this version is generic and easy to understand, but very slow */
-
for (y = 0; y < GBH; y++) {
+ uint32_t out_byte = 0;
+ int out_bits_to_go_in_byte = 8;
+ uint8_t *d = &image->data[image->stride * y];
+ uint8_t *pline = &image->data[image->stride * (y-1)];
+ uint8_t *ppline = &image->data[image->stride * (y-2)];
+ uint32_t pd = 0;
+ uint32_t ppd = 0;
+ if (y > 0) {
+ pd = (*pline++ << 8);
+ if (GBW > 8)
+ pd |= *pline++;
+ if (y > 1) {
+ ppd = (*ppline++ << 8);
+ if (GBW > 8)
+ ppd |= *ppline++;
+ }
+ }
for (x = 0; x < GBW; x++) {
if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
- jbig2_image_set_pixel(image, x, y, 0);
- continue;
+ bit = 0;
+ } else {
+ CONTEXT = out_byte & 0x000F; /* First 4 pixels */
+ CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 4;
+ CONTEXT |= (pd>>8) & 0x03E0; /* Next 5 pixels */
+ CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[2], y + params->gbat[3]) << 10;
+ CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[4], y + params->gbat[5]) << 11;
+ CONTEXT |= (ppd>>2) & 0x7000; /* Next 3 pixels */
+ CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[6], y + params->gbat[7]) << 15;
+ bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template0 unoptimized");
+ }
+ pd = pd<<1;
+ ppd = ppd<<1;
+ out_byte = (out_byte<<1) | bit;
+ out_bits_to_go_in_byte--;
+ *d = out_byte<<out_bits_to_go_in_byte;
+ if (out_bits_to_go_in_byte == 0) {
+ out_bits_to_go_in_byte = 8;
+ d++;
+ if (x+9 < GBW && y > 0) {
+ pd |= *pline++;
+ if (y > 1)
+ ppd |= *ppline++;
+ }
}
- CONTEXT = 0;
- CONTEXT |= jbig2_image_get_pixel(image, x - 1, y) << 0;
- CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
- CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
- CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3;
- CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 4;
- CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 1) << 5;
- CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 6;
- CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 7;
- CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 8;
- CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 9;
- CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[2], y + params->gbat[3]) << 10;
- CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[4], y + params->gbat[5]) << 11;
- CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 12;
- CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 2) << 13;
- CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 14;
- CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[6], y + params->gbat[7]) << 15;
- bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
- if (code)
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template0 unoptimized");
- jbig2_image_set_pixel(image, x, y, bit);
}
+ if (out_bits_to_go_in_byte != 8)
+ *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
}
return 0;
}
@@ -534,33 +524,53 @@ jbig2_decode_generic_template1_unopt(Jbig2Ctx *ctx,
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"adaptive template pixel is out of field");
- /* this version is generic and easy to understand, but very slow */
-
for (y = 0; y < GBH; y++) {
+ uint32_t out_byte = 0;
+ int out_bits_to_go_in_byte = 8;
+ uint8_t *d = &image->data[image->stride * y];
+ uint8_t *pline = &image->data[image->stride * (y-1)];
+ uint8_t *ppline = &image->data[image->stride * (y-2)];
+ uint32_t pd = 0;
+ uint32_t ppd = 0;
+ if (y > 0) {
+ pd = (*pline++ << 8);
+ if (GBW > 8)
+ pd |= *pline++;
+ if (y > 1) {
+ ppd = (*ppline++ << 8);
+ if (GBW > 8)
+ ppd |= *ppline++;
+ }
+ }
for (x = 0; x < GBW; x++) {
if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
- jbig2_image_set_pixel(image, x, y, 0);
- continue;
+ bit = 0;
+ } else {
+ CONTEXT = out_byte & 0x0007; /* First 3 pixels */
+ CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 3;
+ CONTEXT |= (pd>>9) & 0x01F0; /* Next 5 pixels */
+ CONTEXT |= (ppd>>4) & 0x1E00; /* Next 4 pixels */
+ bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template1 unoptimized");
+ }
+ pd = pd<<1;
+ ppd = ppd<<1;
+ out_byte = (out_byte<<1) | bit;
+ out_bits_to_go_in_byte--;
+ *d = out_byte<<out_bits_to_go_in_byte;
+ if (out_bits_to_go_in_byte == 0) {
+ out_bits_to_go_in_byte = 8;
+ d++;
+ if (x+9 < GBW && y > 0) {
+ pd |= *pline++;
+ if (y > 1)
+ ppd |= *ppline++;
+ }
}
- CONTEXT = 0;
- CONTEXT |= jbig2_image_get_pixel(image, x - 1, y) << 0;
- CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
- CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
- CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 3;
- CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 1) << 4;
- CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 5;
- CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 6;
- CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7;
- CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8;
- CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 2) << 9;
- CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 10;
- CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 2) << 11;
- CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 12;
- bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
- if (code)
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template1 unoptimized");
- jbig2_image_set_pixel(image, x, y, bit);
}
+ if (out_bits_to_go_in_byte != 8)
+ *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
}
return 0;
}
@@ -647,30 +657,53 @@ jbig2_decode_generic_template2_unopt(Jbig2Ctx *ctx,
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"adaptive template pixel is out of field");
- /* this version is generic and easy to understand, but very slow */
-
for (y = 0; y < GBH; y++) {
+ uint32_t out_byte = 0;
+ int out_bits_to_go_in_byte = 8;
+ uint8_t *d = &image->data[image->stride * y];
+ uint8_t *pline = &image->data[image->stride * (y-1)];
+ uint8_t *ppline = &image->data[image->stride * (y-2)];
+ uint32_t pd = 0;
+ uint32_t ppd = 0;
+ if (y > 0) {
+ pd = (*pline++ << 8);
+ if (GBW > 8)
+ pd |= *pline++;
+ if (y > 1) {
+ ppd = (*ppline++ << 8);
+ if (GBW > 8)
+ ppd |= *ppline++;
+ }
+ }
for (x = 0; x < GBW; x++) {
if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
- jbig2_image_set_pixel(image, x, y, 0);
- continue;
+ bit = 0;
+ } else {
+ CONTEXT = out_byte & 0x003; /* First 2 pixels */
+ CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 2;
+ CONTEXT |= (pd>>11) & 0x078; /* Next 4 pixels */
+ CONTEXT |= (ppd>>7) & 0x380; /* Next 3 pixels */
+ bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template2 unoptimized");
+ }
+ pd = pd<<1;
+ ppd = ppd<<1;
+ out_byte = (out_byte<<1) | bit;
+ out_bits_to_go_in_byte--;
+ *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
+ if (out_bits_to_go_in_byte == 0) {
+ out_bits_to_go_in_byte = 8;
+ d++;
+ if (x+9 < GBW && y > 0) {
+ pd |= *pline++;
+ if (y > 1)
+ ppd |= *ppline++;
+ }
}
- CONTEXT = 0;
- CONTEXT |= jbig2_image_get_pixel(image, x - 1, y) << 0;
- CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
- CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 2;
- CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 3;
- CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 4;
- CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 5;
- CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 6;
- CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 7;
- CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 2) << 8;
- CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 9;
- bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
- if (code)
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template2 unoptimized");
- jbig2_image_set_pixel(image, x, y, bit);
}
+ if (out_bits_to_go_in_byte != 8)
+ *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
}
return 0;
@@ -817,30 +850,41 @@ jbig2_decode_generic_template3_unopt(Jbig2Ctx *ctx,
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"adaptive template pixel is out of field");
- /* this version is generic and easy to understand, but very slow */
-
for (y = 0; y < GBH; y++) {
+ uint32_t out_byte = 0;
+ int out_bits_to_go_in_byte = 8;
+ uint8_t *d = &image->data[image->stride * y];
+ uint8_t *pline = &image->data[image->stride * (y-1)];
+ uint32_t pd = 0;
+ if (y > 0) {
+ pd = (*pline++ << 8);
+ if (GBW > 8)
+ pd |= *pline++;
+ }
for (x = 0; x < GBW; x++) {
if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
- jbig2_image_set_pixel(image, x, y, 0);
- continue;
+ bit = 0;
+ } else {
+ CONTEXT = out_byte & 0x00F; /* First 4 pixels */
+ CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 4;
+ CONTEXT |= (pd>>9) & 0x3E0; /* Next 5 pixels */
+ bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template3 unoptimized");
+ }
+ pd = pd<<1;
+ out_byte = (out_byte<<1) | bit;
+ out_bits_to_go_in_byte--;
+ *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
+ if (out_bits_to_go_in_byte == 0) {
+ out_bits_to_go_in_byte = 8;
+ d++;
+ if (x+9 < GBW && y > 0)
+ pd |= *pline++;
}
- CONTEXT = 0;
- CONTEXT |= jbig2_image_get_pixel(image, x - 1, y) << 0;
- CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
- CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
- CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3;
- CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 4;
- CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 5;
- CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 6;
- CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7;
- CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8;
- CONTEXT |= jbig2_image_get_pixel(image, x - 3, y - 1) << 9;
- bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
- if (code)
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template3 unoptimized");
- jbig2_image_set_pixel(image, x, y, bit);
}
+ if (out_bits_to_go_in_byte != 8)
+ *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
}
return 0;
}
@@ -890,53 +934,55 @@ jbig2_decode_generic_template0_TPGDON(Jbig2Ctx *ctx,
params->gbat[4] == 2 && params->gbat[5] == -2 &&
params->gbat[6] == -2 && params->gbat[7] == -2)
{
- right = GBW-9; /* To allow us to use get_pixels */
for (y = 0; y < GBH; y++) {
LTP ^= jbig2_arith_decode(as, &GB_stats[0x9B25], &code);
if (code)
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template0 TPGDON1");
if (!LTP) {
+ uint32_t out_byte = 0;
+ int out_bits_to_go_in_byte = 8;
+ uint8_t *d = &image->data[image->stride * y];
+ uint8_t *pline = &image->data[image->stride * (y-1)];
+ uint8_t *ppline = &image->data[image->stride * (y-2)];
+ uint32_t pd = 0;
+ uint32_t ppd = 0;
+ if (y > 0) {
+ pd = (*pline++ << 8);
+ if (GBW > 8)
+ pd |= *pline++;
+ if (y > 1) {
+ ppd = (*ppline++ << 8);
+ if (GBW > 8)
+ ppd |= *ppline++;
+ }
+ }
for (x = 0; x < GBW; x++) {
if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
- jbig2_image_set_pixel_fast(image, x, y, 0);
- continue;
+ bit = 0;
+ } else {
+ CONTEXT = out_byte & 0x00F; /* First 4 pixels */
+ CONTEXT |= (pd>>8) & 0x7F0; /* Next 7 pixels */
+ CONTEXT |= (ppd>>2) & 0xF800; /* Final 5 pixels */
+ bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template0 TPGDON2");
}
- if (y >= 2 && x >= 4 && x < right)
- {
- CONTEXT = jbig2_image_get_pixels_fast(image, x - 4, y, 4);
- CONTEXT |= jbig2_image_get_pixels_fast(image, x - 3, y - 1, 7) << 4;
- CONTEXT |= jbig2_image_get_pixels_fast(image, x - 2, y - 2, 5) << 11;
- }
- else
- {
- CONTEXT = jbig2_image_get_pixel(image, x - 1, y);
- CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
- CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
- CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3;
- if (y >= 1)
- {
- CONTEXT |= jbig2_image_get_pixel(image, x + 3, y - 1) << 4;
- CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 1) << 5;
- CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 6;
- CONTEXT |= jbig2_image_get_pixel(image, x, y - 1) << 7;
- CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 8;
- CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 9;
- CONTEXT |= jbig2_image_get_pixel(image, x - 3, y - 1) << 10;
- }
- if (y >= 2)
- {
- CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 2) << 11;
- CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 12;
- CONTEXT |= jbig2_image_get_pixel(image, x, y - 2) << 13;
- CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 14;
- CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 2) << 15;
+ pd = pd<<1;
+ ppd = ppd<<1;
+ out_byte = (out_byte<<1) | bit;
+ out_bits_to_go_in_byte--;
+ if (out_bits_to_go_in_byte == 0) {
+ out_bits_to_go_in_byte = 8;
+ *d++ = (uint8_t)out_byte;
+ if (x+9 < GBW && y > 0) {
+ pd |= *pline++;
+ if (y > 1)
+ ppd |= *ppline++;
}
}
- bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
- if (code)
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template0 TPGDON2");
- jbig2_image_set_pixel_fast(image, x, y, bit);
}
+ if (out_bits_to_go_in_byte != 8)
+ *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
} else {
copy_prev_row(image, y);
}
@@ -966,10 +1012,6 @@ jbig2_decode_generic_template0_TPGDON(Jbig2Ctx *ctx,
left = -gmin;
if ((int)right < gmax)
right = gmax;
- /* We need to guarantee 9 pixels in the right margin to be able
- * to use jbig2_image_get_pixels_fast. */
- if (right < 9)
- right = 9;
right = GBW - right;
/* So 0 <= x < left or right <= x < GBW needs bounds checking. */
@@ -992,51 +1034,65 @@ jbig2_decode_generic_template0_TPGDON(Jbig2Ctx *ctx,
if (code)
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template0 TPGDON1");
if (!LTP) {
+ uint32_t out_byte = 0;
+ int out_bits_to_go_in_byte = 8;
+ uint8_t *d = &image->data[image->stride * y];
+ uint8_t *pline = &image->data[image->stride * (y-1)];
+ uint8_t *ppline = &image->data[image->stride * (y-2)];
+ uint32_t pd = 0;
+ uint32_t ppd = 0;
+ if (y > 0) {
+ pd = (*pline++ << 8);
+ if (GBW > 8)
+ pd |= *pline++;
+ if (y > 1) {
+ ppd = (*ppline++ << 8);
+ if (GBW > 8)
+ ppd |= *ppline++;
+ }
+ }
for (x = 0; x < GBW; x++) {
if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
- jbig2_image_set_pixel_fast(image, x, y, 0);
- continue;
- }
- if (y >= top && x >= left && x < right)
- {
- CONTEXT = jbig2_image_get_pixels_fast(image, x - 4, y, 4);
- CONTEXT |= jbig2_image_get_pixel_fast(image, x + params->gbat[0], y + params->gbat[1]) << 4;
- CONTEXT |= jbig2_image_get_pixels_fast(image, x - 2, y - 1, 5) << 5;
- CONTEXT |= jbig2_image_get_pixel_fast(image, x + params->gbat[2], y + params->gbat[3]) << 10;
- CONTEXT |= jbig2_image_get_pixel_fast(image, x + params->gbat[4], y + params->gbat[5]) << 11;
- CONTEXT |= jbig2_image_get_pixels_fast(image, x - 1, y - 2, 3) << 12;
- CONTEXT |= jbig2_image_get_pixel_fast(image, x + params->gbat[6], y + params->gbat[7]) << 15;
- }
- else
- {
- CONTEXT = jbig2_image_get_pixel(image, x - 1, y);
- CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
- CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
- CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3;
- CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 4;
- if (y >= 1)
+ bit = 0;
+ } else {
+ CONTEXT = out_byte & 0x000F; /* First 4 pixels */
+ CONTEXT |= (pd>>8) & 0x03E0; /* Skip one, next 5 pixels */
+ CONTEXT |= (ppd>>2) & 0x7000; /* Skip 2, next 3 pixels, skip one */
+ if (y >= top && x >= left && x < right)
{
- CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 1) << 5;
- CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 6;
- CONTEXT |= jbig2_image_get_pixel(image, x, y - 1) << 7;
- CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 8;
- CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 9;
+ CONTEXT |= jbig2_image_get_pixel_fast(image, x + params->gbat[0], y + params->gbat[1]) << 4;
+ CONTEXT |= jbig2_image_get_pixel_fast(image, x + params->gbat[2], y + params->gbat[3]) << 10;
+ CONTEXT |= jbig2_image_get_pixel_fast(image, x + params->gbat[4], y + params->gbat[5]) << 11;
+ CONTEXT |= jbig2_image_get_pixel_fast(image, x + params->gbat[6], y + params->gbat[7]) << 15;
}
- CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[2], y + params->gbat[3]) << 10;
- CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[4], y + params->gbat[5]) << 11;
- if (y >= 2)
+ else
{
- CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 12;
- CONTEXT |= jbig2_image_get_pixel(image, x, y - 2) << 13;
- CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 14;
+ CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 4;
+ CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[2], y + params->gbat[3]) << 10;
+ CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[4], y + params->gbat[5]) << 11;
+ CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[6], y + params->gbat[7]) << 15;
+ }
+ bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template0 TPGDON2");
+ }
+ pd = pd<<1;
+ ppd = ppd<<1;
+ out_byte = (out_byte<<1) | bit;
+ out_bits_to_go_in_byte--;
+ *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
+ if (out_bits_to_go_in_byte == 0) {
+ out_bits_to_go_in_byte = 8;
+ d++;
+ if (x+9 < GBW && y > 0) {
+ pd |= *pline++;
+ if (y > 1)
+ ppd |= *ppline++;
}
- CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[6], y + params->gbat[7]) << 15;
}
- bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
- if (code)
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template0 TPGDON2");
- jbig2_image_set_pixel_fast(image, x, y, bit);
}
+ if (out_bits_to_go_in_byte != 8)
+ *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
} else {
copy_prev_row(image, y);
}
@@ -1067,29 +1123,52 @@ jbig2_decode_generic_template1_TPGDON(Jbig2Ctx *ctx,
if (code)
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template1 TPGDON1");
if (!LTP) {
+ uint32_t out_byte = 0;
+ int out_bits_to_go_in_byte = 8;
+ uint8_t *d = &image->data[image->stride * y];
+ uint8_t *pline = &image->data[image->stride * (y-1)];
+ uint8_t *ppline = &image->data[image->stride * (y-2)];
+ uint32_t pd = 0;
+ uint32_t ppd = 0;
+ if (y > 0) {
+ pd = (*pline++ << 8);
+ if (GBW > 8)
+ pd |= *pline++;
+ if (y > 1) {
+ ppd = (*ppline++ << 8);
+ if (GBW > 8)
+ ppd |= *ppline++;
+ }
+ }
for (x = 0; x < GBW; x++) {
if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
- jbig2_image_set_pixel(image, x, y, 0);
- continue;
+ bit = 0;
+ } else {
+ CONTEXT = out_byte & 0x0007; /* First 3 pixels */
+ CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 3;
+ CONTEXT |= (pd>>9) & 0x01F0; /* next 5 pixels */
+ CONTEXT |= (ppd>>4) & 0x1E00; /* next 4 pixels */
+ bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template1 TPGDON2");
+ }
+ pd = pd<<1;
+ ppd = ppd<<1;
+ out_byte = (out_byte<<1) | bit;
+ out_bits_to_go_in_byte--;
+ *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
+ if (out_bits_to_go_in_byte == 0) {
+ out_bits_to_go_in_byte = 8;
+ d++;
+ if (x+9 < GBW && y > 0) {
+ pd |= *pline++;
+ if (y > 1)
+ ppd |= *ppline++;
+ }
}
- CONTEXT = jbig2_image_get_pixel(image, x - 1, y);
- CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
- CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
- CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 3;
- CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 1) << 4;
- CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 5;
- CONTEXT |= jbig2_image_get_pixel(image, x, y - 1) << 6;
- CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7;
- CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8;
- CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 2) << 9;
- CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 10;
- CONTEXT |= jbig2_image_get_pixel(image, x, y - 2) << 11;
- CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 12;
- bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
- if (code)
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template1 TPGDON2");
- jbig2_image_set_pixel(image, x, y, bit);
}
+ if (out_bits_to_go_in_byte != 8)
+ *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
} else {
copy_prev_row(image, y);
}
@@ -1120,26 +1199,52 @@ jbig2_decode_generic_template2_TPGDON(Jbig2Ctx *ctx,
if (code)
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template2 TPGDON1");
if (!LTP) {
+ uint32_t out_byte = 0;
+ int out_bits_to_go_in_byte = 8;
+ uint8_t *d = &image->data[image->stride * y];
+ uint8_t *pline = &image->data[image->stride * (y-1)];
+ uint8_t *ppline = &image->data[image->stride * (y-2)];
+ uint32_t pd = 0;
+ uint32_t ppd = 0;
+ if (y > 0) {
+ pd = (*pline++ << 8);
+ if (GBW > 8)
+ pd |= *pline++;
+ if (y > 1) {
+ ppd = (*ppline++ << 8);
+ if (GBW > 8)
+ ppd |= *ppline++;
+ }
+ }
for (x = 0; x < GBW; x++) {
if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
- jbig2_image_set_pixel(image, x, y, 0);
- continue;
+ bit = 0;
+ } else {
+ CONTEXT = out_byte & 0x003; /* First 2 pixels */
+ CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 2;
+ CONTEXT |= (pd>>11) & 0x078; /* next 4 pixels */
+ CONTEXT |= (ppd>>7) & 0x380; /* next 3 pixels */
+ bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template2 TPGDON2");
+ }
+ pd = pd<<1;
+ ppd = ppd<<1;
+ out_byte = (out_byte<<1) | bit;
+ out_bits_to_go_in_byte--;
+ *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
+ if (out_bits_to_go_in_byte == 0) {
+ out_bits_to_go_in_byte = 8;
+ d++;
+ if (x+9 < GBW && y > 0) {
+ pd |= *pline++;
+ if (y > 1)
+ ppd |= *ppline++;
+ }
}
- CONTEXT = jbig2_image_get_pixel(image, x - 1, y);
- CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
- CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 2;
- CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 3;
- CONTEXT |= jbig2_image_get_pixel(image, x, y - 1) << 4;
- CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 5;
- CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 6;
- CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 7;
- CONTEXT |= jbig2_image_get_pixel(image, x, y - 2) << 8;
- CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 9;
- bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
- if (code)
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template2 TPGDON2");
- jbig2_image_set_pixel(image, x, y, bit);
}
+ if (out_bits_to_go_in_byte != 8)
+ *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
} else {
copy_prev_row(image, y);
}
@@ -1170,26 +1275,40 @@ jbig2_decode_generic_template3_TPGDON(Jbig2Ctx *ctx,
if (code)
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template3 TPGDON1");
if (!LTP) {
+ uint32_t out_byte = 0;
+ int out_bits_to_go_in_byte = 8;
+ uint8_t *d = &image->data[image->stride * y];
+ uint8_t *pline = &image->data[image->stride * (y-1)];
+ uint32_t pd = 0;
+ if (y > 0) {
+ pd = (*pline++ << 8);
+ if (GBW > 8)
+ pd |= *pline++;
+ }
for (x = 0; x < GBW; x++) {
if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
- jbig2_image_set_pixel(image, x, y, 0);
- continue;
+ bit = 0;
+ } else {
+ CONTEXT = out_byte & 0x0F; /* First 4 pixels */
+ CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 4;
+ CONTEXT |= (pd>>9) & 0x3E0; /* next 5 pixels */
+ bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+ if (code)
+ return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template3 TPGDON2");
+ }
+ pd = pd<<1;
+ out_byte = (out_byte<<1) | bit;
+ out_bits_to_go_in_byte--;
+ *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
+ if (out_bits_to_go_in_byte == 0) {
+ out_bits_to_go_in_byte = 8;
+ d++;
+ if (x+9 < GBW && y > 0)
+ pd |= *pline++;
}
- CONTEXT = jbig2_image_get_pixel(image, x - 1, y);
- CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
- CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
- CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3;
- CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 4;
- CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 5;
- CONTEXT |= jbig2_image_get_pixel(image, x, y - 1) << 6;
- CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7;
- CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8;
- CONTEXT |= jbig2_image_get_pixel(image, x - 3, y - 1) << 9;
- bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
- if (code)
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template3 TPGDON2");
- jbig2_image_set_pixel(image, x, y, bit);
}
+ if (out_bits_to_go_in_byte != 8)
+ *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
} else {
copy_prev_row(image, y);
}