summaryrefslogtreecommitdiff
path: root/render
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2004-10-25 11:42:34 +0200
committerTor Andersson <tor@ghostscript.com>2004-10-25 11:42:34 +0200
commitd0282c705fcdf9c3f1771103093bec25f5bd3ca1 (patch)
treed77299e716922fbe88ca8ce3c17ee946b0977629 /render
parent3dae7919da3ba4baf4dbe4c59dd9202b912d21e9 (diff)
downloadmupdf-d0282c705fcdf9c3f1771103093bec25f5bd3ca1.tar.xz
resample images
Diffstat (limited to 'render')
-rw-r--r--render/pixmap.c125
-rw-r--r--render/render.c24
-rw-r--r--render/renderimage.c203
-rw-r--r--render/scale.c93
4 files changed, 356 insertions, 89 deletions
diff --git a/render/pixmap.c b/render/pixmap.c
index 84a542b9..6ef9d75c 100644
--- a/render/pixmap.c
+++ b/render/pixmap.c
@@ -5,7 +5,7 @@ fz_newpixmap(fz_pixmap **pixp, fz_colorspace *cs, int x, int y, int w, int h, in
{
fz_pixmap *pix;
- pix = *pixp = fz_malloc(sizeof (fz_pixmap));
+ pix = *pixp = fz_malloc(sizeof(fz_pixmap));
if (!pix)
return fz_outofmem;
@@ -43,51 +43,32 @@ fz_clearpixmap(fz_pixmap *pix)
}
void
-fz_debugpixmap(fz_pixmap *pix)
+fz_convertpixmap(fz_pixmap *src, fz_pixmap *dst)
{
- int x, y;
-
- FILE *ppm = fopen("out.ppm", "w");
- FILE *pgm = fopen("out.pgm", "w");
-
- fprintf(ppm, "P6\n%d %d\n255\n", pix->w, pix->h);
- fprintf(pgm, "P5\n%d %d\n255\n", pix->w, pix->h);
-
- if (pix->n == 3 && pix->a == 1)
- {
- for (y = 0; y < pix->h; y++)
- for (x = 0; x < pix->w; x++)
- {
- int r = pix->samples[x * 4 + y * pix->stride + 0];
- int g = pix->samples[x * 4 + y * pix->stride + 1];
- int b = pix->samples[x * 4 + y * pix->stride + 2];
- int a = pix->samples[x * 4 + y * pix->stride + 3];
+ float srcv[32];
+ float dstv[32];
+ int y, x, k;
+ int sna = src->n + src->a;
+ int dna = dst->n + dst->a;
- //putc(r, ppm);
- //putc(g, ppm);
- //putc(b, ppm);
- putc(((r * a) / 255) + (255 - a), ppm);
- putc(((g * a) / 255) + (255 - a), ppm);
- putc(((b * a) / 255) + (255 - a), ppm);
+printf("convert pixmap from %s to %s\n", src->cs->name, dst->cs->name);
- putc(a, pgm);
- }
- }
- else if (pix->n == 0 && pix->a == 1)
+ for (y = 0; y < src->h; y++)
{
- for (y = 0; y < pix->h; y++)
- for (x = 0; x < pix->w; x++)
- {
- int a = pix->samples[x + y * pix->stride];
- putc(0, ppm);
- putc(0, ppm);
- putc(0, ppm);
- putc(a, pgm);
- }
+ for (x = 0; x < src->w; x++)
+ {
+ for (k = 0; k < src->n; k++)
+ srcv[k] = src->samples[ y * src->stride + x * sna + k ] / 255.0;
+ fz_convertcolor(src->cs, srcv, dst->cs, dstv);
+ for (k = 0; k < dst->n; k++)
+ dst->samples[ y * dst->stride + x * dna + k ] = dstv[k] * 255;
+ if (src->a && dst->a)
+ dst->samples[ y * dst->stride + x * dna + dst->n ] =
+ src->samples[ y * src->stride + x * sna + src->n ];
+ else if (dst->a)
+ dst->samples[ y * dst->stride + x * dna + dst->n ] = 255;
+ }
}
-
- fclose(ppm);
- fclose(pgm);
}
void
@@ -147,3 +128,65 @@ fz_blendmask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *msk)
}
}
+void
+fz_debugpixmap(fz_pixmap *pix)
+{
+ int x, y;
+
+ FILE *ppm = fopen("out.ppm", "w");
+ FILE *pgm = fopen("out.pgm", "w");
+
+ fprintf(ppm, "P6\n%d %d\n255\n", pix->w, pix->h);
+ fprintf(pgm, "P5\n%d %d\n255\n", pix->w, pix->h);
+
+ if (pix->n == 3 && pix->a == 1)
+ {
+ for (y = 0; y < pix->h; y++)
+ for (x = 0; x < pix->w; x++)
+ {
+ int r = pix->samples[x * 4 + y * pix->stride + 0];
+ int g = pix->samples[x * 4 + y * pix->stride + 1];
+ int b = pix->samples[x * 4 + y * pix->stride + 2];
+ int a = pix->samples[x * 4 + y * pix->stride + 3];
+
+ putc(r, ppm);
+ putc(g, ppm);
+ putc(b, ppm);
+ // putc(((r * a) / 255) + (255 - a), ppm);
+ // putc(((g * a) / 255) + (255 - a), ppm);
+ // putc(((b * a) / 255) + (255 - a), ppm);
+
+ putc(a, pgm);
+ }
+ }
+ if (pix->n == 3 && pix->a == 0)
+ {
+ for (y = 0; y < pix->h; y++)
+ for (x = 0; x < pix->w; x++)
+ {
+ int r = pix->samples[x * 3 + y * pix->stride + 0];
+ int g = pix->samples[x * 3 + y * pix->stride + 1];
+ int b = pix->samples[x * 3 + y * pix->stride + 2];
+ putc(r, ppm);
+ putc(g, ppm);
+ putc(b, ppm);
+ putc(255, pgm);
+ }
+ }
+ else if (pix->n == 0 && pix->a == 1)
+ {
+ for (y = 0; y < pix->h; y++)
+ for (x = 0; x < pix->w; x++)
+ {
+ int a = pix->samples[x + y * pix->stride];
+ putc(0, ppm);
+ putc(0, ppm);
+ putc(0, ppm);
+ putc(a, pgm);
+ }
+ }
+
+ fclose(ppm);
+ fclose(pgm);
+}
+
diff --git a/render/render.c b/render/render.c
index d77c0c9d..73408a8b 100644
--- a/render/render.c
+++ b/render/render.c
@@ -75,6 +75,8 @@ fz_rendercolor(fz_renderer *gc, fz_colornode *color, fz_matrix ctm)
int x, y;
float rgb[3];
+printf("render color\n");
+
fz_convertcolor(color->cs, color->samples, gc->model, rgb);
gc->r = rgb[0] * 255;
gc->g = rgb[1] * 255;
@@ -118,7 +120,10 @@ fz_renderoverchild(fz_renderer *gc, fz_node *node, fz_matrix ctm)
if (gc->tmp)
{
+printf("over src ");fz_debugpixmap(gc->tmp);getchar();
+printf("over dst ");fz_debugpixmap(gc->acc);getchar();
fz_blendover(gc->tmp, gc->acc);
+printf("over res ");fz_debugpixmap(gc->acc);getchar();
fz_freepixmap(gc->tmp);
gc->tmp = nil;
}
@@ -133,9 +138,12 @@ fz_renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm)
fz_pixmap *oldacc = nil;
int oldmode;
+printf("begin over\n");
+
/* uh-oh! we have a new over cluster */
if (gc->mode != FZ_ROVER)
{
+printf("begin over accumulator\n");
oldacc = gc->acc;
error = fz_newpixmap(&gc->acc, gc->model, gc->x, gc->y, gc->w, gc->h, 3, 1);
if (error)
@@ -160,10 +168,13 @@ fz_renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm)
/* uh-oh! end of over cluster */
if (gc->mode != FZ_ROVER)
{
+printf("end over accumulator\n");
gc->tmp = gc->acc;
gc->acc = oldacc;
}
+printf("end over\n");
+
return nil;
}
@@ -188,6 +199,8 @@ fz_rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm)
return fz_rendercolortext(gc, (fz_textnode*)shape, (fz_colornode*)color, ctm);
}
+printf("begin mask\n");
+
oldmode = gc->mode;
gc->mode = FZ_RMASK;
@@ -209,21 +222,24 @@ fz_rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm)
fz_blendmask(gc->tmp, colorpix, shapepix);
-//printf("mask color");fz_debugpixmap(colorpix);getchar();
-//printf("mask shape");fz_debugpixmap(shapepix);getchar();
-//printf("mask blend");fz_debugpixmap(gc->tmp);getchar();
+printf("mask color");fz_debugpixmap(colorpix);getchar();
+printf("mask shape");fz_debugpixmap(shapepix);getchar();
+printf("mask blend");fz_debugpixmap(gc->tmp);getchar();
fz_freepixmap(shapepix);
fz_freepixmap(colorpix);
gc->mode = oldmode;
+printf("end mask\n");
+
return nil;
}
fz_error *
fz_rendertransform(fz_renderer *gc, fz_transformnode *transform, fz_matrix ctm)
{
+printf("render transform\n");
ctm = fz_concat(transform->m, ctm);
return fz_rendernode(gc, transform->super.child, ctm);
}
@@ -271,6 +287,8 @@ fz_rendertree(fz_pixmap **outp, fz_renderer *gc, fz_tree *tree, fz_matrix ctm, f
ctm.e -= bbox.min.x - floor(bbox.min.x);
ctm.f -= bbox.min.y - floor(bbox.min.y);
+printf("render tree\n");
+
error = fz_rendernode(gc, tree->root, ctm);
if (error)
return error;
diff --git a/render/renderimage.c b/render/renderimage.c
index 15eda833..068c9ca4 100644
--- a/render/renderimage.c
+++ b/render/renderimage.c
@@ -1,42 +1,104 @@
#include <fitz.h>
+fz_error *
+fz_scalepixmap(fz_pixmap *src, fz_pixmap *dst, int xdenom, int ydenom);
+
+static int getcomp(fz_pixmap *pix, float u, float v, int k)
+{
+ float fu = floor(u);
+ float fv = floor(v);
+ float su = u - fu;
+ float sv = v - fv;
+
+ int x0 = fu;
+ int x1 = x0 + 1;
+ int y0 = fv;
+ int y1 = y0 + 1;
+
+ x0 = CLAMP(x0, 0, pix->w - 1);
+ x1 = CLAMP(x1, 0, pix->w - 1);
+ y0 = CLAMP(y0, 0, pix->h - 1);
+ y1 = CLAMP(y1, 0, pix->h - 1);
+
+ float a = pix->samples[ y0 * pix->stride + x0 * (pix->n + pix->a) + k ];
+ float b = pix->samples[ y0 * pix->stride + x1 * (pix->n + pix->a) + k ];
+ float c = pix->samples[ y1 * pix->stride + x0 * (pix->n + pix->a) + k ];
+ float d = pix->samples[ y1 * pix->stride + x1 * (pix->n + pix->a) + k ];
+
+ float ab = a * (1.0 - su) + b * su;
+ float cd = c * (1.0 - su) + d * su;
+ float abcd = ab * (1.0 - sv) + cd * sv;
+
+ return (int)abcd;
+}
+
static inline void
drawscan(fz_matrix *invmat, fz_pixmap *dst, fz_pixmap *src, int y, int x0, int x1)
{
int x, k;
- float u, v;
- float du, dv;
- fz_point p;
- int iu, iv;
- unsigned char c;
- p.x = x0;
- p.y = y;
- p = fz_transformpoint(*invmat, p);
-
- u = p.x;
- v = p.y;
- du = invmat->a;
- dv = invmat->c;
+ float u = invmat->a * x0 + invmat->c * y + invmat->e;
+ float v = invmat->b * x0 + invmat->d * y + invmat->f;
for (x = x0; x < x1; x++)
{
- iu = CLAMP((int)u, 0, src->w - 1);
- iv = CLAMP((int)v, 0, src->h - 1);
-
for (k = 0; k < src->n + src->a; k++)
- {
- c = src->samples[ iv * src->stride + iu * (src->n+src->a) + k];
- dst->samples[ y * dst->stride + x * (dst->n+dst->a) + k ] = c;
- }
+ dst->samples[ y * dst->stride + x * (dst->n+dst->a) + k ] = getcomp(src, u, v, k);
+ if (!src->a && dst->a)
+ dst->samples[ y * dst->stride + x * (dst->n + dst->a) + dst->n ] = 0xFF;
- u += du;
- v += dv;
+ u += invmat->a;
+ v += invmat->c;
+ }
+}
+
+static inline void
+overscanrgb(fz_matrix *invmat, fz_pixmap *dst, fz_pixmap *src, int y, int x0, int x1)
+{
+ int x;
+
+ float u = invmat->a * x0 + invmat->c * y + invmat->e;
+ float v = invmat->b * x0 + invmat->d * y + invmat->f;
+
+ for (x = x0; x < x1; x++)
+ {
+ float a = 1.0;
+ if (u < 0)
+ a *= 1.0 - (u - floor(u));
+ if (u > src->w - 1)
+ a *= u - floor(u);
+ if (v < 0)
+ a *= 1.0 - (v - floor(v));
+ if (v > src->h - 1)
+ a *= v - floor(v);
+
+ int sr = getcomp(src, u, v, 0);
+ int sg = getcomp(src, u, v, 1);
+ int sb = getcomp(src, u, v, 2);
+
+ int dr = dst->samples[ y * dst->stride + x * (dst->n+dst->a) + 0 ];
+ int dg = dst->samples[ y * dst->stride + x * (dst->n+dst->a) + 1 ];
+ int db = dst->samples[ y * dst->stride + x * (dst->n+dst->a) + 2 ];
+
+ int sa = a * 255;
+ int ssa = 255 - sa;
+
+ dr = fz_mul255(sr, sa) + fz_mul255(dr, ssa);
+ dg = fz_mul255(sg, sa) + fz_mul255(dg, ssa);
+ db = fz_mul255(sb, sa) + fz_mul255(db, ssa);
+
+ dst->samples[ y * dst->stride + x * (dst->n+dst->a) + 0 ] = dr;
+ dst->samples[ y * dst->stride + x * (dst->n+dst->a) + 1 ] = dg;
+ dst->samples[ y * dst->stride + x * (dst->n+dst->a) + 2 ] = db;
+ dst->samples[ y * dst->stride + x * (dst->n+dst->a) + 3 ] = sa;
+
+ u += invmat->a;
+ v += invmat->c;
}
}
static fz_error *
-drawtile(fz_renderer *gc, fz_pixmap *out, fz_pixmap *tile, fz_matrix ctm)
+drawtile(fz_renderer *gc, fz_pixmap *out, fz_pixmap *tile, fz_matrix ctm, int over)
{
static const fz_point rect[4] = { {0, 0}, {0, 1}, {1, 1}, {1, 0} };
fz_error *error;
@@ -75,7 +137,16 @@ drawtile(fz_renderer *gc, fz_pixmap *out, fz_pixmap *tile, fz_matrix ctm)
x0 = ael->edges[0]->x;
x1 = ael->edges[ael->len - 1]->x;
- drawscan(&invmat, out, tile, y, x0, x1);
+
+ if (y >= out->y && y < out->y + out->h)
+ {
+ x0 = CLAMP(x0, out->x, out->x + out->w - 1);
+ x1 = CLAMP(x1, out->x, out->x + out->w - 1);
+ if (over && tile->cs && tile->cs->n == 3)
+ overscanrgb(&invmat, out, tile, y, x0, x1);
+ else
+ drawscan(&invmat, out, tile, y, x0, x1);
+ }
fz_advanceael(ael);
@@ -92,39 +163,81 @@ fz_error *
fz_renderimage(fz_renderer *gc, fz_imagenode *node, fz_matrix ctm)
{
fz_error *error;
- fz_pixmap *tile;
+ fz_pixmap *tile1;
+ fz_pixmap *tile2;
+ fz_pixmap *tile3;
fz_image *image = node->image;
fz_colorspace *cs = image->cs;
int w = image->w;
int h = image->h;
int n = image->n;
+ int a = image->a;
+ int sw = w;
+ int sh = h;
- error = fz_newpixmap(&tile, cs, 0, 0, w, h, n, 1);
- if (error)
- return error;
+ float s = sqrt(ctm.a * ctm.a + ctm.b * ctm.b);
- error = fz_newpixmap(&gc->tmp, cs, gc->x, gc->y, gc->w, gc->h, n, 1);
- if (error)
- goto cleanup;
+ int d = 1;
+ while ((w + d - 1) / d > s)
+ d++;
+ if (d > 1)
+ d --;
- fz_clearpixmap(gc->tmp);
+printf("renderimage s=%g d=%d\n", s, d);
- error = image->loadtile(image, tile);
- if (error)
- goto cleanup;
+ error = fz_newpixmap(&tile1, cs, 0, 0, w, h, n, a);
- error = drawtile(gc, gc->tmp, tile, ctm);
- if (error)
- goto cleanup;
+printf(" load tile\n");
+ error = image->loadtile(image, tile1);
-printf("loadtile "); fz_debugpixmap(tile); getchar();
-//printf("drawtile "); fz_debugpixmap(gc->tmp); getchar();
+ if (d != 1)
+ {
+ sw = (w + d - 1) / d;
+ sh = (h + d - 1) / d;
- fz_freepixmap(tile);
- return nil;
+printf(" new pixmap\n");
+ error = fz_newpixmap(&tile2, cs, 0, 0, sw, sh, n, a);
+printf(" scale tile to %d %d\n", sw, sh);
+ error = fz_scalepixmap(tile1, tile2, d, d);
+
+printf(" free loaded tile\n");
+ fz_freepixmap(tile1);
+ }
+ else
+ tile2 = tile1;
+
+printf(" swtich render mode\n");
+
+ /* render image mask */
+ if (n == 0 && a == 1)
+ {
+printf("draw image mask\n");
+ error = fz_newpixmap(&gc->tmp, nil, gc->x, gc->y, gc->w, gc->h, 0, 1);
+ fz_clearpixmap(gc->tmp);
+ error = drawtile(gc, gc->tmp, tile2, ctm, 0);
+fz_debugpixmap(gc->tmp);getchar();
+ }
+
+ /* render rgb over */
+ else if (n == 3 && a == 0 && gc->acc)
+ {
+printf("draw image rgb over\n");
+ error = drawtile(gc, gc->acc, tile2, ctm, 1);
+ }
-cleanup:
- fz_freepixmap(tile);
- return error;
+ /* render generic image */
+ else
+ {
+printf("draw generic image\n");
+ error = fz_newpixmap(&tile3, gc->model, 0, 0, sw, sh, gc->model->n, a);
+ fz_convertpixmap(tile2, tile3);
+ error = fz_newpixmap(&gc->tmp, gc->model, gc->x, gc->y, gc->w, gc->h, gc->model->n, 1);
+ fz_clearpixmap(gc->tmp);
+ error = drawtile(gc, gc->tmp, tile3, ctm, 0);
+ fz_freepixmap(tile3);
+ }
+
+ fz_freepixmap(tile2);
+ return nil;
}
diff --git a/render/scale.c b/render/scale.c
new file mode 100644
index 00000000..1fad5a0b
--- /dev/null
+++ b/render/scale.c
@@ -0,0 +1,93 @@
+#include <fitz.h>
+
+static void
+scalerow(unsigned char *src, int w, int denom, unsigned char *dst, int ncomp)
+{
+ int x, left, n;
+ int sum[32];
+
+ left = 0;
+ for (n = 0; n < ncomp; n++)
+ sum[n] = 0;
+
+ for (x = 0; x < w; x++)
+ {
+ for (n = 0; n < ncomp; n++)
+ sum[n] += src[x * ncomp + n];
+ if (++left == denom)
+ {
+ left = 0;
+ for (n = 0; n < ncomp; n++)
+ {
+ dst[n] = sum[n] / denom;
+ sum[n] = 0;
+ }
+ dst += ncomp;
+ }
+ }
+
+ /* left overs */
+ if (left)
+ for (n = 0; n < ncomp; n++)
+ dst[n] = sum[n] / left;
+}
+
+static void
+scalecols(unsigned char *src, int stride, int w, int denom, unsigned char *dst, int ncomp)
+{
+ int x, y, n;
+ unsigned char *s;
+ int sum[32];
+
+ for (x = 0; x < w; x++)
+ {
+ s = src + (x * ncomp);
+ for (n = 0; n < ncomp; n++)
+ sum[n] = 0;
+ for (y = 0; y < denom; y++)
+ for (n = 0; n < ncomp; n++)
+ sum[n] += s[y * stride + n];
+ for (n = 0; n < ncomp; n++)
+ dst[n] = sum[n] / denom;
+ dst += ncomp;
+ }
+}
+
+fz_error *
+fz_scalepixmap(fz_pixmap *src, fz_pixmap *dst, int xdenom, int ydenom)
+{
+ assert(src->n == dst->n);
+ assert(src->a == dst->a);
+ assert((src->w + xdenom - 1) / xdenom == dst->w);
+ assert((src->h + ydenom - 1) / ydenom == dst->h);
+
+ int ncomp = src->n + src->a;
+ unsigned char scratch[dst->stride * ydenom];
+
+ int y, iy, oy;
+
+ for (y = 0, oy = 0; y < (dst->h - 1) * ydenom; y += ydenom, oy++)
+ {
+ for (iy = 0; iy < ydenom; iy++)
+ scalerow(src->samples + (y + iy) * src->stride, src->w, xdenom,
+ scratch + iy * dst->stride, ncomp);
+ scalecols(scratch, ncomp * dst->w, dst->w, ydenom,
+ dst->samples + (oy * dst->stride), ncomp);
+ }
+
+ ydenom = src->h - y;
+ if (ydenom)
+ {
+ for (iy = 0; iy < ydenom; iy++)
+ scalerow(src->samples + (y + iy) * src->stride, src->w, xdenom,
+ scratch + iy * (ncomp * dst->w), ncomp);
+ scalecols(scratch, ncomp * dst->w, dst->w, ydenom,
+ dst->samples + (oy * dst->stride), ncomp);
+ }
+
+//printf("unscaled image ");fz_debugpixmap(src);getchar();
+//printf("scaled image ");fz_debugpixmap(dst);getchar();
+
+ return nil;
+}
+