summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2004-10-22 10:04:22 +0200
committerTor Andersson <tor@ghostscript.com>2004-10-22 10:04:22 +0200
commit3dae7919da3ba4baf4dbe4c59dd9202b912d21e9 (patch)
tree67af833c4f6ac22cdbc724e04eb71a6065ea45ad
parentf49341e713b65b6e49862d02b38cd89c6a56c568 (diff)
downloadmupdf-3dae7919da3ba4baf4dbe4c59dd9202b912d21e9.tar.xz
image rendering
-rw-r--r--include/mupdf/content.h1
-rw-r--r--include/mupdf/rsrc.h4
-rw-r--r--mupdf/build.c27
-rw-r--r--mupdf/image.c89
-rw-r--r--mupdf/interpret.c26
-rw-r--r--mupdf/resources.c2
-rw-r--r--render/render.c2
-rw-r--r--render/renderimage.c93
-rw-r--r--render/stroke.c4
9 files changed, 228 insertions, 20 deletions
diff --git a/include/mupdf/content.h b/include/mupdf/content.h
index 9448a539..b57a4d96 100644
--- a/include/mupdf/content.h
+++ b/include/mupdf/content.h
@@ -67,6 +67,7 @@ fz_error *pdf_addtransform(pdf_gstate *gs, fz_node *transform);
fz_error *pdf_showpath(pdf_csi*, int close, int fill, int stroke, int evenodd);
fz_error *pdf_showtext(pdf_csi*, fz_obj *text);
fz_error *pdf_flushtext(pdf_csi*);
+fz_error *pdf_showimage(pdf_csi*, pdf_image *img);
/* interpret.c */
fz_error *pdf_newcsi(pdf_csi **csip);
diff --git a/include/mupdf/rsrc.h b/include/mupdf/rsrc.h
index 5d977fd1..cac492c0 100644
--- a/include/mupdf/rsrc.h
+++ b/include/mupdf/rsrc.h
@@ -52,10 +52,10 @@ struct pdf_image_s
fz_image *mask; /* explicit mask with subimage */
float decode[32];
int bpc;
- unsigned char *data;
+ fz_buffer *data;
};
-fz_error *pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *obj);
+fz_error *pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *obj, fz_obj *stm);
/*
* CMap and Font
diff --git a/mupdf/build.c b/mupdf/build.c
index d235c9bc..6d0129ea 100644
--- a/mupdf/build.c
+++ b/mupdf/build.c
@@ -135,6 +135,33 @@ pdf_addtransform(pdf_gstate *gs, fz_node *transform)
return nil;
}
+fz_error *
+pdf_showimage(pdf_csi *csi, pdf_image *img)
+{
+ fz_error *error;
+ fz_node *node;
+
+ error = fz_newimagenode(&node, (fz_image*)img);
+ if (error)
+ return error;
+
+ if (img->super.n == 0 && img->super.a == 1)
+ {
+ error = pdf_addfillshape(csi->gstate + csi->gtop, node);
+ if (error) {
+ fz_freenode(node);
+ return error;
+ }
+ }
+ else
+ {
+ /* TODO image mask sub-image */
+ fz_insertnode(csi->gstate[csi->gtop].head, node);
+ }
+
+ return nil;
+}
+
#if 0
BMC ... EMC object nesting can be completely fucked up
diff --git a/mupdf/image.c b/mupdf/image.c
index 00e6171b..a2dc624e 100644
--- a/mupdf/image.c
+++ b/mupdf/image.c
@@ -1,19 +1,68 @@
#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)
{
+ 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;
+
+ for (y = 0; y < fzimg->h; y++)
+ {
+ srcline = img->data->bp + y * stride;
+ dstline = tile->samples + y * tile->stride;
+
+ for (x = 0; x < fzimg->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;
+ }
+ }
+
return nil;
}
fz_error *
-pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict)
+pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict, fz_obj *ref)
{
fz_error *error;
pdf_image *img;
fz_colorspace *cs;
int ismask;
+ int stride;
fz_obj *obj;
+ int i;
img = fz_malloc(sizeof(pdf_image));
if (!img)
@@ -27,13 +76,14 @@ pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict)
img->super.h = fz_toint(fz_dictgets(dict, "Height"));
img->bpc = fz_toint(fz_dictgets(dict, "BitsPerComponent"));
+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_loadcolorspace(&cs, xref, obj);
ismask = fz_tobool(fz_dictgets(dict, "ImageMask"));
-
if (!ismask)
{
img->super.cs = cs;
@@ -47,6 +97,41 @@ pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict)
img->super.a = 1;
}
+ obj = fz_dictgets(dict, "Decode");
+ if (fz_isarray(obj))
+ for (i = 0; i < (img->super.n + img->super.a) * 2; i++)
+ img->decode[i] = fz_toreal(fz_arrayget(obj, i));
+ else
+ for (i = 0; i < (img->super.n + img->super.a) * 2; i++)
+ img->decode[i] = i & 1;
+
+printf(" cs %s\n", cs ? cs->name : "(null)");
+printf(" mask %d\n", ismask);
+printf(" decode [ ");
+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));
+ if (error)
+ {
+ /* TODO: colorspace? */
+ fz_free(img);
+ 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)
+ {
+ /* TODO: colorspace? */
+ fz_freebuffer(img->data);
+ fz_free(img);
+ return fz_throw("syntaxerror: truncated image data");
+ }
+
*imgp = img;
return nil;
diff --git a/mupdf/interpret.c b/mupdf/interpret.c
index f9179792..ed8fff07 100644
--- a/mupdf/interpret.c
+++ b/mupdf/interpret.c
@@ -544,6 +544,32 @@ runkeyword(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, char *buf)
if (error) return error;
}
+ else if (!strcmp(buf, "Do"))
+ {
+ fz_obj *dict;
+ fz_obj *obj;
+ pdf_image *img;
+
+ if (csi->top != 1)
+ goto syntaxerror;
+
+ dict = fz_dictgets(rdb, "XObject");
+ if (!dict)
+ return fz_throw("syntaxerror: missing xobject resource");
+
+ obj = fz_dictget(dict, csi->stack[0]);
+ if (!obj)
+ return fz_throw("syntaxerror: missing xobject resource");
+
+ img = pdf_findresource(xref->rimage, obj);
+ if (!img)
+ return fz_throw("syntaxerror: missing image resource");
+
+ error = pdf_showimage(csi, img);
+ if (error)
+ return error;
+ }
+
else
fprintf(stderr, "syntaxerror: unknown keyword '%s'\n", buf);
//return fz_throw("syntaxerror: unknown keyword '%s'", buf);
diff --git a/mupdf/resources.c b/mupdf/resources.c
index f859566f..a9ab1b7e 100644
--- a/mupdf/resources.c
+++ b/mupdf/resources.c
@@ -122,7 +122,7 @@ preloadxobject(pdf_xref *xref, fz_obj *ref)
else if (!strcmp(fz_toname(subtype), "Image"))
{
- error = pdf_loadimage((pdf_image**)&rsrc->val, xref, obj);
+ error = pdf_loadimage((pdf_image**)&rsrc->val, xref, obj, ref);
fz_dropobj(obj);
if (error) {
fz_free(rsrc);
diff --git a/render/render.c b/render/render.c
index 29b51480..d77c0c9d 100644
--- a/render/render.c
+++ b/render/render.c
@@ -80,8 +80,6 @@ fz_rendercolor(fz_renderer *gc, fz_colornode *color, fz_matrix ctm)
gc->g = rgb[1] * 255;
gc->b = rgb[2] * 255;
-puts("render color");
-
error = fz_newpixmap(&gc->tmp, color->cs, gc->x, gc->y, gc->w, gc->h, 3, 1);
if (error)
return error;
diff --git a/render/renderimage.c b/render/renderimage.c
index 4c6ef816..15eda833 100644
--- a/render/renderimage.c
+++ b/render/renderimage.c
@@ -1,27 +1,91 @@
#include <fitz.h>
-static int cmpy(const void *a, const void *b)
+static inline void
+drawscan(fz_matrix *invmat, fz_pixmap *dst, fz_pixmap *src, int y, int x0, int x1)
{
- const fz_point *ap = a;
- const fz_point *bp = b;
- return bp->y - ap->y;
+ 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;
+
+ 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;
+ }
+
+ u += du;
+ v += dv;
+ }
}
-static void
-drawtile(fz_pixmap *out, fz_pixmap *tile, fz_matrix ctm)
+static fz_error *
+drawtile(fz_renderer *gc, fz_pixmap *out, fz_pixmap *tile, fz_matrix ctm)
{
static const fz_point rect[4] = { {0, 0}, {0, 1}, {1, 1}, {1, 0} };
+ fz_error *error;
+ fz_gel *gel = gc->gel;
+ fz_ael *ael = gc->ael;
+ fz_matrix imgmat;
+ fz_matrix invmat;
fz_point v[4];
- int i;
+ int i, e, y, x0, x1;
+
+ imgmat.a = 1.0 / tile->w;
+ imgmat.b = 0.0;
+ imgmat.c = 0.0;
+ imgmat.d = -1.0 / tile->h;
+ imgmat.e = 0.0;
+ imgmat.f = 1.0;
+ invmat = fz_invertmatrix(fz_concat(imgmat, ctm));
for (i = 0; i < 4; i++)
v[i] = fz_transformpoint(ctm, rect[i]);
+ fz_resetgel(gel, 1, 1);
+ fz_insertgel(gel, v[0].x, v[0].y, v[1].x, v[1].y);
+ fz_insertgel(gel, v[1].x, v[1].y, v[2].x, v[2].y);
+ fz_insertgel(gel, v[2].x, v[2].y, v[3].x, v[3].y);
+ fz_insertgel(gel, v[3].x, v[3].y, v[0].x, v[0].y);
+ fz_sortgel(gel);
- qsort(v, 4, sizeof(fz_point), cmpy);
+ e = 0;
+ y = gel->edges[0].y;
- for (i = 0; i < 4; i++)
- printf("%d: %g %g\n", i, v[i].x, v[i].y);
+ while (ael->len > 0 || e < gel->len)
+ {
+ error = fz_insertael(ael, gel, y, &e);
+ if (error)
+ return error;
+ x0 = ael->edges[0]->x;
+ x1 = ael->edges[ael->len - 1]->x;
+ drawscan(&invmat, out, tile, y, x0, x1);
+
+ fz_advanceael(ael);
+
+ if (ael->len > 0)
+ y ++;
+ else if (e < gel->len)
+ y = gel->edges[e].y;
+ }
+
+ return nil;
}
fz_error *
@@ -43,11 +107,18 @@ fz_renderimage(fz_renderer *gc, fz_imagenode *node, fz_matrix ctm)
if (error)
goto cleanup;
+ fz_clearpixmap(gc->tmp);
+
error = image->loadtile(image, tile);
if (error)
goto cleanup;
- drawtile(gc->tmp, tile, ctm);
+ error = drawtile(gc, gc->tmp, tile, ctm);
+ if (error)
+ goto cleanup;
+
+printf("loadtile "); fz_debugpixmap(tile); getchar();
+//printf("drawtile "); fz_debugpixmap(gc->tmp); getchar();
fz_freepixmap(tile);
return nil;
diff --git a/render/stroke.c b/render/stroke.c
index cd4f5a13..2527e6ad 100644
--- a/render/stroke.c
+++ b/render/stroke.c
@@ -469,7 +469,7 @@ fz_strokepath(fz_gel *gel, fz_pathnode *path, fz_matrix ctm, float flatness)
s.linecap = path->linecap;
s.linejoin = path->linejoin;
- s.linewidth = path->linewidth;
+ s.linewidth = path->linewidth * 0.5;
s.miterlimit = path->miterlimit;
s.sn = 0;
s.bn = 0;
@@ -664,7 +664,7 @@ fz_dashpath(fz_gel *gel, fz_pathnode *path, fz_matrix ctm, float flatness)
s.linecap = path->linecap;
s.linejoin = path->linejoin;
- s.linewidth = path->linewidth;
+ s.linewidth = path->linewidth * 0.5;
s.miterlimit = path->miterlimit;
s.sn = 0;
s.bn = 0;