diff options
author | Tor Andersson <tor@ghostscript.com> | 2004-10-25 11:42:34 +0200 |
---|---|---|
committer | Tor Andersson <tor@ghostscript.com> | 2004-10-25 11:42:34 +0200 |
commit | d0282c705fcdf9c3f1771103093bec25f5bd3ca1 (patch) | |
tree | d77299e716922fbe88ca8ce3c17ee946b0977629 /render/renderimage.c | |
parent | 3dae7919da3ba4baf4dbe4c59dd9202b912d21e9 (diff) | |
download | mupdf-d0282c705fcdf9c3f1771103093bec25f5bd3ca1.tar.xz |
resample images
Diffstat (limited to 'render/renderimage.c')
-rw-r--r-- | render/renderimage.c | 203 |
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; } |