summaryrefslogtreecommitdiff
path: root/source/fitz/colorspace.c
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2017-07-07 14:27:33 +0100
committerRobin Watts <robin.watts@artifex.com>2017-09-08 17:46:50 +0100
commita7f36241cba4d1807ab4664201aa0975755d6772 (patch)
tree6a15ab1b47af54d9f733915a20c0f609b07bc72f /source/fitz/colorspace.c
parentd4afa7b72e0b7d774250f13c3c36d04a5e1415d0 (diff)
downloadmupdf-a7f36241cba4d1807ab4664201aa0975755d6772.tar.xz
Update draw device to cope with spots.
If draw device is passed a pixmap with disabled separations, it may have to push an extra group at the top to allow for the actual rendering to properly happen in cmyk+spots, and then get folded down at the end. This pushing cannot happen at create time, due to it being dependent on the defualt_cs settings. Accordingly, we push it (just once) on the first drawing operation. This means we need to be able to convert from "colorspace + set of spots" to "different colorspace + different set of spots". This in turn means we need to be able to drive lcms slightly differently (to tell it whether to copy the spots unchanged or not), so we have to amend the CMS interface code a bit for that. Currently we lack plotters to properly cope with plotting images and shades with spots, so this will give a warning and do nothing. To be filled in in future commits. Ensure fz_get_icc_link accepts NULL to mean default color params. Incorporates fixes from Michel Vrhel: With transparency groups we can have RGB + spot pixmaps. When drawing into those we need a mixture of colorant polarity. Ensure that fz_convert_separation_colors takes account of this. Fix C1 of Altona_Technical_1v1_x3.pdf (allow for output intent in fz_clone_pixmap_area_with_different_seps).
Diffstat (limited to 'source/fitz/colorspace.c')
-rw-r--r--source/fitz/colorspace.c394
1 files changed, 315 insertions, 79 deletions
diff --git a/source/fitz/colorspace.c b/source/fitz/colorspace.c
index 29ad18d3..3e322bd9 100644
--- a/source/fitz/colorspace.c
+++ b/source/fitz/colorspace.c
@@ -32,10 +32,10 @@ fz_cmm_transform_color(fz_context *ctx, fz_icclink *link, unsigned short *dst, c
}
void
-fz_cmm_init_link(fz_context *ctx, fz_icclink *link, const fz_color_params *rend, int cmm_flags, int num_bytes, int extras, const fz_iccprofile *src, const fz_iccprofile *prf, const fz_iccprofile *des)
+fz_cmm_init_link(fz_context *ctx, fz_icclink *link, const fz_iccprofile *dst, int dst_extras, const fz_iccprofile *src, int src_extras, const fz_iccprofile *prf, const fz_color_params *rend, int cmm_flags, int num_bytes, int copy_spots)
{
if (ctx && ctx->colorspace && ctx->colorspace->cmm && ctx->cmm_instance)
- ctx->colorspace->cmm->init_link(ctx->cmm_instance, link, rend, cmm_flags, num_bytes, extras, src, prf, des);
+ ctx->colorspace->cmm->init_link(ctx->cmm_instance, link, dst, dst_extras, src, src_extras, prf, rend, cmm_flags, num_bytes, copy_spots);
}
void
@@ -201,7 +201,9 @@ struct fz_link_key_s {
unsigned char src_md5[16];
unsigned char dst_md5[16];
fz_color_params rend;
- int extras;
+ int src_extras;
+ int dst_extras;
+ int copy_spots;
int depth;
int proof;
};
@@ -227,7 +229,9 @@ fz_cmp_link_key(fz_context *ctx, void *k0_, void *k1_)
fz_link_key *k0 = (fz_link_key *)k0_;
fz_link_key *k1 = (fz_link_key *)k1_;
return k0->proof == k1->proof &&
- k0->extras == k1->extras &&
+ k0->src_extras == k1->src_extras &&
+ k0->dst_extras == k1->dst_extras &&
+ k0->copy_spots == k1->copy_spots &&
k0->depth == k1->depth &&
k0->rend.bp == k1->rend.bp &&
k0->rend.ri == k1->rend.ri &&
@@ -260,10 +264,13 @@ fz_make_hash_link_key(fz_context *ctx, fz_store_hash *hash, void *key_)
fz_link_key *key = (fz_link_key *)key_;
memcpy(hash->u.link.dst_md5, key->dst_md5, 16);
memcpy(hash->u.link.src_md5, key->src_md5, 16);
- hash->u.link.ri_bp = (key->rend.ri<<1) | key->rend.bp;
- hash->u.link.extras = key->extras;
- hash->u.link.depth = key->depth;
+ hash->u.link.ri = key->rend.ri;
+ hash->u.link.bp = key->rend.bp;
+ hash->u.link.src_extras = key->src_extras;
+ hash->u.link.dst_extras = key->dst_extras;
+ hash->u.link.bpp16 = key->depth == 2;
hash->u.link.proof = key->proof;
+ hash->u.link.copy_spots = key->copy_spots;
return 1;
}
@@ -319,14 +326,11 @@ get_base_icc_profile(fz_context *ctx, const fz_colorspace *cs)
}
static fz_icclink *
-fz_new_icc_link(fz_context *ctx, fz_iccprofile *src, fz_iccprofile *prf, fz_iccprofile *dst, const fz_color_params *rend, int num_bytes, int extras)
+fz_new_icc_link(fz_context *ctx, fz_iccprofile *dst, int dst_extras, fz_iccprofile *src, int src_extras, fz_iccprofile *prf, const fz_color_params *rend, int num_bytes, int copy_extras)
{
fz_icclink *link = fz_malloc_struct(ctx, fz_icclink);
FZ_INIT_STORABLE(link, 1, fz_drop_link_imp);
- link->num_in = src->num_devcomp;
- link->num_out = dst->num_devcomp;
-
if (memcmp(src->md5, dst->md5, 16) == 0 && prf == NULL)
{
link->is_identity = 1;
@@ -334,7 +338,7 @@ fz_new_icc_link(fz_context *ctx, fz_iccprofile *src, fz_iccprofile *prf, fz_iccp
}
fz_try(ctx)
- fz_cmm_init_link(ctx, link, rend, 0, num_bytes, extras, src, prf, dst);
+ fz_cmm_init_link(ctx, link, dst, dst_extras, src, src_extras, prf, rend, 0, num_bytes, copy_extras);
fz_catch(ctx)
{
fz_free(ctx, link);
@@ -378,7 +382,7 @@ fz_icc_from_cal(fz_context *ctx, const fz_colorspace *cs)
}
static fz_icclink *
-fz_get_icc_link(fz_context *ctx, const fz_colorspace *src, const fz_colorspace *prf, const fz_colorspace *dst, const fz_color_params *rend, int num_bytes, int extras, int *src_n)
+fz_get_icc_link(fz_context *ctx, const fz_colorspace *dst, int dst_extras, const fz_colorspace *src, int src_extras, const fz_colorspace *prf, const fz_color_params *rend, int num_bytes, int copy_spots, int *src_n)
{
fz_icclink *link = NULL;
fz_iccprofile *src_icc = NULL;
@@ -387,6 +391,8 @@ fz_get_icc_link(fz_context *ctx, const fz_colorspace *src, const fz_colorspace *
fz_link_key *key = NULL;
fz_icclink *new_link;
+ assert(!copy_spots || src_extras == dst_extras);
+
if (prf != NULL)
prf_icc = prf->data;
@@ -440,6 +446,9 @@ fz_get_icc_link(fz_context *ctx, const fz_colorspace *src, const fz_colorspace *
fz_var(link);
fz_var(key);
+ if (rend == NULL)
+ rend = fz_default_color_params(ctx);
+
fz_try(ctx)
{
/* Check the storable to see if we have a copy. */
@@ -449,15 +458,17 @@ fz_get_icc_link(fz_context *ctx, const fz_colorspace *src, const fz_colorspace *
memcpy(&key->src_md5, src_icc->md5, 16);
key->rend.ri = rend->ri;
key->rend.bp = rend->bp;
- key->extras = extras;
+ key->src_extras = src_extras;
+ key->dst_extras = dst_extras;
key->depth = num_bytes;
key->proof = (prf_icc != NULL);
+ key->copy_spots = copy_spots;
link = fz_find_item(ctx, fz_drop_link_imp, key, &fz_link_store_type);
/* Not found. Make new one add to store. */
if (link == NULL)
{
- link = fz_new_icc_link(ctx, src_icc, prf_icc, dst_icc, rend, num_bytes, extras);
+ link = fz_new_icc_link(ctx, dst_icc, dst_extras, src_icc, src_extras, prf_icc, rend, num_bytes, copy_spots);
new_link = fz_store_item(ctx, key, link, sizeof(fz_icclink), &fz_link_store_type);
if (new_link != NULL)
{
@@ -828,21 +839,23 @@ fz_default_color_params(fz_context *ctx)
/* Fast pixmap color conversions */
-static void fast_gray_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+static void fast_gray_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
size_t w = src->w;
int h = src->h;
+ int sn = src->n;
int ss = src->s;
int sa = src->alpha;
+ int dn = dst->n;
int ds = dst->s;
int da = dst->alpha;
- ptrdiff_t d_line_inc = dst->stride - w * (da + ds + 3);
- ptrdiff_t s_line_inc = src->stride - w * (sa + ss + 1);
+ ptrdiff_t d_line_inc = dst->stride - w * dn;
+ ptrdiff_t s_line_inc = src->stride - w * sn;
- /* Spots must match, and we can never drop alpha (but we can invent it) */
- if (dst->n != 3 + ds + da || src->n != 1 + ss + sa || ss != ds || (!da && sa))
+ /* If copying spots, they must match, and we can never drop alpha (but we can invent it) */
+ if ((copy_spots && ss != ds) || (!da && sa))
{
assert("This should never happen" == NULL);
fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps");
@@ -917,7 +930,7 @@ static void fast_gray_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
}
}
}
- else
+ else if (copy_spots)
{
/* Slower, spots capable version */
int i;
@@ -940,23 +953,44 @@ static void fast_gray_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
s += s_line_inc;
}
}
+ else
+ {
+ while (h--)
+ {
+ size_t ww = w;
+ while (ww--)
+ {
+ d[0] = s[0];
+ d[1] = s[0];
+ d[2] = s[0];
+ s += sn;
+ d += dn;
+ if (da)
+ d[-1] = sa ? s[-1] : 255;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
}
-static void fast_gray_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+static void fast_gray_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
size_t w = src->w;
int h = src->h;
+ int sn = src->n;
int ss = src->s;
int sa = src->alpha;
+ int dn = dst->n;
int ds = dst->s;
int da = dst->alpha;
- ptrdiff_t d_line_inc = dst->stride - w * (da + ds + 4);
- ptrdiff_t s_line_inc = src->stride - w * (sa + ss + 1);
+ ptrdiff_t d_line_inc = dst->stride - w * dn;
+ ptrdiff_t s_line_inc = src->stride - w * sn;
- /* Spots must match, and we can never drop alpha (but we can invent it) */
- if (dst->n != 4 + ds + da || src->n != 1 + ss + sa || ss != ds || (!da && sa))
+ /* If copying spots, they must match, and we can never drop alpha (but we can invent it) */
+ if ((copy_spots && ss != ds) || (!da && sa))
{
assert("This should never happen" == NULL);
fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps");
@@ -1034,7 +1068,7 @@ static void fast_gray_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, f
}
}
}
- else
+ else if (copy_spots)
{
/* Slower, spots capable version */
int i;
@@ -1058,23 +1092,45 @@ static void fast_gray_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, f
s += s_line_inc;
}
}
+ else
+ {
+ while (h--)
+ {
+ size_t ww = w;
+ while (ww--)
+ {
+ d[0] = 0;
+ d[1] = 0;
+ d[2] = 0;
+ d[3] = s[0];
+ s += sn;
+ d += dn;
+ if (da)
+ d[-1] = sa ? s[-1] : 255;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
}
-static void fast_rgb_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+static void fast_rgb_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
size_t w = src->w;
int h = src->h;
+ int sn = src->n;
int ss = src->s;
int sa = src->alpha;
+ int dn = dst->n;
int ds = dst->s;
int da = dst->alpha;
- ptrdiff_t d_line_inc = dst->stride - w * (da + ds + 1);
- ptrdiff_t s_line_inc = src->stride - w * (sa + ss + 3);
+ ptrdiff_t d_line_inc = dst->stride - w * dn;
+ ptrdiff_t s_line_inc = src->stride - w * sn;
- /* Spots must match, and we can never drop alpha (but we can invent it) */
- if (dst->n != 1 + ds + da || src->n != 3 + ss + sa || ss != ds || (!da && sa))
+ /* If copying spots, they must match, and we can never drop alpha (but we can invent it) */
+ if ((copy_spots && ss != ds) || (!da && sa))
{
assert("This should never happen" == NULL);
fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps");
@@ -1143,7 +1199,7 @@ static void fast_rgb_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
}
}
}
- else
+ else if (copy_spots)
{
/* Slower, spots capable version */
int i;
@@ -1164,23 +1220,42 @@ static void fast_rgb_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
s += s_line_inc;
}
}
+ else
+ {
+ while (h--)
+ {
+ size_t ww = w;
+ while (ww--)
+ {
+ d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
+ s += sn;
+ d += dn;
+ if (da)
+ d[-1] = sa ? s[-1] : 255;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
}
-static void fast_bgr_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+static void fast_bgr_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
size_t w = src->w;
int h = src->h;
+ int sn = src->n;
int ss = src->s;
int sa = src->alpha;
+ int dn = dst->n;
int ds = dst->s;
int da = dst->alpha;
- ptrdiff_t d_line_inc = dst->stride - w * (da + ds + 1);
- ptrdiff_t s_line_inc = src->stride - w * (sa + ss + 3);
+ ptrdiff_t d_line_inc = dst->stride - w * dn;
+ ptrdiff_t s_line_inc = src->stride - w * sn;
- /* Spots must match, and we can never drop alpha (but we can invent it) */
- if (dst->n != 1 + ds + da || src->n != 3 + ss + sa || ss != ds || (!da && sa))
+ /* If copying spots, they must match, and we can never drop alpha (but we can invent it) */
+ if ((copy_spots && ss != ds) || (!da && sa))
{
assert("This should never happen" == NULL);
fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps");
@@ -1251,7 +1326,7 @@ static void fast_bgr_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
}
}
}
- else
+ else if (copy_spots)
{
/* Slower, spots capable version */
while (h--)
@@ -1272,23 +1347,43 @@ static void fast_bgr_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
s += s_line_inc;
}
}
+ else
+ {
+ /* Slower, spots capable version */
+ while (h--)
+ {
+ size_t ww = w;
+ while (ww--)
+ {
+ d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
+ s += sn;
+ d += dn;
+ if (da)
+ d[-1] = sa ? s[-1] : 255;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
}
-static void fast_rgb_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+static void fast_rgb_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
size_t w = src->w;
int h = src->h;
+ int sn = src->n;
int ss = src->s;
int sa = src->alpha;
+ int dn = dst->n;
int ds = dst->s;
int da = dst->alpha;
- ptrdiff_t d_line_inc = dst->stride - w * (da + ds + 4);
- ptrdiff_t s_line_inc = src->stride - w * (sa + ss + 3);
+ ptrdiff_t d_line_inc = dst->stride - w * dn;
+ ptrdiff_t s_line_inc = src->stride - w * sn;
/* Spots must match, and we can never drop alpha (but we can invent it) */
- if (dst->n != 4 + ds + da || src->n != 3 + ss + sa || ss != ds || (!da && sa))
+ if ((copy_spots || ss != ds) || (!da && sa))
{
assert("This should never happen" == NULL);
fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps");
@@ -1378,7 +1473,7 @@ static void fast_rgb_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
}
}
}
- else
+ else if (copy_spots)
{
/* Slower, spots capable version */
while (h--)
@@ -1406,23 +1501,49 @@ static void fast_rgb_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
s += s_line_inc;
}
}
+ else
+ {
+ while (h--)
+ {
+ size_t ww = w;
+ while (ww--)
+ {
+ unsigned char c = s[0];
+ unsigned char m = s[1];
+ unsigned char y = s[2];
+ unsigned char k = (unsigned char)(255 - fz_maxi(c, fz_maxi(m, y)));
+ d[0] = c + k;
+ d[1] = m + k;
+ d[2] = y + k;
+ d[3] = 255 - k;
+ s += sn;
+ d += dn;
+ if (da)
+ d[-1] = sa ? s[-1] : 255;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
}
-static void fast_bgr_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+static void fast_bgr_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
size_t w = src->w;
int h = src->h;
+ int sn = src->n;
int ss = src->s;
int sa = src->alpha;
+ int dn = dst->n;
int ds = dst->s;
int da = dst->alpha;
- ptrdiff_t d_line_inc = dst->stride - w * (da + ds + 4);
- ptrdiff_t s_line_inc = src->stride - w * (sa + ss + 3);
+ ptrdiff_t d_line_inc = dst->stride - w * dn;
+ ptrdiff_t s_line_inc = src->stride - w * sn;
/* Spots must match, and we can never drop alpha (but we can invent it) */
- if (dst->n != 4 + ds + da || src->n != 3 + ss + sa || ss != ds || (!da && sa))
+ if ((copy_spots && ss != ds) || (!da && sa))
{
assert("This should never happen" == NULL);
fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps");
@@ -1512,7 +1633,7 @@ static void fast_bgr_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
}
}
}
- else
+ else if (copy_spots)
{
/* Slower, spots capable version */
while (h--)
@@ -1540,23 +1661,49 @@ static void fast_bgr_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
s += s_line_inc;
}
}
+ else
+ {
+ while (h--)
+ {
+ size_t ww = w;
+ while (ww--)
+ {
+ unsigned char c = s[2];
+ unsigned char m = s[1];
+ unsigned char y = s[0];
+ unsigned char k = (unsigned char)(255 - fz_maxi(c, fz_maxi(m, y)));
+ d[0] = c + k;
+ d[1] = m + k;
+ d[2] = y + k;
+ d[3] = 255 - k;
+ s += sn;
+ d += dn;
+ if (da)
+ d[-1] = sa ? s[-1] : 255;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
}
-static void fast_cmyk_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+static void fast_cmyk_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
size_t w = src->w;
int h = src->h;
+ int sn = src->n;
int ss = src->s;
int sa = src->alpha;
+ int dn = dst->n;
int ds = dst->s;
int da = dst->alpha;
- ptrdiff_t d_line_inc = dst->stride - w * (da + ds + 1);
- ptrdiff_t s_line_inc = src->stride - w * (sa + ss + 4);
+ ptrdiff_t d_line_inc = dst->stride - w * dn;
+ ptrdiff_t s_line_inc = src->stride - w * sn;
/* Spots must match, and we can never drop alpha (but we can invent it) */
- if (dst->n != 1 + ds + da || src->n != 4 + ss + sa || ss != ds || (!da && sa))
+ if ((copy_spots && ss != ds) || (!da && sa))
{
assert("This should never happen" == NULL);
fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps");
@@ -1634,7 +1781,7 @@ static void fast_cmyk_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, f
}
}
}
- else
+ else if (copy_spots)
{
/* Slower, spots capable version */
while (h--)
@@ -1658,6 +1805,26 @@ static void fast_cmyk_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, f
s += s_line_inc;
}
}
+ else
+ {
+ while (h--)
+ {
+ size_t ww = w;
+ while (ww--)
+ {
+ unsigned char c = fz_mul255(255 - s[0], 77);
+ unsigned char m = fz_mul255(255 - s[1], 150);
+ unsigned char y = fz_mul255(255 - s[2], 28);
+ d[0] = (unsigned char)fz_maxi(s[3] - c - m - y, 0);
+ s += sn;
+ d += dn;
+ if (da)
+ d[-1] = sa ? s[-1] : 255;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
}
#ifdef ARCH_ARM
@@ -1987,23 +2154,25 @@ static inline void cached_cmyk_conv(unsigned char *restrict const pr, unsigned c
#endif
}
-static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
size_t w = src->w;
int h = src->h;
+ int sn = src->n;
int ss = src->s;
int sa = src->alpha;
+ int dn = dst->n;
int ds = dst->s;
int da = dst->alpha;
- ptrdiff_t d_line_inc = dst->stride - w * (da + ds + 3);
- ptrdiff_t s_line_inc = src->stride - w * (sa + ss + 4);
+ ptrdiff_t d_line_inc = dst->stride - w * dn;
+ ptrdiff_t s_line_inc = src->stride - w * sn;
unsigned int C,M,Y,K;
unsigned char r,g,b;
/* Spots must match, and we can never drop alpha (but we can invent it) */
- if (dst->n != 3 + ds + da || src->n != 4 + ss + sa || ss != ds || (!da && sa))
+ if ((copy_spots && ss != ds) || (!da && sa))
{
assert("This should never happen" == NULL);
fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps");
@@ -2033,13 +2202,13 @@ static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
{
if (sa)
{
- #ifdef ARCH_ARM
+#ifdef ARCH_ARM
if (h == 1)
{
fast_cmyk_to_rgb_ARM(d, s, w);
return;
}
- #endif
+#endif
while (h--)
{
size_t ww = w;
@@ -2096,7 +2265,7 @@ static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
}
}
}
- else
+ else if (copy_spots)
{
/* Slower, spots capable version */
while (h--)
@@ -2120,25 +2289,48 @@ static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
s += s_line_inc;
}
}
+ else
+ {
+ /* Slower, spots capable version */
+ while (h--)
+ {
+ size_t ww = w;
+ while (ww--)
+ {
+ cached_cmyk_conv(&r, &g, &b, &C, &M, &Y, &K, s[0], s[1], s[2], s[3]);
+ d[0] = r;
+ d[1] = g;
+ d[2] = b;
+ s += sn;
+ d += dn;
+ if (da)
+ d[-1] = sa ? s[-1] : 255;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
}
-static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
size_t w = src->w;
int h = src->h;
+ int sn = src->n;
int ss = src->s;
int sa = src->alpha;
+ int dn = dst->n;
int ds = dst->s;
int da = dst->alpha;
- ptrdiff_t d_line_inc = dst->stride - w * (da + ds + 3);
- ptrdiff_t s_line_inc = src->stride - w * (sa + ss + 4);
+ ptrdiff_t d_line_inc = dst->stride - w * dn;
+ ptrdiff_t s_line_inc = src->stride - w * sn;
unsigned int C,M,Y,K;
unsigned char r,g,b;
/* Spots must match, and we can never drop alpha (but we can invent it) */
- if (dst->n != 3 + ds + da || src->n != 4 + ss + sa || ss != ds || (!da && sa))
+ if ((copy_spots && ss != ds) || (!da && sa))
{
assert("This should never happen" == NULL);
fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps");
@@ -2227,7 +2419,7 @@ static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
}
}
}
- else
+ else if (copy_spots)
{
/* Slower, spots capable version */
while (h--)
@@ -2251,23 +2443,46 @@ static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
s += s_line_inc;
}
}
+ else
+ {
+ /* Slower, spots capable version */
+ while (h--)
+ {
+ size_t ww = w;
+ while (ww--)
+ {
+ cached_cmyk_conv(&r, &g, &b, &C, &M, &Y, &K, s[0], s[1], s[2], s[3]);
+ d[0] = b;
+ d[1] = g;
+ d[2] = r;
+ s += sn;
+ d += dn;
+ if (da)
+ d[-1] = sa ? s[-1] : 255;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
}
-static void fast_rgb_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+static void fast_rgb_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
size_t w = src->w;
int h = src->h;
+ int sn = src->n;
int ss = src->s;
int sa = src->alpha;
+ int dn = dst->n;
int ds = dst->s;
int da = dst->alpha;
- ptrdiff_t d_line_inc = dst->stride - w * (da + ds + 3);
- ptrdiff_t s_line_inc = src->stride - w * (sa + ss + 3);
+ ptrdiff_t d_line_inc = dst->stride - w * dn;
+ ptrdiff_t s_line_inc = src->stride - w * sn;
- /* Spots must match, and we can never drop alpha (but we can invent it) */
- if (dst->n != 3 + ds + da || src->n != 3 + ss + sa || ss != ds || (!da && sa))
+ /* If copying spots, they must match, and we can never drop alpha (but we can invent it) */
+ if ((copy_spots && ss != ds) || (!da && sa))
{
assert("This should never happen" == NULL);
fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps");
@@ -2336,7 +2551,7 @@ static void fast_rgb_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_
}
}
}
- else
+ else if (copy_spots)
{
/* Slower, spots capable version */
while (h--)
@@ -2359,10 +2574,29 @@ static void fast_rgb_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_
s += s_line_inc;
}
}
+ else
+ {
+ while (h--)
+ {
+ size_t ww = w;
+ while (ww--)
+ {
+ d[0] = s[2];
+ d[1] = s[1];
+ d[2] = s[0];
+ s += sn;
+ d += dn;
+ if (da)
+ d[-1] = sa ? s[-1] : 255;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
}
static void
-icc_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+icc_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
fz_colorspace *srcs = src->colorspace;
fz_colorspace *dsts = dst->colorspace;
@@ -2394,7 +2628,7 @@ icc_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *
inputpos = src->samples;
outputpos = dst->samples;
- link = fz_get_icc_link(ctx, srcs, prf, dsts, color_params, 1, dst->alpha, &src_n);
+ link = fz_get_icc_link(ctx, dsts, dst->s + dst->alpha, srcs, src->s + src->alpha, prf, color_params, 1, copy_spots, &src_n);
if (link->is_identity)
{
@@ -2450,7 +2684,7 @@ convert_to_icc_base(fz_context *ctx, fz_colorspace *srcs, float *src_f, float *d
* be handled. Realize those can map from index->devn->pdf-cal->icc for
* example. */
static void
-icc_base_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+icc_base_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
fz_colorspace *srcs = src->colorspace;
fz_colorspace *base_cs = get_base_icc_space(ctx, srcs);
@@ -2501,7 +2735,7 @@ icc_base_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorsp
}
fz_try(ctx)
- icc_conv_pixmap(ctx, dst, base, prf, default_cs, color_params);
+ icc_conv_pixmap(ctx, dst, base, prf, default_cs, color_params, copy_spots);
fz_always(ctx)
fz_drop_pixmap(ctx, base);
fz_catch(ctx)
@@ -2509,7 +2743,7 @@ icc_base_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorsp
}
static void
-std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
float srcv[FZ_MAX_COLORS];
float dstv[FZ_MAX_COLORS];
@@ -2710,8 +2944,10 @@ std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *
}
}
-static void fast_any_to_alpha(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+static void fast_any_to_alpha(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
+ assert(copy_spots && dst->s == 0 && src->s == 0);
+
if (!src->alpha)
fz_clear_pixmap_with_value(ctx, dst, 255);
else
@@ -3060,7 +3296,7 @@ void fz_find_color_converter(fz_context *ctx, fz_color_converter *cc, const fz_c
cc->convert = icc_conv_color;
else
cc->convert = icc_base_conv_color;
- cc->link = fz_get_icc_link(ctx, ss_base, is, ds, params, 2, 0, &cc->n);
+ cc->link = fz_get_icc_link(ctx, ds, 0, ss_base, 0, is, params, 2, 0, &cc->n);
}
else
cc->convert = std_conv_color;