summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Jamfile2
-rw-r--r--include/fitz/pixmap.h2
-rw-r--r--include/mupdf/rsrc.h3
-rw-r--r--mupdf/image.c124
-rw-r--r--mupdf/interpret.c13
-rw-r--r--mupdf/page.c8
-rw-r--r--mupdf/repair.c1
-rw-r--r--render/pixmap.c125
-rw-r--r--render/render.c24
-rw-r--r--render/renderimage.c203
-rw-r--r--render/scale.c93
-rw-r--r--tree/image.c9
12 files changed, 457 insertions, 150 deletions
diff --git a/Jamfile b/Jamfile
index 3ce33eab..da99d0a1 100644
--- a/Jamfile
+++ b/Jamfile
@@ -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);
+}
+