diff options
author | Robin Watts <robin.watts@artifex.com> | 2012-11-19 16:40:51 +0000 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2012-11-19 16:49:29 +0000 |
commit | b1e3f310637a22c6b4c5e142e3582f90ff467ddf (patch) | |
tree | 09fa46ac420806bb23d0c7d247d03f956a97e27d /fitz/res_pixmap.c | |
parent | a8560c74b6b655386c4530383eebda4e7cc239c2 (diff) | |
download | mupdf-b1e3f310637a22c6b4c5e142e3582f90ff467ddf.tar.xz |
Add image subsampling function.
When drawing images, if they are much bigger than we need, quickly
subsample them. Makes images much more cachable, reduces time spent
in expensive smooth scaler.
Diffstat (limited to 'fitz/res_pixmap.c')
-rw-r--r-- | fitz/res_pixmap.c | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/fitz/res_pixmap.c b/fitz/res_pixmap.c index f7fbf239..a3ae7562 100644 --- a/fitz/res_pixmap.c +++ b/fitz/res_pixmap.c @@ -687,3 +687,123 @@ fz_drop_image(fz_context *ctx, fz_image *image) { fz_drop_storable(ctx, &image->storable); } + +void +fz_subsample_pixmap(fz_context *ctx, fz_pixmap *tile, int factor) +{ + int dst_w, dst_h, w, h, fwd, fwd2, fwd3, back, back2, x, y, n, xx, yy, nn, f; + unsigned char *s, *d; + + if (!tile) + return; + s = d = tile->samples; + f = 1<<factor; + w = tile->w; + h = tile->h; + n = tile->n; + dst_w = (w + f-1)>>factor; + dst_h = (h + f-1)>>factor; + fwd = w*n; + back = f*fwd-n; + back2 = f*n-1; + fwd2 = (f-1)*n; + fwd3 = (f-1)*fwd; + factor *= 2; + for (y = h - f; y >= 0; y -= f) + { + for (x = w - f; x >= 0; x -= f) + { + for (nn = n; nn > 0; nn--) + { + int v = 0; + for (xx = f; xx > 0; xx--) + { + for (yy = f; yy > 0; yy--) + { + v += *s; + s += fwd; + } + s -= back; + } + *d++ = v >> factor; + s -= back2; + } + s += fwd2; + } + /* Do any strays */ + x += f; + if (x > 0) + { + int div = x * f; + int fwd4 = (x-1) * n; + int back4 = x*n-1; + for (nn = n; nn > 0; nn--) + { + int v = 0; + for (;x > 0; x--) + { + for (yy = f; yy > 0; yy--) + { + v += *s; + s += fwd; + } + s -= back; + } + *d++ = v / div; + s -= back4; + } + s += fwd4; + } + s += fwd3; + } + /* Do any stray line */ + y += f; + if (y > 0) + { + int div = y * f; + back = fwd * y - 1; + for (x = w - f; x >= 0; x -= f) + { + for (nn = n; nn > 0; nn--) + { + int v = 0; + for (xx = f; xx > 0; xx--) + { + for (yy = y; yy > 0; yy--) + { + v += *s; + s += fwd; + } + s -= back; + } + *d++ = v / div; + s -= back2; + } + s += fwd2; + } + /* Do any stray at the end of the stray line */ + x += f; + if (x > 0) + { + int div = x * y; + for (nn = n; nn > 0; nn--) + { + int v = 0; + for (;x > 0; x--) + { + for (; y > 0; y--) + { + v += *s; + s += fwd; + } + s -= back; + } + *d++ = v / div; + s -= back2; + } + } + } + tile->w = dst_w; + tile->h = dst_h; + tile->samples = fz_resize_array(ctx, tile->samples, dst_w * n, dst_h); +} |