summaryrefslogtreecommitdiff
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
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.
-rw-r--r--fitz/fitz-internal.h1
-rw-r--r--fitz/res_colorspace.c25
-rw-r--r--fitz/res_pixmap.c120
-rw-r--r--pdf/pdf_image.c24
4 files changed, 163 insertions, 7 deletions
diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h
index 528fb50a..2f1d137e 100644
--- a/fitz/fitz-internal.h
+++ b/fitz/fitz-internal.h
@@ -836,6 +836,7 @@ fz_pixmap *fz_alpha_from_gray(fz_context *ctx, fz_pixmap *gray, int luminosity);
unsigned int fz_pixmap_size(fz_context *ctx, fz_pixmap *pix);
fz_pixmap *fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h, fz_bbox *clip);
+void fz_subsample_pixmap(fz_context *ctx, fz_pixmap *tile, int factor);
fz_bbox fz_pixmap_bbox_no_ctx(fz_pixmap *src);
diff --git a/fitz/res_colorspace.c b/fitz/res_colorspace.c
index 7b36ac1e..edda776d 100644
--- a/fitz/res_colorspace.c
+++ b/fitz/res_colorspace.c
@@ -316,6 +316,31 @@ static void fast_cmyk_to_gray(fz_pixmap *dst, fz_pixmap *src)
}
}
+#if 0
+static void
+fast_cmyk_to_rgb_ARM(unsigned char *dst, unsigned char *src, int n)
+{
+ asm volatile(
+ ENTER_ARM
+ "stmfd r13!,{r4-r12,r14} \n"
+ "@ r0 = dst \n"
+ "@ r1 = src \n"
+ "@ r2 = weights \n"
+ "mov r4, #0 @ r4 = CMYK = 0 \n"
+ "mvn r5, #0xFF000000 @ r5 = RGB = FFFFFF \n"
+ "1: \n"
+ "ldr r3, [r1], #4 @ r3 = cmyk \n"
+ "cmp r3, r4 @ if (cmyk == CMYK) \n"
+ "beq match @ goto match \n"
+ "cmp r3, #0 @ if (cmyk = 0000) \n"
+ "beq black @
+
+ "ldmfd r13!,{r4-r7,r9,PC} @ pop, return to thumb \n"
+ ENTER_THUMB
+ );
+}
+#endif
+
static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
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);
+}
diff --git a/pdf/pdf_image.c b/pdf/pdf_image.c
index 27a13100..ead7db49 100644
--- a/pdf/pdf_image.c
+++ b/pdf/pdf_image.c
@@ -99,15 +99,15 @@ static fz_store_type pdf_image_store_type =
};
static fz_pixmap *
-decomp_image_from_stream(fz_context *ctx, fz_stream *stm, pdf_image *image, int in_line, int indexed, int l2factor, int cache)
+decomp_image_from_stream(fz_context *ctx, fz_stream *stm, pdf_image *image, int in_line, int indexed, int l2factor, int native_l2factor, int cache)
{
fz_pixmap *tile = NULL;
fz_pixmap *existing_tile;
int stride, len, i;
unsigned char *samples = NULL;
- int f = 1<<l2factor;
- int w = (image->base.w + f-1) >> l2factor;
- int h = (image->base.h + f-1) >> l2factor;
+ int f = 1<<native_l2factor;
+ int w = (image->base.w + f-1) >> native_l2factor;
+ int h = (image->base.h + f-1) >> native_l2factor;
pdf_image_key *key;
fz_var(tile);
@@ -195,6 +195,14 @@ decomp_image_from_stream(fz_context *ctx, fz_stream *stm, pdf_image *image, int
fz_rethrow(ctx);
}
+ /* Now apply any extra subsampling required */
+ if (l2factor - native_l2factor > 0)
+ {
+ if (l2factor - native_l2factor > 8)
+ l2factor = native_l2factor + 8;
+ fz_subsample_pixmap(ctx, tile, l2factor - native_l2factor);
+ }
+
if (!cache)
return tile;
@@ -249,6 +257,7 @@ pdf_image_get_pixmap(fz_context *ctx, fz_image *image_, int w, int h)
fz_stream *stm;
int l2factor;
pdf_image_key key;
+ int native_l2factor;
/* Check for 'simple' images which are just pixmaps */
if (image->buffer == NULL)
@@ -285,9 +294,10 @@ pdf_image_get_pixmap(fz_context *ctx, fz_image *image_, int w, int h)
while (key.l2factor >= 0);
/* We need to make a new one. */
- stm = fz_open_image_decomp_stream(ctx, image->buffer, &l2factor);
+ native_l2factor = l2factor;
+ stm = fz_open_image_decomp_stream(ctx, image->buffer, &native_l2factor);
- return decomp_image_from_stream(ctx, stm, image, 0, 0, l2factor, 1);
+ return decomp_image_from_stream(ctx, stm, image, 0, 0, l2factor, native_l2factor, 1);
}
static pdf_image *
@@ -450,7 +460,7 @@ pdf_load_image_imp(pdf_document *xref, pdf_obj *rdb, pdf_obj *dict, fz_stream *c
stm = pdf_open_stream(xref, pdf_to_num(dict), pdf_to_gen(dict));
}
- image->tile = decomp_image_from_stream(ctx, stm, image, cstm != NULL, indexed, 0, 0);
+ image->tile = decomp_image_from_stream(ctx, stm, image, cstm != NULL, indexed, 0, 0, 0);
}
fz_catch(ctx)
{