diff options
-rw-r--r-- | Jamfile | 2 | ||||
-rw-r--r-- | include/fitz/pixmap.h | 2 | ||||
-rw-r--r-- | include/mupdf/rsrc.h | 3 | ||||
-rw-r--r-- | mupdf/image.c | 124 | ||||
-rw-r--r-- | mupdf/interpret.c | 13 | ||||
-rw-r--r-- | mupdf/page.c | 8 | ||||
-rw-r--r-- | mupdf/repair.c | 1 | ||||
-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 | ||||
-rw-r--r-- | tree/image.c | 9 |
12 files changed, 457 insertions, 150 deletions
@@ -66,6 +66,7 @@ Library libfitz : tree/cmap.c tree/font.c tree/colorspace.c + tree/image.c tree/tree.c tree/node1.c @@ -81,6 +82,7 @@ Library libfitz : render/scanconv.c render/fill.c render/stroke.c + render/scale.c render/render.c render/rendertext.c render/renderpath.c diff --git a/include/fitz/pixmap.h b/include/fitz/pixmap.h index 24584f30..7b8bfb1e 100644 --- a/include/fitz/pixmap.h +++ b/include/fitz/pixmap.h @@ -10,10 +10,10 @@ struct fz_pixmap_s }; fz_error *fz_newpixmap(fz_pixmap **mapp, fz_colorspace *cs, int x, int y, int w, int h, int n, int a); -fz_error *fz_convertpixmap(fz_pixmap **dstp, fz_pixmap *src, fz_colorspace *dstcs); void fz_debugpixmap(fz_pixmap *map); void fz_freepixmap(fz_pixmap *map); void fz_clearpixmap(fz_pixmap *map); +void fz_convertpixmap(fz_pixmap *src, fz_pixmap *dst); void fz_blendover(fz_pixmap *src, fz_pixmap *dst); void fz_blendmask(fz_pixmap *dst, fz_pixmap *color, fz_pixmap *shape); diff --git a/include/mupdf/rsrc.h b/include/mupdf/rsrc.h index cac492c0..1cf5d654 100644 --- a/include/mupdf/rsrc.h +++ b/include/mupdf/rsrc.h @@ -52,7 +52,8 @@ struct pdf_image_s fz_image *mask; /* explicit mask with subimage */ float decode[32]; int bpc; - fz_buffer *data; + int stride; + fz_buffer *samples; }; fz_error *pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *obj, fz_obj *stm); diff --git a/mupdf/image.c b/mupdf/image.c index a2dc624e..f866264a 100644 --- a/mupdf/image.c +++ b/mupdf/image.c @@ -1,56 +1,63 @@ #include <fitz.h> #include <mupdf.h> -#define NEXTBYTE() \ - { c = *srcline++; } -#define NEEDBITS(n) \ - { while (k<(n)) { NEXTBYTE(); b = (b << 8) | c; k += 8; } } -#define DUMPBITS(n) \ - { k -= (n); } -#define GETCOMP1 NEEDBITS(1);(cc)=((b>>(k-(1)))&0x0001);DUMPBITS(1) -#define GETCOMP2 NEEDBITS(2);(cc)=((b>>(k-(2)))&0x0003);DUMPBITS(2) -#define GETCOMP4 NEEDBITS(4);(cc)=((b>>(k-(4)))&0x000f);DUMPBITS(4) -#define GETCOMP8 NEXTBYTE();(cc)=c - -static fz_error *loadtile(fz_image *fzimg, fz_pixmap *tile) +static inline int getbit(const unsigned char *buf, int x) { - pdf_image *img = (pdf_image*)fzimg; - unsigned char *srcline; - unsigned char *dstline; - int x, y, z; - int stride; - unsigned cc, c, k, b; - - assert(fzimg->w == tile->w && fzimg->h == tile->h); - assert(fzimg->n == tile->n); - - stride = ((fzimg->w * (fzimg->n + fzimg->a)) * img->bpc + 7) / 8; - k = 0; - b = 0; + return ( buf[x >> 3] >> ( 7 - (x & 7) ) ) & 1; +} - for (y = 0; y < fzimg->h; y++) +static void loadtile1(pdf_image *src, fz_pixmap *dst) +{ + int x, y, k; + int n = dst->n + dst->a; + for (y = 0; y < dst->h; y++) { - srcline = img->data->bp + y * stride; - dstline = tile->samples + y * tile->stride; + unsigned char *srcp = src->samples->bp + (dst->y + y) * src->stride; + unsigned char *dstp = dst->samples + (dst->y + y) * dst->stride; + for (x = 0; x < dst->w; x++) + { + for (k = 0; k < n; k++) + dstp[(dst->x + x) * n + k] = getbit(srcp, (dst->x + x) * n + k) * 255; + } + } +} - for (x = 0; x < fzimg->w; x++) +static void loadtile8(pdf_image *src, fz_pixmap *dst) +{ + int x, y, k; + int n = dst->n + dst->a; + for (y = 0; y < dst->h; y++) + { + unsigned char *srcp = src->samples->bp + (dst->y + y) * src->stride; + unsigned char *dstp = dst->samples + (dst->y + y) * dst->stride; + for (x = 0; x < dst->w; x++) { - for (z = 0; z < fzimg->n + fzimg->a; z++) - { - switch (img->bpc) - { - case 1: GETCOMP1; *dstline++ = cc * 255; break; - case 2: GETCOMP2; *dstline++ = cc * 85; break; - case 4: GETCOMP4; *dstline++ = cc * 17; break; - case 8: GETCOMP8; *dstline++ = cc; break; - } - } - if (!fzimg->a && tile->a) - *dstline++ = 0xff; + for (k = 0; k < n; k++) + dstp[(dst->x + x) * n + k] = srcp[(dst->x + x) * n + k]; } } +} - return nil; +static fz_error *loadtile(fz_image *img, fz_pixmap *tile) +{ + pdf_image *src = (pdf_image*)img; + + assert(tile->n == img->n); + assert(tile->a == img->a); + assert(tile->x >= 0); + assert(tile->y >= 0); + assert(tile->x + tile->w <= img->w); + assert(tile->y + tile->h <= img->h); + + switch (src->bpc) + { + case 1: loadtile1(src, tile); return nil; +// case 2: loadtile2(src, tile); return nil; +// case 4: loadtile4(src, tile); return nil; + case 8: loadtile8(src, tile); return nil; + } + + return fz_throw("rangecheck: unsupported bit depth: %d", src->bpc); } fz_error * @@ -60,7 +67,6 @@ pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) pdf_image *img; fz_colorspace *cs; int ismask; - int stride; fz_obj *obj; int i; @@ -81,7 +87,17 @@ printf("load image %d x %d @ %d\n", img->super.w, img->super.h, img->bpc); cs = nil; obj = fz_dictgets(dict, "ColorSpace"); if (obj) + { + error = pdf_resolve(&obj, xref); + if (error) + return error; + error = pdf_loadcolorspace(&cs, xref, obj); + if (error) + return error; + + fz_dropobj(obj); + } ismask = fz_tobool(fz_dictgets(dict, "ImageMask")); if (!ismask) @@ -97,6 +113,8 @@ printf("load image %d x %d @ %d\n", img->super.w, img->super.h, img->bpc); img->super.a = 1; } + img->stride = ((img->super.w * (img->super.n + img->super.a)) * img->bpc + 7) / 8; + obj = fz_dictgets(dict, "Decode"); if (fz_isarray(obj)) for (i = 0; i < (img->super.n + img->super.a) * 2; i++) @@ -112,7 +130,7 @@ for (i = 0; i < (img->super.n + img->super.a) * 2; i++) printf("%g ", img->decode[i]); printf("]\n"); - error = pdf_loadstream(&img->data, xref, fz_tonum(ref), fz_togen(ref)); + error = pdf_loadstream(&img->samples, xref, fz_tonum(ref), fz_togen(ref)); if (error) { /* TODO: colorspace? */ @@ -120,18 +138,24 @@ printf("]\n"); return error; } - stride = img->super.w * (img->super.n + img->super.a); - stride = (stride * img->bpc + 7) / 8; -printf(" stride = %d -> %d bytes\n", stride, stride * img->super.h); -printf(" data = %d bytes\n", img->data->wp - img->data->bp); - if (img->data->wp - img->data->bp != stride * img->super.h) +printf(" stride = %d -> %d bytes\n", img->stride, img->stride * img->super.h); +printf(" samples = %d bytes\n", img->samples->wp - img->samples->bp); + if (img->samples->wp - img->samples->bp != img->stride * img->super.h) { /* TODO: colorspace? */ - fz_freebuffer(img->data); + fz_freebuffer(img->samples); fz_free(img); return fz_throw("syntaxerror: truncated image data"); } + /* 0 means opaque and 1 means transparent, so we invert to get alpha */ + if (ismask) + { + unsigned char *p; + for (p = img->samples->bp; p < img->samples->ep; p++) + *p = ~*p; + } + *imgp = img; return nil; diff --git a/mupdf/interpret.c b/mupdf/interpret.c index ed8fff07..79d15d55 100644 --- a/mupdf/interpret.c +++ b/mupdf/interpret.c @@ -37,8 +37,8 @@ pdf_newcsi(pdf_csi **csip) csi->tree->root = node; csi->gstate[0].head = node; -// error = fz_newcolornode(&node, pdf_devicegray, 1, &white); -// fz_insertnode(csi->tree->root, node); + error = fz_newcolornode(&node, pdf_devicegray, 1, &white); + fz_insertnode(csi->tree->root, node); csi->clip = nil; @@ -361,7 +361,7 @@ runkeyword(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, char *buf) } } - else if (!strcmp(buf, "sc")) + else if (!strcmp(buf, "sc") || !strcmp(buf, "scn")) { if (csi->top != gstate->fillcs->n) goto syntaxerror; @@ -369,7 +369,7 @@ runkeyword(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, char *buf) gstate->fill[i] = fz_toreal(csi->stack[i]); } - else if (!strcmp(buf, "SC")) + else if (!strcmp(buf, "SC") || !strcmp(buf, "SCN")) { if (csi->top != gstate->strokecs->n) goto syntaxerror; @@ -563,7 +563,10 @@ runkeyword(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, char *buf) img = pdf_findresource(xref->rimage, obj); if (!img) - return fz_throw("syntaxerror: missing image resource"); + { +fprintf(stderr, "syntaxerror: missing image resource"); +return nil; + } error = pdf_showimage(csi, img); if (error) diff --git a/mupdf/page.c b/mupdf/page.c index 48e8af77..b5e12a4e 100644 --- a/mupdf/page.c +++ b/mupdf/page.c @@ -91,10 +91,10 @@ pdf_loadpage(pdf_page **pagep, pdf_xref *xref, fz_obj *dict) obj = fz_dictgets(dict, "MediaBox"); if (!fz_isarray(obj)) return fz_throw("syntaxerror: Page missing MediaBox"); - bbox.min.x = fz_toint(fz_arrayget(obj, 0)); - bbox.min.y = fz_toint(fz_arrayget(obj, 1)); - bbox.max.x = fz_toint(fz_arrayget(obj, 2)); - bbox.max.y = fz_toint(fz_arrayget(obj, 3)); + bbox.min.x = fz_toreal(fz_arrayget(obj, 0)); + bbox.min.y = fz_toreal(fz_arrayget(obj, 1)); + bbox.max.x = fz_toreal(fz_arrayget(obj, 2)); + bbox.max.y = fz_toreal(fz_arrayget(obj, 3)); obj = fz_dictgets(dict, "Rotate"); if (fz_isint(obj)) diff --git a/mupdf/repair.c b/mupdf/repair.c index 5f4a139e..91d46a39 100644 --- a/mupdf/repair.c +++ b/mupdf/repair.c @@ -280,6 +280,7 @@ pdf_repairpdf(pdf_xref **xrefp, char *filename) } } + *xrefp = xref; fz_free(list); return nil; 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; +} + diff --git a/tree/image.c b/tree/image.c new file mode 100644 index 00000000..dd4b030a --- /dev/null +++ b/tree/image.c @@ -0,0 +1,9 @@ +#include <fitz.h> + +void fz_freeimage(fz_image *image) +{ + if (image->free) + image->free(image); + fz_free(image); +} + |