summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/fitz/base_pixmap.h4
-rw-r--r--mupdf/pdf_image.c10
-rw-r--r--raster/imagescale.c92
-rw-r--r--raster/imageunpack.c27
-rw-r--r--raster/render.c41
5 files changed, 159 insertions, 15 deletions
diff --git a/include/fitz/base_pixmap.h b/include/fitz/base_pixmap.h
index 9a0f2b43..ca8fa883 100644
--- a/include/fitz/base_pixmap.h
+++ b/include/fitz/base_pixmap.h
@@ -24,3 +24,7 @@ void fz_droppixmap(fz_pixmap *map);
fz_error *fz_scalepixmap(fz_pixmap **dstp, fz_pixmap *src, int xdenom, int ydenom);
+/* needed for tiled rendering */
+fz_error *fz_newscaledpixmap(fz_pixmap **dstp, int w, int h, int n, int xdenom, int ydenom);
+fz_error *fz_scalepixmaptile(fz_pixmap *dstp, int xoffs, int yoffs,
+ fz_pixmap *tile, int xdenom, int ydenom);
diff --git a/mupdf/pdf_image.c b/mupdf/pdf_image.c
index 1d510ab9..5fd5f406 100644
--- a/mupdf/pdf_image.c
+++ b/mupdf/pdf_image.c
@@ -464,6 +464,8 @@ pdf_loadtile(fz_image *img, fz_pixmap *tile)
void (*tilefunc)(unsigned char*,int,unsigned char*, int, int, int, int);
fz_error *error;
+ assert(tile->x == 0); // can't handle general tile yet, only y-banding
+
assert(tile->n == img->n + 1);
assert(tile->x >= 0);
assert(tile->y >= 0);
@@ -498,7 +500,7 @@ pdf_loadtile(fz_image *img, fz_pixmap *tile)
case 8: bpcfact = 1; break;
}
- tilefunc(src->samples->rp, src->stride,
+ tilefunc(src->samples->rp + (tile->y * src->stride), src->stride,
tmp->samples, tmp->w,
tmp->w, tmp->h, 0);
@@ -507,7 +509,7 @@ pdf_loadtile(fz_image *img, fz_pixmap *tile)
for (x = 0; x < tile->w; x++)
{
tile->samples[(y * tile->w + x) * tile->n] = 255;
- i = tmp->samples[y * tile->w + x] / bpcfact;
+ i = tmp->samples[y * tmp->w + x] / bpcfact;
i = CLAMP(i, 0, src->indexed->high);
for (k = 0; k < src->indexed->base->n; k++)
{
@@ -525,9 +527,9 @@ pdf_loadtile(fz_image *img, fz_pixmap *tile)
else
{
- tilefunc(src->samples->rp, src->stride,
+ tilefunc(src->samples->rp + (tile->y * src->stride), src->stride,
tile->samples, tile->w * tile->n,
- img->w * (img->n + img->a), img->h, img->a ? 0 : img->n);
+ tile->w * (img->n + img->a), tile->h, img->a ? 0 : img->n);
if (src->usecolorkey)
maskcolorkey(tile, src->colorkey);
fz_decodetile(tile, !img->a, src->decode);
diff --git a/raster/imagescale.c b/raster/imagescale.c
index 9ff58d24..a728a998 100644
--- a/raster/imagescale.c
+++ b/raster/imagescale.c
@@ -180,6 +180,98 @@ void (*fz_scol4)(byte *src, byte *dst, int w, int denom) = scol4;
void (*fz_scol5)(byte *src, byte *dst, int w, int denom) = scol5;
fz_error *
+fz_newscaledpixmap(fz_pixmap **dstp, int w, int h, int n, int xdenom, int ydenom)
+{
+ int ow = (w + xdenom - 1) / xdenom;
+ int oh = (h + ydenom - 1) / ydenom;
+ return fz_newpixmap(dstp, 0, 0, ow, oh, n);
+}
+
+// TODO: refactor
+fz_error *
+fz_scalepixmaptile(fz_pixmap *dst, int xoffs, int yoffs, fz_pixmap *src, int xdenom, int ydenom)
+{
+ unsigned char *buf;
+ unsigned char *dstsamples;
+ int y, iy, oy;
+ int ow, oh, n;
+ int ydenom2 = ydenom;
+
+ void (*srowx)(byte *src, byte *dst, int w, int denom) = nil;
+ void (*scolx)(byte *src, byte *dst, int w, int denom) = nil;
+
+ ow = (src->w + xdenom - 1) / xdenom;
+ oh = (src->h + ydenom - 1) / ydenom;
+ xoffs /= xdenom;
+ yoffs /= ydenom;
+ n = src->n;
+
+ assert(xoffs == 0); // don't handle stride properly yet
+ assert(dst->n == n);
+ assert(dst->w >= xoffs + ow && dst->h >= yoffs + oh);
+
+ buf = fz_malloc(ow * n * ydenom);
+ if (!buf)
+ return fz_outofmem;
+
+ switch (n)
+ {
+ case 1: srowx = fz_srow1; scolx = fz_scol1; break;
+ case 2: srowx = fz_srow2; scolx = fz_scol2; break;
+ case 4: srowx = fz_srow4; scolx = fz_scol4; break;
+ case 5: srowx = fz_srow5; scolx = fz_scol5; break;
+ }
+
+ dstsamples = dst->samples + (yoffs * dst->w + xoffs)*dst->n;
+ if (srowx && scolx)
+ {
+ for (y = 0, oy = 0; y < (src->h / ydenom) * ydenom; y += ydenom, oy++)
+ {
+ for (iy = 0; iy < ydenom; iy++)
+ srowx(src->samples + (y + iy) * src->w * n,
+ buf + iy * ow * n,
+ src->w, xdenom);
+ scolx(buf, dstsamples + oy * dst->w * n, ow, ydenom2);
+ }
+
+ ydenom = src->h - y;
+ if (ydenom)
+ {
+ for (iy = 0; iy < ydenom; iy++)
+ srowx(src->samples + (y + iy) * src->w * n,
+ buf + iy * ow * n,
+ src->w, xdenom);
+ scolx(buf, dstsamples + oy * dst->w * n, ow, ydenom2);
+ }
+ }
+
+ else
+ {
+ for (y = 0, oy = 0; y < (src->h / ydenom) * ydenom; y += ydenom, oy++)
+ {
+ for (iy = 0; iy < ydenom; iy++)
+ fz_srown(src->samples + (y + iy) * src->w * n,
+ buf + iy * ow * n,
+ src->w, xdenom, n);
+ fz_scoln(buf, dstsamples + oy * dst->w * n, ow, ydenom2, n);
+ }
+
+ ydenom = src->h - y;
+ if (ydenom)
+ {
+ for (iy = 0; iy < ydenom; iy++)
+ fz_srown(src->samples + (y + iy) * src->w * n,
+ buf + iy * ow * n,
+ src->w, xdenom, n);
+ fz_scoln(buf, dstsamples + oy * dst->w * n, ow, ydenom2, n);
+ }
+ }
+
+ fz_free(buf);
+ return nil;
+}
+
+fz_error *
fz_scalepixmap(fz_pixmap **dstp, fz_pixmap *src, int xdenom, int ydenom)
{
fz_error *error;
diff --git a/raster/imageunpack.c b/raster/imageunpack.c
index 9a6fe1b1..93f5cf39 100644
--- a/raster/imageunpack.c
+++ b/raster/imageunpack.c
@@ -14,8 +14,8 @@ static void decodetile(fz_pixmap *pix, int skip, float *decode)
int max[FZ_MAXCOLORS];
int sub[FZ_MAXCOLORS];
int needed = 0;
- byte *p = pix->samples;
int n = pix->n;
+ byte *p = pix->samples;
int wh = pix->w * pix->h;
int i;
int justinvert = 1;
@@ -35,6 +35,7 @@ static void decodetile(fz_pixmap *pix, int skip, float *decode)
if (!needed)
return;
+
switch (n) {
case 1:
while (wh--)
@@ -45,18 +46,22 @@ static void decodetile(fz_pixmap *pix, int skip, float *decode)
break;
case 2:
if (justinvert) {
- int hwh = wh / 2;
unsigned *wp = (unsigned *)p;
- assert((((unsigned)wp) & 3) == 0);
-
- wh = hwh * 2 - wh;
- while(hwh--) {
- unsigned in = *wp;
- unsigned out = in ^ 0xff00ff00;
- *wp++ = out;
+ if ((((unsigned)wp) & 3) == 0) {
+ int hwh = wh / 2;
+ wh = hwh * 2 - wh;
+ while(hwh--) {
+ unsigned in = *wp;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ unsigned out = in ^ 0xff00ff00;
+#else
+ unsigned out = in ^ 0x00ff00ff;
+#endif
+ *wp++ = out;
+ }
+ p = (byte *)wp;
}
- p = (byte *)wp;
while(wh--) {
p[0] = p[0];
p[1] = 255 - p[1];
@@ -117,7 +122,7 @@ static void init1()
inited = 1;
}
-static void loadtile1(byte *src, int sw, byte *dst, int dw, int w, int h, int pad)
+static void loadtile1(byte * restrict src, int sw, byte * restrict dst, int dw, int w, int h, int pad)
{
byte *sp;
byte *dp;
diff --git a/raster/render.c b/raster/render.c
index 50e16d8a..e750642f 100644
--- a/raster/render.c
+++ b/raster/render.c
@@ -373,6 +373,46 @@ DEBUG("image %dx%d %d+%d %s\n{\n", image->w, image->h, image->n, image->a, image
calcimagescale(ctm, image->w, image->h, &dx, &dy);
+ // y-banded loading/scaling of image, more cache-friendly
+ int tileheight = MAX(512*1024/(image->w * image->n), dy);
+ if ((dx != 1 || dy != 1) && image->h > tileheight) {
+ int y = 0;
+
+ DEBUG(" load image tile size = %dx%d\n", image->w, tileheight);
+ error = fz_newpixmap(&tile, 0, 0, image->w,
+ tileheight, image->n + 1);
+ if (error)
+ return error;
+
+ error = fz_newscaledpixmap(&temp, image->w, image->h, image->n + 1, dx, dy);
+
+ do {
+ if (y + tileheight > image->h)
+ tileheight = image->h - y;
+ tile->y = y;
+ tile->h = tileheight;
+ DEBUG(" tile xywh=%d %d %d %d sxsy=1/%d 1/%d\n",
+ 0, y, image->w, tileheight, dx, dy);
+ error = image->loadtile(image, tile);
+ if (error)
+ goto cleanup;
+
+ error = fz_scalepixmaptile(temp, 0, y, tile, dx, dy);
+ if (error) {
+ if (temp)
+ fz_droppixmap(temp);
+ goto cleanup;
+ }
+
+ y += tileheight;
+ } while (y < image->h);
+
+ fz_droppixmap(tile);
+ tile = temp;
+ }
+ else {
+
+
DEBUG(" load image\n");
error = fz_newpixmap(&tile, 0, 0, image->w, image->h, image->n + 1);
if (error)
@@ -391,6 +431,7 @@ DEBUG(" scale image 1/%d 1/%d\n", dx, dy);
fz_droppixmap(tile);
tile = temp;
}
+ }
if (image->cs && image->cs != gc->model)
{