Example #1
0
/* Get the link from the CMS, but include proofing.
    We need to note that as an option in the rendering params.  If we are doing
    transparency, that would only occur at the top of the stack
TODO:  Add error checking */
gcmmhlink_t
gscms_get_link_proof(gcmmhprofile_t  lcms_srchandle,
                    gcmmhprofile_t lcms_deshandle, gcmmhprofile_t lcms_proofhandle,
                    gsicc_rendering_param_t *rendering_params)
{
    DWORD src_data_type,des_data_type;
    icColorSpaceSignature src_color_space,des_color_space;
    int src_nChannels,des_nChannels;

    /* Get the data types */
    src_color_space  = cmsGetColorSpace(lcms_srchandle);
    des_color_space  = cmsGetColorSpace(lcms_deshandle);
    src_nChannels = _cmsChannelsOf(src_color_space);
    des_nChannels = _cmsChannelsOf(des_color_space);
    /* For now, just do single byte data, interleaved.  We can change this when we
       use the transformation. */
    src_data_type= (CHANNELS_SH(src_nChannels)|BYTES_SH(1));
    des_data_type= (CHANNELS_SH(des_nChannels)|BYTES_SH(1));
    /* Create the link.  Note the gamut check alarm */
    return(cmsCreateProofingTransform(lcms_srchandle, src_data_type,
                                      lcms_deshandle, des_data_type,
                                      lcms_proofhandle,
                                      rendering_params->rendering_intent,
                                      INTENT_ABSOLUTE_COLORIMETRIC,
                                      cmsFLAGS_GAMUTCHECK | cmsFLAGS_SOFTPROOFING ));
}
Example #2
0
/* Get the link from the CMS, but include proofing and/or a device link  
   profile. */
gcmmhlink_t
gscms_get_link_proof_devlink(gcmmhprofile_t lcms_srchandle,
                             gcmmhprofile_t lcms_proofhandle,
                             gcmmhprofile_t lcms_deshandle, 
                             gcmmhprofile_t lcms_devlinkhandle, 
                             gsicc_rendering_param_t *rendering_params,
                             bool src_dev_link, int cmm_flags,
                             gs_memory_t *mem)
{
    DWORD src_data_type,des_data_type;
    icColorSpaceSignature src_color_space,des_color_space;
    int src_nChannels,des_nChannels;
    int lcms_src_color_space, lcms_des_color_space;
    cmsHPROFILE hProfiles[5]; 
    int nProfiles = 0;

   /* First handle all the source stuff */
    src_color_space  = cmsGetColorSpace(lcms_srchandle);
    lcms_src_color_space = _cmsLCMScolorSpace(src_color_space);
    /* littlecms returns -1 for types it does not (but should) understand */
    if (lcms_src_color_space < 0) lcms_src_color_space = 0;
    src_nChannels = _cmsChannelsOf(src_color_space);
    /* For now, just do single byte data, interleaved.  We can change this
      when we use the transformation. */
    src_data_type = (COLORSPACE_SH(lcms_src_color_space)|
                        CHANNELS_SH(src_nChannels)|BYTES_SH(2));    
    if (lcms_deshandle != NULL) {
        des_color_space  = cmsGetColorSpace(lcms_deshandle);
    } else {
        /* We must have a device link profile. */
        des_color_space = cmsGetPCS(lcms_deshandle);
    }
    lcms_des_color_space = _cmsLCMScolorSpace(des_color_space);
    if (lcms_des_color_space < 0) lcms_des_color_space = 0;
    des_nChannels = _cmsChannelsOf(des_color_space);
    des_data_type = (COLORSPACE_SH(lcms_des_color_space)|
                        CHANNELS_SH(des_nChannels)|BYTES_SH(2));
    /* lcms proofing transform has a clunky API and can't include the device 
       link profile if we have both. So use cmsCreateMultiprofileTransform 
       instead and round trip the proofing profile. */
    hProfiles[nProfiles++] = lcms_srchandle;
    if (lcms_proofhandle != NULL) {
        hProfiles[nProfiles++] = lcms_proofhandle;
        hProfiles[nProfiles++] = lcms_proofhandle;
    }
    hProfiles[nProfiles++] = lcms_deshandle;
    if (lcms_devlinkhandle != NULL) {
        hProfiles[nProfiles++] = lcms_devlinkhandle;
    }
    return(cmsCreateMultiprofileTransform(hProfiles, nProfiles, src_data_type, 
                                          des_data_type, rendering_params->rendering_intent, 
                                          (cmm_flags | cmsFLAGS_BLACKPOINTCOMPENSATION | 
                                           cmsFLAGS_HIGHRESPRECALC |
                                           cmsFLAGS_NOTCACHE)));
}
void IccColorProfile::calculateFloatUIMinMax(void)
{
    QVector<KoChannelInfo::DoubleRange> &ret = d->shared->uiMinMaxes;

    cmsHPROFILE cprofile = d->shared->lcmsProfile->lcmsProfile();
    Q_ASSERT(cprofile);

    cmsColorSpaceSignature color_space_sig = cmsGetColorSpace(cprofile);
    unsigned int num_channels = cmsChannelsOf(color_space_sig);
    unsigned int color_space_mask = _cmsLCMScolorSpace(color_space_sig);

    Q_ASSERT(num_channels>=1 && num_channels <=4);  // num_channels==1 is for grayscale, we need to handle it
    Q_ASSERT(color_space_mask);

    // to try to find the max range of float/doubles for this profile,
    // pass in min/max int and make the profile convert that
    // this is far from perfect, we need a better way, if possible to get the "bounds" of a profile

    uint16_t in_min_pixel[4] = {0,0,0,0};
    uint16_t in_max_pixel[4] = {0xFFFF,0xFFFF,0xFFFF,0xFFFF};
    double out_min_pixel[4] = {0,0,0,0};
    double out_max_pixel[4] = {0,0,0,0};

    cmsHTRANSFORM trans = cmsCreateTransform(
        cprofile,
        (COLORSPACE_SH(color_space_mask)|CHANNELS_SH(num_channels)|BYTES_SH(2)),
        cprofile,
        (COLORSPACE_SH(color_space_mask)|FLOAT_SH(1)|CHANNELS_SH(num_channels)|BYTES_SH(0)), //NOTE THAT 'BYTES' FIELD IS SET TO ZERO ON DLB because 8 bytes overflows the bitfield
        INTENT_PERCEPTUAL, 0);      // does the intent matter in this case?

    if (trans) {
        cmsDoTransform(trans, in_min_pixel, out_min_pixel, 1);
        cmsDoTransform(trans, in_max_pixel, out_max_pixel, 1);
        cmsDeleteTransform(trans);
    }//else, we'll just default to [0..1] below

    ret.resize(num_channels);
    for (unsigned int i=0; i<num_channels; ++i) {
        if (out_min_pixel[i] < out_max_pixel[i]) {
            ret[i].minVal = out_min_pixel[i];
            ret[i].maxVal = out_max_pixel[i];
        } else {
            // aparently we can't even guarentee that converted_to_double(0x0000) < converted_to_double(0xFFFF)
            // assume [0..1] in such cases
            // we need to find a really solid way of determining the bounds of a profile, if possible
            ret[i].minVal = 0;
            ret[i].maxVal = 1;
        }
    }
}
Example #4
0
static cmsUInt32Number
determine_lcms_format (const Babl *babl, cmsHPROFILE profile)
{
  cmsUInt32Number format = COLORSPACE_SH (PT_ANY);
  gint channels, bpc, alpha;
  const Babl *type;

  channels = cmsChannelsOf (cmsGetColorSpace (profile));
  alpha = babl_format_get_n_components (babl) - channels;
  bpc = babl_format_get_bytes_per_pixel (babl)
          / babl_format_get_n_components (babl);

  type = babl_format_get_type (babl, 0);
  if (type == babl_type ("half") ||
      type == babl_type ("float") ||
      type == babl_type ("double"))
    format |= FLOAT_SH (1);

  /* bpc == 8 overflows the bitfield otherwise */
  bpc &= 0x07;

  /*
   * This is needed so the alpha component lines up with RGBA float
   * for our memcpy hack later on.
   */
  if (alpha > 1 || (alpha && channels != 3))
    return 0;

  format |= EXTRA_SH (alpha) | CHANNELS_SH (channels) | BYTES_SH (bpc);
  return format;
}
Example #5
0
static cmsUInt32Number ComputeFormatDescriptor (int OutColorSpace, int bps)
{
  int IsPlanar  = 0;
  int Channels  = 3;
  int IsFlt = 0;
  return (FLOAT_SH(IsFlt)|COLORSPACE_SH(OutColorSpace)|PLANAR_SH(IsPlanar)|CHANNELS_SH(Channels)|BYTES_SH(bps));
}
Example #6
0
// Rearrange pixel type to build output descriptor
static
cmsUInt32Number ComputeOutputFormatDescriptor(cmsUInt32Number dwInput, int OutColorSpace)
{
	int IsPlanar  = T_PLANAR(dwInput);
	int Channels  = 0;
	int Flavor    = 0;

	switch (OutColorSpace) {

   case PT_GRAY:
	   Channels = 1;
	   break;
   case PT_RGB:
   case PT_CMY:
   case PT_Lab:
   case PT_YUV:
   case PT_YCbCr:
	   Channels = 3;
	   break;

   case PT_CMYK:
	   if (Compressor.write_Adobe_marker)   // Adobe keeps CMYK inverted, so change flavor to chocolate
		   Flavor = 1;
	   Channels = 4;
	   break;
   default:
	   FatalError("Unsupported output color space");
	}

	return (COLORSPACE_SH(OutColorSpace)|PLANAR_SH(IsPlanar)|CHANNELS_SH(Channels)|BYTES_SH(1)|FLAVOR_SH(Flavor));
}
Example #7
0
static
cmsUInt32Number GetInputPixelType(void)
{
     int space, bps, extra, ColorChannels, Flavor;

     lIsITUFax         = IsITUFax(Decompressor.marker_list);
     lIsPhotoshopApp13 = HandlePhotoshopAPP13(Decompressor.marker_list);
     lIsEXIF           = HandleEXIF(&Decompressor);

     ColorChannels = Decompressor.num_components;
     extra  = 0;            // Alpha = None
     bps    = 1;            // 8 bits
     Flavor = 0;            // Vanilla

     if (lIsITUFax) {

        space = PT_Lab;
        Decompressor.out_color_space = JCS_YCbCr;  // Fake to don't touch
     }
     else
     switch (Decompressor.jpeg_color_space) {

     case JCS_GRAYSCALE:        // monochrome
              space = PT_GRAY;
              Decompressor.out_color_space = JCS_GRAYSCALE;
              break;

     case JCS_RGB:             // red/green/blue
              space = PT_RGB;
              Decompressor.out_color_space = JCS_RGB;
              break;

     case JCS_YCbCr:               // Y/Cb/Cr (also known as YUV)
              space = PT_RGB;      // Let IJG code to do the conversion
              Decompressor.out_color_space = JCS_RGB;
              break;

     case JCS_CMYK:            // C/M/Y/K
              space = PT_CMYK;
              Decompressor.out_color_space = JCS_CMYK;
              if (Decompressor.saw_Adobe_marker)            // Adobe keeps CMYK inverted, so change flavor
                                Flavor = 1;                 // from vanilla to chocolate
              break;

     case JCS_YCCK:            // Y/Cb/Cr/K
              space = PT_CMYK;
              Decompressor.out_color_space = JCS_CMYK;
              if (Decompressor.saw_Adobe_marker)            // ditto
                                Flavor = 1;
              break;

     default:
              FatalError("Unsupported color space (0x%x)", Decompressor.jpeg_color_space);
              return 0;
     }

     return (EXTRA_SH(extra)|CHANNELS_SH(ColorChannels)|BYTES_SH(bps)|COLORSPACE_SH(space)|FLAVOR_SH(Flavor));
}
Example #8
0
/* Get the link from the CMS. TODO:  Add error checking */
gcmmhlink_t
gscms_get_link(gcmmhprofile_t  lcms_srchandle,
                    gcmmhprofile_t lcms_deshandle,
                    gsicc_rendering_param_t *rendering_params)
{
    DWORD src_data_type,des_data_type;
    icColorSpaceSignature src_color_space,des_color_space;
    int src_nChannels,des_nChannels;
    int lcms_src_color_space, lcms_des_color_space;

    /* Check for case of request for a transfrom from a device link profile
       in that case, the destination profile is NULL */

   /* First handle all the source stuff */
    src_color_space  = cmsGetColorSpace(lcms_srchandle);
    lcms_src_color_space = _cmsLCMScolorSpace(src_color_space);
    /* littlecms returns -1 for types it does not (but should) understand */
    if (lcms_src_color_space < 0) lcms_src_color_space = 0;
    src_nChannels = _cmsChannelsOf(src_color_space);
    /* For now, just do single byte data, interleaved.  We can change this
      when we use the transformation. */
    src_data_type = (COLORSPACE_SH(lcms_src_color_space)|
                        CHANNELS_SH(src_nChannels)|BYTES_SH(2));

    if (lcms_deshandle != NULL) {
        des_color_space  = cmsGetColorSpace(lcms_deshandle);
    } else {
        /* We must have a device link profile. */
        des_color_space = cmsGetPCS(lcms_deshandle);
    }
    lcms_des_color_space = _cmsLCMScolorSpace(des_color_space);
    if (lcms_des_color_space < 0) lcms_des_color_space = 0;
    des_nChannels = _cmsChannelsOf(des_color_space);
    des_data_type = (COLORSPACE_SH(lcms_des_color_space)|
                        CHANNELS_SH(des_nChannels)|BYTES_SH(2));
/* Create the link */
    return(cmsCreateTransform(lcms_srchandle, src_data_type, lcms_deshandle,
                        des_data_type, rendering_params->rendering_intent,
               (cmsFLAGS_BLACKPOINTCOMPENSATION | cmsFLAGS_HIGHRESPRECALC)));
    /* cmsFLAGS_HIGHRESPRECALC)  cmsFLAGS_NOTPRECALC  cmsFLAGS_LOWRESPRECALC*/
}
DWORD ScLcmsColorMgmtEngineImpl::translateFormatToLcmsFormat(eColorFormat format)
{
	DWORD lFormat = 0;
	if (format == Format_RGB_8)
		lFormat = TYPE_RGB_8;
	if (format == Format_RGB_16)
		lFormat = TYPE_RGB_16;
	if (format == Format_RGBA_8)
		lFormat = TYPE_RGBA_8;
	if (format == Format_RGBA_16)
		lFormat = TYPE_RGBA_16;
	if (format == Format_ARGB_8)
		lFormat = TYPE_ARGB_8;
	if (format == Format_ARGB_16)
		lFormat = TYPE_ARGB_16;
	if (format == Format_BGRA_8)
		lFormat = TYPE_BGRA_8;
	if (format == Format_BGRA_16)
		lFormat = TYPE_BGRA_16;
	if (format == Format_CMYK_8)
		lFormat = TYPE_CMYK_8;
	if (format == Format_CMYK_16)
		lFormat = TYPE_CMYK_16;
	if (format == Format_CMYKA_8)
		lFormat = (COLORSPACE_SH(PT_CMYK)|EXTRA_SH(1)|CHANNELS_SH(4)|BYTES_SH(1));
	if (format == Format_CMYKA_16)
		lFormat = (COLORSPACE_SH(PT_CMYK)|EXTRA_SH(1)|CHANNELS_SH(4)|BYTES_SH(2));
	if (format == Format_YMCK_8)
		lFormat = (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1));
	if (format == Format_YMCK_16)
		lFormat = (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1)|SWAPFIRST_SH(1));
	if (format == Format_GRAY_8)
		lFormat = TYPE_GRAY_8;
	if (format == Format_GRAY_16)
		lFormat = TYPE_GRAY_16;
	if (format == Format_LabA_8)
		lFormat = COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1);
	return lFormat;
}
Example #10
0
// This function creates a named color profile dumping all the contents of transform to a single profile
// In this way, LittleCMS may be used to "group" several named color databases into a single profile.
// It has, however, several minor limitations. PCS is always Lab, which is not very critic since this
// is the normal PCS for named color profiles.
static
cmsHPROFILE CreateNamedColorDevicelink(cmsHTRANSFORM xform)
{
    _cmsTRANSFORM* v = (_cmsTRANSFORM*) xform;
    cmsHPROFILE hICC = NULL;
    int i, nColors;
    cmsNAMEDCOLORLIST *nc2 = NULL, *Original = NULL;

    // Create an empty placeholder
    hICC = cmsCreateProfilePlaceholder(v->ContextID);
    if (hICC == NULL) return NULL;

    // Critical information
    cmsSetDeviceClass(hICC, cmsSigNamedColorClass);
    cmsSetColorSpace(hICC, v ->ExitColorSpace);
    cmsSetPCS(hICC, cmsSigLabData);

    // Tag profile with information
    if (!SetTextTags(hICC, L"Named color devicelink")) goto Error;

    Original = cmsGetNamedColorList(xform);
    if (Original == NULL) goto Error;

    nColors = cmsNamedColorCount(Original);
    nc2     = cmsDupNamedColorList(Original);
    if (nc2 == NULL) goto Error;

    // Colorant count now depends on the output space
    nc2 ->ColorantCount = cmsPipelineOutputChannels(v ->Lut);

    // Make sure we have proper formatters
    cmsChangeBuffersFormat(xform, TYPE_NAMED_COLOR_INDEX,
        FLOAT_SH(0) | COLORSPACE_SH(_cmsLCMScolorSpace(v ->ExitColorSpace))
        | BYTES_SH(2) | CHANNELS_SH(cmsChannelsOf(v ->ExitColorSpace)));

    // Apply the transfor to colorants.
    for (i=0; i < nColors; i++) {
        cmsDoTransform(xform, &i, nc2 ->List[i].DeviceColorant, 1);
    }

    if (!cmsWriteTag(hICC, cmsSigNamedColor2Tag, (void*) nc2)) goto Error;
    cmsFreeNamedColorList(nc2);

    return hICC;

Error:
    if (hICC != NULL) cmsCloseProfile(hICC);
    return NULL;
}
Example #11
0
/* Create a link to return device values inside the named color profile or link
   it with a destination profile and potentially a proofing profile.  If the
   output_colorspace and the proof_color space are NULL, then we will be
   returning the device values that are contained in the named color profile.
   i.e. in namedcolor_information.  Note that an ICC named color profile
    need NOT contain the device values but must contain the CIELAB values. */
void
gscms_get_name2device_link(gsicc_link_t *icclink,
                           gcmmhprofile_t  lcms_srchandle,
                           gcmmhprofile_t lcms_deshandle,
                           gcmmhprofile_t lcms_proofhandle,
                           gsicc_rendering_param_t *rendering_params,
                           gs_memory_t *memory)
{
    cmsHTRANSFORM hTransform;
    cmsUInt32Number dwOutputFormat;
    cmsUInt32Number lcms_proof_flag;
    int number_colors;

    /* NOTE:  We need to add a test here to check that we even HAVE
    device values in here and NOT just CIELAB values */
    if ( lcms_proofhandle != NULL ) {
        lcms_proof_flag = cmsFLAGS_GAMUTCHECK | cmsFLAGS_SOFTPROOFING;
    } else {
        lcms_proof_flag = 0;
    }
    /* Create the transform */
    /* ToDo:  Adjust rendering intent */
    hTransform = cmsCreateProofingTransformTHR(memory,
                 lcms_srchandle, TYPE_NAMED_COLOR_INDEX,
                 lcms_deshandle, TYPE_CMYK_8,
                 lcms_proofhandle,INTENT_PERCEPTUAL,
                 INTENT_ABSOLUTE_COLORIMETRIC,
                 lcms_proof_flag);
    /* In littleCMS there is no easy way to find out the size of the device
        space returned by the named color profile until after the transform is made.
        Hence we adjust our output format after creating the transform.  It is
        set to CMYK8 initially. */
    number_colors = cmsNamedColorCount(cmsGetNamedColorList(hTransform));
    /* NOTE: Output size of gx_color_value with no color space type check */
    dwOutputFormat =  (CHANNELS_SH(number_colors)|BYTES_SH(sizeof(gx_color_value)));
    /* Change the formatters */
    cmsChangeBuffersFormat(hTransform,TYPE_NAMED_COLOR_INDEX,dwOutputFormat);
    icclink->link_handle = hTransform;
    cmsCloseProfile(lcms_srchandle);
    if(lcms_deshandle) cmsCloseProfile(lcms_deshandle);
    if(lcms_proofhandle) cmsCloseProfile(lcms_proofhandle);
    return;
}
Example #12
0
static cmsUInt32Number
findLCMStype(char* PILmode)
{
    if (strcmp(PILmode, "RGB") == 0) {
        return TYPE_RGBA_8;
    }
    else if (strcmp(PILmode, "RGBA") == 0) {
        return TYPE_RGBA_8;
    }
    else if (strcmp(PILmode, "RGBX") == 0) {
        return TYPE_RGBA_8;
    }
    else if (strcmp(PILmode, "RGBA;16B") == 0) {
        return TYPE_RGBA_16;
    }
    else if (strcmp(PILmode, "CMYK") == 0) {
        return TYPE_CMYK_8;
    }
    else if (strcmp(PILmode, "L") == 0) {
        return TYPE_GRAY_8;
    }
    else if (strcmp(PILmode, "L;16") == 0) {
        return TYPE_GRAY_16;
    }
    else if (strcmp(PILmode, "L;16B") == 0) {
        return TYPE_GRAY_16_SE;
    }
    else if (strcmp(PILmode, "YCCA") == 0) {
        return TYPE_YCbCr_8;
    }
    else if (strcmp(PILmode, "YCC") == 0) {
        return TYPE_YCbCr_8;
    }
    else if (strcmp(PILmode, "LAB") == 0) {
        // LabX equvalent like ALab, but not reversed -- no #define in lcms2
        return (COLORSPACE_SH(PT_LabV2)|CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1));
    }

    else {
        /* take a wild guess... but you probably should fail instead. */
        return TYPE_GRAY_8; /* so there's no buffer overrun... */
    }
}
Example #13
0
/* Get the link from the CMS, but include proofing and/or a device link
   profile.  Note also, that the source may be a device link profile, in
   which case we will not have a destination profile but could still have
   a proof profile or an additional device link profile */
gcmmhlink_t
gscms_get_link_proof_devlink(gcmmhprofile_t lcms_srchandle,
                             gcmmhprofile_t lcms_proofhandle,
                             gcmmhprofile_t lcms_deshandle,
                             gcmmhprofile_t lcms_devlinkhandle,
                             gsicc_rendering_param_t *rendering_params,
                             bool src_dev_link, int cmm_flags,
                             gs_memory_t *memory)
{
    cmsUInt32Number src_data_type,des_data_type;
    cmsColorSpaceSignature src_color_space,des_color_space;
    int src_nChannels,des_nChannels;
    int lcms_src_color_space, lcms_des_color_space;
    cmsHPROFILE hProfiles[5];
    int nProfiles = 0;
    unsigned int flag;

    /* Check if the rendering intent is something other than relative colorimetric
       and  if we have a proofing profile.  In this case we need to create the
       combined profile a bit different.  LCMS does not allow us to use different
       intents in the cmsCreateMultiprofileTransform transform.  Also, don't even
       think about doing this if someone has snuck in a source based device link
       profile into the mix */
    if (lcms_proofhandle != NULL &&
            rendering_params->rendering_intent != gsRELATIVECOLORIMETRIC &&
            !src_dev_link) {
        /* First handle the source to proof profile with its particular intent as
           a device link profile */
        cmsHPROFILE src_to_proof;
        cmsHTRANSFORM temptransform;

        temptransform = gscms_get_link(lcms_srchandle, lcms_proofhandle,
                                       rendering_params, cmm_flags, memory);
        /* Now mash that to a device link profile */
        flag = cmsFLAGS_HIGHRESPRECALC;
        if (rendering_params->black_point_comp == gsBLACKPTCOMP_ON ||
                rendering_params->black_point_comp == gsBLACKPTCOMP_ON_OR) {
            flag = (flag | cmsFLAGS_BLACKPOINTCOMPENSATION);
        }
        src_to_proof = cmsTransform2DeviceLink(temptransform, 3.4, flag);
        /* Free up the link handle */
        cmsDeleteTransform(temptransform);
        src_color_space  = cmsGetColorSpace(src_to_proof);
        lcms_src_color_space = _cmsLCMScolorSpace(src_color_space);
        /* littlecms returns -1 for types it does not (but should) understand */
        if (lcms_src_color_space < 0) lcms_src_color_space = 0;
        src_nChannels = cmsChannelsOf(src_color_space);
        /* For now, just do single byte data, interleaved.  We can change this
          when we use the transformation. */
        src_data_type = (COLORSPACE_SH(lcms_src_color_space)|
                         CHANNELS_SH(src_nChannels)|BYTES_SH(2));
        if (lcms_devlinkhandle == NULL) {
            des_color_space = cmsGetColorSpace(lcms_deshandle);
        } else {
            des_color_space = cmsGetPCS(lcms_devlinkhandle);
        }
        lcms_des_color_space = _cmsLCMScolorSpace(des_color_space);
        if (lcms_des_color_space < 0) lcms_des_color_space = 0;
        des_nChannels = cmsChannelsOf(des_color_space);
        des_data_type = (COLORSPACE_SH(lcms_des_color_space)|
                         CHANNELS_SH(des_nChannels)|BYTES_SH(2));
        /* Now, we need to go back through the proofing profile, to the
           destination and then to the device link profile if there was one. */
        hProfiles[nProfiles++] = src_to_proof;  /* Src to proof with special intent */
        hProfiles[nProfiles++] = lcms_proofhandle; /* Proof to CIELAB */
        if (lcms_deshandle != NULL) {
            hProfiles[nProfiles++] = lcms_deshandle;  /* Our destination */
        }
        /* The output device link profile */
        if (lcms_devlinkhandle != NULL) {
            hProfiles[nProfiles++] = lcms_devlinkhandle;
        }
        flag = cmsFLAGS_HIGHRESPRECALC;
        if (rendering_params->black_point_comp == gsBLACKPTCOMP_ON
                || rendering_params->black_point_comp == gsBLACKPTCOMP_ON_OR) {
            flag = (flag | cmsFLAGS_BLACKPOINTCOMPENSATION);
        }
        /* Use relative colorimetric here */
        temptransform = cmsCreateMultiprofileTransformTHR((cmsContext)memory,
                        hProfiles, nProfiles, src_data_type,
                        des_data_type, gsRELATIVECOLORIMETRIC, flag);
        cmsCloseProfile(src_to_proof);
        return temptransform;
    } else {
        /* First handle all the source stuff */
        src_color_space  = cmsGetColorSpace(lcms_srchandle);
        lcms_src_color_space = _cmsLCMScolorSpace(src_color_space);
        /* littlecms returns -1 for types it does not (but should) understand */
        if (lcms_src_color_space < 0) lcms_src_color_space = 0;
        src_nChannels = cmsChannelsOf(src_color_space);
        /* For now, just do single byte data, interleaved.  We can change this
          when we use the transformation. */
        src_data_type = (COLORSPACE_SH(lcms_src_color_space)|
                         CHANNELS_SH(src_nChannels)|BYTES_SH(2));
        if (lcms_devlinkhandle == NULL) {
            if (src_dev_link) {
                des_color_space = cmsGetPCS(lcms_srchandle);
            } else {
                des_color_space = cmsGetColorSpace(lcms_deshandle);
            }
        } else {
            des_color_space = cmsGetPCS(lcms_devlinkhandle);
        }
        lcms_des_color_space = _cmsLCMScolorSpace(des_color_space);
        if (lcms_des_color_space < 0) lcms_des_color_space = 0;
        des_nChannels = cmsChannelsOf(des_color_space);
        des_data_type = (COLORSPACE_SH(lcms_des_color_space)|
                         CHANNELS_SH(des_nChannels)|BYTES_SH(2));
        /* lcms proofing transform has a clunky API and can't include the device
           link profile if we have both. So use cmsCreateMultiprofileTransform
           instead and round trip the proofing profile. */
        hProfiles[nProfiles++] = lcms_srchandle;
        /* Note if source is device link, we cannot do any proofing */
        if (lcms_proofhandle != NULL && !src_dev_link) {
            hProfiles[nProfiles++] = lcms_proofhandle;
            hProfiles[nProfiles++] = lcms_proofhandle;
        }
        /* This should be NULL if we have a source device link */
        if (lcms_deshandle != NULL) {
            hProfiles[nProfiles++] = lcms_deshandle;
        }
        /* Someone could have a device link at the output, giving us possibly two
           device link profiles to smash together */
        if (lcms_devlinkhandle != NULL) {
            hProfiles[nProfiles++] = lcms_devlinkhandle;
        }
        flag = cmsFLAGS_HIGHRESPRECALC;
        if (rendering_params->black_point_comp == gsBLACKPTCOMP_ON
                || rendering_params->black_point_comp == gsBLACKPTCOMP_ON_OR) {
            flag = (flag | cmsFLAGS_BLACKPOINTCOMPENSATION);
        }
        return cmsCreateMultiprofileTransformTHR((cmsContext)memory,
                hProfiles, nProfiles, src_data_type,
                des_data_type, rendering_params->rendering_intent, flag);
    }
}
Example #14
0
// This is the entry for black-plane preserving, which are non-ICC
static
cmsPipeline* BlackPreservingKPlaneIntents(cmsContext     ContextID,
                                          cmsUInt32Number nProfiles,
                                          cmsUInt32Number TheIntents[],
                                          cmsHPROFILE     hProfiles[],
                                          cmsBool         BPC[],
                                          cmsFloat64Number AdaptationStates[],
                                          cmsUInt32Number dwFlags)
{
    PreserveKPlaneParams bp;
    cmsPipeline*    Result = NULL;
    cmsUInt32Number ICCIntents[256];
    cmsStage*         CLUT;
    cmsUInt32Number i, nGridPoints;
    cmsHPROFILE hLab;

    // Sanity check
    if (nProfiles < 1 || nProfiles > 255) return NULL;

    // Translate black-preserving intents to ICC ones
    for (i=0; i < nProfiles; i++)
        ICCIntents[i] = TranslateNonICCIntents(TheIntents[i]);

    // Check for non-cmyk profiles
    if (cmsGetColorSpace(hProfiles[0]) != cmsSigCmykData ||
        !(cmsGetColorSpace(hProfiles[nProfiles-1]) == cmsSigCmykData ||
        cmsGetDeviceClass(hProfiles[nProfiles-1]) == cmsSigOutputClass))
           return  DefaultICCintents(ContextID, nProfiles, ICCIntents, hProfiles, BPC, AdaptationStates, dwFlags);

    // Allocate an empty LUT for holding the result
    Result = cmsPipelineAlloc(ContextID, 4, 4);
    if (Result == NULL) return NULL;


    memset(&bp, 0, sizeof(bp));

    // We need the input LUT of the last profile, assuming this one is responsible of
    // black generation. This LUT will be seached in inverse order.
    bp.LabK2cmyk = _cmsReadInputLUT(hProfiles[nProfiles-1], INTENT_RELATIVE_COLORIMETRIC);
    if (bp.LabK2cmyk == NULL) goto Cleanup;

    // Get total area coverage (in 0..1 domain)
    bp.MaxTAC = cmsDetectTAC(hProfiles[nProfiles-1]) / 100.0;
    if (bp.MaxTAC <= 0) goto Cleanup;


    // Create a LUT holding normal ICC transform
    bp.cmyk2cmyk = DefaultICCintents(ContextID,
                                         nProfiles,
                                         ICCIntents,
                                         hProfiles,
                                         BPC,
                                         AdaptationStates,
                                         dwFlags);
    if (bp.cmyk2cmyk == NULL) goto Cleanup;

    // Now the tone curve
    bp.KTone = _cmsBuildKToneCurve(ContextID, 4096, nProfiles,
                                   ICCIntents,
                                   hProfiles,
                                   BPC,
                                   AdaptationStates,
                                   dwFlags);
    if (bp.KTone == NULL) goto Cleanup;

    // To measure the output, Last profile to Lab
    hLab = cmsCreateLab4ProfileTHR(ContextID, NULL);
    bp.hProofOutput = cmsCreateTransformTHR(ContextID, hProfiles[nProfiles-1],
                                         CHANNELS_SH(4)|BYTES_SH(2), hLab, TYPE_Lab_DBL,
                                         INTENT_RELATIVE_COLORIMETRIC,
                                         cmsFLAGS_NOCACHE|cmsFLAGS_NOOPTIMIZE);
    if ( bp.hProofOutput == NULL) goto Cleanup;

    // Same as anterior, but lab in the 0..1 range
    bp.cmyk2Lab = cmsCreateTransformTHR(ContextID, hProfiles[nProfiles-1],
                                         FLOAT_SH(1)|CHANNELS_SH(4)|BYTES_SH(4), hLab,
                                         FLOAT_SH(1)|CHANNELS_SH(3)|BYTES_SH(4),
                                         INTENT_RELATIVE_COLORIMETRIC,
                                         cmsFLAGS_NOCACHE|cmsFLAGS_NOOPTIMIZE);
    if (bp.cmyk2Lab == NULL) goto Cleanup;
    cmsCloseProfile(hLab);

    // Error estimation (for debug only)
    bp.MaxError = 0;

    // How many gridpoints are we going to use?
    nGridPoints = _cmsReasonableGridpointsByColorspace(cmsSigCmykData, dwFlags);


    CLUT = cmsStageAllocCLut16bit(ContextID, nGridPoints, 4, 4, NULL);
    if (CLUT == NULL) goto Cleanup;

    if (!cmsPipelineInsertStage(Result, cmsAT_BEGIN, CLUT))
        goto Cleanup;

    cmsStageSampleCLut16bit(CLUT, BlackPreservingSampler, (void*) &bp, 0);

Cleanup:

    if (bp.cmyk2cmyk) cmsPipelineFree(bp.cmyk2cmyk);
    if (bp.cmyk2Lab) cmsDeleteTransform(bp.cmyk2Lab);
    if (bp.hProofOutput) cmsDeleteTransform(bp.hProofOutput);

    if (bp.KTone) cmsFreeToneCurve(bp.KTone);
    if (bp.LabK2cmyk) cmsPipelineFree(bp.LabK2cmyk);

    return Result;
}
Example #15
0
static
DWORD GetInputPixelType(TIFF *Bank)
{
     uint16 Photometric, bps, spp, extra, PlanarConfig, *info;
     uint16 Compression, reverse = 0;
     int ColorChannels, IsPlanar = 0, pt = 0;

     TIFFGetField(Bank,           TIFFTAG_PHOTOMETRIC,   &Photometric);
     TIFFGetFieldDefaulted(Bank,  TIFFTAG_BITSPERSAMPLE, &bps);

     if (bps == 1)
       FatalError("Sorry, bilevel TIFFs has nothig to do with ICC profiles");

     if (bps != 8 && bps != 16)
              FatalError("Sorry, 8 or 16 bits per sample only");

     TIFFGetFieldDefaulted(Bank, TIFFTAG_SAMPLESPERPIXEL, &spp);
     TIFFGetFieldDefaulted(Bank, TIFFTAG_PLANARCONFIG, &PlanarConfig);

     switch (PlanarConfig)
     {
     case PLANARCONFIG_CONTIG: IsPlanar = 0; break;
     case PLANARCONFIG_SEPARATE: IsPlanar = 1; break;
     default:

     FatalError("Unsupported planar configuration (=%d) ", (int) PlanarConfig);
     }

     // If Samples per pixel == 1, PlanarConfiguration is irrelevant and need
     // not to be included.

     if (spp == 1) IsPlanar = 0;


     // Any alpha?

     TIFFGetFieldDefaulted(Bank, TIFFTAG_EXTRASAMPLES, &extra, &info);

     // Read alpha channels as colorant

     if (StoreAsAlpha) {

         ColorChannels = spp;
         extra = 0;
     }
     else
        ColorChannels = spp - extra;

     switch (Photometric) {

     case PHOTOMETRIC_MINISWHITE:
                                   
            reverse = 1;

     case PHOTOMETRIC_MINISBLACK:
                                   
            pt = PT_GRAY;                                
            break;

     case PHOTOMETRIC_RGB:
                                   
            pt = PT_RGB;
            break;


     case PHOTOMETRIC_PALETTE:
                                             
            FatalError("Sorry, palette images not supported (at least on this version)"); 

     case PHOTOMETRIC_SEPARATED:
           if (ColorChannels == 4)
                  pt = PT_CMYK;
           else
           if (ColorChannels == 3)
                  pt = PT_CMY;
           else
           if (ColorChannels == 6)
                  pt = PT_HiFi;
           else
           if (ColorChannels == 7)
                  pt = PT_HiFi7;
           else
           if (ColorChannels == 8)
                  pt = PT_HiFi8;           
           else
           if (ColorChannels == 9)
                  pt = PT_HiFi9;           
           else
           if (ColorChannels == 10)
                  pt = PT_HiFi10;           
           else
           if (ColorChannels == 11)
                  pt = PT_HiFi11;           
           else
		   if (ColorChannels == 12)
                  pt = PT_HiFi8;           
		   else
           if (ColorChannels == 13)
                  pt = PT_HiFi13;           
           else
           if (ColorChannels == 14)
                  pt = PT_HiFi14;           
           else
           if (ColorChannels == 15)
                  pt = PT_HiFi15;           
           else
                  FatalError("What a weird separation of %d channels?!?!", ColorChannels);
           break;

     case PHOTOMETRIC_YCBCR:
           TIFFGetField(Bank, TIFFTAG_COMPRESSION, &Compression);
           {
                  uint16 subx, suby;

                  pt = PT_YCbCr;
                  TIFFGetFieldDefaulted(Bank, TIFFTAG_YCBCRSUBSAMPLING, &subx, &suby);
                  if (subx != 1 || suby != 1)
                         FatalError("Sorry, subsampled images not supported");

           }
           break;

     case 9:
			pt = PT_Lab;
			InputLabUsingICC = TRUE;
			break;

     case PHOTOMETRIC_CIELAB:
           pt = PT_Lab;
		   InputLabUsingICC = FALSE;
           break;

    
     case PHOTOMETRIC_LOGLUV:      /* CIE Log2(L) (u',v') */

           TIFFSetField(Bank, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_16BIT);
           pt = PT_YUV;             // *ICCSpace = icSigLuvData;
           bps = 16;               // 16 bits forced by LibTiff
           break;

     default:
           FatalError("Unsupported TIFF color space (Photometric %d)", Photometric);
     }

     // Convert bits per sample to bytes per sample

     bps >>= 3; 

     return (COLORSPACE_SH(pt)|PLANAR_SH(IsPlanar)|EXTRA_SH(extra)|CHANNELS_SH(ColorChannels)|BYTES_SH(bps)|FLAVOR_SH(reverse));
}
Example #16
0
static
DWORD ComputeOutputFormatDescriptor(DWORD dwInput, int OutColorSpace, int bps)
{
    int IsPlanar  = T_PLANAR(dwInput);
    int Channels = 0;
    
    switch (OutColorSpace) {
        
    case PT_GRAY:
        Channels = 1;
        break;
    case PT_RGB:
    case PT_CMY:
    case PT_Lab:
    case PT_YUV:
    case PT_YCbCr:
        Channels = 3;
        break;
        
    case PT_CMYK:
        Channels = 4;
        break;
        
    case  PT_HiFi:
        Channels = 6;
        break;
        
    case PT_HiFi7:
        Channels = 7;
        break;
        
    case  PT_HiFi8:
        Channels = 8;
        break;
        
    case  PT_HiFi9:
        Channels = 9;
        break;
        
    case  PT_HiFi10:
        Channels = 10;
        break;
        
    case  PT_HiFi11:
        Channels = 11;
        break;
        
    case PT_HiFi12:
        Channels = 12;
        break;
        
    case  PT_HiFi13:
        Channels = 13;
        break;
        
    case  PT_HiFi14:
        Channels = 14;
        break;
        
    case  PT_HiFi15:
        Channels = 15;
        break;
        
    default:
        FatalError("Unsupported output color space");
    }
    
    return (COLORSPACE_SH(OutColorSpace)|PLANAR_SH(IsPlanar)|CHANNELS_SH(Channels)|BYTES_SH(bps));
}
Example #17
0
static
DWORD MakeFormatDescriptor(icColorSpaceSignature ColorSpace, int Bytes)
{
    int Channels = _cmsChannelsOf(ColorSpace);
    return COLORSPACE_SH(ICC2LCMS(ColorSpace))|BYTES_SH(Bytes)|CHANNELS_SH(Channels)|PLANAR_SH(1);
}
Example #18
0
// Does convert a transform into a device link profile
cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat64Number Version, cmsUInt32Number dwFlags)
{
    cmsHPROFILE hProfile = NULL;
    cmsUInt32Number FrmIn, FrmOut, ChansIn, ChansOut;
    cmsUInt32Number ColorSpaceBitsIn, ColorSpaceBitsOut;
    _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform;
    cmsPipeline* LUT = NULL;
    cmsStage* mpe;
    cmsContext ContextID = cmsGetTransformContextID(hTransform);
    const cmsAllowedLUT* AllowedLUT;
    cmsTagSignature DestinationTag;
    cmsProfileClassSignature deviceClass; 

    _cmsAssert(hTransform != NULL);

    // Get the first mpe to check for named color
    mpe = cmsPipelineGetPtrToFirstStage(xform ->Lut);

    // Check if is a named color transform
    if (mpe != NULL) {

        if (cmsStageType(mpe) == cmsSigNamedColorElemType) {
            return CreateNamedColorDevicelink(hTransform);
        }
    }

    // First thing to do is to get a copy of the transformation
    LUT = cmsPipelineDup(xform ->Lut);
    if (LUT == NULL) return NULL;

    // Time to fix the Lab2/Lab4 issue.
    if ((xform ->EntryColorSpace == cmsSigLabData) && (Version < 4.0)) {

        if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocLabV2ToV4curves(ContextID)))
            goto Error;
    }

    // On the output side too
    if ((xform ->ExitColorSpace) == cmsSigLabData && (Version < 4.0)) {

        if (!cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocLabV4ToV2(ContextID)))
            goto Error;
    }


    hProfile = cmsCreateProfilePlaceholder(ContextID);
    if (!hProfile) goto Error;                    // can't allocate

    cmsSetProfileVersion(hProfile, Version);

    FixColorSpaces(hProfile, xform -> EntryColorSpace, xform -> ExitColorSpace, dwFlags);

    // Optimize the LUT and precalculate a devicelink

    ChansIn  = cmsChannelsOf(xform -> EntryColorSpace);
    ChansOut = cmsChannelsOf(xform -> ExitColorSpace);

    ColorSpaceBitsIn  = _cmsLCMScolorSpace(xform -> EntryColorSpace);
    ColorSpaceBitsOut = _cmsLCMScolorSpace(xform -> ExitColorSpace);

    FrmIn  = COLORSPACE_SH(ColorSpaceBitsIn) | CHANNELS_SH(ChansIn)|BYTES_SH(2);
    FrmOut = COLORSPACE_SH(ColorSpaceBitsOut) | CHANNELS_SH(ChansOut)|BYTES_SH(2);

    deviceClass = cmsGetDeviceClass(hProfile);

     if (deviceClass == cmsSigOutputClass)
         DestinationTag = cmsSigBToA0Tag;
     else
         DestinationTag = cmsSigAToB0Tag;

    // Check if the profile/version can store the result
    if (dwFlags & cmsFLAGS_FORCE_CLUT)
        AllowedLUT = NULL;
    else
        AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag);

    if (AllowedLUT == NULL) {

        // Try to optimize
        _cmsOptimizePipeline(ContextID, &LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags);
        AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag);

    }

    // If no way, then force CLUT that for sure can be written
    if (AllowedLUT == NULL) {

        dwFlags |= cmsFLAGS_FORCE_CLUT;
        _cmsOptimizePipeline(ContextID, &LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags);

        // Put identity curves if needed
        if (cmsPipelineGetPtrToFirstStage(LUT) ->Type != cmsSigCurveSetElemType)
             if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, ChansIn)))
                 goto Error;

        if (cmsPipelineGetPtrToLastStage(LUT) ->Type != cmsSigCurveSetElemType)
             if (!cmsPipelineInsertStage(LUT, cmsAT_END,   _cmsStageAllocIdentityCurves(ContextID, ChansOut)))
                 goto Error;

        AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag);
    }

    // Somethings is wrong...
    if (AllowedLUT == NULL) {
        goto Error;
    }


    if (dwFlags & cmsFLAGS_8BITS_DEVICELINK)
                     cmsPipelineSetSaveAs8bitsFlag(LUT, TRUE);

    // Tag profile with information
    if (!SetTextTags(hProfile, L"devicelink")) goto Error;

    // Store result
    if (!cmsWriteTag(hProfile, DestinationTag, LUT)) goto Error;


    if (xform -> InputColorant != NULL) {
           if (!cmsWriteTag(hProfile, cmsSigColorantTableTag, xform->InputColorant)) goto Error;
    }

    if (xform -> OutputColorant != NULL) {
           if (!cmsWriteTag(hProfile, cmsSigColorantTableOutTag, xform->OutputColorant)) goto Error;
    }

    if ((deviceClass == cmsSigLinkClass) && (xform ->Sequence != NULL)) {
        if (!_cmsWriteProfileSequence(hProfile, xform ->Sequence)) goto Error;
    }

    // Set the white point
    if (deviceClass == cmsSigInputClass) {
        if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, &xform ->EntryWhitePoint)) goto Error;
    }
    else {
         if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, &xform ->ExitWhitePoint)) goto Error;
    }

  
    // Per 7.2.15 in spec 4.3
    cmsSetHeaderRenderingIntent(hProfile, xform ->RenderingIntent);

    cmsPipelineFree(LUT);
    return hProfile;

Error:
    if (LUT != NULL) cmsPipelineFree(LUT);
    cmsCloseProfile(hProfile);
    return NULL;
}
Example #19
0
/* Get the link from the CMS. TODO:  Add error checking */
gcmmhlink_t
gscms_get_link(gcmmhprofile_t  lcms_srchandle,
               gcmmhprofile_t lcms_deshandle,
               gsicc_rendering_param_t *rendering_params, int cmm_flags,
               gs_memory_t *memory)
{
    cmsUInt32Number src_data_type,des_data_type;
    cmsColorSpaceSignature src_color_space,des_color_space;
    int src_nChannels,des_nChannels;
    int lcms_src_color_space, lcms_des_color_space;
    unsigned int flag;

    /* Check for case of request for a transfrom from a device link profile
       in that case, the destination profile is NULL */

    /* First handle all the source stuff */
    src_color_space  = cmsGetColorSpace(lcms_srchandle);
    lcms_src_color_space = _cmsLCMScolorSpace(src_color_space);
    /* littlecms returns -1 for types it does not (but should) understand */
    if (lcms_src_color_space < 0) lcms_src_color_space = 0;
    src_nChannels = cmsChannelsOf(src_color_space);
    /* For now, just do single byte data, interleaved.  We can change this
      when we use the transformation. */
    src_data_type = (COLORSPACE_SH(lcms_src_color_space)|
                     CHANNELS_SH(src_nChannels)|BYTES_SH(2));
#if 0
    src_data_type = src_data_type | ENDIAN16_SH(1);
#endif
    if (lcms_deshandle != NULL) {
        des_color_space  = cmsGetColorSpace(lcms_deshandle);
    } else {
        /* We must have a device link profile. */
        des_color_space = cmsGetPCS(lcms_deshandle);
    }
    lcms_des_color_space = _cmsLCMScolorSpace(des_color_space);
    if (lcms_des_color_space < 0) lcms_des_color_space = 0;
    des_nChannels = cmsChannelsOf(des_color_space);
    des_data_type = (COLORSPACE_SH(lcms_des_color_space)|
                     CHANNELS_SH(des_nChannels)|BYTES_SH(2));
    /* endian */
#if 0
    des_data_type = des_data_type | ENDIAN16_SH(1);
#endif
    /* Set up the flags */
    flag = cmsFLAGS_HIGHRESPRECALC;
    if (rendering_params->black_point_comp == gsBLACKPTCOMP_ON
            || rendering_params->black_point_comp == gsBLACKPTCOMP_ON_OR) {
        flag = (flag | cmsFLAGS_BLACKPOINTCOMPENSATION);
    }
    if (rendering_params->preserve_black == gsBLACKPRESERVE_KONLY) {
        switch (rendering_params->rendering_intent) {
        case INTENT_PERCEPTUAL:
            rendering_params->rendering_intent = INTENT_PRESERVE_K_ONLY_PERCEPTUAL;
            break;
        case INTENT_RELATIVE_COLORIMETRIC:
            rendering_params->rendering_intent = INTENT_PRESERVE_K_ONLY_RELATIVE_COLORIMETRIC;
            break;
        case INTENT_SATURATION:
            rendering_params->rendering_intent = INTENT_PRESERVE_K_ONLY_SATURATION;
            break;
        default:
            break;
        }
    }
    if (rendering_params->preserve_black == gsBLACKPRESERVE_KPLANE) {
        switch (rendering_params->rendering_intent) {
        case INTENT_PERCEPTUAL:
            rendering_params->rendering_intent = INTENT_PRESERVE_K_PLANE_PERCEPTUAL;
            break;
        case INTENT_RELATIVE_COLORIMETRIC:
            rendering_params->rendering_intent = INTENT_PRESERVE_K_PLANE_RELATIVE_COLORIMETRIC;
            break;
        case INTENT_SATURATION:
            rendering_params->rendering_intent = INTENT_PRESERVE_K_PLANE_SATURATION;
            break;
        default:
            break;
        }
    }
    /* Create the link */
    return cmsCreateTransformTHR((cmsContext)memory,
                                 lcms_srchandle, src_data_type,
                                 lcms_deshandle, des_data_type,
                                 rendering_params->rendering_intent, flag | cmm_flags);
    /* cmsFLAGS_HIGHRESPRECALC)  cmsFLAGS_NOTPRECALC  cmsFLAGS_LOWRESPRECALC*/
}
Example #20
0
static
int BlackPointAsDarkerColorant(cmsHPROFILE hInput,                               
                               int Intent,
                               LPcmsCIEXYZ BlackPoint,
                               DWORD dwFlags)
{
    WORD *Black, *White;
    cmsHTRANSFORM xform;
    icColorSpaceSignature Space;
    int nChannels;
    DWORD dwFormat; 
    cmsHPROFILE hLab;
    cmsCIELab  Lab;
    cmsCIEXYZ  BlackXYZ, MediaWhite;        
    
    // If the profile does not support input direction, assume Black point 0
    
    if (!cmsIsIntentSupported(hInput, Intent, LCMS_USED_AS_INPUT)) {

        BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
        return 0;
    }
    

    // Try to get black by using black colorant

    Space = cmsGetColorSpace(hInput);
    
    if (!_cmsEndPointsBySpace(Space, &White, &Black, &nChannels)) {
        
        BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
        return 0;
    }
    
    dwFormat = CHANNELS_SH(nChannels)|BYTES_SH(2);

    hLab = cmsCreateLabProfile(NULL);
    
    xform = cmsCreateTransform(hInput, dwFormat,
                                hLab, TYPE_Lab_DBL, Intent, cmsFLAGS_NOTPRECALC);
    
    
    cmsDoTransform(xform, Black, &Lab, 1);

    // Force it to be neutral, clip to max. L* of 50

    Lab.a = Lab.b = 0;
    if (Lab.L > 50) Lab.L = 50;

    cmsCloseProfile(hLab);
    cmsDeleteTransform(xform);
    
    cmsLab2XYZ(NULL, &BlackXYZ, &Lab);
    
    if (Intent == INTENT_ABSOLUTE_COLORIMETRIC) {
        
        *BlackPoint = BlackXYZ; 
    }
    else {
        
        if (!(dwFlags & LCMS_BPFLAGS_D50_ADAPTED)) {

            cmsTakeMediaWhitePoint(&MediaWhite, hInput);
            cmsAdaptToIlluminant(BlackPoint, cmsD50_XYZ(), &MediaWhite, &BlackXYZ);
        }
        else
            *BlackPoint = BlackXYZ;
    }
        
    return 1;
}
Example #21
0
LPLUT _cmsComputeSoftProofLUT(cmsHPROFILE hProfile, int nIntent)
{
    cmsHPROFILE hLab;
    LPLUT SoftProof;
    DWORD dwFormat;
    GAMUTCHAIN Chain;
    int nErrState;
    LPGAMMATABLE Trans[3];
        

    // LUTs are never abs. colorimetric, is the transform who
    // is responsible of generating white point displacement
    if (nIntent == INTENT_ABSOLUTE_COLORIMETRIC)
        nIntent = INTENT_RELATIVE_COLORIMETRIC;

    ZeroMemory(&Chain, sizeof(GAMUTCHAIN));

    hLab = cmsCreateLabProfile(NULL);

    // ONLY 4 channels  
    dwFormat = (CHANNELS_SH(4)|BYTES_SH(2));
    
    // Safeguard against early abortion
    nErrState = cmsErrorAction(LCMS_ERROR_IGNORE);

    // Does create the first step
    Chain.hForward = cmsCreateTransform(hLab, TYPE_Lab_16, 
                                        hProfile, dwFormat, 
                                        nIntent,
                                        cmsFLAGS_NOTPRECALC);

    // Does create the last step
    Chain.hReverse = cmsCreateTransform(hProfile, dwFormat, 
                                        hLab, TYPE_Lab_16,                                      
                                        INTENT_RELATIVE_COLORIMETRIC, 
                                        cmsFLAGS_NOTPRECALC);

    // Restores error handler previous state
    cmsErrorAction(nErrState);

    // All ok?
    if (Chain.hForward && Chain.hReverse) {
                
    // This is Lab -> Lab, so 33 point should hold anything
    SoftProof = cmsAllocLUT();
    SoftProof = cmsAlloc3DGrid(SoftProof, 33, 3, 3);

    CreateLabPrelinearization(Trans);
    cmsAllocLinearTable(SoftProof, Trans, 1);
    cmsFreeGammaTriple(Trans);

    cmsSample3DGrid(SoftProof, SoftProofSampler, (LPVOID) &Chain, SoftProof->wFlags);
    }
    else 
        SoftProof = NULL;   // Didn't work...

    // Free all needed stuff.
    if (Chain.hForward) cmsDeleteTransform(Chain.hForward);
    if (Chain.hReverse) cmsDeleteTransform(Chain.hReverse);

    cmsCloseProfile(hLab);

    return SoftProof;
}
Example #22
0
/* Transform an entire buffer */
void
gscms_transform_color_buffer(gsicc_link_t *icclink,
                             gsicc_bufferdesc_t *input_buff_desc,
                             gsicc_bufferdesc_t *output_buff_desc,
                             void *inputbuffer,
                             void *outputbuffer)
{

    cmsHTRANSFORM hTransform = (cmsHTRANSFORM) icclink->link_handle;
    DWORD dwInputFormat,dwOutputFormat,curr_input,curr_output;
    int planar,numbytes,big_endian,hasalpha,k;
    unsigned char *inputpos, *outputpos;
    int numchannels;
#if DUMP_CMS_BUFFER
    FILE *fid_in, *fid_out;
#endif
    /* Although little CMS does  make assumptions about data types in its
       transformations you can change it after the fact.  */
    /* Set us to the proper output type */
    /* Note, we could speed this up by passing back the encoded data type
        to the caller so that we could avoid having to go through this
        computation each time if they are doing multiple calls to this
        operation */
    _LPcmsTRANSFORM p = (_LPcmsTRANSFORM) (LPSTR) hTransform;

    curr_input = p->InputFormat;
    curr_output = p->OutputFormat;

    /* Color space MUST be the same */
    dwInputFormat = COLORSPACE_SH(T_COLORSPACE(curr_input));
    dwOutputFormat = COLORSPACE_SH(T_COLORSPACE(curr_output));

    /* Now set if we have planar, num bytes, endian case, and alpha data to skip */
    /* Planar -- pdf14 case for example */
    planar = input_buff_desc->is_planar;
    dwInputFormat = dwInputFormat | PLANAR_SH(planar);
    planar = output_buff_desc->is_planar;
    dwOutputFormat = dwOutputFormat | PLANAR_SH(planar);

    /* 8 or 16 byte input and output */
    numbytes = input_buff_desc->bytes_per_chan;
    if (numbytes>2) numbytes = 0;  /* littleCMS encodes float with 0 ToDO. */
    dwInputFormat = dwInputFormat | BYTES_SH(numbytes);
    numbytes = output_buff_desc->bytes_per_chan;
    if (numbytes>2) numbytes = 0;
    dwOutputFormat = dwOutputFormat | BYTES_SH(numbytes);

    /* endian */
    big_endian = !input_buff_desc->little_endian;
    dwInputFormat = dwInputFormat | ENDIAN16_SH(big_endian);
    big_endian = !output_buff_desc->little_endian;
    dwOutputFormat = dwOutputFormat | ENDIAN16_SH(big_endian);

    /* number of channels */
    numchannels = input_buff_desc->num_chan;
    dwInputFormat = dwInputFormat | CHANNELS_SH(numchannels);
    numchannels = output_buff_desc->num_chan;
    dwOutputFormat = dwOutputFormat | CHANNELS_SH(numchannels);

    /* alpha, which is passed through unmolested */
    /* ToDo:  Right now we always must have alpha last */
    /* This is really only going to be an issue when we have
       interleaved alpha data */
    hasalpha = input_buff_desc->has_alpha;
    dwInputFormat = dwInputFormat | EXTRA_SH(hasalpha);
    dwOutputFormat = dwOutputFormat | EXTRA_SH(hasalpha);

    /* Change the formaters */
    cmsChangeBuffersFormat(hTransform,dwInputFormat,dwOutputFormat);

    /* littleCMS knows nothing about word boundarys.  As such, we need to do
       this row by row adjusting for our stride.  Output buffer must already
       be allocated. ToDo:  Check issues with plane and row stride and word
       boundry */
    inputpos = (unsigned char *) inputbuffer;
    outputpos = (unsigned char *) outputbuffer;
    if(input_buff_desc->is_planar){
        /* Do entire buffer.  Care must be taken here
           with respect to row stride, word boundry and number
           of source versus output channels.  We may
           need to take a closer look at this. */
        cmsDoTransform(hTransform,inputpos,outputpos,
                        input_buff_desc->plane_stride);
    } else {
        /* Do row by row. */
        for(k = 0; k < input_buff_desc->num_rows ; k++){
            cmsDoTransform(hTransform,inputpos,outputpos,
                            input_buff_desc->pixels_per_row);
            inputpos += input_buff_desc->row_stride;
            outputpos += output_buff_desc->row_stride;
        }
    }
#if DUMP_CMS_BUFFER
    fid_in = fopen("CM_Input.raw","ab");
    fid_out = fopen("CM_Output.raw","ab");
    fwrite((unsigned char*) inputbuffer,sizeof(unsigned char),
                            input_buff_desc->row_stride,fid_in);
    fwrite((unsigned char*) outputbuffer,sizeof(unsigned char),
                            output_buff_desc->row_stride,fid_out);
    fclose(fid_in);
    fclose(fid_out);
#endif
}
Example #23
0
static
LPLUT ComputeGamutWithInput(cmsHPROFILE hInput, cmsHPROFILE hProfile, int Intent)
{
    cmsHPROFILE hLab;
    LPLUT Gamut;
    DWORD dwFormat;
    GAMUTCHAIN Chain;
    int nErrState, nChannels, nGridpoints;
    LPGAMMATABLE Trans[3];
    icColorSpaceSignature ColorSpace;
            
    
    ZeroMemory(&Chain, sizeof(GAMUTCHAIN)); 
       
    hLab = cmsCreateLabProfile(NULL);
    
    // Safeguard against early abortion
    nErrState = cmsErrorAction(LCMS_ERROR_IGNORE);

    // The figure of merit. On matrix-shaper profiles, should be almost zero as
    // the conversion is pretty exact. On LUT based profiles, different resolutions
    // of input and output CLUT may result in differences. 

    if (!cmsIsIntentSupported(hProfile, Intent, LCMS_USED_AS_INPUT) &&
        !cmsIsIntentSupported(hProfile, Intent, LCMS_USED_AS_OUTPUT))

        Chain.Thereshold = 1.0;
    else
        Chain.Thereshold = ERR_THERESHOLD;
   
    ColorSpace  = cmsGetColorSpace(hProfile);  

    // If input profile specified, create a transform from such profile to Lab
    if (hInput != NULL) {
          
        nChannels   = _cmsChannelsOf(ColorSpace);     
        nGridpoints = _cmsReasonableGridpointsByColorspace(ColorSpace, cmsFLAGS_HIGHRESPRECALC);
        dwFormat    = (CHANNELS_SH(nChannels)|BYTES_SH(2));

        Chain.hInput = cmsCreateTransform(hInput, dwFormat, 
                                          hLab,   TYPE_Lab_16, 
                                          Intent, 
                                          cmsFLAGS_NOTPRECALC);
    }
    else  {
        // Input transform=NULL (Lab) Used to compute the gamut tag
        // This table will take 53 points to give some accurancy, 
        // 53 * 53 * 53 * 2 = 291K

        nChannels    = 3;      // For Lab
        nGridpoints  = 53;
        Chain.hInput = NULL;
        dwFormat = (CHANNELS_SH(_cmsChannelsOf(ColorSpace))|BYTES_SH(2)); 
    }

   
    // Does create the forward step
    Chain.hForward = cmsCreateTransform(hLab, TYPE_Lab_16, 
                                        hProfile, dwFormat, 
                                        INTENT_RELATIVE_COLORIMETRIC,
                                        cmsFLAGS_NOTPRECALC);

    // Does create the backwards step
    Chain.hReverse = cmsCreateTransform(hProfile, dwFormat, 
                                        hLab, TYPE_Lab_16,                                      
                                        INTENT_RELATIVE_COLORIMETRIC,
                                        cmsFLAGS_NOTPRECALC);

    // Restores error handler previous state
    cmsErrorAction(nErrState);

   
    // All ok?
    if (Chain.hForward && Chain.hReverse) {
           
    // Go on, try to compute gamut LUT from PCS.
    // This consist on a single channel containing 
    // dE when doing a transform back and forth on
    // the colorimetric intent. 

    Gamut = cmsAllocLUT();
    Gamut = cmsAlloc3DGrid(Gamut, nGridpoints, nChannels, 1);
     
    // If no input, then this is a gamut tag operated by Lab,
    // so include pertinent prelinearization
    if (hInput == NULL) {
       
        CreateLabPrelinearization(Trans);               
        cmsAllocLinearTable(Gamut, Trans, 1);              
        cmsFreeGammaTriple(Trans);
    }

   
    cmsSample3DGrid(Gamut, GamutSampler, (LPVOID) &Chain, Gamut ->wFlags);          
    }
    else 
        Gamut = NULL;   // Didn't work...

    // Free all needed stuff.
    if (Chain.hInput)   cmsDeleteTransform(Chain.hInput);
    if (Chain.hForward) cmsDeleteTransform(Chain.hForward);
    if (Chain.hReverse) cmsDeleteTransform(Chain.hReverse);

    cmsCloseProfile(hLab);
    
    // And return computed hull
    return Gamut;
}
Example #24
0
// Simplified version of multiprofile transform creator
// Flags are removed from arguments. 
// Gamut checking and named color profiles are not supported.
// WARNING: I/O pixel formats should be specified for the created transform later by caller.
cmsHTRANSFORM cmmCreateMultiprofileTransform(cmsHPROFILE hProfiles[], int nProfiles, int Intent) 
{   
  DWORD inFmt, outFmt;
  cmsHPROFILE hTargetProfile, hProfile;   
  icColorSpaceSignature csIn, csOut;   

  LPLUT Grid = NULL;
  int nGridPoints, nInChannels, nOutChannels = 3, i = 0;

  _LPcmsTRANSFORM p; // Resulting transform        

  cmsHTRANSFORM transforms[255]; // Cannot merge more than 255 profiles
  ZeroMemory(transforms, sizeof(transforms));
  if (nProfiles > 255) {
    return NULL; // Too many profiles
  }

  // Check if there are any named color profiles
  for (i=0; i < nProfiles; i++) {
    if (cmsGetDeviceClass(hProfiles[i]) == icSigNamedColorClass ||
        cmsGetDeviceClass(hProfiles[i]) == icSigLinkClass) {
      return NULL; // Unsupported named color and device link profiles
    }
  }

  // Create a placeholder transform with dummy I/O formats to place LUT in it
  p = (_LPcmsTRANSFORM) 
    cmsCreateTransform(NULL, TYPE_RGB_8, NULL, TYPE_RGB_8, Intent, cmsFLAGS_NULLTRANSFORM);

  p->EntryColorSpace = cmsGetColorSpace(hProfiles[0]);    

  // Gater information about first input profile
  hProfile = hProfiles[0];
  csIn = cmsGetColorSpace(hProfile);
  nInChannels  = _cmsChannelsOf(csIn);
  inFmt = BYTES_SH(2) | CHANNELS_SH(nInChannels);

  // Create a sequence
  for (i=1; i < nProfiles; i++) {
    // Gather output parameters
    hTargetProfile = hProfiles[i];
    csOut = cmsGetColorSpace(hTargetProfile);
    nOutChannels = _cmsChannelsOf(csOut);               
    outFmt = BYTES_SH(2)|CHANNELS_SH(nOutChannels);
        
    transforms[i-1] = 
      cmsCreateTransform(
        hProfile, inFmt, 
        hTargetProfile, outFmt, 
        Intent, cmsFLAGS_NOTPRECALC | cmsFLAGS_NOTCACHE
      );           
    
    if(transforms[i-1] == NULL)
      CLEANUP_AND_RETURN(NULL); // Incompatible profiles?

    // Assign output parameters to input
    hProfile = hTargetProfile;
    csIn = csOut;
    nInChannels = nOutChannels;               
    inFmt = outFmt;
  }

  p->ExitColorSpace = csOut;
  transforms[i] = NULL; // End marker 

  p->InputProfile  = hProfiles[0];
  p->OutputProfile = hProfiles[nProfiles-1];

  nGridPoints = _cmsReasonableGridpointsByColorspace(p->EntryColorSpace, 0);
   
  nInChannels  = _cmsChannelsOf(cmsGetColorSpace(p->InputProfile));

  // Create 3DCLUT
  if (! (Grid = cmsAllocLUT())) 
    CLEANUP_AND_RETURN(NULL);

  Grid = cmsAlloc3DGrid(Grid, nGridPoints, nInChannels, nOutChannels);

  _cmsComputePrelinearizationTablesFromXFORM(transforms, nProfiles-1, Grid);
      
  // Compute device link on 16-bit basis                
  if (!cmsSample3DGrid(Grid, cmmMultiprofileSampler, (LPVOID) transforms, Grid -> wFlags)) 
    CLEANUP_AND_RETURN(NULL);
  
  // Put the new LUT into resulting transform
  p->DeviceLink = Grid;
  // Set transform method
  p->xform = cmmPrecalculatedXformImpl;

  // Commented out since it is not clear if it is correct or not
  // Sequential transforms gives same result as multiprofile with this call commented out
  /*  
  if(Intent != INTENT_ABSOLUTE_COLORIMETRIC)
      _cmsFixWhiteMisalignment(p);
  */

  // Don't clean LUT
  Grid = NULL;

  CLEANUP_AND_RETURN((cmsHTRANSFORM) p);
}
Example #25
0
/* Transform an entire buffer */
void
gscms_transform_color_buffer(gx_device *dev, gsicc_link_t *icclink,
                             gsicc_bufferdesc_t *input_buff_desc,
                             gsicc_bufferdesc_t *output_buff_desc,
                             void *inputbuffer,
                             void *outputbuffer)
{
    cmsHTRANSFORM hTransform = (cmsHTRANSFORM)icclink->link_handle;
    cmsUInt32Number dwInputFormat, dwOutputFormat, num_src_lcms, num_des_lcms;
    int planar,numbytes, big_endian, hasalpha, k;
    unsigned char *inputpos, *outputpos;
#if DUMP_CMS_BUFFER
    FILE *fid_in, *fid_out;
#endif
    /* Although little CMS does  make assumptions about data types in its
       transformations you can change it after the fact.  */
    /* Set us to the proper output type */
    /* Note, we could speed this up by passing back the encoded data type
        to the caller so that we could avoid having to go through this
        computation each time if they are doing multiple calls to this
        operation */
    /* Color space MUST be the same */
    dwInputFormat = COLORSPACE_SH(T_COLORSPACE(cmsGetTransformInputFormat(hTransform)));
    dwOutputFormat = COLORSPACE_SH(T_COLORSPACE(cmsGetTransformOutputFormat(hTransform)));

    /* Now set if we have planar, num bytes, endian case, and alpha data to skip */
    /* Planar -- pdf14 case for example */
    planar = input_buff_desc->is_planar;
    dwInputFormat = dwInputFormat | PLANAR_SH(planar);
    planar = output_buff_desc->is_planar;
    dwOutputFormat = dwOutputFormat | PLANAR_SH(planar);

    /* 8 or 16 byte input and output */
    numbytes = input_buff_desc->bytes_per_chan;
    if (numbytes>2) numbytes = 0;  /* littleCMS encodes float with 0 ToDO. */
    dwInputFormat = dwInputFormat | BYTES_SH(numbytes);
    numbytes = output_buff_desc->bytes_per_chan;
    if (numbytes>2) numbytes = 0;
    dwOutputFormat = dwOutputFormat | BYTES_SH(numbytes);

    /* endian */
    big_endian = !input_buff_desc->little_endian;
    dwInputFormat = dwInputFormat | ENDIAN16_SH(big_endian);
    big_endian = !output_buff_desc->little_endian;
    dwOutputFormat = dwOutputFormat | ENDIAN16_SH(big_endian);

    /* number of channels.  This should not really be changing! */
    num_src_lcms = T_CHANNELS(cmsGetTransformInputFormat(hTransform));
    num_des_lcms = T_CHANNELS(cmsGetTransformOutputFormat(hTransform));
    if (num_src_lcms != input_buff_desc->num_chan ||
            num_des_lcms != output_buff_desc->num_chan) {
        /* We can't transform this. Someone is doing something odd */
        return;
    }
    dwInputFormat = dwInputFormat | CHANNELS_SH(num_src_lcms);
    dwOutputFormat = dwOutputFormat | CHANNELS_SH(num_des_lcms);

    /* alpha, which is passed through unmolested */
    /* ToDo:  Right now we always must have alpha last */
    /* This is really only going to be an issue when we have
       interleaved alpha data */
    hasalpha = input_buff_desc->has_alpha;
    dwInputFormat = dwInputFormat | EXTRA_SH(hasalpha);
    dwOutputFormat = dwOutputFormat | EXTRA_SH(hasalpha);

    /* Change the formatters */
    cmsChangeBuffersFormat(hTransform,dwInputFormat,dwOutputFormat);

    /* littleCMS knows nothing about word boundarys.  As such, we need to do
       this row by row adjusting for our stride.  Output buffer must already
       be allocated. ToDo:  Check issues with plane and row stride and word
       boundry */
    inputpos = (byte *) inputbuffer;
    outputpos = (byte *) outputbuffer;
    if(input_buff_desc->is_planar) {
        /* Determine if we can do this in one operation or if we have to break
           it up.  Essentially if the width * height = plane_stride then yes.  If
           we are doing some subsection of a plane then no. */
        if (input_buff_desc->num_rows * input_buff_desc->pixels_per_row ==
                input_buff_desc->plane_stride  &&
                output_buff_desc->num_rows * output_buff_desc->pixels_per_row ==
                output_buff_desc->plane_stride) {
            /* Do entire buffer.*/
            cmsDoTransform(hTransform, inputpos, outputpos,
                           input_buff_desc->plane_stride);
        } else {
            /* We have to do this row by row, with memory transfers */
            byte *temp_des, *temp_src;
            int source_size = input_buff_desc->bytes_per_chan *
                              input_buff_desc->pixels_per_row;

            int des_size = output_buff_desc->bytes_per_chan *
                           output_buff_desc->pixels_per_row;
            int y, i;

            temp_src = (byte*) gs_alloc_bytes(icclink->icc_link_cache->memory,
                                              source_size * input_buff_desc->num_chan,
                                              "gscms_transform_color_buffer");
            if (temp_src == NULL)
                return;
            temp_des = (byte*) gs_alloc_bytes(icclink->icc_link_cache->memory,
                                              des_size * output_buff_desc->num_chan,
                                              "gscms_transform_color_buffer");
            if (temp_des == NULL)
                return;
            for (y = 0; y < input_buff_desc->num_rows; y++) {
                byte *src_cm = temp_src;
                byte *src_buff = inputpos;
                byte *des_cm = temp_des;
                byte *des_buff = outputpos;

                /* Put into planar temp buffer */
                for (i = 0; i < input_buff_desc->num_chan; i ++) {
                    memcpy(src_cm, src_buff, source_size);
                    src_cm += source_size;
                    src_buff += input_buff_desc->plane_stride;
                }
                /* Transform */
                cmsDoTransform(hTransform, temp_src, temp_des,
                               input_buff_desc->pixels_per_row);
                /* Get out of temp planar buffer */
                for (i = 0; i < output_buff_desc->num_chan; i ++) {
                    memcpy(des_buff, des_cm, des_size);
                    des_cm += des_size;
                    des_buff += output_buff_desc->plane_stride;
                }
                inputpos += input_buff_desc->row_stride;
                outputpos += output_buff_desc->row_stride;
            }
            gs_free_object(icclink->icc_link_cache->memory, temp_src,
                           "gscms_transform_color_buffer");
            gs_free_object(icclink->icc_link_cache->memory, temp_des,
                           "gscms_transform_color_buffer");
        }
    } else {
        /* Do row by row. */
        for(k = 0; k < input_buff_desc->num_rows ; k++) {
            cmsDoTransform(hTransform, inputpos, outputpos,
                           input_buff_desc->pixels_per_row);
            inputpos += input_buff_desc->row_stride;
            outputpos += output_buff_desc->row_stride;
        }
    }
#if DUMP_CMS_BUFFER
    fid_in = gp_fopen("CM_Input.raw","ab");
    fid_out = gp_fopen("CM_Output.raw","ab");
    fwrite((unsigned char*) inputbuffer,sizeof(unsigned char),
           input_buff_desc->row_stride,fid_in);
    fwrite((unsigned char*) outputbuffer,sizeof(unsigned char),
           output_buff_desc->row_stride,fid_out);
    fclose(fid_in);
    fclose(fid_out);
#endif
}
Example #26
0
cmsPipeline* _cmsCreateGamutCheckPipeline(cmsContext ContextID,
                                          cmsHPROFILE hProfiles[],
                                          cmsBool  BPC[],
                                          cmsUInt32Number Intents[],
                                          cmsFloat64Number AdaptationStates[],
                                          cmsUInt32Number nGamutPCSposition,
                                          cmsHPROFILE hGamut)
{
    cmsHPROFILE hLab;
    cmsPipeline* Gamut;
    cmsStage* CLUT;
    cmsUInt32Number dwFormat;
    GAMUTCHAIN Chain;
    int nChannels, nGridpoints;
    cmsColorSpaceSignature ColorSpace;
    cmsUInt32Number i;
    cmsHPROFILE ProfileList[256];
    cmsBool     BPCList[256];
    cmsFloat64Number AdaptationList[256];
    cmsUInt32Number IntentList[256];

    memset(&Chain, 0, sizeof(GAMUTCHAIN));


    if (nGamutPCSposition <= 0 || nGamutPCSposition > 255) {
        cmsSignalError(ContextID, cmsERROR_RANGE, "Wrong position of PCS. 1..255 expected, %d found.", nGamutPCSposition);
        return NULL;
    }

    hLab = cmsCreateLab4ProfileTHR(ContextID, NULL);
    if (hLab == NULL) return NULL;


    // The figure of merit. On matrix-shaper profiles, should be almost zero as
    // the conversion is pretty exact. On LUT based profiles, different resolutions
    // of input and output CLUT may result in differences.

    if (cmsIsMatrixShaper(hGamut)) {

        Chain.Thereshold = 1.0;
    }
    else {
        Chain.Thereshold = ERR_THERESHOLD;
    }


    // Create a copy of parameters
    for (i=0; i < nGamutPCSposition; i++) {
        ProfileList[i]    = hProfiles[i];
        BPCList[i]        = BPC[i];
        AdaptationList[i] = AdaptationStates[i];
        IntentList[i]     = Intents[i];
    }

    // Fill Lab identity
    ProfileList[nGamutPCSposition] = hLab;
    BPCList[nGamutPCSposition] = 0;
    AdaptationList[nGamutPCSposition] = 1.0;
    IntentList[nGamutPCSposition] = INTENT_RELATIVE_COLORIMETRIC;


    ColorSpace  = cmsGetColorSpace(hGamut);

    nChannels   = cmsChannelsOf(ColorSpace);
    nGridpoints = _cmsReasonableGridpointsByColorspace(ColorSpace, cmsFLAGS_HIGHRESPRECALC);
    dwFormat    = (CHANNELS_SH(nChannels)|BYTES_SH(2));

    // 16 bits to Lab double
    Chain.hInput = cmsCreateExtendedTransform(ContextID,
        nGamutPCSposition + 1,
        ProfileList,
        BPCList,
        IntentList,
        AdaptationList,
        NULL, 0,
        dwFormat, TYPE_Lab_DBL,
        cmsFLAGS_NOCACHE);


    // Does create the forward step. Lab double to device
    dwFormat    = (CHANNELS_SH(nChannels)|BYTES_SH(2));
    Chain.hForward = cmsCreateTransformTHR(ContextID,
        hLab, TYPE_Lab_DBL,
        hGamut, dwFormat,
        INTENT_RELATIVE_COLORIMETRIC,
        cmsFLAGS_NOCACHE);

    // Does create the backwards step
    Chain.hReverse = cmsCreateTransformTHR(ContextID, hGamut, dwFormat,
        hLab, TYPE_Lab_DBL,
        INTENT_RELATIVE_COLORIMETRIC,
        cmsFLAGS_NOCACHE);


    // All ok?
    if (Chain.hInput && Chain.hForward && Chain.hReverse) {

        // Go on, try to compute gamut LUT from PCS. This consist on a single channel containing
        // dE when doing a transform back and forth on the colorimetric intent.

        Gamut = cmsPipelineAlloc(ContextID, 3, 1);
        if (Gamut != NULL) {

            CLUT = cmsStageAllocCLut16bit(ContextID, nGridpoints, nChannels, 1, NULL);
            if (!cmsPipelineInsertStage(Gamut, cmsAT_BEGIN, CLUT)) {
                cmsPipelineFree(Gamut);
                Gamut = NULL;
            }
            else {
                cmsStageSampleCLut16bit(CLUT, GamutSampler, (void*) &Chain, 0);
            }
        }
    }
    else
        Gamut = NULL;   // Didn't work...

    // Free all needed stuff.
    if (Chain.hInput)   cmsDeleteTransform(Chain.hInput);
    if (Chain.hForward) cmsDeleteTransform(Chain.hForward);
    if (Chain.hReverse) cmsDeleteTransform(Chain.hReverse);
    if (hLab) cmsCloseProfile(hLab);

    // And return computed hull
    return Gamut;
}
Example #27
0
static
void OpenTransforms(void)
{

    DWORD dwIn, dwOut, dwFlags;

    dwFlags = 0;
    
    
    if (lIsDeviceLink) {

            hInput  = cmsOpenProfileFromFile(cInProf, "r");
            hOutput = NULL;
            InputColorSpace   = cmsGetColorSpace(hInput);
            OutputColorSpace = cmsGetPCS(hInput);
        
            
       }
    else {

            hInput  = OpenStockProfile(cInProf);
            hOutput = OpenStockProfile(cOutProf);    
            hProof  = NULL;

            if (cProofing != NULL) {

                   hProof = OpenStockProfile(cProofing);
                   dwFlags |= cmsFLAGS_SOFTPROOFING;
            }

            InputColorSpace   = cmsGetColorSpace(hInput);
            OutputColorSpace  = cmsGetColorSpace(hOutput);

            if (cmsGetDeviceClass(hInput) == icSigLinkClass ||
                cmsGetDeviceClass(hOutput) == icSigLinkClass)   
                        FatalError("Use %cl flag for devicelink profiles!\n", SW);
    
    }

       hXYZ    = cmsCreateXYZProfile();
       hLab    = cmsCreateLabProfile(NULL);


       if (Verbose) {

            printf("From: %s\n", cmsTakeProductName(hInput));
            printf("Desc: %s\n", cmsTakeProductDesc(hInput));
            if (hOutput) printf("To  : %s\n\n", cmsTakeProductName(hOutput));
       }

      
       dwIn  = BYTES_SH(2) | CHANNELS_SH(_cmsChannelsOf(InputColorSpace));
       dwOut = BYTES_SH(2) | CHANNELS_SH(_cmsChannelsOf(OutputColorSpace));
              
       switch (PrecalcMode) {
           
       case 0: dwFlags |= cmsFLAGS_NOTPRECALC; break;
       case 2: dwFlags |= cmsFLAGS_HIGHRESPRECALC; break;
	   case 3: dwFlags |= cmsFLAGS_LOWRESPRECALC; break;
	   case 1: break;

       default: FatalError("Unknown precalculation mode '%d'", PrecalcMode);
       }
       
       
       if (BlackPointCompensation) 
            dwFlags |= cmsFLAGS_BLACKPOINTCOMPENSATION;

       if (GamutCheck) {

            if (hProof == NULL)
                FatalError("I need proofing profile -p for gamut checking!");

            cmsSetAlarmCodes(0xFF, 0xFF, 0xFF);
            dwFlags |= cmsFLAGS_GAMUTCHECK;            
       }

       if (cmsGetDeviceClass(hInput) == icSigNamedColorClass) {
           dwIn = TYPE_NAMED_COLOR_INDEX;
       }

       hTrans     = cmsCreateProofingTransform(hInput,  dwIn,
                                               hOutput, dwOut,
                                               hProof,
                                               Intent, ProofingIntent, dwFlags);


       
       
       hTransXYZ = NULL; hTransLab = NULL;
       if (hOutput && Verbose) {

            hTransXYZ = cmsCreateTransform(hInput, dwIn,
                                      hXYZ,  TYPE_XYZ_16,
                                      Intent, cmsFLAGS_NOTPRECALC);

            hTransLab = cmsCreateTransform(hInput, dwIn,
                                      hLab,  TYPE_Lab_16,
                                      Intent, cmsFLAGS_NOTPRECALC);    
       }
       
}