summaryrefslogtreecommitdiff
path: root/render/renderimage.c
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/renderimage.c
parent3dae7919da3ba4baf4dbe4c59dd9202b912d21e9 (diff)
downloadmupdf-d0282c705fcdf9c3f1771103093bec25f5bd3ca1.tar.xz
resample images
Diffstat (limited to 'render/renderimage.c')
-rw-r--r--render/renderimage.c203
1 files changed, 158 insertions, 45 deletions
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;
}