summaryrefslogtreecommitdiff
path: root/fitz/filt_faxd.c
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2012-11-16 13:48:04 +0000
committerRobin Watts <robin.watts@artifex.com>2012-11-19 16:49:26 +0000
commitbc3ce65fce7b41270933395f1c7d2aa935b2cc11 (patch)
tree49256637b1953b0b8dca72ed5830a295876ef8cf /fitz/filt_faxd.c
parent88e4317b964d09b6581818a6f18fc64817559ec3 (diff)
downloadmupdf-bc3ce65fce7b41270933395f1c7d2aa935b2cc11.tar.xz
Attempt to speed up fax decompression.
A huge number of calls are made to getbit from find_changing in fax decompression. On Android profiling shows that this accounts for 25% of time in handling page 2 of IA3Z0845.pdf. Rewrite code to deal with bytes at a time for speed. Profiling now shows 5% in this function.
Diffstat (limited to 'fitz/filt_faxd.c')
-rw-r--r--fitz/filt_faxd.c66
1 files changed, 53 insertions, 13 deletions
diff --git a/fitz/filt_faxd.c b/fitz/filt_faxd.c
index febc6a65..8c6ee5a5 100644
--- a/fitz/filt_faxd.c
+++ b/fitz/filt_faxd.c
@@ -175,33 +175,73 @@ static inline int getbit(const unsigned char *buf, int x)
return ( buf[x >> 3] >> ( 7 - (x & 7) ) ) & 1;
}
-static int
+static const unsigned char mask[8] = {
+ 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0
+};
+
+static const unsigned char clz[256] = {
+ 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static inline int
find_changing(const unsigned char *line, int x, int w)
{
- int a, b;
+ int a, b, m, W;
if (!line)
return w;
- if (x == -1)
+ /* We assume w > 0, -1 <= x < w */
+ if (x < 0)
{
- a = 0;
x = 0;
+ m = 0xFF;
}
else
{
- a = getbit(line, x);
- x++;
+ /* Mask out the bits we've already used (including the one
+ * we started from) */
+ m = mask[x & 7];
}
-
- while (x < w)
+ W = w>>3;
+ x >>= 3;
+ a = line[x];
+ b = a ^ (a>>1);
+ b &= m;
+ while (b == 0)
{
- b = getbit(line, x);
- if (a != b)
- break;
- x++;
+ if (++x >= W)
+ goto nearend;
+ b = a & 1;
+ a = line[x];
+ b = (b<<7) ^ a ^ (a>>1);
}
-
+ return (x<<3) + clz[b];
+nearend:
+ /* We have less than a byte to go. If no stray bits, exit now. */
+ if ((x<<3) == w)
+ return w;
+ b = a&1;
+ b = line[x];
+ b = (b<<7) ^ a ^ (a>>1);
+ x = (x<<3) + clz[b];
+ if (x > w)
+ x = w;
return x;
}