/* currentcmykcolor */ int gs_currentcmykcolor(const gs_state *pgs, float pr4[4]) { const gs_client_color *pcc = pgs->ccolor; switch ( pgs->color_space->type->index ) { case gs_color_space_index_DeviceGray: pr4[0] = pr4[1] = pr4[2] = 0.0; pr4[3] = 1.0 - pcc->paint.values[0]; break; case gs_color_space_index_DeviceRGB: { frac fcmyk[4]; color_rgb_to_cmyk( float2frac(pcc->paint.values[0]), float2frac(pcc->paint.values[1]), float2frac(pcc->paint.values[2]), (const gs_imager_state *)pgs, fcmyk); pr4[0] = frac2float(fcmyk[0]); pr4[1] = frac2float(fcmyk[1]); pr4[2] = frac2float(fcmyk[2]); pr4[3] = frac2float(fcmyk[3]); } break; case gs_color_space_index_DeviceCMYK: pr4[0] = pcc->paint.values[0]; pr4[1] = pcc->paint.values[1]; pr4[2] = pcc->paint.values[2]; pr4[3] = pcc->paint.values[3]; break; default: pr4[0] = pr4[1] = pr4[2] = 0.0; pr4[3] = 1.0; } return 0; }
static void cmyk_cs_to_spotn_cm(gx_device * dev, frac c, frac m, frac y, frac k, frac out[]) { /* TO_DO_DEVICEN This routine needs to include the effects of the SeparationOrder array */ xcf_device *xdev = (xcf_device *)dev; int n = xdev->separation_names.num_names; icmLuBase *luo = xdev->lu_cmyk; int i; if (luo != NULL) { double in[4]; double tmp[MAX_CHAN]; int outn = xdev->lu_cmyk_outn; in[0] = frac2float(c); in[1] = frac2float(m); in[2] = frac2float(y); in[3] = frac2float(k); luo->lookup(luo, tmp, in); for (i = 0; i < outn; i++) out[i] = float2frac(tmp[i]); for (; i < n + 4; i++) out[i] = 0; } else { /* If no profile given, assume CMYK */ out[0] = c; out[1] = m; out[2] = y; out[3] = k; for(i = 0; i < n; i++) /* Clear spot colors */ out[4 + i] = 0; } }
static void rgb_cs_to_spotn_cm(gx_device * dev, const gs_imager_state *pis, frac r, frac g, frac b, frac out[]) { /* TO_DO_DEVICEN This routine needs to include the effects of the SeparationOrder array */ xcf_device *xdev = (xcf_device *)dev; int n = xdev->separation_names.num_names; icmLuBase *luo = xdev->lu_rgb; int i; if (luo != NULL) { double in[3]; double tmp[MAX_CHAN]; int outn = xdev->lu_rgb_outn; in[0] = frac2float(r); in[1] = frac2float(g); in[2] = frac2float(b); luo->lookup(luo, tmp, in); for (i = 0; i < outn; i++) out[i] = float2frac(tmp[i]); for (; i < n + 4; i++) out[i] = 0; } else { frac cmyk[4]; color_rgb_to_cmyk(r, g, b, pis, cmyk); cmyk_cs_to_spotn_cm(dev, cmyk[0], cmyk[1], cmyk[2], cmyk[3], out); } }
static int gx_concretize_ICC( const gs_client_color * pcc, const gs_color_space * pcs, frac * pconc, const gs_gstate * pgs, gx_device *dev) { gsicc_link_t *icc_link; gsicc_rendering_param_t rendering_params; unsigned short psrc[GS_CLIENT_COLOR_MAX_COMPONENTS], psrc_cm[GS_CLIENT_COLOR_MAX_COMPONENTS]; int k; unsigned short *psrc_temp; int num_des_comps; int code; cmm_dev_profile_t *dev_profile; code = dev_proc(dev, get_profile)(dev, &dev_profile); if (code < 0) return code; num_des_comps = gsicc_get_device_profile_comps(dev_profile); /* Define the rendering intents. */ rendering_params.black_point_comp = pgs->blackptcomp; rendering_params.graphics_type_tag = dev->graphics_type_tag; rendering_params.override_icc = false; rendering_params.preserve_black = gsBKPRESNOTSPECIFIED; rendering_params.rendering_intent = pgs->renderingintent; rendering_params.cmm = gsCMM_DEFAULT; for (k = 0; k < pcs->cmm_icc_profile_data->num_comps; k++) { psrc[k] = (unsigned short) (pcc->paint.values[k]*65535.0); } /* Get a link from the cache, or create if it is not there. Get 16 bit profile */ icc_link = gsicc_get_link(pgs, dev, pcs, NULL, &rendering_params, pgs->memory); if (icc_link == NULL) { #ifdef DEBUG gs_warn("Could not create ICC link: Check profiles"); #endif return -1; } /* Transform the color */ if (icc_link->is_identity) { psrc_temp = &(psrc[0]); } else { /* Transform the color */ psrc_temp = &(psrc_cm[0]); (icc_link->procs.map_color)(dev, icc_link, psrc, psrc_temp, 2); } /* This needs to be optimized */ for (k = 0; k < num_des_comps; k++){ pconc[k] = float2frac(((float) psrc_temp[k])/65535.0); } /* Release the link */ gsicc_release_link(icc_link); return 0; }
/* Convert RGB to HSB. */ static void color_rgb_to_hsb(floatp r, floatp g, floatp b, float hsb[3]) { frac red = float2frac(r), green = float2frac(g), blue = float2frac(b); #define rhue hsb[0] #define rsat hsb[1] #define rbri hsb[2] if (red == green && green == blue) { rhue = 0; /* arbitrary */ rsat = 0; rbri = r; /* pick any one */ } else { /* Convert rgb to hsb */ frac V, Temp, diff; long H; V = (red > green ? red : green); if (blue > V) V = blue; Temp = (red > green ? green : red); if (blue < Temp) Temp = blue; diff = V - Temp; if (V == red) H = (green - blue) * frac_1_long / diff; else if (V == green) H = (blue - red) * frac_1_long / diff + 2 * frac_1_long; else /* V == blue */ H = (red - green) * frac_1_long / diff + 4 * frac_1_long; if (H < 0) H += 6 * frac_1_long; rhue = H / (frac_1 * 6.0); rsat = diff / (float)V; rbri = frac2float(V); } #undef rhue #undef rsat #undef rbri }
/* dotablefilter() * * * * */ static int32_t dotablefilter (CSOUND *csound, TABFILT *p) { int32 loopcount; /* Loop counter. Set by the length of the dest table.*/ int32 indx = 0; /* Index to be added to offsets */ int32 indx2 = 0; /*index into source table*/ MYFLT *based, *bases; /* Base addresses of the two tables.*/ int32 masks; /* Binary masks for the source table */ MYFLT *pdest, *ps; MYFLT threshold; int32 ftype; MYFLT previous = FL(0.0); //int32 sourcelength; ftype = (int32) *p->ftype; threshold = Digest (*p->threshold); loopcount = p->funcd->flen; //sourcelength = loopcount; /* Now get the base addresses and length masks of the tables. */ based = p->funcd->ftable; bases = p->funcs->ftable; masks = p->funcs->lenmask; do { /* Create source pointers by ANDing index with mask, and adding to base * address. This causes source addresses to wrap around if the * destination table is longer. * Destination address is simply the index plus the base address since * we know we will be writing within the table. */ pdest = based + indx; ps = bases + (masks & indx2); switch (ftype) { default: case 0: *pdest = *ps; indx++; indx2++; break; case 1: { /* filter all above threshold */ int32_t p, q = 0; float2frac (csound, *ps, &p, &q); if (Digest (q) > threshold) { indx2++; } else { *pdest = *ps; indx++; indx2++; } break; } case 2: { /* filter all below threshold */ int32_t p, q = 0; float2frac (csound, *ps, &p, &q); if (Digest (q) < threshold) { indx2++; } else { *pdest = *ps; indx++; indx2++; } break; } case 3: { /* generate IOIs from source and write into destination */ if (*ps == FL(0.0)) { /* skip zeros in source table */ indx2++; break; } *pdest = *ps - previous; previous = *ps; indx++; indx2++; break; } } } while (--loopcount); *p->result = indx; return OK; }
/* Convert HSB to RGB. */ static void color_hsb_to_rgb(floatp hue, floatp saturation, floatp brightness, float rgb[3]) { if (saturation == 0) { rgb[0] = rgb[1] = rgb[2] = brightness; } else { /* Convert hsb to rgb. */ /* We rely on the fact that the product of two */ /* fracs fits into an unsigned long. */ floatp h6 = hue * 6; ulong V = float2frac(brightness); /* force arithmetic to long */ frac S = float2frac(saturation); int I = (int)h6; ulong F = float2frac(h6 - I); /* ditto */ /* M = V*(1-S), N = V*(1-S*F), K = V*(1-S*(1-F)) = M-N+V */ frac M = V * (frac_1_long - S) / frac_1_long; frac N = V * (frac_1_long - S * F / frac_1_long) / frac_1_long; frac K = M - N + V; frac R, G, B; switch (I) { default: R = V; G = K; B = M; break; case 1: R = N; G = V; B = M; break; case 2: R = M; G = V; B = K; break; case 3: R = M; G = N; B = V; break; case 4: R = K; G = M; B = V; break; case 5: R = V; G = M; B = N; break; } rgb[0] = frac2float(R); rgb[1] = frac2float(G); rgb[2] = frac2float(B); #ifdef DEBUG if (gs_debug_c('c')) { dlprintf7("[c]hsb(%g,%g,%g)->VSFI(%ld,%d,%ld,%d)->\n", hue, saturation, brightness, V, S, F, I); dlprintf6(" RGB(%d,%d,%d)->rgb(%g,%g,%g)\n", R, G, B, rgb[0], rgb[1], rgb[2]); } #endif } }
/* * Finish "remapping" a CIEBased color only to the XYZ intermediate values. * Note that we can't currently represent values outside the range [0..1]: * this is a bug that we will have to address someday. */ static frac float2frac_clamp(floatp x) { return float2frac((x <= 0 ? 0 : x >= 1 ? 1 : x)); }
static int gx_concretize_Separation(const gs_client_color *pc, const gs_color_space *pcs, frac *pconc, const gs_imager_state *pis, gx_device *dev) { int code; gs_client_color cc; gs_color_space *pacs = pcs->base_space; bool is_lab; int k; int num_des_comps = dev->color_info.num_components; if (pcs->params.separation.sep_type == SEP_OTHER && pcs->params.separation.use_alt_cspace) { gs_device_n_map *map = pcs->params.separation.map; /* First see if we have a named color object that we can use to try to map from the spot color into device values. */ if (pis->icc_manager->device_named != NULL) { /* There is a table present. If we have the colorant name then get the device values */ gx_color_value device_values[GX_DEVICE_COLOR_MAX_COMPONENTS]; const gs_separation_name name = pcs->params.separation.sep_name; byte *pname; uint name_size; gsicc_rendering_param_t rendering_params; /* Define the rendering intents. */ rendering_params.black_point_comp = BP_ON; rendering_params.graphics_type_tag = GS_PATH_TAG; rendering_params.rendering_intent = pis->renderingintent; pcs->params.separation.get_colorname_string(pis->memory, name, &pname, &name_size); code = gsicc_transform_named_color(pc->paint.values[0], pname, name_size, device_values, pis, dev, NULL, &rendering_params); if (code == 0) { for (k = 0; k < num_des_comps; k++){ pconc[k] = float2frac(((float) device_values[k])/65535.0); } return(0); } } /* Check the 1-element cache first. */ if (map->cache_valid && map->tint[0] == pc->paint.values[0]) { int i, num_out = gs_color_space_num_components(pacs); for (i = 0; i < num_out; ++i) pconc[i] = map->conc[i]; return 0; } code = (*pcs->params.separation.map->tint_transform) (pc->paint.values, &cc.paint.values[0], pis, pcs->params.separation.map->tint_transform_data); if (code < 0) return code; /* First check if this was PS based. */ if (gs_color_space_is_PSCIE(pacs)) { /* If we have not yet create the profile do that now */ if (pacs->icc_equivalent == NULL) { gs_colorspace_set_icc_equivalent(pacs, &(is_lab), pis->memory); } /* Use the ICC equivalent color space */ pacs = pacs->icc_equivalent; } if (pacs->cmm_icc_profile_data->data_cs == gsCIELAB) { /* Get the data in a form that is concrete for the CMM */ cc.paint.values[0] /= 100.0; cc.paint.values[1] = (cc.paint.values[1]+128)/255.0; cc.paint.values[2] = (cc.paint.values[2]+128)/255.0; } return cs_concretize_color(&cc, pacs, pconc, pis, dev); } else { pconc[0] = gx_unit_frac(pc->paint.values[0]); } return 0; }
static int gx_concretize_DeviceN(const gs_client_color * pc, const gs_color_space * pcs, frac * pconc, const gs_imager_state * pis, gx_device *dev) { int code, tcode = 0; gs_client_color cc; gs_color_space *pacs = (gs_color_space*) (pcs->base_space); gs_device_n_map *map = pcs->params.device_n.map; bool is_lab; int k; int num_des_comps = dev->color_info.num_components; gsicc_namedcolor_t *named_color; const gs_separation_name *names = pcs->params.device_n.names; int num_src_comps = pcs->params.device_n.num_components; #ifdef DEBUG /* * Verify that the color space and imager state info match. */ if (pcs->id != pis->color_component_map.cspace_id) dmprintf(dev->memory, "gx_concretize_DeviceN: color space id mismatch"); #endif /* * Check if we need to map into the alternate color space. * We must preserve tcode for implementing a semi-hack in the interpreter. */ if (pis->color_component_map.use_alt_cspace) { /* First see if we have a named color object that we can use to try to map from the spot color into device values. */ if (pis->icc_manager->device_named != NULL) { /* There is a table present. If we have the colorant name then get the device values */ gx_color_value device_values[GX_DEVICE_COLOR_MAX_COMPONENTS]; byte *pname; uint name_size; gsicc_rendering_param_t rendering_params; /* Define the rendering intents. */ rendering_params.black_point_comp = pis->blackptcomp; rendering_params.graphics_type_tag = dev->graphics_type_tag; rendering_params.override_icc = false; rendering_params.preserve_black = gsBKPRESNOTSPECIFIED; rendering_params.rendering_intent = pis->renderingintent; rendering_params.cmm = gsCMM_DEFAULT; /* Allocate and initialize name structure */ named_color = (gsicc_namedcolor_t*) gs_alloc_bytes(dev->memory, num_src_comps * sizeof(gsicc_namedcolor_t), "gx_remap_concrete_DeviceN"); for (k = 0; k < num_src_comps; k++) { pcs->params.device_n.get_colorname_string(dev->memory, names[k], &pname, &name_size); named_color[k].colorant_name = (char*) pname; named_color[k].name_size = name_size; } code = gsicc_transform_named_color(pc->paint.values, named_color, num_src_comps, device_values, pis, dev, NULL, &rendering_params); gs_free_object(dev->memory, named_color, "gx_remap_concrete_DeviceN"); if (code == 0) { for (k = 0; k < num_des_comps; k++){ pconc[k] = float2frac(((float) device_values[k])/65535.0); } return(0); } } /* Check the 1-element cache first. */ if (map->cache_valid) { int i; for (i = pcs->params.device_n.num_components; --i >= 0;) { if (map->tint[i] != pc->paint.values[i]) break; } if (i < 0) { int num_out = gs_color_space_num_components(pacs); for (i = 0; i < num_out; ++i) pconc[i] = map->conc[i]; return 0; } } tcode = (*pcs->params.device_n.map->tint_transform) (pc->paint.values, &cc.paint.values[0], pis, pcs->params.device_n.map->tint_transform_data); (*pacs->type->restrict_color)(&cc, pacs); if (tcode < 0) return tcode; /* First check if this was PS based. */ if (gs_color_space_is_PSCIE(pacs)) { /* We may have to rescale data to 0 to 1 range */ rescale_cie_colors(pacs, &cc); /* If we have not yet created the profile do that now */ if (pacs->icc_equivalent == NULL) { gs_colorspace_set_icc_equivalent(pacs, &(is_lab), pis->memory); } /* Use the ICC equivalent color space */ pacs = pacs->icc_equivalent; } if (pacs->cmm_icc_profile_data->data_cs == gsCIELAB || pacs->cmm_icc_profile_data->islab) { /* Get the data in a form that is concrete for the CMM */ cc.paint.values[0] /= 100.0; cc.paint.values[1] = (cc.paint.values[1]+128)/255.0; cc.paint.values[2] = (cc.paint.values[2]+128)/255.0; } code = cs_concretize_color(&cc, pacs, pconc, pis, dev); } else { int i; for (i = num_src_comps; --i >= 0;) pconc[i] = gx_unit_frac(pc->paint.values[i]); return 0; } return (code < 0 || tcode == 0 ? code : tcode); }