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 | |
parent | 3dae7919da3ba4baf4dbe4c59dd9202b912d21e9 (diff) | |
download | mupdf-d0282c705fcdf9c3f1771103093bec25f5bd3ca1.tar.xz |
resample images
Diffstat (limited to 'render')
-rw-r--r-- | render/pixmap.c | 125 | ||||
-rw-r--r-- | render/render.c | 24 | ||||
-rw-r--r-- | render/renderimage.c | 203 | ||||
-rw-r--r-- | render/scale.c | 93 |
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; +} + |