summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2017-10-16 13:44:52 +0100
committerRobin Watts <robin.watts@artifex.com>2017-10-24 15:16:36 +0100
commitc413f4db6a54846ae85393a87fa1b53b93a966ee (patch)
tree3a06363e8f0570cc139e8cf486f2d9b00c0c52cd
parentc7c407b57a6e1aa5b1a11034ec7cb308cf4ad3c4 (diff)
downloadmupdf-c413f4db6a54846ae85393a87fa1b53b93a966ee.tar.xz
Add support for use of proofing profile.
This is a first cut to get us to demo-ability. There will likely be a few changes as we do a bit more testing with different scenarios with Gray, RGB, CMYK combos of destination, proof and output intent ICC profiles.
-rw-r--r--include/mupdf/fitz/device.h34
-rw-r--r--source/fitz/draw-device.c61
-rw-r--r--source/fitz/separation.c13
-rw-r--r--source/tools/mudraw.c26
4 files changed, 97 insertions, 37 deletions
diff --git a/include/mupdf/fitz/device.h b/include/mupdf/fitz/device.h
index 891f3aad..549ae9be 100644
--- a/include/mupdf/fitz/device.h
+++ b/include/mupdf/fitz/device.h
@@ -339,6 +339,40 @@ fz_device *fz_new_draw_device(fz_context *ctx, const fz_matrix *transform, fz_pi
*/
fz_device *fz_new_draw_device_with_bbox(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest, const fz_irect *clip);
+/*
+ fz_new_draw_device_with_proof: Create a device to draw on a pixmap.
+
+ dest: Target pixmap for the draw device. See fz_new_pixmap*
+ for how to obtain a pixmap. The pixmap is not cleared by the
+ draw device, see fz_clear_pixmap* for how to clear it prior to
+ calling fz_new_draw_device. Free the device by calling
+ fz_drop_device.
+
+ transform: Transform from user space in points to device space in pixels.
+
+ proof_cs: Intermediate color space to map though when mapping to
+ color space defined by pixmap.
+*/
+fz_device *fz_new_draw_device_with_proof(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest, fz_colorspace *proof_cs);
+
+/*
+ fz_new_draw_device_with_bbox_proof: Create a device to draw on a pixmap.
+
+ dest: Target pixmap for the draw device. See fz_new_pixmap*
+ for how to obtain a pixmap. The pixmap is not cleared by the
+ draw device, see fz_clear_pixmap* for how to clear it prior to
+ calling fz_new_draw_device. Free the device by calling
+ fz_drop_device.
+
+ transform: Transform from user space in points to device space in pixels.
+
+ clip: Bounding box to restrict any marking operations of the
+ draw device.
+
+ proof_cs: Color space to render to prior to mapping to color space defined by pixmap.
+*/
+fz_device *fz_new_draw_device_with_bbox_proof(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest, const fz_irect *clip, fz_colorspace *cs);
+
fz_device *fz_new_draw_device_type3(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest);
/*
diff --git a/source/fitz/draw-device.c b/source/fitz/draw-device.c
index ff6097fb..64de42ae 100644
--- a/source/fitz/draw-device.c
+++ b/source/fitz/draw-device.c
@@ -46,6 +46,7 @@ struct fz_draw_device_s
fz_matrix transform;
fz_rasterizer *rast;
fz_default_colorspaces *default_cs;
+ fz_colorspace *proof_cs;
int flags;
int resolve_spots;
int top;
@@ -114,21 +115,6 @@ static void stack_change(fz_context *ctx, fz_draw_device *dev, char *s)
#define STACK_CONVERT(A) do {} while (0)
#endif
-/* Based upon the existence of a proof color space, and if we happen to be
- * in a color space that is our target color space or a transparency group
- * color space decide if we should be using the proof color space at this time */
-static fz_colorspace *
-fz_proof_cs(fz_context *ctx, fz_draw_device *dev)
-{
- fz_colorspace *prf = fz_default_output_intent(ctx, dev->default_cs);
- fz_draw_state *state = &dev->stack[dev->top];
- fz_colorspace *model = state->dest->colorspace;
-
- if (prf == NULL || model == prf)
- return NULL;
- return prf;
-}
-
/* Logic below assumes that default cs is set to color context cs if there
* was not a default in the document for that particular cs
*/
@@ -510,9 +496,24 @@ static fz_draw_state *
push_group_for_separations(fz_context *ctx, fz_draw_device *dev, const fz_color_params *color_params, fz_default_colorspaces *default_cs)
{
fz_separations *clone = fz_clone_separations_for_overprint(ctx, dev->stack[0].dest->seps);
+ fz_colorspace *oi = fz_default_output_intent(ctx, default_cs);
+ fz_colorspace *dcs = fz_device_cmyk(ctx);
+
+ /* Pick sep target CMYK based upon proof and output intent settings. Priority
+ * is oi, proof, devicecmyk. */
+ /* FIXME: Look into non-CMYK proofing profiles */
+ if (dev->proof_cs && fz_colorspace_n(ctx, dev->proof_cs) == 4)
+ {
+ dcs = dev->proof_cs;
+ }
+ /* FIXME : We need to create a file with an RGB output intent at some point and test a few things */
+ if (oi && fz_colorspace_n(ctx, oi) == 4)
+ {
+ dcs = oi;
+ }
/* Not needed */
- if (clone == NULL)
+ if (clone == NULL && dev->proof_cs == NULL)
{
dev->resolve_spots = 0;
return &dev->stack[0];
@@ -523,7 +524,7 @@ push_group_for_separations(fz_context *ctx, fz_draw_device *dev, const fz_color_
{
dev->stack[1] = dev->stack[0];
dev->stack[1].dest = NULL; /* So we are safe to destroy */
- dev->stack[1].dest = fz_clone_pixmap_area_with_different_seps(ctx, dev->stack[0].dest, &dev->stack[0].scissor, fz_device_cmyk(ctx), clone, color_params, default_cs);
+ dev->stack[1].dest = fz_clone_pixmap_area_with_different_seps(ctx, dev->stack[0].dest, &dev->stack[0].scissor, dcs, clone, color_params, default_cs);
dev->top++;
}
fz_always(ctx)
@@ -1641,6 +1642,7 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
if (dev->top == 0 && dev->resolve_spots)
state = push_group_for_separations(ctx, dev, color_params, dev->default_cs);
+ model = state->dest->colorspace;
model = state->dest->colorspace;
@@ -2817,7 +2819,6 @@ static void
fz_draw_close_device(fz_context *ctx, fz_device *devp)
{
fz_draw_device *dev = (fz_draw_device*)devp;
- fz_colorspace *prf = fz_proof_cs(ctx, dev);
/* pop and free the stacks */
if (dev->top > dev->resolve_spots)
@@ -2839,7 +2840,7 @@ fz_draw_close_device(fz_context *ctx, fz_device *devp)
if (dev->resolve_spots && dev->top)
{
fz_draw_state *state = &dev->stack[--dev->top];
- fz_copy_pixmap_area_converting_seps(ctx, state[0].dest, state[1].dest, fz_default_color_params(ctx)/* FIXME */, prf, dev->default_cs);
+ fz_copy_pixmap_area_converting_seps(ctx, state[0].dest, state[1].dest, fz_default_color_params(ctx)/* FIXME */, dev->proof_cs, dev->default_cs);
fz_drop_pixmap(ctx, state[1].dest);
assert(state[1].mask == NULL);
assert(state[1].shape == NULL);
@@ -2854,6 +2855,7 @@ fz_draw_drop_device(fz_context *ctx, fz_device *devp)
fz_rasterizer *rast = dev->rast;
fz_drop_default_colorspaces(ctx, dev->default_cs);
+ fz_drop_colorspace(ctx, dev->proof_cs);
/* pop and free the stacks */
if (dev->top > 0)
@@ -2884,7 +2886,7 @@ fz_draw_drop_device(fz_context *ctx, fz_device *devp)
}
fz_device *
-new_draw_device(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest, const fz_aa_context *aa, const fz_irect *clip)
+new_draw_device(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest, const fz_aa_context *aa, const fz_irect *clip, fz_colorspace *proof_cs)
{
fz_draw_device *dev = fz_new_derived_device(ctx, fz_draw_device);
@@ -2920,6 +2922,7 @@ new_draw_device(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest, co
dev->super.render_flags = fz_draw_render_flags;
dev->super.set_default_colorspaces = fz_draw_set_default_colorspaces;
+ dev->proof_cs = fz_keep_colorspace(ctx, proof_cs);
dev->transform = transform ? *transform : fz_identity;
dev->flags = 0;
dev->resolve_spots = 0;
@@ -2965,7 +2968,7 @@ new_draw_device(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest, co
* the default_colorspaces etc are, so set a flag for us
* to trigger on later.
*/
- if (dest->seps)
+ if (dest->seps || dev->proof_cs != NULL)
#ifdef FZ_ENABLE_SPOT_RENDERING
dev->resolve_spots = 1;
#else
@@ -2990,13 +2993,25 @@ new_draw_device(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest, co
fz_device *
fz_new_draw_device(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest)
{
- return new_draw_device(ctx, transform, dest, NULL, NULL);
+ return new_draw_device(ctx, transform, dest, NULL, NULL, NULL);
}
fz_device *
fz_new_draw_device_with_bbox(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest, const fz_irect *clip)
{
- return new_draw_device(ctx, transform, dest, NULL, clip);
+ return new_draw_device(ctx, transform, dest, NULL, clip, NULL);
+}
+
+fz_device *
+fz_new_draw_device_with_proof(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest, fz_colorspace *cs)
+{
+ return new_draw_device(ctx, transform, dest, NULL, NULL, cs);
+}
+
+fz_device *
+fz_new_draw_device_with_bbox_proof(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest, const fz_irect *clip, fz_colorspace *cs)
+{
+ return new_draw_device(ctx, transform, dest, NULL, clip, cs);
}
fz_device *
diff --git a/source/fitz/separation.c b/source/fitz/separation.c
index ba3ab96e..5f8fee41 100644
--- a/source/fitz/separation.c
+++ b/source/fitz/separation.c
@@ -242,10 +242,6 @@ fz_clone_pixmap_area_with_different_seps(fz_context *ctx, fz_pixmap *src, const
{
fz_irect local_bbox;
fz_pixmap *dst;
- fz_colorspace *oi = fz_default_output_intent(ctx, default_cs);
-
- if (fz_colorspace_n(ctx, dcs) == fz_colorspace_n(ctx, oi))
- dcs = oi;
if (bbox == NULL)
{
@@ -291,6 +287,7 @@ fz_copy_pixmap_area_converting_seps(fz_context *ctx, fz_pixmap *dst, fz_pixmap *
unsigned char mapped[FZ_MAX_COLORS];
int unmapped = sseps_n;
int device_n = 0;
+ fz_colorspace *proof_cs = (prf == src->colorspace ? NULL : prf);
assert(da == sa);
assert(ss == fz_count_active_separations(ctx, sseps));
@@ -300,7 +297,7 @@ fz_copy_pixmap_area_converting_seps(fz_context *ctx, fz_pixmap *dst, fz_pixmap *
sstride -= sn * dw;
/* Process colorants first */
- if (dst->colorspace == src->colorspace)
+ if (dst->colorspace == src->colorspace && proof_cs == NULL)
{
/* Simple copy */
unsigned char *dd = ddata;
@@ -327,7 +324,7 @@ fz_copy_pixmap_area_converting_seps(fz_context *ctx, fz_pixmap *dst, fz_pixmap *
{
fz_pixmap_converter *pc = fz_lookup_pixmap_converter(ctx, dst->colorspace, src->colorspace);
- pc(ctx, dst, src, prf, default_cs, NULL, 0);
+ pc(ctx, dst, src, proof_cs, default_cs, NULL, 0);
}
}
@@ -398,7 +395,7 @@ fz_copy_pixmap_area_converting_seps(fz_context *ctx, fz_pixmap *dst, fz_pixmap *
if (mapped[i])
continue;
/* Src spot i is not mapped. We need to convert that down. */
- fz_separation_equivalent(ctx, sseps, i, color_params, dst->colorspace, prf, convert);
+ fz_separation_equivalent(ctx, sseps, i, color_params, dst->colorspace, proof_cs, convert);
if (fz_colorspace_is_subtractive(ctx, dst->colorspace))
{
@@ -491,7 +488,7 @@ fz_copy_pixmap_area_converting_seps(fz_context *ctx, fz_pixmap *dst, fz_pixmap *
int n = fz_colorspace_n(ctx, src->colorspace);
fz_color_converter cc;
- fz_find_color_converter(ctx, &cc, prf, dst->colorspace, src->colorspace, color_params);
+ fz_find_color_converter(ctx, &cc, proof_cs, dst->colorspace, src->colorspace, color_params);
fz_try(ctx)
{
diff --git a/source/tools/mudraw.c b/source/tools/mudraw.c
index 8f3547b7..6382e95c 100644
--- a/source/tools/mudraw.c
+++ b/source/tools/mudraw.c
@@ -246,6 +246,8 @@ static int alphabits_text = 8;
static int alphabits_graphics = 8;
static int out_cs = CS_UNSET;
+static const char *proof_filename = NULL;
+fz_colorspace *proof_cs = NULL;
static const char *icc_filename = NULL;
static float gamma_value = 1;
static int invert = 0;
@@ -333,7 +335,8 @@ static void usage(void)
"\t-U -\tfile name of user stylesheet for EPUB layout\n"
"\t-X\tdisable document styles for EPUB layout\n"
"\n"
- "\t-c -\tcolorspace (mono, gray, grayalpha, rgb, rgba, cmyk, cmykalpha)\n"
+ "\t-c -\tcolorspace (mono, gray, grayalpha, rgb, rgba, cmyk, cmykalpha, filename of ICC profile)\n"
+ "\t-e -\tproof icc profile (filename of ICC profile)\n"
"\t-G -\tapply gamma correction\n"
"\t-I\tinvert colors\n"
"\n"
@@ -462,7 +465,7 @@ static void drawband(fz_context *ctx, fz_page *page, fz_display_list *list, cons
else
fz_clear_pixmap_with_value(ctx, pix, 255);
- dev = fz_new_draw_device(ctx, NULL, pix);
+ dev = fz_new_draw_device_with_proof(ctx, NULL, pix, proof_cs);
if (lowmemory)
fz_enable_device_hints(ctx, dev, FZ_NO_CACHE);
if (alphabits_graphics == 0)
@@ -1440,7 +1443,7 @@ int mudraw_main(int argc, char **argv)
fz_var(doc);
- while ((c = fz_getopt(argc, argv, "p:o:F:R:r:w:h:fB:c:G:Is:A:DiW:H:S:T:U:XLvPl:y:NO:")) != -1)
+ while ((c = fz_getopt(argc, argv, "p:o:F:R:r:w:h:fB:c:e:G:Is:A:DiW:H:S:T:U:XLvPl:y:NO:")) != -1)
{
switch (c)
{
@@ -1459,6 +1462,7 @@ int mudraw_main(int argc, char **argv)
case 'B': band_height = atoi(fz_optarg); break;
case 'c': out_cs = parse_colorspace(fz_optarg); break;
+ case 'e': proof_filename = fz_optarg; break;
case 'G': gamma_value = fz_atof(fz_optarg); break;
case 'I': invert++; break;
@@ -1561,6 +1565,9 @@ int mudraw_main(int argc, char **argv)
exit(1);
}
+ if (proof_filename)
+ proof_cs = fz_new_icc_colorspace_from_file(ctx, NULL, proof_filename);
+
fz_set_text_aa_level(ctx, alphabits_text);
fz_set_graphics_aa_level(ctx, alphabits_graphics);
fz_set_graphics_min_line_width(ctx, min_line_width);
@@ -1841,10 +1848,16 @@ int mudraw_main(int argc, char **argv)
oi = fz_document_output_intent(ctx, doc);
if (oi)
{
- if (fz_colorspace_n(ctx, oi) == fz_colorspace_n(ctx, colorspace))
+ /* See if we had explicitly set a profile to render */
+ if (out_cs != CS_ICC)
{
- fz_drop_colorspace(ctx, colorspace);
- colorspace = fz_keep_colorspace(ctx, oi);
+ /* In this case, we want to render to the output intent
+ * color space if the number of channels is the same */
+ if (fz_colorspace_n(ctx, oi) == fz_colorspace_n(ctx, colorspace))
+ {
+ fz_drop_colorspace(ctx, colorspace);
+ colorspace = fz_keep_colorspace(ctx, oi);
+ }
}
}
@@ -1980,6 +1993,7 @@ int mudraw_main(int argc, char **argv)
#endif /* DISABLE_MUTHREADS */
fz_drop_colorspace(ctx, colorspace);
+ fz_drop_colorspace(ctx, proof_cs);
fz_drop_context(ctx);
#ifndef DISABLE_MUTHREADS