diff options
-rw-r--r-- | include/mupdf/rsrc.h | 2 | ||||
-rw-r--r-- | mupdf/colorspace.c | 381 | ||||
-rw-r--r-- | mupdf/function.c | 6 | ||||
-rw-r--r-- | mupdf/interpret.c | 4 | ||||
-rw-r--r-- | render/renderimage.c | 36 | ||||
-rw-r--r-- | test/pdffunction.c | 2 |
6 files changed, 259 insertions, 172 deletions
diff --git a/include/mupdf/rsrc.h b/include/mupdf/rsrc.h index 20df27e7..4b656910 100644 --- a/include/mupdf/rsrc.h +++ b/include/mupdf/rsrc.h @@ -22,7 +22,7 @@ typedef struct pdf_function_s pdf_function; fz_error *pdf_loadfunction(pdf_function **func, pdf_xref *xref, fz_obj *obj); fz_error *pdf_evalfunction(pdf_function *func, float *in, int inlen, float *out, int outlen); -void pdf_freefunc(pdf_function *func); +void pdf_freefunction(pdf_function *func); /* * ColorSpace diff --git a/mupdf/colorspace.c b/mupdf/colorspace.c index 3511dc91..85fdc283 100644 --- a/mupdf/colorspace.c +++ b/mupdf/colorspace.c @@ -112,6 +112,45 @@ newcalgray(fz_colorspace **csp, float *white, float *black, float gamma) return nil; } +static fz_error * +loadcalgray(fz_colorspace **csp, pdf_xref *xref, fz_obj *dict) +{ + fz_obj *tmp; + + float white[3]; + float black[3]; + float gamma; + + tmp = fz_dictgets(dict, "WhitePoint"); + if (!fz_isarray(tmp)) + return fz_throw("syntaxerror: CalGray missing WhitePoint"); + white[0] = fz_toreal(fz_arrayget(tmp, 0)); + white[1] = fz_toreal(fz_arrayget(tmp, 1)); + white[2] = fz_toreal(fz_arrayget(tmp, 2)); + + tmp = fz_dictgets(dict, "BlackPoint"); + if (fz_isarray(tmp)) + { + black[0] = fz_toreal(fz_arrayget(tmp, 0)); + black[1] = fz_toreal(fz_arrayget(tmp, 1)); + black[2] = fz_toreal(fz_arrayget(tmp, 2)); + } + else + { + black[0] = 0.0; + black[1] = 0.0; + black[2] = 0.0; + } + + tmp = fz_dictgets(dict, "Gamma"); + if (fz_isreal(tmp)) + gamma = fz_toreal(tmp); + else + gamma = 1.0; + + return newcalgray(csp, white, black, gamma); +} + /* * DeviceRGB */ @@ -192,6 +231,68 @@ newcalrgb(fz_colorspace **csp, float *white, float *black, float *gamma, float * return nil; } +static fz_error * +loadcalrgb(fz_colorspace **csp, pdf_xref *xref, fz_obj *dict) +{ + fz_obj *tmp; + + float white[3]; + float black[3]; + float gamma[3]; + float matrix[9]; + + tmp = fz_dictgets(dict, "WhitePoint"); + if (!fz_isarray(tmp)) + return fz_throw("syntaxerror: CalRGB missing White"); + white[0] = fz_toreal(fz_arrayget(tmp, 0)); + white[1] = fz_toreal(fz_arrayget(tmp, 1)); + white[2] = fz_toreal(fz_arrayget(tmp, 2)); + + tmp = fz_dictgets(dict, "BlackPoint"); + if (fz_isarray(tmp)) + { + black[0] = fz_toreal(fz_arrayget(tmp, 0)); + black[1] = fz_toreal(fz_arrayget(tmp, 1)); + black[2] = fz_toreal(fz_arrayget(tmp, 2)); + } + else + { + black[0] = 0.0; + black[1] = 0.0; + black[2] = 0.0; + } + + tmp = fz_dictgets(dict, "Gamma"); + if (fz_isarray(tmp)) + { + gamma[0] = fz_toreal(fz_arrayget(tmp, 0)); + gamma[1] = fz_toreal(fz_arrayget(tmp, 1)); + gamma[2] = fz_toreal(fz_arrayget(tmp, 2)); + } + else + { + gamma[0] = 1.0; + gamma[1] = 1.0; + gamma[2] = 1.0; + } + + tmp = fz_dictgets(dict, "Matrix"); + if (fz_isarray(tmp)) + { + int i; + for (i = 0; i < 9; i++) + matrix[i] = fz_toreal(fz_arrayget(tmp, i)); + } + else + { + matrix[0] = 1.0; matrix[1] = 0.0; matrix[2] = 0.0; + matrix[3] = 0.0; matrix[4] = 1.0; matrix[5] = 0.0; + matrix[6] = 0.0; matrix[7] = 0.0; matrix[8] = 1.0; + } + + return newcalrgb(csp, white, black, gamma, matrix); +} + /* * DeviceCMYK */ @@ -252,7 +353,7 @@ static inline float cielabinvg(float x) return (7.787 * x) + (16.0 / 116.0); } -static void labtoxyz(fz_colorspace *fzcs, float *xyz, float *lab) +static void labtoxyz(fz_colorspace *fzcs, float *lab, float *xyz) { struct cielab *cs = (struct cielab *) fzcs; float lstar = lab[0]; @@ -303,8 +404,57 @@ newlab(fz_colorspace **csp, float *white, float *black, float *range) return nil; } +static fz_error * +loadlab(fz_colorspace **csp, pdf_xref *xref, fz_obj *dict) +{ + fz_obj *tmp; + + float white[3]; + float black[3]; + float range[4]; + + tmp = fz_dictgets(dict, "WhitePoint"); + if (!fz_isarray(tmp)) + return fz_throw("syntaxerror: Lab missing WhitePoint"); + white[0] = fz_toreal(fz_arrayget(tmp, 0)); + white[1] = fz_toreal(fz_arrayget(tmp, 1)); + white[2] = fz_toreal(fz_arrayget(tmp, 2)); + + tmp = fz_dictgets(dict, "BlackPoint"); + if (fz_isarray(tmp)) + { + black[0] = fz_toreal(fz_arrayget(tmp, 0)); + black[1] = fz_toreal(fz_arrayget(tmp, 1)); + black[2] = fz_toreal(fz_arrayget(tmp, 2)); + } + else + { + black[0] = 0.0; + black[1] = 0.0; + black[2] = 0.0; + } + + tmp = fz_dictgets(dict, "Range"); + if (fz_isarray(tmp)) + { + range[0] = fz_toreal(fz_arrayget(tmp, 0)); + range[1] = fz_toreal(fz_arrayget(tmp, 1)); + range[2] = fz_toreal(fz_arrayget(tmp, 2)); + range[3] = fz_toreal(fz_arrayget(tmp, 3)); + } + else + { + range[0] = -100; + range[1] = 100; + range[2] = -100; + range[3] = 100; + } + + return newlab(csp, white, black, range); +} + /* - * Load from PDF + * ICCBased */ static fz_error * @@ -333,6 +483,79 @@ loadiccbased(fz_colorspace **csp, pdf_xref *xref, fz_obj *ref) } /* + * Separation + */ + +struct separation +{ + fz_colorspace super; + fz_colorspace *base; + pdf_function *tint; +}; + +static void separationtoxyz(fz_colorspace *fzcs, float *sep, float *xyz) +{ + struct separation *cs = (struct separation *)fzcs; + fz_error *error; + float alt[32]; + + error = pdf_evalfunction(cs->tint, sep, 1, alt, cs->base->n); + if (error) + { + fz_warn("separation: %s", error->msg); + fz_freeerror(error); + xyz[0] = 0; + xyz[1] = 0; + xyz[2] = 0; + return; + } + + cs->base->toxyz(cs->base, alt, xyz); +} + +fz_error * +loadseparation(fz_colorspace **csp, pdf_xref *xref, fz_obj *array) +{ + fz_error *error; + struct separation *sep; + fz_obj *baseobj = fz_arrayget(array, 2); + fz_obj *tintobj = fz_arrayget(array, 3); + fz_colorspace *base; + pdf_function *tint; + + error = pdf_resolve(&baseobj, xref); + if (error) + return error; + error = pdf_loadcolorspace(&base, xref, baseobj); + fz_dropobj(baseobj); + if (error) + return error; + + error = pdf_loadfunction(&tint, xref, tintobj); + if (error) + { + fz_freecolorspace(base); + return error; + } + + sep = fz_malloc(sizeof(struct separation)); + if (!sep) + { + pdf_freefunction(tint); + fz_freecolorspace(base); + return fz_outofmem; + } + + initcs((fz_colorspace*)sep, "Separation", 1, separationtoxyz, nil, nil); + + sep->base = base; + sep->tint = tint; + + *csp = (fz_colorspace*)sep; + return nil; +} + +/* * Parse and create colorspace from PDF object. */ @@ -371,105 +594,10 @@ printf("\n"); if (fz_isname(name)) { if (!strcmp(fz_toname(name), "CalGray")) - { - fz_obj *dict = fz_arrayget(obj, 1); - fz_obj *tmp; - - float white[3]; - float black[3]; - float gamma; - - tmp = fz_dictgets(dict, "WhitePoint"); - if (!fz_isarray(tmp)) - return fz_throw("syntaxerror: CalGray missing WhitePoint"); - white[0] = fz_toreal(fz_arrayget(tmp, 0)); - white[1] = fz_toreal(fz_arrayget(tmp, 1)); - white[2] = fz_toreal(fz_arrayget(tmp, 2)); - - tmp = fz_dictgets(dict, "BlackPoint"); - if (fz_isarray(tmp)) - { - black[0] = fz_toreal(fz_arrayget(tmp, 0)); - black[1] = fz_toreal(fz_arrayget(tmp, 1)); - black[2] = fz_toreal(fz_arrayget(tmp, 2)); - } - else - { - black[0] = 0.0; - black[1] = 0.0; - black[2] = 0.0; - } - - tmp = fz_dictgets(dict, "Gamma"); - if (fz_isreal(tmp)) - gamma = fz_toreal(tmp); - else - gamma = 1.0; - - return newcalgray(csp, white, black, gamma); - } + return loadcalgray(csp, xref, fz_arrayget(obj, 1)); if (!strcmp(fz_toname(name), "CalRGB")) - { - fz_obj *dict = fz_arrayget(obj, 1); - fz_obj *tmp; - - float white[3]; - float black[3]; - float gamma[3]; - float matrix[9]; - - tmp = fz_dictgets(dict, "WhitePoint"); - if (!fz_isarray(tmp)) - return fz_throw("syntaxerror: CalRGB missing White"); - white[0] = fz_toreal(fz_arrayget(tmp, 0)); - white[1] = fz_toreal(fz_arrayget(tmp, 1)); - white[2] = fz_toreal(fz_arrayget(tmp, 2)); - - tmp = fz_dictgets(dict, "BlackPoint"); - if (fz_isarray(tmp)) - { - black[0] = fz_toreal(fz_arrayget(tmp, 0)); - black[1] = fz_toreal(fz_arrayget(tmp, 1)); - black[2] = fz_toreal(fz_arrayget(tmp, 2)); - } - else - { - black[0] = 0.0; - black[1] = 0.0; - black[2] = 0.0; - } - - tmp = fz_dictgets(dict, "Gamma"); - if (fz_isarray(tmp)) - { - gamma[0] = fz_toreal(fz_arrayget(tmp, 0)); - gamma[1] = fz_toreal(fz_arrayget(tmp, 1)); - gamma[2] = fz_toreal(fz_arrayget(tmp, 2)); - } - else - { - gamma[0] = 1.0; - gamma[1] = 1.0; - gamma[2] = 1.0; - } - - tmp = fz_dictgets(dict, "Matrix"); - if (fz_isarray(tmp)) - { - int i; - for (i = 0; i < 9; i++) - matrix[i] = fz_toreal(fz_arrayget(tmp, i)); - } - else - { - matrix[0] = 1.0; matrix[1] = 0.0; matrix[2] = 0.0; - matrix[3] = 0.0; matrix[4] = 1.0; matrix[5] = 0.0; - matrix[6] = 0.0; matrix[7] = 0.0; matrix[8] = 1.0; - } - - return newcalrgb(csp, white, black, gamma, matrix); - } + return loadcalrgb(csp, xref, fz_arrayget(obj, 1)); if (!strcmp(fz_toname(name), "CalCMYK")) { @@ -478,64 +606,13 @@ printf("\n"); } if (!strcmp(fz_toname(name), "Lab")) - { - fz_obj *dict = fz_arrayget(obj, 1); - fz_obj *tmp; - - float white[3]; - float black[3]; - float range[4]; - - tmp = fz_dictgets(dict, "WhitePoint"); - if (!fz_isarray(tmp)) - return fz_throw("syntaxerror: Lab missing WhitePoint"); - white[0] = fz_toreal(fz_arrayget(tmp, 0)); - white[1] = fz_toreal(fz_arrayget(tmp, 1)); - white[2] = fz_toreal(fz_arrayget(tmp, 2)); - - tmp = fz_dictgets(dict, "BlackPoint"); - if (fz_isarray(tmp)) - { - black[0] = fz_toreal(fz_arrayget(tmp, 0)); - black[1] = fz_toreal(fz_arrayget(tmp, 1)); - black[2] = fz_toreal(fz_arrayget(tmp, 2)); - } - else - { - black[0] = 0.0; - black[1] = 0.0; - black[2] = 0.0; - } - - tmp = fz_dictgets(dict, "Range"); - if (fz_isarray(tmp)) - { - range[0] = fz_toreal(fz_arrayget(tmp, 0)); - range[1] = fz_toreal(fz_arrayget(tmp, 1)); - range[2] = fz_toreal(fz_arrayget(tmp, 2)); - range[3] = fz_toreal(fz_arrayget(tmp, 3)); - } - else - { - range[0] = -100; - range[1] = 100; - range[2] = -100; - range[3] = 100; - } - - return newlab(csp, white, black, range); - } + return loadlab(csp, xref, fz_arrayget(obj, 1)); if (!strcmp(fz_toname(name), "ICCBased")) - { return loadiccbased(csp, xref, fz_arrayget(obj, 1)); - } if (!strcmp(fz_toname(name), "Separation")) - { - *csp = pdf_devicegray; - return nil; - } + return loadseparation(csp, xref, obj); } } diff --git a/mupdf/function.c b/mupdf/function.c index 6ec76e66..fb71da89 100644 --- a/mupdf/function.c +++ b/mupdf/function.c @@ -1385,7 +1385,7 @@ cleanup: } void -pdf_freefunc(pdf_function *func) +pdf_freefunction(pdf_function *func) { int i; @@ -1417,7 +1417,7 @@ pdf_freefunc(pdf_function *func) fz_free(func->u.st.encode); if(func->u.st.funcs) { for(i = 0; i < func->u.st.k; ++i) - pdf_freefunc(func->u.st.funcs[i]); + pdf_freefunction(func->u.st.funcs[i]); fz_free(func->u.st.funcs); } @@ -1541,7 +1541,7 @@ cleanup: if(objfunc) fz_dropobj(objfunc); - pdf_freefunc(newfunc); + pdf_freefunction(newfunc); if(err) return err; return fz_throw("syntaxerror : "); diff --git a/mupdf/interpret.c b/mupdf/interpret.c index 2d2b9a42..eb9f60e0 100644 --- a/mupdf/interpret.c +++ b/mupdf/interpret.c @@ -329,6 +329,8 @@ runkeyword(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, char *buf) if (!gstate->fillcs) return fz_throw("syntaxerror: missing colorspace resource"); } + + // FIXME set default color } else if (!strcmp(buf, "CS")) @@ -365,6 +367,8 @@ runkeyword(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, char *buf) if (!gstate->strokecs) return fz_throw("syntaxerror: missing colorspace resource"); } + + // FIXME set default color } else if (!strcmp(buf, "sc") || !strcmp(buf, "scn")) diff --git a/render/renderimage.c b/render/renderimage.c index 80b7b771..a89409c5 100644 --- a/render/renderimage.c +++ b/render/renderimage.c @@ -5,23 +5,28 @@ void fz_gammapixmap(fz_pixmap *pix, float gamma); #define LERP(a,b,t) (a + (((b - a) * t) >> 16)) +#define OUTSIDE(x,a,b) (x < a || x >= b) -static int getcomp(fz_pixmap *pix, int u, int v, int k) +static inline int getcomp(fz_pixmap *pix, int u, int v, int k) +{ + if (u < 0 || u >= pix->w) + return 0; + if (v < 0 || v >= pix->h) + return 0; + return pix->samples[ (v * pix->w + u) * pix->n + k ]; +} + +static inline int sampleimage(fz_pixmap *pix, int u, int v, int k) { int ui = u >> 16; int vi = v >> 16; int ud = u & 0xFFFF; int vd = v & 0xFFFF; - int x0 = CLAMP(ui, 0, pix->w - 1); - int x1 = CLAMP(ui + 1, 0, pix->w - 1); - int y0 = CLAMP(vi, 0, pix->h - 1); - int y1 = CLAMP(vi + 1, 0, pix->h - 1); - - int a = pix->samples[ (y0 * pix->w + x0) * pix->n + k ]; - int b = pix->samples[ (y0 * pix->w + x1) * pix->n + k ]; - int c = pix->samples[ (y1 * pix->w + x0) * pix->n + k ]; - int d = pix->samples[ (y1 * pix->w + x1) * pix->n + k ]; + int a = getcomp(pix, ui, vi, k); + int b = getcomp(pix, ui + 1, vi, k); + int c = getcomp(pix, ui, vi + 1, k); + int d = getcomp(pix, ui + 1, vi + 1, k); int ab = LERP(a, b, ud); int cd = LERP(c, d, ud); @@ -41,7 +46,8 @@ drawscan(fz_matrix *invmat, fz_pixmap *dst, fz_pixmap *src, int y, int x0, int x for (x = x0; x < x1; x++) { for (k = 0; k < src->n; k++) - dst->samples[ (y * dst->w + x) * dst->n + k ] = getcomp(src, u, v, k); + dst->samples[ (y * dst->w + x) * dst->n + k ] + = sampleimage(src, u, v, k); u += du; v += dv; } @@ -59,10 +65,10 @@ overscanrgb(fz_matrix *invmat, fz_pixmap *dst, fz_pixmap *src, int y, int x0, in for (x = x0; x < x1; x++) { - int sa = getcomp(src, u, v, 0); - int sr = getcomp(src, u, v, 1); - int sg = getcomp(src, u, v, 2); - int sb = getcomp(src, u, v, 3); + int sa = sampleimage(src, u, v, 0); + int sr = sampleimage(src, u, v, 1); + int sg = sampleimage(src, u, v, 2); + int sb = sampleimage(src, u, v, 3); int da = dst->samples[ (y * dst->w + x) * dst->n + 0 ]; int dr = dst->samples[ (y * dst->w + x) * dst->n + 1 ]; diff --git a/test/pdffunction.c b/test/pdffunction.c index d2acd691..c67e60d7 100644 --- a/test/pdffunction.c +++ b/test/pdffunction.c @@ -243,7 +243,7 @@ int main(int argc, char **argv) fprintf(stderr, "output[%d] : %f\n", i, out[i]); fz_dropobj(funcobj); - pdf_freefunc(func); + pdf_freefunction(func); } } |