summaryrefslogtreecommitdiff
path: root/fitz/res_pixmap.c
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2012-11-19 16:40:51 +0000
committerRobin Watts <robin.watts@artifex.com>2012-11-19 16:49:29 +0000
commitb1e3f310637a22c6b4c5e142e3582f90ff467ddf (patch)
tree09fa46ac420806bb23d0c7d247d03f956a97e27d /fitz/res_pixmap.c
parenta8560c74b6b655386c4530383eebda4e7cc239c2 (diff)
downloadmupdf-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.c120
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);
+}