shithub: jbig2

Download patch

ref: 4b88931b21f0795eb90f18a79284332c2b92e583
parent: 8a5ad7cc54f23fb99e231be3a123d6488829dc9e
author: Robin Watts <Robin.Watts@artifex.com>
date: Thu Jan 23 07:55:27 EST 2020

Further optimisations to jbig2_decode_generic_template0_TPGDON.

Add a function to get a 'run' of pixels, and call that.

This takes the time spent in this function from 29% to 22% for
Jbig2_042_08.pdf.

--- a/jbig2_generic.c
+++ b/jbig2_generic.c
@@ -863,6 +863,10 @@
         left = -gmin;
     if (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. */
 
@@ -892,21 +896,12 @@
                 }
                 if (y >= top && x >= left && x < right)
                 {
-                    CONTEXT = jbig2_image_get_pixel_fast(image, x - 1, y);
-                    CONTEXT |= jbig2_image_get_pixel_fast(image, x - 2, y) << 1;
-                    CONTEXT |= jbig2_image_get_pixel_fast(image, x - 3, y) << 2;
-                    CONTEXT |= jbig2_image_get_pixel_fast(image, x - 4, y) << 3;
+                    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_pixel_fast(image, x + 2, y - 1) << 5;
-                    CONTEXT |= jbig2_image_get_pixel_fast(image, x + 1, y - 1) << 6;
-                    CONTEXT |= jbig2_image_get_pixel_fast(image, x, y - 1) << 7;
-                    CONTEXT |= jbig2_image_get_pixel_fast(image, x - 1, y - 1) << 8;
-                    CONTEXT |= jbig2_image_get_pixel_fast(image, x - 2, y - 1) << 9;
+                    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_pixel_fast(image, x + 1, y - 2) << 12;
-                    CONTEXT |= jbig2_image_get_pixel_fast(image, x, y - 2) << 13;
-                    CONTEXT |= jbig2_image_get_pixel_fast(image, x - 1, y - 2) << 14;
+                    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
--- a/jbig2_image.h
+++ b/jbig2_image.h
@@ -39,6 +39,7 @@
 int jbig2_image_get_pixel(Jbig2Image *image, int x, int y);
 void jbig2_image_set_pixel(Jbig2Image *image, int x, int y, bool value);
 
+/* Get a bit. No bounds checking. */
 static inline int
 jbig2_image_get_pixel_fast(Jbig2Image *image, int x, int y)
 {
@@ -48,7 +49,20 @@
     return ((image->data[byte] >> bit) & 1);
 }
 
-/* set an individual pixel value in an image */
+/* 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)
 {