summaryrefslogtreecommitdiff
path: root/draw
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2010-06-18 14:55:15 +0200
committerRobin Watts <robin.watts@artifex.com>2010-06-18 14:55:15 +0200
commitbbfa56340be7f5315159b41f521a2188681ca671 (patch)
tree7626ec1228204a5892c88d7b793fea317798738c /draw
parent77b29ff82106c89bf3a410bd4bf1901b891ffc91 (diff)
downloadmupdf-bbfa56340be7f5315159b41f521a2188681ca671.tar.xz
Optimise image scaling.
Tweak C to use pointer arithmetic rather than array indexing. Decrement vars rather than increment which gets us free/cheap tests against 0 on some architectures. Add new scolc and srowc implementations for common cases.
Diffstat (limited to 'draw')
-rw-r--r--draw/imagescale.c105
1 files changed, 75 insertions, 30 deletions
diff --git a/draw/imagescale.c b/draw/imagescale.c
index b2a499b0..687b53b5 100644
--- a/draw/imagescale.c
+++ b/draw/imagescale.c
@@ -47,60 +47,58 @@ static inline void srowc(byte * restrict src, byte * restrict dst, int w, int de
assert(n <= 5);
- left = 0;
+ left = denom;
- for (x = 0; x < w; x++)
+ for (x = w; x > 0; x--)
{
- sum1 += src[x * n + 0];
+ sum1 += *src++;
/* the compiler eliminates these if-tests */
if (n >= 2)
- sum2 += src[x * n + 1];
+ sum2 += *src++;
if (n >= 3)
- sum3 += src[x * n + 2];
+ sum3 += *src++;
if (n >= 4)
- sum4 += src[x * n + 3];
+ sum4 += *src++;
if (n >= 5)
- sum5 += src[x * n + 4];
+ sum5 += *src++;
- if (++left == denom)
+ if (--left == 0)
{
- left = 0;
+ left = denom;
- dst[0] = (sum1 * invdenom + (1<<15)) >> 16;
+ *dst++ = (sum1 * invdenom + (1<<15)) >> 16;
sum1 = 0;
if (n >= 2) {
- dst[1] = (sum2 * invdenom + (1<<15)) >> 16;
+ *dst++ = (sum2 * invdenom + (1<<15)) >> 16;
sum2 = 0;
}
if (n >= 3) {
- dst[2] = (sum3 * invdenom + (1<<15)) >> 16;
+ *dst++ = (sum3 * invdenom + (1<<15)) >> 16;
sum3 = 0;
}
if (n >= 4) {
- dst[3] = (sum4 * invdenom + (1<<15)) >> 16;
+ *dst++ = (sum4 * invdenom + (1<<15)) >> 16;
sum4 = 0;
}
if (n >= 5) {
- dst[4] = (sum5 * invdenom + (1<<15)) >> 16;
+ *dst++ = (sum5 * invdenom + (1<<15)) >> 16;
sum5 = 0;
}
-
-
- dst += n;
}
}
/* left overs */
+ left = denom - left;
if (left) {
- dst[0] = sum1 / left;
- if (n >=2)
- dst[1] = sum2 / left;
- if (n >=3)
- dst[2] = sum3 / left;
- if (n >=4)
- dst[3] = sum4 / left;
- if (n >=5)
- dst[4] = sum5 / left;
+ *dst++ = sum1 / left;
+ if (n >= 2)
+ *dst++ = sum2 / left;
+ if (n >= 3)
+ *dst++ = sum3 / left;
+ if (n >= 4)
+ *dst++ = sum4 / left;
+ if (n >= 5)
+ *dst++ = sum5 / left;
}
}
@@ -145,24 +143,71 @@ static inline void scoln(byte * restrict src, byte * restrict dst, int w, int de
}
}
+static inline void scolc(byte * restrict src, byte * restrict dst, int w, int denom, int n)
+{
+ int invdenom = (1<<16) / denom;
+ int x, y;
+ int sum0;
+ int sum1;
+ int sum2;
+ int sum3;
+ int sum4;
+
+ assert(n <= 5);
+
+ x = w;
+ w *= n;
+ for (; x > 0; x--)
+ {
+ sum0 = 0;
+ sum1 = 0;
+ sum2 = 0;
+ sum3 = 0;
+ sum4 = 0;
+ for (y = denom; y > 0; y--)
+ {
+ sum0 += src[0];
+ if (n >= 2)
+ sum1 += src[1];
+ if (n >= 3)
+ sum2 += src[2];
+ if (n >= 4)
+ sum3 += src[3];
+ if (n >= 5)
+ sum4 += src[4];
+ src += w;
+ }
+ src += n - denom * w;
+ *dst++ = (sum0 * invdenom + (1<<15)) >> 16;
+ if (n >= 2)
+ *dst++ = (sum1 * invdenom + (1<<15)) >> 16;
+ if (n >= 3)
+ *dst++ = (sum2 * invdenom + (1<<15)) >> 16;
+ if (n >= 4)
+ *dst++ = (sum3 * invdenom + (1<<15)) >> 16;
+ if (n >= 5)
+ *dst++ = (sum4 * invdenom + (1<<15)) >> 16;
+ }
+}
+
static void scol1(byte *src, byte *dst, int w, int denom)
{
- scoln(src, dst, w, denom, 1);
+ scolc(src, dst, w, denom, 1);
}
static void scol2(byte *src, byte *dst, int w, int denom)
{
- scoln(src, dst, w, denom, 2);
+ scolc(src, dst, w, denom, 2);
}
static void scol4(byte *src, byte *dst, int w, int denom)
{
- scoln(src, dst, w, denom, 4);
+ scolc(src, dst, w, denom, 4);
}
static void scol5(byte *src, byte *dst, int w, int denom)
{
- scoln(src, dst, w, denom, 5);
+ scolc(src, dst, w, denom, 5);
}
void (*fz_srown)(byte *src, byte *dst, int w, int denom, int n) = srown;