From 5242318aae6b46777326eb4b10514aabd21d7eea Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Wed, 5 Jul 2017 10:35:12 +0100 Subject: Add knowledge of spots to color conversions. --- source/fitz/color-lcms.c | 44 ++- source/fitz/colorspace-imp.h | 4 +- source/fitz/colorspace.c | 865 +++++++++++++++++++++++++++++++------------ 3 files changed, 651 insertions(+), 262 deletions(-) (limited to 'source/fitz') diff --git a/source/fitz/color-lcms.c b/source/fitz/color-lcms.c index 82d05c98..2c25e8e7 100644 --- a/source/fitz/color-lcms.c +++ b/source/fitz/color-lcms.c @@ -70,7 +70,7 @@ fz_lcms_num_devcomps(cmsContext cmm_ctx, fz_iccprofile *profile) } static void -fz_lcms_premultiply_row(fz_context *ctx, int n, int w, unsigned char *s) +fz_lcms_premultiply_row(fz_context *ctx, int n, int c, int w, unsigned char *s) { unsigned char a; int k; @@ -79,14 +79,14 @@ fz_lcms_premultiply_row(fz_context *ctx, int n, int w, unsigned char *s) for (; w > 0; w--) { a = s[n1]; - for (k = 0; k < n1; k++) + for (k = 0; k < c; k++) s[k] = fz_mul255(s[k], a); s += n; } } static void -fz_lcms_unmultiply_row(fz_context *ctx, int n, int w, unsigned char *s, const unsigned char *in) +fz_lcms_unmultiply_row(fz_context *ctx, int n, int c, int w, unsigned char *s, const unsigned char *in) { int a, inva; int k; @@ -96,8 +96,10 @@ fz_lcms_unmultiply_row(fz_context *ctx, int n, int w, unsigned char *s, const un { a = in[n1]; inva = a ? 255 * 256 / a : 0; - for (k = 0; k < n1; k++) + for (k = 0; k < c; k++) s[k] = (in[k] * inva) >> 8; + for (;k < n1; k++) + s[k] = in[k]; s[n1] = a; s += n; in += n; @@ -111,7 +113,7 @@ fz_lcms_transform_pixmap(fz_cmm_instance *instance, fz_icclink *link, fz_pixmap cmsContext cmm_ctx = (cmsContext)instance; fz_context *ctx = (fz_context *)cmsGetContextUserData(cmm_ctx); cmsHTRANSFORM hTransform = (cmsHTRANSFORM)link->cmm_handle; - int cmm_num_src, cmm_num_des; + int cmm_num_src, cmm_num_des, cmm_extras; unsigned char *inputpos, *outputpos, *buffer; int ss = src->stride; int ds = dst->stride; @@ -121,27 +123,35 @@ fz_lcms_transform_pixmap(fz_cmm_instance *instance, fz_icclink *link, fz_pixmap int dn = dst->n; int sa = src->alpha; int da = dst->alpha; + int ssp = src->s; + int dsp = dst->s; + int sc = sn - ssp - sa; + int dc = dn - dsp - da; int h = src->h; + cmsUInt32Number src_format, dst_format; DEBUG_LCMS_MEM(("@@@@@@@ Transform Pixmap Start:: mupdf ctx = %p lcms ctx = %p link = %p \n", (void*)ctx, (void*)cmm_ctx, (void*)link->cmm_handle)); /* check the channels. */ - cmm_num_src = T_CHANNELS(cmsGetTransformInputFormat(cmm_ctx, hTransform)); - cmm_num_des = T_CHANNELS(cmsGetTransformOutputFormat(cmm_ctx, hTransform)); - if (cmm_num_src != sn - sa || cmm_num_des != dn - da || sa != da) - fz_throw(ctx, FZ_ERROR_GENERIC, "Mismatching color setup in cmm pixmap transformation: src: %d vs %d+%d, dst: %d vs %d+%d", cmm_num_src, sn-sa, sa, cmm_num_des, dn-da, da); + src_format = cmsGetTransformInputFormat(cmm_ctx, hTransform); + dst_format = cmsGetTransformOutputFormat(cmm_ctx, hTransform); + cmm_num_src = T_CHANNELS(src_format); + cmm_num_des = T_CHANNELS(dst_format); + cmm_extras = T_EXTRA(src_format); + if (cmm_num_src != sc || cmm_num_des != dc || cmm_extras != ssp+sa || sa != da || ssp != dsp) + fz_throw(ctx, FZ_ERROR_GENERIC, "Mismatching color setup in cmm pixmap transformation: src: %d vs %d+%d+%d, dst: %d vs %d+%d+%d", cmm_num_src, sc, ssp, sa, cmm_num_des, dc, dsp, da); /* Transform */ inputpos = src->samples; outputpos = dst->samples; - if (src->alpha) + if (sa) { /* Allow for premultiplied alpha */ buffer = fz_malloc(ctx, ss); for (; h > 0; h--) { - fz_lcms_unmultiply_row(ctx, sn, sw, buffer, inputpos); + fz_lcms_unmultiply_row(ctx, sn, sc, sw, buffer, inputpos); cmsDoTransform(cmm_ctx, hTransform, buffer, outputpos, sw); - fz_lcms_premultiply_row(ctx, dn, dw, outputpos); + fz_lcms_premultiply_row(ctx, dn, dc, dw, outputpos); inputpos += ss; outputpos += ds; } @@ -170,7 +180,7 @@ fz_lcms_transform_color(fz_cmm_instance *instance, fz_icclink *link, unsigned sh } void -fz_lcms_init_link(fz_cmm_instance *instance, fz_icclink *link, const fz_color_params *rend, int cmm_flags, int num_bytes, int alpha, const fz_iccprofile *src, const fz_iccprofile *prf, const fz_iccprofile *dst) +fz_lcms_init_link(fz_cmm_instance *instance, 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 *dst) { cmsContext cmm_ctx = (cmsContext)instance; fz_context *ctx = (fz_context *)cmsGetContextUserData(cmm_ctx); @@ -189,7 +199,7 @@ fz_lcms_init_link(fz_cmm_instance *instance, fz_icclink *link, const fz_color_pa if (lcms_src_cs < 0) lcms_src_cs = 0; src_num_chan = cmsChannelsOf(cmm_ctx, src_cs); - src_data_type = (COLORSPACE_SH(lcms_src_cs) | CHANNELS_SH(src_num_chan) | DOSWAP_SH(src->bgr) | BYTES_SH(num_bytes) | EXTRA_SH(alpha)); + src_data_type = (COLORSPACE_SH(lcms_src_cs) | CHANNELS_SH(src_num_chan) | DOSWAP_SH(src->bgr) | BYTES_SH(num_bytes) | EXTRA_SH(extras)); /* dst */ des_cs = cmsGetColorSpace(cmm_ctx, dst->cmm_handle); @@ -197,17 +207,17 @@ fz_lcms_init_link(fz_cmm_instance *instance, fz_icclink *link, const fz_color_pa if (lcms_des_cs < 0) lcms_des_cs = 0; des_num_chan = cmsChannelsOf(cmm_ctx, des_cs); - des_data_type = (COLORSPACE_SH(lcms_des_cs) | CHANNELS_SH(des_num_chan) | DOSWAP_SH(dst->bgr) | BYTES_SH(num_bytes) | EXTRA_SH(alpha)); + des_data_type = (COLORSPACE_SH(lcms_des_cs) | CHANNELS_SH(des_num_chan) | DOSWAP_SH(dst->bgr) | BYTES_SH(num_bytes) | EXTRA_SH(extras)); /* flags */ if (rend->bp) flag |= cmsFLAGS_BLACKPOINTCOMPENSATION; - if (alpha) + if (extras) flag |= cmsFLAGS_COPY_ALPHA; link->depth = num_bytes; - link->alpha = alpha; + link->extras = extras; if (prf == NULL) { diff --git a/source/fitz/colorspace-imp.h b/source/fitz/colorspace-imp.h index 47688c4a..fb10bf80 100644 --- a/source/fitz/colorspace-imp.h +++ b/source/fitz/colorspace-imp.h @@ -15,7 +15,7 @@ int fz_cmm_avoid_white_fix_flag(fz_context *ctx); void fz_cmm_transform_pixmap(fz_context *ctx, fz_icclink *link, fz_pixmap *dst, fz_pixmap *src); void fz_cmm_transform_color(fz_context *ctx, fz_icclink *link, unsigned short *dst, const unsigned short *src); -void fz_cmm_init_link(fz_context *ctx, fz_icclink *link, const fz_color_params *rend, int cmm_flags, int num_bytes, int alpha, const fz_iccprofile *src, const fz_iccprofile *prf, const fz_iccprofile *des); +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); void fz_cmm_fin_link(fz_context *ctx, fz_icclink *link); fz_cmm_instance *fz_cmm_new_instance(fz_context *ctx); void fz_cmm_drop_instance(fz_context *ctx); @@ -52,7 +52,7 @@ struct fz_icclink_s int num_in; int num_out; int depth; - int alpha; + int extras; int is_identity; void *cmm_handle; }; diff --git a/source/fitz/colorspace.c b/source/fitz/colorspace.c index 61988f17..2d66e8a2 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 alpha, const fz_iccprofile *src, const fz_iccprofile *prf, const fz_iccprofile *des) +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) { if (ctx && ctx->colorspace && ctx->colorspace->cmm && ctx->cmm_instance) - ctx->colorspace->cmm->init_link(ctx->cmm_instance, link, rend, cmm_flags, num_bytes, alpha, src, prf, des); + ctx->colorspace->cmm->init_link(ctx->cmm_instance, link, rend, cmm_flags, num_bytes, extras, src, prf, des); } void @@ -197,7 +197,7 @@ struct fz_link_key_s { unsigned char src_md5[16]; unsigned char dst_md5[16]; fz_color_params rend; - int alpha; + int extras; int depth; int proof; }; @@ -223,7 +223,7 @@ 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->alpha == k1->alpha && + k0->extras == k1->extras && k0->depth == k1->depth && k0->rend.bp == k1->rend.bp && k0->rend.ri == k1->rend.ri && @@ -256,8 +256,8 @@ 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.alpha = key->alpha; 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.proof = key->proof; return 1; @@ -315,7 +315,7 @@ get_base_icc_profile(fz_context *ctx, 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 alpha) +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_icclink *link = fz_malloc_struct(ctx, fz_icclink); FZ_INIT_STORABLE(link, 1, fz_drop_link_imp); @@ -330,7 +330,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, alpha, src, prf, dst); + fz_cmm_init_link(ctx, link, rend, 0, num_bytes, extras, src, prf, dst); fz_catch(ctx) { fz_free(ctx, link); @@ -374,7 +374,7 @@ fz_icc_from_cal(fz_context *ctx, fz_colorspace *cs) } static fz_icclink * -fz_get_icc_link(fz_context *ctx, fz_colorspace *src, fz_colorspace *prf, fz_colorspace *dst, const fz_color_params *rend, int num_bytes, int alpha, int *src_n) +fz_get_icc_link(fz_context *ctx, fz_colorspace *src, fz_colorspace *prf, fz_colorspace *dst, const fz_color_params *rend, int num_bytes, int extras, int *src_n) { fz_icclink *link = NULL; fz_iccprofile *src_icc = NULL; @@ -445,7 +445,7 @@ fz_get_icc_link(fz_context *ctx, fz_colorspace *src, fz_colorspace *prf, fz_colo memcpy(&key->src_md5, src_icc->md5, 16); key->rend.ri = rend->ri; key->rend.bp = rend->bp; - key->alpha = alpha; + key->extras = extras; key->depth = num_bytes; key->proof = (prf_icc != NULL); link = fz_find_item(ctx, fz_drop_link_imp, key, &fz_link_store_type); @@ -453,7 +453,7 @@ fz_get_icc_link(fz_context *ctx, fz_colorspace *src, fz_colorspace *prf, fz_colo /* 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, alpha); + link = fz_new_icc_link(ctx, src_icc, prf_icc, dst_icc, rend, num_bytes, extras); new_link = fz_store_item(ctx, key, link, sizeof(fz_icclink), &fz_link_store_type); if (new_link != NULL) { @@ -830,8 +830,19 @@ static void fast_gray_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz unsigned char *d = dst->samples; size_t w = src->w; int h = src->h; - ptrdiff_t d_line_inc = dst->stride - w * (dst->alpha + 3); - ptrdiff_t s_line_inc = src->stride - w * (src->alpha + 1); + int ss = src->s; + int sa = src->alpha; + 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); + + /* 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)) + { + assert("This should never happen" == NULL); + fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps"); + } if ((int)w < 0 || h < 0) return; @@ -842,24 +853,46 @@ static void fast_gray_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz h = 1; } - if (dst->alpha) + if (ss == 0) { - if (src->alpha) + /* Common, no spots case */ + if (da) { - while (h--) + if (sa) { - size_t ww = w; - while (ww--) + while (h--) { - d[0] = s[0]; - d[1] = s[0]; - d[2] = s[0]; - d[3] = s[1]; - s += 2; - d += 4; + size_t ww = w; + while (ww--) + { + d[0] = s[0]; + d[1] = s[0]; + d[2] = s[0]; + d[3] = s[1]; + s += 2; + d += 4; + } + d += d_line_inc; + 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]; + d[3] = 255; + s++; + d += 4; + } + d += d_line_inc; + s += s_line_inc; } - d += d_line_inc; - s += s_line_inc; } } else @@ -872,9 +905,8 @@ static void fast_gray_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz d[0] = s[0]; d[1] = s[0]; d[2] = s[0]; - d[3] = 255; s++; - d += 4; + d += 3; } d += d_line_inc; s += s_line_inc; @@ -883,8 +915,8 @@ static void fast_gray_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz } else { - int si = 1 + src->alpha; - + /* Slower, spots capable version */ + int i; while (h--) { size_t ww = w; @@ -893,8 +925,12 @@ static void fast_gray_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz d[0] = s[0]; d[1] = s[0]; d[2] = s[0]; - s += si; + s += 1; d += 3; + for (i=ss; i > 0; i--) + *d++ = *s++; + if (da) + *d++ = sa ? *s++ : 255; } d += d_line_inc; s += s_line_inc; @@ -908,8 +944,19 @@ static void fast_gray_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, f unsigned char *d = dst->samples; size_t w = src->w; int h = src->h; - ptrdiff_t d_line_inc = dst->stride - w * (dst->alpha + 4); - ptrdiff_t s_line_inc = src->stride - w * (src->alpha + 1); + int ss = src->s; + int sa = src->alpha; + 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); + + /* 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)) + { + assert("This should never happen" == NULL); + fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps"); + } if ((int)w < 0 || h < 0) return; @@ -920,25 +967,48 @@ static void fast_gray_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, f h = 1; } - if (dst->alpha) + if (ss == 0) { - if (src->alpha) + /* Common, no spots case */ + if (da) { - while (h--) + if (sa) { - size_t ww = w; - while (ww--) + while (h--) { - d[0] = 0; - d[1] = 0; - d[2] = 0; - d[3] = 255 - s[0]; - d[4] = s[1]; - s += 2; - d += 5; + size_t ww = w; + while (ww--) + { + d[0] = 0; + d[1] = 0; + d[2] = 0; + d[3] = 255 - s[0]; + d[4] = s[1]; + s += 2; + d += 5; + } + d += d_line_inc; + s += s_line_inc; + } + } + else + { + while (h--) + { + size_t ww = w; + while (ww--) + { + d[0] = 0; + d[1] = 0; + d[2] = 0; + d[3] = 255 - s[0]; + d[4] = 255; + s++; + d += 5; + } + d += d_line_inc; + s += s_line_inc; } - d += d_line_inc; - s += s_line_inc; } } else @@ -952,9 +1022,8 @@ static void fast_gray_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, f d[1] = 0; d[2] = 0; d[3] = 255 - s[0]; - d[4] = 255; s++; - d += 5; + d += 4; } d += d_line_inc; s += s_line_inc; @@ -963,8 +1032,8 @@ static void fast_gray_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, f } else { - int si = 1 + src->alpha; - + /* Slower, spots capable version */ + int i; while (h--) { size_t ww = w; @@ -974,8 +1043,12 @@ static void fast_gray_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, f d[1] = 0; d[2] = 0; d[3] = 255 - s[0]; - s += si; + s += 1; d += 4; + for (i=ss; i > 0; i--) + *d++ = *s++; + if (da) + *d++ = sa ? *s++ : 255; } d += d_line_inc; s += s_line_inc; @@ -989,8 +1062,19 @@ static void fast_rgb_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz unsigned char *d = dst->samples; size_t w = src->w; int h = src->h; - ptrdiff_t d_line_inc = dst->stride - w * (dst->alpha + 1); - ptrdiff_t s_line_inc = src->stride - w * (src->alpha + 3); + int ss = src->s; + int sa = src->alpha; + 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); + + /* 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)) + { + assert("This should never happen" == NULL); + fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps"); + } if ((int)w < 0 || h < 0) return; @@ -1001,22 +1085,42 @@ static void fast_rgb_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz h = 1; } - if (dst->alpha) + if (ss == 0) { - if (src->alpha) + /* Common, no spots case */ + if (da) { - while (h--) + if (sa) { - size_t ww = w; - while (ww--) + while (h--) { - d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8; - d[1] = s[3]; - s += 4; - d += 2; + size_t ww = w; + while (ww--) + { + d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8; + d[1] = s[3]; + s += 4; + d += 2; + } + d += d_line_inc; + 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; + d[1] = 255; + s += 3; + d += 2; + } + d += d_line_inc; + s += s_line_inc; } - d += d_line_inc; - s += s_line_inc; } } else @@ -1027,9 +1131,8 @@ static void fast_rgb_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz while (ww--) { d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8; - d[1] = 255; s += 3; - d += 2; + d++; } d += d_line_inc; s += s_line_inc; @@ -1038,16 +1141,20 @@ static void fast_rgb_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz } else { - int sn = src->n; - + /* Slower, spots capable version */ + int i; 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; + s += 3; d++; + for (i=ss; i > 0; i--) + *d++ = *s++; + if (da) + *d++ = sa ? *s++ : 255; } d += d_line_inc; s += s_line_inc; @@ -1061,8 +1168,19 @@ static void fast_bgr_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz unsigned char *d = dst->samples; size_t w = src->w; int h = src->h; - ptrdiff_t d_line_inc = dst->stride - w * (dst->alpha + 1); - ptrdiff_t s_line_inc = src->stride - w * (src->alpha + 3); + int ss = src->s; + int sa = src->alpha; + 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); + + /* 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)) + { + assert("This should never happen" == NULL); + fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps"); + } if ((int)w < 0 || h < 0) return; @@ -1073,35 +1191,56 @@ static void fast_bgr_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz h = 1; } - if (dst->alpha) + if (ss == 0) { - if (src->alpha) + /* Common, no spots case */ + if (da) { - while (h--) + if (sa) { - size_t ww = w; - while (ww--) + while (h--) { - d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8; - d[1] = s[3]; - s += 4; - d += 2; + size_t ww = w; + while (ww--) + { + d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8; + d[1] = s[3]; + s += 4; + d += 2; + } + d += d_line_inc; + s += s_line_inc; + } + } + else + { + while (h--) + { + size_t ww = w; + while (ww--) + { + d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8; + d[1] = 255; + s += 3; + d += 2; + } + d += d_line_inc; + s += s_line_inc; } - d += d_line_inc; - s += s_line_inc; } } else { + int si = 3 + src->alpha; + while (h--) { size_t ww = w; while (ww--) { d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8; - d[1] = 255; - s += 3; - d += 2; + s += si; + d++; } d += d_line_inc; s += s_line_inc; @@ -1110,16 +1249,20 @@ static void fast_bgr_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz } else { - int si = 3 + src->alpha; - + /* Slower, spots capable version */ while (h--) { + int i; size_t ww = w; while (ww--) { d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8; - s += si; + s += 3; d++; + for (i=ss; i > 0; i--) + *d++ = *s++; + if (da) + *d++ = sa ? *s++ : 255; } d += d_line_inc; s += s_line_inc; @@ -1133,8 +1276,19 @@ static void fast_rgb_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz unsigned char *d = dst->samples; size_t w = src->w; int h = src->h; - ptrdiff_t d_line_inc = dst->stride - w * (dst->alpha + 4); - ptrdiff_t s_line_inc = src->stride - w * (src->alpha + 3); + int ss = src->s; + int sa = src->alpha; + 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); + + /* 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)) + { + assert("This should never happen" == NULL); + fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps"); + } if ((int)w < 0 || h < 0) return; @@ -1145,29 +1299,56 @@ static void fast_rgb_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz h = 1; } - if (dst->alpha) + if (ss == 0) { - if (src->alpha) + /* Common, no spots case */ + if (da) { - while (h--) + if (sa) { - size_t ww = w; - while (ww--) + while (h--) { - unsigned char c = 255 - s[0]; - unsigned char m = 255 - s[1]; - unsigned char y = 255 - s[2]; - unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y)); - d[0] = c - k; - d[1] = m - k; - d[2] = y - k; - d[3] = k; - d[4] = s[3]; - s += 4; - d += 5; + 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)fz_mini(c, fz_mini(m, y)); + d[0] = c - k; + d[1] = m - k; + d[2] = y - k; + d[3] = k; + d[4] = s[3]; + s += 4; + d += 5; + } + d += d_line_inc; + 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)fz_mini(c, fz_mini(m, y)); + d[0] = c - k; + d[1] = m - k; + d[2] = y - k; + d[3] = k; + d[4] = 255; + s += 3; + d += 5; + } + d += d_line_inc; + s += s_line_inc; } - d += d_line_inc; - s += s_line_inc; } } else @@ -1177,17 +1358,16 @@ static void fast_rgb_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz size_t ww = w; while (ww--) { - unsigned char c = 255 - s[0]; - unsigned char m = 255 - s[1]; - unsigned char y = 255 - s[2]; + unsigned char c = s[0]; + unsigned char m = s[1]; + unsigned char y = s[2]; unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y)); d[0] = c - k; d[1] = m - k; d[2] = y - k; d[3] = k; - d[4] = 255; s += 3; - d += 5; + d += 4; } d += d_line_inc; s += s_line_inc; @@ -1196,23 +1376,27 @@ static void fast_rgb_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz } else { - int si = 3 + src->alpha; - + /* Slower, spots capable version */ while (h--) { + int i; size_t ww = w; while (ww--) { - unsigned char c = 255 - s[0]; - unsigned char m = 255 - s[1]; - unsigned char y = 255 - s[2]; + unsigned char c = s[0]; + unsigned char m = s[1]; + unsigned char y = s[2]; unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y)); d[0] = c - k; d[1] = m - k; d[2] = y - k; d[3] = k; - s += si; + s += 3; d += 4; + for (i=ss; i > 0; i--) + *d++ = *s++; + if (da) + *d++ = sa ? *s++ : 255; } d += d_line_inc; s += s_line_inc; @@ -1226,8 +1410,19 @@ static void fast_bgr_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz unsigned char *d = dst->samples; size_t w = src->w; int h = src->h; - ptrdiff_t d_line_inc = dst->stride - w * (dst->alpha + 4); - ptrdiff_t s_line_inc = src->stride - w * (src->alpha + 3); + int ss = src->s; + int sa = src->alpha; + 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); + + /* 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)) + { + assert("This should never happen" == NULL); + fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps"); + } if ((int)w < 0 || h < 0) return; @@ -1238,29 +1433,56 @@ static void fast_bgr_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz h = 1; } - if (dst->alpha) + if (ss == 0) { - if (src->alpha) + /* Common, no spots case */ + if (da) { - while (h--) + if (sa) { - size_t ww = w; - while (ww--) + while (h--) { - unsigned char c = 255 - s[2]; - unsigned char m = 255 - s[1]; - unsigned char y = 255 - s[0]; - unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y)); - d[0] = c - k; - d[1] = m - k; - d[2] = y - k; - d[3] = k; - d[4] = s[3]; - s += 4; - d += 5; + 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)fz_mini(c, fz_mini(m, y)); + d[0] = c - k; + d[1] = m - k; + d[2] = y - k; + d[3] = k; + d[4] = s[3]; + s += 4; + d += 5; + } + d += d_line_inc; + 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)fz_mini(c, fz_mini(m, y)); + d[0] = c - k; + d[1] = m - k; + d[2] = y - k; + d[3] = k; + d[4] = 255; + s += 3; + d += 5; + } + d += d_line_inc; + s += s_line_inc; } - d += d_line_inc; - s += s_line_inc; } } else @@ -1270,17 +1492,16 @@ static void fast_bgr_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz size_t ww = w; while (ww--) { - unsigned char c = 255 - s[2]; - unsigned char m = 255 - s[1]; - unsigned char y = 255 - s[0]; + unsigned char c = s[2]; + unsigned char m = s[1]; + unsigned char y = s[0]; unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y)); d[0] = c - k; d[1] = m - k; d[2] = y - k; d[3] = k; - d[4] = 255; s += 3; - d += 5; + d += 4; } d += d_line_inc; s += s_line_inc; @@ -1289,23 +1510,27 @@ static void fast_bgr_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz } else { - int si = 3 + src->alpha; - + /* Slower, spots capable version */ while (h--) { + int i; size_t ww = w; while (ww--) { - unsigned char c = 255 - s[2]; - unsigned char m = 255 - s[1]; - unsigned char y = 255 - s[0]; + unsigned char c = s[2]; + unsigned char m = s[1]; + unsigned char y = s[0]; unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y)); d[0] = c - k; d[1] = m - k; d[2] = y - k; d[3] = k; - s += si; + s += 3; d += 4; + for (i=ss; i > 0; i--) + *d++ = *s++; + if (da) + *d++ = sa ? *s++ : 255; } d += d_line_inc; s += s_line_inc; @@ -1319,8 +1544,19 @@ static void fast_cmyk_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, f unsigned char *d = dst->samples; size_t w = src->w; int h = src->h; - ptrdiff_t d_line_inc = dst->stride - w * (dst->alpha + 1); - ptrdiff_t s_line_inc = src->stride - w * (src->alpha + 4); + int ss = src->s; + int sa = src->alpha; + 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); + + /* 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)) + { + assert("This should never happen" == NULL); + fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps"); + } if ((int)w < 0 || h < 0) return; @@ -1331,25 +1567,48 @@ static void fast_cmyk_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, f h = 1; } - if (dst->alpha) + if (ss == 0) { - if (src->alpha) + /* Common, no spots case */ + if (da) { - while (h--) + if (sa) { - size_t ww = w; - while (ww--) + while (h--) { - unsigned char c = fz_mul255(s[0], 77); - unsigned char m = fz_mul255(s[1], 150); - unsigned char y = fz_mul255(s[2], 28); - d[0] = 255 - (unsigned char)fz_mini(c + m + y + s[3], 255); - d[1] = s[4]; - s += 5; - d += 2; + size_t ww = w; + while (ww--) + { + unsigned char c = fz_mul255(s[0], 77); + unsigned char m = fz_mul255(s[1], 150); + unsigned char y = fz_mul255(s[2], 28); + d[0] = 255 - (unsigned char)fz_mini(c + m + y + s[3], 255); + d[1] = s[4]; + s += 5; + d += 2; + } + d += d_line_inc; + s += s_line_inc; + } + } + else + { + while (h--) + { + size_t ww = w; + while (ww--) + { + unsigned char c = fz_mul255(s[0], 77); + unsigned char m = fz_mul255(s[1], 150); + unsigned char y = fz_mul255(s[2], 28); + d[0] = 255 - (unsigned char)fz_mini(c + m + y + s[3], 255); + d[1] = 255; + s += 3; + d += 2; + } + d += d_line_inc; + s += s_line_inc; } - d += d_line_inc; - s += s_line_inc; } } else @@ -1363,9 +1622,8 @@ static void fast_cmyk_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, f unsigned char m = fz_mul255(s[1], 150); unsigned char y = fz_mul255(s[2], 28); d[0] = 255 - (unsigned char)fz_mini(c + m + y + s[3], 255); - d[1] = 255; - s += 3; - d += 2; + s += 4; + d++; } d += d_line_inc; s += s_line_inc; @@ -1374,9 +1632,10 @@ static void fast_cmyk_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, f } else { - int si = 4 + src->alpha; + /* Slower, spots capable version */ while (h--) { + int i; size_t ww = w; while (ww--) { @@ -1384,8 +1643,12 @@ static void fast_cmyk_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, f unsigned char m = fz_mul255(s[1], 150); unsigned char y = fz_mul255(s[2], 28); d[0] = 255 - (unsigned char)fz_mini(c + m + y + s[3], 255); - s += si; + s += 4; d++; + for (i=ss; i > 0; i--) + *d++ = *s++; + if (da) + *d++ = sa ? *s++ : 255; } d += d_line_inc; s += s_line_inc; @@ -1726,11 +1989,22 @@ static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz unsigned char *d = dst->samples; size_t w = src->w; int h = src->h; - ptrdiff_t d_line_inc = dst->stride - w * (dst->alpha + 3); - ptrdiff_t s_line_inc = src->stride - w * (src->alpha + 4); + int ss = src->s; + int sa = src->alpha; + 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); 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)) + { + assert("This should never happen" == NULL); + fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps"); + } + if ((int)w < 0 || h < 0) return; @@ -1748,32 +2022,55 @@ static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz h = 1; } - if (dst->alpha) + if (ss == 0) { - if (src->alpha) + /* Common, no spots case */ + if (da) { -#ifdef ARCH_ARM - if (h == 1) + if (sa) { - fast_cmyk_to_rgb_ARM(d, s, w); - return; + #ifdef ARCH_ARM + if (h == 1) + { + fast_cmyk_to_rgb_ARM(d, s, w); + return; + } + #endif + 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; + d[3] = s[4]; + s += 5; + d += 4; + } + d += d_line_inc; + s += s_line_inc; + } } -#endif - while (h--) + else { - size_t ww = w; - while (ww--) + while (h--) { - 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; - d[3] = s[4]; - s += 5; - d += 4; + 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; + d[3] = 255; + s += 4; + d += 4; + } + d += d_line_inc; + s += s_line_inc; } - d += d_line_inc; - s += s_line_inc; } } else @@ -1787,9 +2084,8 @@ static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz d[0] = r; d[1] = g; d[2] = b; - d[3] = 255; s += 4; - d += 4; + d += 3; } d += d_line_inc; s += s_line_inc; @@ -1798,11 +2094,10 @@ static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz } else { - /* We shouldn't lose alpha */ - assert(src->alpha == 0); - + /* Slower, spots capable version */ while (h--) { + int i; size_t ww = w; while (ww--) { @@ -1812,6 +2107,10 @@ static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz d[2] = b; s += 4; d += 3; + for (i=ss; i > 0; i--) + *d++ = *s++; + if (da) + *d++ = sa ? *s++ : 255; } d += d_line_inc; s += s_line_inc; @@ -1825,11 +2124,22 @@ static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz unsigned char *d = dst->samples; size_t w = src->w; int h = src->h; - ptrdiff_t d_line_inc = dst->stride - w * (dst->alpha + 3); - ptrdiff_t s_line_inc = src->stride - w * (src->alpha + 4); + int ss = src->s; + int sa = src->alpha; + 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); 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)) + { + assert("This should never happen" == NULL); + fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps"); + } + if ((int)w < 0 || h < 0) return; @@ -1847,29 +2157,55 @@ static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz h = 1; } - if (dst->alpha) + if (ss == 0) { - if (src->alpha) + /* Common, no spots case */ + if (da) { - while (h--) + if (sa) { - size_t ww = w; - while (ww--) + while (h--) { - 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; - d[3] = s[4]; - s += 5; - d += 4; + 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; + d[3] = s[4]; + s += 5; + d += 4; + } + d += d_line_inc; + s += s_line_inc; + } + } + else + { + 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; + d[3] = 255; + s += 4; + d += 4; + } + d += d_line_inc; + s += s_line_inc; } - d += d_line_inc; - s += s_line_inc; } } else { + /* We shouldn't lose alpha */ + assert(src->alpha == 0); + while (h--) { size_t ww = w; @@ -1879,9 +2215,8 @@ static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz d[0] = b; d[1] = g; d[2] = r; - d[3] = 255; s += 4; - d += 4; + d += 3; } d += d_line_inc; s += s_line_inc; @@ -1890,11 +2225,10 @@ static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz } else { - /* We shouldn't lose alpha */ - assert(src->alpha == 0); - + /* Slower, spots capable version */ while (h--) { + int i; size_t ww = w; while (ww--) { @@ -1904,6 +2238,10 @@ static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz d[2] = r; s += 4; d += 3; + for (i=ss; i > 0; i--) + *d++ = *s++; + if (da) + *d++ = sa ? *s++ : 255; } d += d_line_inc; s += s_line_inc; @@ -1917,8 +2255,19 @@ static void fast_rgb_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_ unsigned char *d = dst->samples; size_t w = src->w; int h = src->h; - ptrdiff_t d_line_inc = dst->stride - w * (dst->alpha + 3); - ptrdiff_t s_line_inc = src->stride - w * (src->alpha + 3); + int ss = src->s; + int sa = src->alpha; + 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); + + /* 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)) + { + assert("This should never happen" == NULL); + fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps"); + } if ((int)w < 0 || h < 0) return; @@ -1929,21 +2278,41 @@ static void fast_rgb_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_ h = 1; } - if (dst->alpha) + if (ss == 0) { - if (src->alpha) + /* Common, no spots case */ + if (da) { - while (h--) + if (sa) { - size_t ww = w; - while (ww--) + while (h--) { - d[0] = s[2]; - d[1] = s[1]; - d[2] = s[0]; - d[3] = s[3]; - s += 4; - d += 4; + size_t ww = w; + while (ww--) + { + d[0] = s[2]; + d[1] = s[1]; + d[2] = s[0]; + d[3] = s[3]; + s += 4; + d += 4; + } + } + } + else + { + while (h--) + { + size_t ww = w; + while (ww--) + { + d[0] = s[2]; + d[1] = s[1]; + d[2] = s[0]; + d[3] = 255; + s += 3; + d += 4; + } } } } @@ -1957,20 +2326,18 @@ static void fast_rgb_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_ d[0] = s[2]; d[1] = s[1]; d[2] = s[0]; - d[3] = 255; s += 3; - d += 4; + d += 3; } } } } else { - /* We shouldn't lose alpha */ - assert(src->alpha == 0); - + /* Slower, spots capable version */ while (h--) { + int i; size_t ww = w; while (ww--) { @@ -1979,7 +2346,13 @@ static void fast_rgb_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_ d[2] = s[0]; s += 3; d += 3; + for (i=ss; i > 0; i--) + *d++ = *s++; + if (da) + *d++ = sa ? *s++ : 255; } + d += d_line_inc; + s += s_line_inc; } } } @@ -2077,19 +2450,21 @@ icc_base_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorsp { fz_colorspace *srcs = src->colorspace; fz_colorspace *base_cs = get_base_icc_space(ctx, srcs); - int i; + int i, j; unsigned char *inputpos, *outputpos; fz_pixmap *base; fz_irect bbox; int h, len; float src_f[FZ_MAX_COLORS], des_f[FZ_MAX_COLORS]; int sn = src->n; + int sc = sn - src->alpha - src->s; int stride_src = src->stride - src->w * sn; int stride_base; - int bn; + int bn, bc; base = fz_new_pixmap_with_bbox(ctx, base_cs, fz_pixmap_bbox(ctx, src, &bbox), src->seps, src->alpha); bn = base->n; + bc = base->n - base->alpha - base->s; stride_base = base->stride - base->w * bn; inputpos = src->samples; @@ -2101,14 +2476,18 @@ icc_base_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorsp len = src->w; while (len--) { - for (i = 0; i < sn; i++) + /* Convert the actual colors */ + for (i = 0; i < sc; i++) src_f[i] = (float) inputpos[i] / 255.0; convert_to_icc_base(ctx, srcs, src_f, des_f); base_cs->clamp(base_cs, des_f, des_f); - for (i = 0; i < bn; i++) - outputpos[i] = des_f[i] * 255.0; + for (j = 0; j < bc; j++) + outputpos[j] = des_f[j] * 255.0; + /* Copy spots and alphas unchanged */ + for (; i < sn; i++, j++) + outputpos[j] = inputpos[i]; outputpos += bn; inputpos += sn; @@ -2294,7 +2673,7 @@ std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace * memcpy(d, color, dstn); s += srcn; d += dstn; - if (dst->alpha) + if (da) *d++ = (sa ? *s : 255); s += sa; } @@ -2308,7 +2687,7 @@ std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace * fz_hash_insert(ctx, lookup, s - srcn, d - dstn); - if (dst->alpha) + if (da) *d++ = (sa ? *s : 255); s += sa; } -- cgit v1.2.3