diff options
-rw-r--r-- | include/fitz/base_pixmap.h | 4 | ||||
-rw-r--r-- | mupdf/pdf_image.c | 10 | ||||
-rw-r--r-- | raster/imagescale.c | 92 | ||||
-rw-r--r-- | raster/imageunpack.c | 27 | ||||
-rw-r--r-- | raster/render.c | 41 |
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) { |