Example #1
0
cmsHPROFILE
dt_colorspaces_create_xyz_profile(void)
{
  cmsHPROFILE hXYZ = cmsCreateXYZProfile();
  // revert some settings which prevent us from using XYZ as output profile:
  cmsSetDeviceClass(hXYZ,            cmsSigDisplayClass);
  cmsSetColorSpace(hXYZ,             cmsSigRgbData);
  cmsSetPCS(hXYZ,                    cmsSigXYZData);
  cmsSetHeaderRenderingIntent(hXYZ,  INTENT_PERCEPTUAL);

  if (hXYZ == NULL) return NULL;

  cmsSetProfileVersion(hXYZ, 2.1);
  cmsMLU *mlu0 = cmsMLUalloc(NULL, 1);
  cmsMLUsetASCII(mlu0, "en", "US", "(dt internal)");
  cmsMLU *mlu1 = cmsMLUalloc(NULL, 1);
  cmsMLUsetASCII(mlu1, "en", "US", "linear XYZ");
  cmsMLU *mlu2 = cmsMLUalloc(NULL, 1);
  cmsMLUsetASCII(mlu2, "en", "US", "Darktable linear XYZ");
  cmsWriteTag(hXYZ, cmsSigDeviceMfgDescTag,   mlu0);
  cmsWriteTag(hXYZ, cmsSigDeviceModelDescTag, mlu1);
  // this will only be displayed when the embedded profile is read by for example GIMP
  cmsWriteTag(hXYZ, cmsSigProfileDescriptionTag, mlu2);
  cmsMLUfree(mlu0);
  cmsMLUfree(mlu1);
  cmsMLUfree(mlu2);

  return hXYZ;
}
static
cmsBool SetTextTags(cmsHPROFILE hProfile, const wchar_t* Description)
{
    cmsMLU *DescriptionMLU, *CopyrightMLU;
    cmsBool  rc = FALSE;
    cmsContext ContextID = cmsGetProfileContextID(hProfile);

    DescriptionMLU  = cmsMLUalloc(ContextID, 1);
    CopyrightMLU    = cmsMLUalloc(ContextID, 1);

    if (DescriptionMLU == NULL || CopyrightMLU == NULL) goto Error;

    if (!cmsMLUsetWide(DescriptionMLU,  "en", "US", Description)) goto Error;
    if (!cmsMLUsetWide(CopyrightMLU,    "en", "US", L"No copyright, use freely")) goto Error;

    if (!cmsWriteTag(hProfile, cmsSigProfileDescriptionTag,  DescriptionMLU)) goto Error;
    if (!cmsWriteTag(hProfile, cmsSigCopyrightTag,           CopyrightMLU)) goto Error;

    rc = TRUE;

Error:

    if (DescriptionMLU)
        cmsMLUfree(DescriptionMLU);
    if (CopyrightMLU)
        cmsMLUfree(CopyrightMLU);
    return rc;
}
Example #3
0
cmsHPROFILE
dt_colorspaces_create_srgb_profile()
{
  cmsHPROFILE hsRGB;

  cmsCIEXYZTRIPLE Colorants =
  {
    {0.436066, 0.222488, 0.013916},
    {0.385147, 0.716873, 0.097076},
    {0.143066, 0.060608, 0.714096}
  };

  cmsCIEXYZ black = { 0, 0, 0 };
  cmsCIEXYZ D65 = { 0.95045, 1, 1.08905 };
  cmsToneCurve* transferFunction;

  transferFunction = cmsBuildTabulatedToneCurve16(NULL, dt_srgb_tone_curve_values_n, dt_srgb_tone_curve_values);

  hsRGB = cmsCreateProfilePlaceholder(0);

  cmsSetProfileVersion(hsRGB, 2.1);

  cmsMLU *mlu0 = cmsMLUalloc(NULL, 1);
  cmsMLUsetASCII(mlu0, "en", "US", "Public Domain");
  cmsMLU *mlu1 = cmsMLUalloc(NULL, 1);
  cmsMLUsetASCII(mlu1, "en", "US", "sRGB");
  cmsMLU *mlu2 = cmsMLUalloc(NULL, 1);
  cmsMLUsetASCII(mlu2, "en", "US", "Darktable");
  cmsMLU *mlu3 = cmsMLUalloc(NULL, 1);
  cmsMLUsetASCII(mlu3, "en", "US", "sRGB");
  // this will only be displayed when the embedded profile is read by for example GIMP
  cmsWriteTag(hsRGB, cmsSigCopyrightTag,          mlu0);
  cmsWriteTag(hsRGB, cmsSigProfileDescriptionTag, mlu1);
  cmsWriteTag(hsRGB, cmsSigDeviceMfgDescTag,      mlu2);
  cmsWriteTag(hsRGB, cmsSigDeviceModelDescTag,    mlu3);
  cmsMLUfree(mlu0);
  cmsMLUfree(mlu1);
  cmsMLUfree(mlu2);
  cmsMLUfree(mlu3);

  cmsSetDeviceClass(hsRGB, cmsSigDisplayClass);
  cmsSetColorSpace(hsRGB, cmsSigRgbData);
  cmsSetPCS(hsRGB, cmsSigXYZData);

  cmsWriteTag(hsRGB, cmsSigMediaWhitePointTag, &D65);
  cmsWriteTag(hsRGB, cmsSigMediaBlackPointTag, &black);

  cmsWriteTag(hsRGB, cmsSigRedColorantTag, (void*) &Colorants.Red);
  cmsWriteTag(hsRGB, cmsSigGreenColorantTag, (void*) &Colorants.Green);
  cmsWriteTag(hsRGB, cmsSigBlueColorantTag, (void*) &Colorants.Blue);

  cmsWriteTag(hsRGB, cmsSigRedTRCTag, (void*) transferFunction);
  cmsLinkTag(hsRGB, cmsSigGreenTRCTag, cmsSigRedTRCTag );
  cmsLinkTag(hsRGB, cmsSigBlueTRCTag, cmsSigRedTRCTag );

  return hsRGB;
}
Example #4
0
// Create the ICC virtual profile for adobe rgb space
cmsHPROFILE
dt_colorspaces_create_adobergb_profile(void)
{
  cmsHPROFILE  hAdobeRGB;

  cmsCIEXYZTRIPLE Colorants =
  {
    {0.609741, 0.311111, 0.019470},
    {0.205276, 0.625671, 0.060867},
    {0.149185, 0.063217, 0.744568}
  };

  cmsCIEXYZ black = { 0, 0, 0 };
  cmsCIEXYZ D65 = { 0.95045, 1, 1.08905 };
  cmsToneCurve* transferFunction;

  transferFunction = cmsBuildGamma(NULL, 2.2);

  hAdobeRGB = cmsCreateProfilePlaceholder(0);

  cmsSetProfileVersion(hAdobeRGB, 2.1);

  cmsMLU *mlu0 = cmsMLUalloc(NULL, 1);
  cmsMLUsetASCII(mlu0, "en", "US", "Public Domain");
  cmsMLU *mlu1 = cmsMLUalloc(NULL, 1);
  cmsMLUsetASCII(mlu1, "en", "US", "AdobeRGB");
  cmsMLU *mlu2 = cmsMLUalloc(NULL, 1);
  cmsMLUsetASCII(mlu2, "en", "US", "Darktable");
  cmsMLU *mlu3 = cmsMLUalloc(NULL, 1);
  cmsMLUsetASCII(mlu3, "en", "US", "AdobeRGB");
  // this will only be displayed when the embedded profile is read by for example GIMP
  cmsWriteTag(hAdobeRGB, cmsSigCopyrightTag,          mlu0);
  cmsWriteTag(hAdobeRGB, cmsSigProfileDescriptionTag, mlu1);
  cmsWriteTag(hAdobeRGB, cmsSigDeviceMfgDescTag,      mlu2);
  cmsWriteTag(hAdobeRGB, cmsSigDeviceModelDescTag,    mlu3);
  cmsMLUfree(mlu0);
  cmsMLUfree(mlu1);
  cmsMLUfree(mlu2);
  cmsMLUfree(mlu3);

  cmsSetDeviceClass(hAdobeRGB, cmsSigDisplayClass);
  cmsSetColorSpace(hAdobeRGB, cmsSigRgbData);
  cmsSetPCS(hAdobeRGB, cmsSigXYZData);

  cmsWriteTag(hAdobeRGB, cmsSigMediaWhitePointTag, &D65);
  cmsWriteTag(hAdobeRGB, cmsSigMediaBlackPointTag, &black);

  cmsWriteTag(hAdobeRGB, cmsSigRedColorantTag, (void*) &Colorants.Red);
  cmsWriteTag(hAdobeRGB, cmsSigGreenColorantTag, (void*) &Colorants.Green);
  cmsWriteTag(hAdobeRGB, cmsSigBlueColorantTag, (void*) &Colorants.Blue);

  cmsWriteTag(hAdobeRGB, cmsSigRedTRCTag, (void*) transferFunction);
  cmsLinkTag(hAdobeRGB, cmsSigGreenTRCTag, cmsSigRedTRCTag );
  cmsLinkTag(hAdobeRGB, cmsSigBlueTRCTag, cmsSigRedTRCTag );

  return hAdobeRGB;
}
Example #5
0
// Dump the contents of profile sequence in both tags (if v4 available)
cmsBool _cmsWriteProfileSequence(cmsHPROFILE hProfile, const cmsSEQ* seq)
{
    if (!cmsWriteTag(hProfile, cmsSigProfileSequenceDescTag, seq)) return FALSE;

    if (cmsGetEncodedICCversion(hProfile) >= 0x4000000) {

            if (!cmsWriteTag(hProfile, cmsSigProfileSequenceIdTag, seq)) return FALSE;
    }

    return TRUE;
}
Example #6
0
cmsHPROFILE
dt_colorspaces_create_darktable_profile(const char *makermodel)
{
  dt_profiled_colormatrix_t *preset = NULL;
  for(int k=0; k<dt_profiled_colormatrix_cnt; k++)
  {
    if(!strcasecmp(makermodel, dt_profiled_colormatrices[k].makermodel))
    {
      preset = dt_profiled_colormatrices + k;
      break;
    }
  }
  if(!preset) return NULL;

  const float wxyz = preset->white[0]+preset->white[1]+preset->white[2];
  const float rxyz = preset->rXYZ[0] +preset->rXYZ[1] +preset->rXYZ[2];
  const float gxyz = preset->gXYZ[0] +preset->gXYZ[1] +preset->gXYZ[2];
  const float bxyz = preset->bXYZ[0] +preset->bXYZ[1] +preset->bXYZ[2];
  cmsCIExyY       WP = {preset->white[0]/wxyz, preset->white[1]/wxyz, 1.0};
  cmsCIExyYTRIPLE XYZPrimaries   =
  {
    {preset->rXYZ[0]/rxyz, preset->rXYZ[1]/rxyz, 1.0},
    {preset->gXYZ[0]/gxyz, preset->gXYZ[1]/gxyz, 1.0},
    {preset->bXYZ[0]/bxyz, preset->bXYZ[1]/bxyz, 1.0}
  };
  cmsToneCurve *Gamma[3];
  cmsHPROFILE  hp;

  Gamma[0] = Gamma[1] = Gamma[2] = build_linear_gamma();

  hp = cmsCreateRGBProfile(&WP, &XYZPrimaries, Gamma);
  cmsFreeToneCurve(Gamma[0]);
  if (hp == NULL) return NULL;

  char name[512];
  snprintf(name, 512, "Darktable profiled %s", makermodel);
  cmsSetProfileVersion(hp, 2.1);
  cmsMLU *mlu0 = cmsMLUalloc(NULL, 1);
  cmsMLUsetASCII(mlu0, "en", "US", "(dt internal)");
  cmsMLU *mlu1 = cmsMLUalloc(NULL, 1);
  cmsMLUsetASCII(mlu1, "en", "US", name);
  cmsMLU *mlu2 = cmsMLUalloc(NULL, 1);
  cmsMLUsetASCII(mlu2, "en", "US", name);
  cmsWriteTag(hp, cmsSigDeviceMfgDescTag,   mlu0);
  cmsWriteTag(hp, cmsSigDeviceModelDescTag, mlu1);
  // this will only be displayed when the embedded profile is read by for example GIMP
  cmsWriteTag(hp, cmsSigProfileDescriptionTag, mlu2);
  cmsMLUfree(mlu0);
  cmsMLUfree(mlu1);
  cmsMLUfree(mlu2);

  return hp;
}
// This function creates a profile based on White point and transfer function.
cmsHPROFILE CMSEXPORT cmsCreateGrayProfileTHR(cmsContext ContextID,
                                           const cmsCIExyY* WhitePoint,
                                           const cmsToneCurve* TransferFunction)
{
    cmsHPROFILE hICC;
    cmsCIEXYZ tmp;

    hICC = cmsCreateProfilePlaceholder(ContextID);
    if (!hICC)                          // can't allocate
        return NULL;

    cmsSetProfileVersion(hICC, 4.3);

    cmsSetDeviceClass(hICC,      cmsSigDisplayClass);
    cmsSetColorSpace(hICC,       cmsSigGrayData);
    cmsSetPCS(hICC,              cmsSigXYZData);
    cmsSetHeaderRenderingIntent(hICC,  INTENT_PERCEPTUAL);


    // Implement profile using following tags:
    //
    //  1 cmsSigProfileDescriptionTag
    //  2 cmsSigMediaWhitePointTag
    //  3 cmsSigGrayTRCTag

    // This conforms a standard Gray DisplayProfile

    // Fill-in the tags

    if (!SetTextTags(hICC, L"gray built-in")) goto Error;


    if (WhitePoint) {

        cmsxyY2XYZ(&tmp, WhitePoint);
        if (!cmsWriteTag(hICC, cmsSigMediaWhitePointTag, (void*) &tmp)) goto Error;
    }

    if (TransferFunction) {

        if (!cmsWriteTag(hICC, cmsSigGrayTRCTag, (void*) TransferFunction)) goto Error;
    }

    return hICC;

Error:
    if (hICC)
        cmsCloseProfile(hICC);
    return NULL;
}
QByteArray LcmsColorProfileContainer::createFromChromacities(const KoRGBChromaticities& _chromacities, qreal gamma, QString _profileName)
{
    cmsCIExyYTRIPLE primaries;
    cmsCIExyY whitePoint;
    lcmsToPigmentViceVersaStructureCopy(primaries.Red, _chromacities.primaries.Red);
    lcmsToPigmentViceVersaStructureCopy(primaries.Green, _chromacities.primaries.Green);
    lcmsToPigmentViceVersaStructureCopy(primaries.Blue, _chromacities.primaries.Blue);
    lcmsToPigmentViceVersaStructureCopy(whitePoint, _chromacities.whitePoint);
    cmsToneCurve* gammaTable = cmsBuildGamma(0, gamma);

    const int numTransferFunctions = 3;
    cmsToneCurve* transferFunctions[numTransferFunctions];

    for (int i = 0; i < numTransferFunctions; ++i) {
        transferFunctions[i] = gammaTable;
    }

    cmsHPROFILE profile = cmsCreateRGBProfile(&whitePoint, &primaries,
                          transferFunctions);
    QString name = _profileName;

    if (name.isEmpty()) {
        name = QString("lcms virtual RGB profile - R(%1, %2) G(%3, %4) B(%5, %6) W(%7, %8) gamma %9")
               .arg(primaries.Red.x)
               .arg(primaries.Red.y)
               .arg(primaries.Green.x)
               .arg(primaries.Green.y)
               .arg(primaries.Blue.x)
               .arg(primaries.Blue.y)
               .arg(whitePoint.x)
               .arg(whitePoint.y)
               .arg(gamma);
    }

    // icSigProfileDescriptionTag is the compulsory tag and is the profile name
    // displayed by other applications.
    cmsWriteTag(profile, cmsSigProfileDescriptionTag, name.toLatin1().data());

    cmsWriteTag(profile, cmsSigDeviceModelDescTag, name.toLatin1().data());

    // Clear the default manufacturer's tag that is set to "(lcms internal)"
    QByteArray ba("");
    cmsWriteTag(profile, cmsSigDeviceMfgDescTag, ba.data());

    cmsFreeToneCurve(gammaTable);
    QByteArray profileArray = lcmsProfileToByteArray(profile);
    cmsCloseProfile(profile);
    return profileArray;
}
// Creates a fake NULL profile. This profile return 1 channel as always 0.
// Is useful only for gamut checking tricks
cmsHPROFILE CMSEXPORT cmsCreateNULLProfileTHR(cmsContext ContextID)
{
    cmsHPROFILE hProfile;
    cmsPipeline* LUT = NULL;
    cmsStage* PostLin;
    cmsToneCurve* EmptyTab;
    cmsUInt16Number Zero[2] = { 0, 0 };

    hProfile = cmsCreateProfilePlaceholder(ContextID);
    if (!hProfile)                          // can't allocate
        return NULL;

    cmsSetProfileVersion(hProfile, 4.3);

    if (!SetTextTags(hProfile, L"NULL profile built-in")) goto Error;



    cmsSetDeviceClass(hProfile, cmsSigOutputClass);
    cmsSetColorSpace(hProfile,  cmsSigGrayData);
    cmsSetPCS(hProfile,         cmsSigLabData);

    // An empty LUTs is all we need
    LUT = cmsPipelineAlloc(ContextID, 1, 1);
    if (LUT == NULL) goto Error;

    EmptyTab = cmsBuildTabulatedToneCurve16(ContextID, 2, Zero);
    PostLin = cmsStageAllocToneCurves(ContextID, 1, &EmptyTab);
    cmsFreeToneCurve(EmptyTab);

    if (!cmsPipelineInsertStage(LUT, cmsAT_END, PostLin))
        goto Error;

    if (!cmsWriteTag(hProfile, cmsSigBToA0Tag, (void*) LUT)) goto Error;
    if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, cmsD50_XYZ())) goto Error;

    cmsPipelineFree(LUT);
    return hProfile;

Error:

    if (LUT != NULL)
        cmsPipelineFree(LUT);

    if (hProfile != NULL)
        cmsCloseProfile(hProfile);

    return NULL;
}
Example #10
0
static gboolean
set_vcgt_from_data (cmsHPROFILE profile,
		    const guint16 *red,
		    const guint16 *green,
		    const guint16 *blue,
		    guint size)
{
	guint i;
	gboolean ret = FALSE;
	cmsToneCurve *vcgt_curve[3];

	/* build tone curve */
	vcgt_curve[0] = cmsBuildTabulatedToneCurve16 (NULL, size, red);
	vcgt_curve[1] = cmsBuildTabulatedToneCurve16 (NULL, size, green);
	vcgt_curve[2] = cmsBuildTabulatedToneCurve16 (NULL, size, blue);

	/* smooth it */
	for (i = 0; i < 3; i++)
		cmsSmoothToneCurve (vcgt_curve[i], 5);

	/* write the tag */
	ret = cmsWriteTag (profile, cmsSigVcgtType, vcgt_curve);

	/* free the tonecurves */
	for (i = 0; i < 3; i++)
		cmsFreeToneCurve (vcgt_curve[i]);
	return ret;
}
Example #11
0
// This function does create the virtual output profile, with the necessary gamut mapping
static
cmsHPROFILE CreatePCS2ITU_ICC(void)
{
    cmsHPROFILE hProfile;
    cmsPipeline* BToA0;
    cmsStage* ColorMap;

    BToA0 = cmsPipelineAlloc(0, 3, 3);
    if (BToA0 == NULL) return NULL;

    ColorMap = cmsStageAllocCLut16bit(0, GRID_POINTS, 3, 3, NULL);
    if (ColorMap == NULL) return NULL;

    cmsPipelineInsertStage(BToA0, cmsAT_BEGIN, ColorMap);
    cmsStageSampleCLut16bit(ColorMap, PCS2ITU, NULL, 0);

    hProfile = cmsCreateProfilePlaceholder(0);
    if (hProfile == NULL) {
        cmsPipelineFree(BToA0);
        return NULL;
    }

    cmsWriteTag(hProfile, cmsSigBToA0Tag, BToA0);
    cmsSetColorSpace(hProfile, cmsSigLabData);
    cmsSetPCS(hProfile, cmsSigLabData);
    cmsSetDeviceClass(hProfile, cmsSigColorSpaceClass);

    cmsPipelineFree(BToA0);

    return hProfile;
}
Example #12
0
cmsHPROFILE
dt_colorspaces_create_xyzmatrix_profile(float mat[3][3])
{
  // mat: cam -> xyz
  cmsCIExyY D65;
  float x[3], y[3];
  for(int k=0; k<3; k++)
  {
    const float norm = mat[0][k] + mat[1][k] + mat[2][k];
    x[k] = mat[0][k] / norm;
    y[k] = mat[1][k] / norm;
  }
  cmsCIExyYTRIPLE CameraPrimaries =
  {
    {x[0], y[0], 1.0},
    {x[1], y[1], 1.0},
    {x[2], y[2], 1.0}
  };
  cmsHPROFILE  cmat;

  cmsWhitePointFromTemp(&D65, 6504.0);

  cmsToneCurve *Gamma[3];
  Gamma[0] = Gamma[1] = Gamma[2] = build_linear_gamma();
  cmat = cmsCreateRGBProfile(&D65, &CameraPrimaries, Gamma);
  if (cmat == NULL) return NULL;
  cmsFreeToneCurve(Gamma[0]);

  cmsSetProfileVersion(cmat, 2.1);
  cmsMLU *mlu0 = cmsMLUalloc(NULL, 1);
  cmsMLUsetASCII(mlu0, "en", "US", "(dt internal)");
  cmsMLU *mlu1 = cmsMLUalloc(NULL, 1);
  cmsMLUsetASCII(mlu1, "en", "US", "color matrix built-in");
  cmsMLU *mlu2 = cmsMLUalloc(NULL, 1);
  cmsMLUsetASCII(mlu2, "en", "US", "color matrix built-in");
  cmsWriteTag(cmat, cmsSigDeviceMfgDescTag,   mlu0);
  cmsWriteTag(cmat, cmsSigDeviceModelDescTag, mlu1);
  // this will only be displayed when the embedded profile is read by for example GIMP
  cmsWriteTag(cmat, cmsSigProfileDescriptionTag, mlu2);
  cmsMLUfree(mlu0);
  cmsMLUfree(mlu1);
  cmsMLUfree(mlu2);

  return cmat;
}
Example #13
0
cmsBool ProfileUtils::cmsWriteTagTextAscii(cmsHPROFILE lcms_profile,
                                           cmsTagSignature sig,
                                           const QString &text)
{
    cmsBool ret;
    cmsMLU *mlu = cmsMLUalloc(0, 1);
    cmsMLUsetASCII(mlu, "EN", "us", text.toLatin1().constData());
    ret = cmsWriteTag(lcms_profile, sig, mlu);
    cmsMLUfree(mlu);
    return ret;
}
Example #14
0
cmsHPROFILE CMSEXPORT cmsCreateLinearizationDeviceLinkTHR(cmsContext ContextID,
                                                          cmsColorSpaceSignature ColorSpace,
                                                          cmsToneCurve* const TransferFunctions[])
{
    cmsHPROFILE hICC;
    cmsPipeline* Pipeline;
    cmsStage* Lin;
    int nChannels;

    hICC = cmsCreateProfilePlaceholder(ContextID);
    if (!hICC)                          
        return NULL;

    cmsSetProfileVersion(hICC, 4.3);

    cmsSetDeviceClass(hICC,      cmsSigLinkClass);
    cmsSetColorSpace(hICC,       ColorSpace);
    cmsSetPCS(hICC,              ColorSpace);

    cmsSetHeaderRenderingIntent(hICC,  INTENT_PERCEPTUAL); 

    // Set up channels
    nChannels = cmsChannelsOf(ColorSpace);

    // Creates a Pipeline with prelinearization step only
    Pipeline = cmsPipelineAlloc(ContextID, nChannels, nChannels);
    if (Pipeline == NULL) goto Error;


    // Copy tables to Pipeline
    Lin = cmsStageAllocToneCurves(ContextID, nChannels, TransferFunctions);
    if (Lin == NULL) goto Error;

    cmsPipelineInsertStage(Pipeline, cmsAT_BEGIN, Lin);

    // Create tags       
    if (!SetTextTags(hICC, L"Linearization built-in")) goto Error;    
    if (!cmsWriteTag(hICC, cmsSigAToB0Tag, (void*) Pipeline)) goto Error;       
    if (!SetSeqDescTag(hICC, "Linearization built-in")) goto Error;

    // Pipeline is already on virtual profile
    cmsPipelineFree(Pipeline);

    // Ok, done
    return hICC;

Error:
    if (hICC)
        cmsCloseProfile(hICC);


    return NULL;
}
Example #15
0
static void
gimp_lcms_profile_set_tag (cmsHPROFILE      profile,
                           cmsTagSignature  sig,
                           const gchar     *tag)
{
  cmsMLU *mlu;

  mlu = cmsMLUalloc (NULL, 1);
  cmsMLUsetASCII (mlu, "en", "US", tag);
  cmsWriteTag (profile, sig, mlu);
  cmsMLUfree (mlu);
}
Example #16
0
cmsHPROFILE
dt_colorspaces_create_linear_infrared_profile(void)
{
  // linear rgb with r and b swapped:
  cmsCIExyY       D65;
  cmsCIExyYTRIPLE Rec709Primaries =
  {
    {0.1500, 0.0600, 1.0},
    {0.3000, 0.6000, 1.0},
    {0.6400, 0.3300, 1.0}
  };
  cmsToneCurve *Gamma[3];
  cmsHPROFILE  hsRGB;

  cmsWhitePointFromTemp(&D65, 6504.0);
  Gamma[0] = Gamma[1] = Gamma[2] = build_linear_gamma();

  hsRGB = cmsCreateRGBProfile(&D65, &Rec709Primaries, Gamma);
  cmsFreeToneCurve(Gamma[0]);
  if (hsRGB == NULL) return NULL;

  cmsSetProfileVersion(hsRGB, 2.1);
  cmsMLU *mlu0 = cmsMLUalloc(NULL, 1);
  cmsMLUsetASCII(mlu0, "en", "US", "(dt internal)");
  cmsMLU *mlu1 = cmsMLUalloc(NULL, 1);
  cmsMLUsetASCII(mlu1, "en", "US", "linear infrared bgr");
  cmsMLU *mlu2 = cmsMLUalloc(NULL, 1);
  cmsMLUsetASCII(mlu2, "en", "US", "Darktable Linear Infrared RGB");
  cmsWriteTag(hsRGB, cmsSigDeviceMfgDescTag,   mlu0);
  cmsWriteTag(hsRGB, cmsSigDeviceModelDescTag, mlu1);
  // this will only be displayed when the embedded profile is read by for example GIMP
  cmsWriteTag(hsRGB, cmsSigProfileDescriptionTag, mlu2);
  cmsMLUfree(mlu0);
  cmsMLUfree(mlu1);
  cmsMLUfree(mlu2);

  return hsRGB;
}
Example #17
0
// Create the ICC virtual profile for adobe rgb space
cmsHPROFILE
dt_colorspaces_create_adobergb_profile(void)
{
  cmsCIExyY       D65;
  cmsCIExyYTRIPLE AdobePrimaries =
  {
    {0.6400, 0.3300, 1.0},
    {0.2100, 0.7100, 1.0},
    {0.1500, 0.0600, 1.0}
  };
  cmsToneCurve *Gamma22[3];
  cmsHPROFILE  hAdobeRGB;

  cmsWhitePointFromTemp(&D65, 6504.0);
  Gamma22[0] = Gamma22[1] = Gamma22[2] = build_adobergb_gamma();

  hAdobeRGB = cmsCreateRGBProfile(&D65, &AdobePrimaries, Gamma22);
  cmsFreeToneCurve(Gamma22[0]);
  if (hAdobeRGB == NULL) return NULL;

  cmsSetProfileVersion(hAdobeRGB, 2.1);
  cmsMLU *mlu0 = cmsMLUalloc(NULL, 1);
  cmsMLUsetASCII(mlu0, "en", "US", "(dt internal)");
  cmsMLU *mlu1 = cmsMLUalloc(NULL, 1);
  cmsMLUsetASCII(mlu1, "en", "US", "AdobeRGB");
  cmsMLU *mlu2 = cmsMLUalloc(NULL, 1);
  cmsMLUsetASCII(mlu2, "en", "US", "Darktable AdobeRGB");
  cmsWriteTag(hAdobeRGB, cmsSigDeviceMfgDescTag,   mlu0);
  cmsWriteTag(hAdobeRGB, cmsSigDeviceModelDescTag, mlu1);
  // this will only be displayed when the embedded profile is read by for example GIMP
  cmsWriteTag(hAdobeRGB, cmsSigProfileDescriptionTag, mlu2);
  cmsMLUfree(mlu0);
  cmsMLUfree(mlu1);
  cmsMLUfree(mlu2);

  return hAdobeRGB;
}
Example #18
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 #19
0
// Creates a fake Lab identity.
cmsHPROFILE CMSEXPORT cmsCreateLab2ProfileTHR(cmsContext ContextID, const cmsCIExyY* WhitePoint)
{
    cmsHPROFILE hProfile;
    cmsPipeline* LUT = NULL;

    hProfile = cmsCreateRGBProfileTHR(ContextID, WhitePoint == NULL ? cmsD50_xyY() : WhitePoint, NULL, NULL);
    if (hProfile == NULL) return NULL;

    cmsSetProfileVersion(hProfile, 2.1);

    cmsSetDeviceClass(hProfile, cmsSigAbstractClass);
    cmsSetColorSpace(hProfile,  cmsSigLabData);
    cmsSetPCS(hProfile,         cmsSigLabData);

    if (!SetTextTags(hProfile, L"Lab identity built-in")) return NULL;

    // An identity LUT is all we need
    LUT = cmsPipelineAlloc(ContextID, 3, 3);
    if (LUT == NULL) goto Error;

    if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCLut(ContextID, 3)))
        goto Error;

    if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error;
    cmsPipelineFree(LUT);

    return hProfile;

Error:

    if (LUT != NULL)
        cmsPipelineFree(LUT);

    if (hProfile != NULL)
        cmsCloseProfile(hProfile);

    return NULL;
}
Example #20
0
// Creates a fake XYZ identity
cmsHPROFILE CMSEXPORT cmsCreateXYZProfileTHR(cmsContext ContextID)
{
    cmsHPROFILE hProfile;
    cmsPipeline* LUT = NULL;

    hProfile = cmsCreateRGBProfileTHR(ContextID, cmsD50_xyY(), NULL, NULL);
    if (hProfile == NULL) return NULL;

    cmsSetProfileVersion(hProfile, 4.3);

    cmsSetDeviceClass(hProfile, cmsSigAbstractClass);
    cmsSetColorSpace(hProfile,  cmsSigXYZData);
    cmsSetPCS(hProfile,         cmsSigXYZData);

    if (!SetTextTags(hProfile, L"XYZ identity built-in")) goto Error;

    // An identity LUT is all we need
    LUT = cmsPipelineAlloc(ContextID, 3, 3);
    if (LUT == NULL) goto Error;

    if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, 3)))
        goto Error;

    if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error;
    cmsPipelineFree(LUT);

    return hProfile;

Error:

    if (LUT != NULL)
        cmsPipelineFree(LUT);

    if (hProfile != NULL)
        cmsCloseProfile(hProfile);

    return NULL;
}
Example #21
0
static GimpColorProfile *
gimp_color_profile_new_from_color_profile (GimpColorProfile *profile,
                                           gboolean          linear)
{
  GimpColorProfile *new_profile;
  cmsHPROFILE       target_profile;
  GimpMatrix3       matrix = { 0, };
  cmsCIEXYZ        *whitepoint;
  cmsToneCurve     *curve;
  const gchar      *model;
  gchar            *new_model;

  g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (profile), NULL);

  if (gimp_color_profile_is_rgb (profile))
    {
      if (! gimp_color_profile_get_rgb_matrix_colorants (profile, &matrix))
        return NULL;
    }
  else if (! gimp_color_profile_is_gray (profile))
    {
      return NULL;
    }

  whitepoint = cmsReadTag (profile->priv->lcms_profile,
                           cmsSigMediaWhitePointTag);

  target_profile = cmsCreateProfilePlaceholder (0);

  cmsSetProfileVersion (target_profile, 4.3);
  cmsSetDeviceClass (target_profile, cmsSigDisplayClass);
  cmsSetPCS (target_profile, cmsSigXYZData);

  cmsWriteTag (target_profile, cmsSigMediaWhitePointTag, whitepoint);

  if (linear)
    {
      /* linear light */
      curve = cmsBuildGamma (NULL, 1.00);

      gimp_color_profile_set_tag (target_profile, cmsSigProfileDescriptionTag,
                                  "linear TRC variant generated by GIMP");
    }
  else
    {
      cmsFloat64Number srgb_parameters[5] =
        { 2.4, 1.0 / 1.055,  0.055 / 1.055, 1.0 / 12.92, 0.04045 };

      /* sRGB curve */
      curve = cmsBuildParametricToneCurve (NULL, 4, srgb_parameters);

      gimp_color_profile_set_tag (target_profile, cmsSigProfileDescriptionTag,
                                  "sRGB TRC variant generated by GIMP");
    }

  if (gimp_color_profile_is_rgb (profile))
    {
      cmsCIEXYZ red;
      cmsCIEXYZ green;
      cmsCIEXYZ blue;

      cmsSetColorSpace (target_profile, cmsSigRgbData);

      red.X = matrix.coeff[0][0];
      red.Y = matrix.coeff[0][1];
      red.Z = matrix.coeff[0][2];

      green.X = matrix.coeff[1][0];
      green.Y = matrix.coeff[1][1];
      green.Z = matrix.coeff[1][2];

      blue.X = matrix.coeff[2][0];
      blue.Y = matrix.coeff[2][1];
      blue.Z = matrix.coeff[2][2];

      cmsWriteTag (target_profile, cmsSigRedColorantTag,   &red);
      cmsWriteTag (target_profile, cmsSigGreenColorantTag, &green);
      cmsWriteTag (target_profile, cmsSigBlueColorantTag,  &blue);

      cmsWriteTag (target_profile, cmsSigRedTRCTag,   curve);
      cmsWriteTag (target_profile, cmsSigGreenTRCTag, curve);
      cmsWriteTag (target_profile, cmsSigBlueTRCTag,  curve);
    }
  else
    {
      cmsSetColorSpace (target_profile, cmsSigGrayData);

      cmsWriteTag (target_profile, cmsSigGrayTRCTag, curve);
    }

  cmsFreeToneCurve (curve);

  model = gimp_color_profile_get_model (profile);

  if (model && g_str_has_prefix (model, "Generated from '"))
    {
      /* don't add multiple "Generated from 'foo'" */
      new_model = g_strdup (model);
    }
  else
    {
      new_model = g_strdup_printf ("Generated from '%s'",
                                   gimp_color_profile_get_description (profile));
    }

  gimp_color_profile_set_tag (target_profile, cmsSigDeviceMfgDescTag,
                              "GIMP");
  gimp_color_profile_set_tag (target_profile, cmsSigDeviceModelDescTag,
                              new_model);
  gimp_color_profile_set_tag (target_profile, cmsSigCopyrightTag,
                              "Public Domain");

  g_free (new_model);

  new_profile = gimp_color_profile_new_from_lcms_profile (target_profile, NULL);

  cmsCloseProfile (target_profile);

  return new_profile;
}
Example #22
0
/**
 * cd_util_create_named_color:
 **/
static gboolean
cd_util_create_named_color (CdUtilPrivate *priv,
			    CdDom *dom,
			    const GNode *root,
			    GError **error)
{
	CdColorLab lab;
	cmsNAMEDCOLORLIST *nc2 = NULL;
	cmsUInt16Number pcs[3];
	const GNode *name;
	const GNode *named;
	const GNode *prefix;
	const GNode *suffix;
	const GNode *tmp;
	gboolean ret = TRUE;

	priv->lcms_profile = cmsCreateNULLProfileTHR (cd_icc_get_context (priv->icc));
	if (priv->lcms_profile == NULL) {
		ret = FALSE;
		g_set_error_literal (error, 1, 0,
				     "failed to create NULL profile");
		goto out;
	}

	cmsSetDeviceClass(priv->lcms_profile, cmsSigNamedColorClass);
	cmsSetPCS (priv->lcms_profile, cmsSigLabData);
	cmsSetColorSpace (priv->lcms_profile, cmsSigLabData);

	/* create a named color structure */
	prefix = cd_dom_get_node (dom, root, "prefix");
	suffix = cd_dom_get_node (dom, root, "suffix");
	nc2 = cmsAllocNamedColorList (NULL, 1, /* will realloc more as required */
				      3,
				      prefix != NULL ? cd_dom_get_node_data (prefix) : "",
				      suffix != NULL ? cd_dom_get_node_data (suffix) : "");

	named = cd_dom_get_node (dom, root, "named");
	if (named == NULL) {
		ret = FALSE;
		g_set_error_literal (error, 1, 0,
				     "XML error: missing named");
		goto out;
	}
	for (tmp = named->children; tmp != NULL; tmp = tmp->next) {
		name = cd_dom_get_node (dom, tmp, "name");
		if (name == NULL) {
			ret = FALSE;
			g_set_error_literal (error, 1, 0,
					     "XML error: missing name");
			goto out;
		}
		ret = cd_dom_get_node_lab (tmp, &lab);
		if (!ret) {
			ret = FALSE;
			g_set_error (error, 1, 0,
				     "XML error: missing Lab for %s",
				     cd_dom_get_node_data (name));
			goto out;
		}

		/* PCS = colours in PCS colour space CIE*Lab
		 * colorant = colours in device colour space */
		cmsFloat2LabEncoded (pcs, (cmsCIELab *) &lab);
		ret = cmsAppendNamedColor (nc2, cd_dom_get_node_data (name), pcs, pcs);
		g_assert (ret);
	}
	cmsWriteTag (priv->lcms_profile, cmsSigNamedColor2Tag, nc2);
out:
	if (nc2 != NULL)
		cmsFreeNamedColorList (nc2);
	return ret;
}
Example #23
0
// This function creates a profile based on White point, primaries and
// transfer functions.
cmsHPROFILE CMSEXPORT cmsCreateRGBProfileTHR(cmsContext ContextID,
                                          const cmsCIExyY* WhitePoint,
                                          const cmsCIExyYTRIPLE* Primaries,
                                          cmsToneCurve* const TransferFunction[3])
{
    cmsHPROFILE hICC;
    cmsMAT3 MColorants;
    cmsCIEXYZTRIPLE Colorants;
    cmsCIExyY MaxWhite;
    cmsMAT3 CHAD;
    cmsCIEXYZ WhitePointXYZ;

    hICC = cmsCreateProfilePlaceholder(ContextID);
    if (!hICC)                          // can't allocate
        return NULL;

    cmsSetProfileVersion(hICC, 4.3);

    cmsSetDeviceClass(hICC,      cmsSigDisplayClass);
    cmsSetColorSpace(hICC,       cmsSigRgbData);
    cmsSetPCS(hICC,              cmsSigXYZData);

    cmsSetHeaderRenderingIntent(hICC,  INTENT_PERCEPTUAL);


    // Implement profile using following tags:
    //
    //  1 cmsSigProfileDescriptionTag
    //  2 cmsSigMediaWhitePointTag
    //  3 cmsSigRedColorantTag
    //  4 cmsSigGreenColorantTag
    //  5 cmsSigBlueColorantTag
    //  6 cmsSigRedTRCTag
    //  7 cmsSigGreenTRCTag
    //  8 cmsSigBlueTRCTag
    //  9 Chromatic adaptation Tag
    // This conforms a standard RGB DisplayProfile as says ICC, and then I add (As per addendum II)
    // 10 cmsSigChromaticityTag


    if (!SetTextTags(hICC, L"RGB built-in")) goto Error;

    if (WhitePoint) {

        if (!cmsWriteTag(hICC, cmsSigMediaWhitePointTag, cmsD50_XYZ())) goto Error;

        cmsxyY2XYZ(&WhitePointXYZ, WhitePoint);
        _cmsAdaptationMatrix(&CHAD, NULL, &WhitePointXYZ, cmsD50_XYZ());

        // This is a V4 tag, but many CMM does read and understand it no matter which version
        if (!cmsWriteTag(hICC, cmsSigChromaticAdaptationTag, (void*) &CHAD)) goto Error;
    }

    if (WhitePoint && Primaries) {

        MaxWhite.x =  WhitePoint -> x;
        MaxWhite.y =  WhitePoint -> y;
        MaxWhite.Y =  1.0;

        if (!_cmsBuildRGB2XYZtransferMatrix(&MColorants, &MaxWhite, Primaries)) goto Error;

        Colorants.Red.X   = MColorants.v[0].n[0];
        Colorants.Red.Y   = MColorants.v[1].n[0];
        Colorants.Red.Z   = MColorants.v[2].n[0];

        Colorants.Green.X = MColorants.v[0].n[1];
        Colorants.Green.Y = MColorants.v[1].n[1];
        Colorants.Green.Z = MColorants.v[2].n[1];

        Colorants.Blue.X  = MColorants.v[0].n[2];
        Colorants.Blue.Y  = MColorants.v[1].n[2];
        Colorants.Blue.Z  = MColorants.v[2].n[2];

        if (!cmsWriteTag(hICC, cmsSigRedColorantTag,   (void*) &Colorants.Red)) goto Error;
        if (!cmsWriteTag(hICC, cmsSigBlueColorantTag,  (void*) &Colorants.Blue)) goto Error;
        if (!cmsWriteTag(hICC, cmsSigGreenColorantTag, (void*) &Colorants.Green)) goto Error;
    }


    if (TransferFunction) {

        // Tries to minimize space. Thanks to Richard Hughes for this nice idea         
        if (!cmsWriteTag(hICC, cmsSigRedTRCTag,   (void*) TransferFunction[0])) goto Error;

        if (TransferFunction[1] == TransferFunction[0]) {

            if (!cmsLinkTag (hICC, cmsSigGreenTRCTag, cmsSigRedTRCTag)) goto Error;

        } else {

            if (!cmsWriteTag(hICC, cmsSigGreenTRCTag, (void*) TransferFunction[1])) goto Error;
        }

        if (TransferFunction[2] == TransferFunction[0]) {

            if (!cmsLinkTag (hICC, cmsSigBlueTRCTag, cmsSigRedTRCTag)) goto Error;

        } else {

            if (!cmsWriteTag(hICC, cmsSigBlueTRCTag, (void*) TransferFunction[2])) goto Error;
        }
    }

    if (Primaries) {
        if (!cmsWriteTag(hICC, cmsSigChromaticityTag, (void*) Primaries)) goto Error;
    }


    return hICC;

Error:
    if (hICC)
        cmsCloseProfile(hICC);
    return NULL;
}
Example #24
0
bool ProfileUtils::createIccProfile(bool isLaptop, const Edid &edid, const QString &filename)
{
    cmsCIExyYTRIPLE chroma;
    cmsCIExyY white_point;
    cmsHPROFILE lcms_profile = NULL;
    cmsToneCurve *transfer_curve[3] = { NULL, NULL, NULL };
    bool ret = false;
    cmsHANDLE dict = NULL;

    /* ensure the per-user directory exists */
    // Create dir path if not available
    // check if the file doesn't already exist
    QFileInfo fileInfo(filename);
    if (fileInfo.exists()) {
        qCWarning(COLORD) << "EDID ICC Profile already exists" << filename;
        if (*transfer_curve != NULL)
            cmsFreeToneCurve(*transfer_curve);
        return false;
    }

    // copy color data from our structures
    // Red
    chroma.Red.x = edid.red().x();
    chroma.Red.y = edid.red().y();
    // Green
    chroma.Green.x = edid.green().x();
    chroma.Green.y = edid.green().y();
    // Blue
    chroma.Blue.x = edid.blue().x();
    chroma.Blue.y = edid.blue().y();
    // White
    white_point.x = edid.white().x();
    white_point.y = edid.white().y();
    white_point.Y = 1.0;

    // estimate the transfer function for the gamma
    transfer_curve[0] = transfer_curve[1] = transfer_curve[2] = cmsBuildGamma(NULL, edid.gamma());

    // create our generated profile
    lcms_profile = cmsCreateRGBProfile(&white_point, &chroma, transfer_curve);
    if (lcms_profile == NULL) {
        qCWarning(COLORD) << "Failed to create ICC profile on cmsCreateRGBProfile";
        if (*transfer_curve != NULL)
            cmsFreeToneCurve(*transfer_curve);
        return false;
    }

    cmsSetColorSpace(lcms_profile, cmsSigRgbData);
    cmsSetPCS(lcms_profile, cmsSigXYZData);
    cmsSetHeaderRenderingIntent(lcms_profile, INTENT_RELATIVE_COLORIMETRIC);
    cmsSetDeviceClass(lcms_profile, cmsSigDisplayClass);

    // copyright
    ret = cmsWriteTagTextAscii(lcms_profile,
                               cmsSigCopyrightTag,
                               "No copyright");
    if (!ret) {
        qCWarning(COLORD) << "Failed to write copyright";
        if (*transfer_curve != NULL)
            cmsFreeToneCurve(*transfer_curve);
        return false;
    }

    // set model
    QString model;
    if (isLaptop) {
        model = DmiUtils::deviceModel();
    } else {
        model = edid.name();
    }

    if (model.isEmpty()) {
        model = QStringLiteral("Unknown monitor");
    }
    ret = cmsWriteTagTextAscii(lcms_profile,
                               cmsSigDeviceModelDescTag,
                               model);
    if (!ret) {
        qCWarning(COLORD) << "Failed to write model";
        if (*transfer_curve != NULL) {
            cmsFreeToneCurve(*transfer_curve);
        }
        return false;
    }

    // write title
    ret = cmsWriteTagTextAscii(lcms_profile,
                               cmsSigProfileDescriptionTag,
                               model);
    if (!ret) {
        qCWarning(COLORD) << "Failed to write description";
        if (*transfer_curve != NULL)
            cmsFreeToneCurve(*transfer_curve);
        return false;
    }

    // get manufacturer
    QString vendor;
    if (isLaptop) {
        vendor = DmiUtils::deviceVendor();
    } else {
        vendor = edid.vendor();
    }

    if (vendor.isEmpty()) {
        vendor = QStringLiteral("Unknown vendor");
    }
    ret = cmsWriteTagTextAscii(lcms_profile,
                               cmsSigDeviceMfgDescTag,
                               vendor);
    if (!ret) {
        qCWarning(COLORD) << "Failed to write manufacturer";
        if (*transfer_curve != NULL)
            cmsFreeToneCurve(*transfer_curve);
        return false;
    }

    // just create a new dict
    dict = cmsDictAlloc(NULL);

    // set the framework creator metadata
    cmsDictAddEntryAscii(dict,
                         CD_PROFILE_METADATA_CMF_PRODUCT,
                         PACKAGE_NAME);
    cmsDictAddEntryAscii(dict,
                         CD_PROFILE_METADATA_CMF_BINARY,
                         PACKAGE_NAME);
    cmsDictAddEntryAscii(dict,
                         CD_PROFILE_METADATA_CMF_VERSION,
                         PACKAGE_VERSION);

    /* set the data source so we don't ever prompt the user to
         * recalibrate (as the EDID data won't have changed) */
    cmsDictAddEntryAscii(dict,
                         CD_PROFILE_METADATA_DATA_SOURCE,
                         CD_PROFILE_METADATA_DATA_SOURCE_EDID);

    // set 'ICC meta Tag for Monitor Profiles' data
    cmsDictAddEntryAscii(dict, "EDID_md5", edid.hash());

    if (!model.isEmpty())
        cmsDictAddEntryAscii(dict, "EDID_model", model);

    if (!edid.serial().isEmpty()) {
        cmsDictAddEntryAscii(dict, "EDID_serial", edid.serial());
    }

    if (!edid.pnpId().isEmpty()) {
        cmsDictAddEntryAscii(dict, "EDID_mnft", edid.pnpId());
    }

    if (!vendor.isEmpty()) {
        cmsDictAddEntryAscii(dict, "EDID_manufacturer", vendor);
    }

    /* write new tag */
    ret = cmsWriteTag(lcms_profile, cmsSigMetaTag, dict);
    if (!ret) {
        qCWarning(COLORD) << "Failed to write profile metadata";
        if (*transfer_curve != NULL)
            cmsFreeToneCurve(*transfer_curve);
        return false;
    }

    /* write profile id */
    ret = cmsMD5computeID(lcms_profile);
    if (!ret) {
        qCWarning(COLORD) << "Failed to write profile id";
        if (dict != NULL)
            cmsDictFree (dict);
        if (*transfer_curve != NULL)
            cmsFreeToneCurve(*transfer_curve);
        return false;
    }

    /* save, TODO: get error */
    ret = cmsSaveProfileToFile(lcms_profile, filename.toUtf8());

    if (dict != NULL) {
        cmsDictFree (dict);
    }
    if (*transfer_curve != NULL) {
        cmsFreeToneCurve (*transfer_curve);
    }

    return ret;
}
Example #25
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 #26
0
cmsHPROFILE CMSEXPORT cmsCreateInkLimitingDeviceLinkTHR(cmsContext ContextID,
                                                     cmsColorSpaceSignature ColorSpace,
                                                     cmsFloat64Number Limit)
{
    cmsHPROFILE hICC;
    cmsPipeline* LUT;
    cmsStage* CLUT;
    int nChannels;

    if (ColorSpace != cmsSigCmykData) {
        cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "InkLimiting: Only CMYK currently supported");
        return NULL;
    }

    if (Limit < 0.0 || Limit > 400) {

        cmsSignalError(ContextID, cmsERROR_RANGE, "InkLimiting: Limit should be between 0..400");
        if (Limit < 0) Limit = 0;
        if (Limit > 400) Limit = 400;

    }

    hICC = cmsCreateProfilePlaceholder(ContextID);
    if (!hICC)                          // can't allocate
        return NULL;

    cmsSetProfileVersion(hICC, 4.3);

    cmsSetDeviceClass(hICC,      cmsSigLinkClass);
    cmsSetColorSpace(hICC,       ColorSpace);
    cmsSetPCS(hICC,              ColorSpace);

    cmsSetHeaderRenderingIntent(hICC,  INTENT_PERCEPTUAL);


    // Creates a Pipeline with 3D grid only
    LUT = cmsPipelineAlloc(ContextID, 4, 4);
    if (LUT == NULL) goto Error;


    nChannels = cmsChannelsOf(ColorSpace);

    CLUT = cmsStageAllocCLut16bit(ContextID, 17, nChannels, nChannels, NULL);
    if (CLUT == NULL) goto Error;

    if (!cmsStageSampleCLut16bit(CLUT, InkLimitingSampler, (void*) &Limit, 0)) goto Error;

    if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, nChannels)) ||
        !cmsPipelineInsertStage(LUT, cmsAT_END, CLUT) ||
        !cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocIdentityCurves(ContextID, nChannels)))
        goto Error;

    // Create tags
    if (!SetTextTags(hICC, L"ink-limiting built-in")) goto Error;

    if (!cmsWriteTag(hICC, cmsSigAToB0Tag, (void*) LUT))  goto Error;
    if (!SetSeqDescTag(hICC, "ink-limiting built-in")) goto Error;

    // cmsPipeline is already on virtual profile
    cmsPipelineFree(LUT);

    // Ok, done
    return hICC;

Error:
    if (LUT != NULL)
        cmsPipelineFree(LUT);

    if (hICC != NULL)
        cmsCloseProfile(hICC);

    return NULL;
}
Example #27
0
cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID,
    int nLUTPoints,
    cmsFloat64Number Bright,
    cmsFloat64Number Contrast,
    cmsFloat64Number Hue,
    cmsFloat64Number Saturation,
    int TempSrc,
    int TempDest)
{
    cmsHPROFILE hICC;
    cmsPipeline* Pipeline;
    BCHSWADJUSTS bchsw;
    cmsCIExyY WhitePnt;
    cmsStage* CLUT;
    cmsUInt32Number Dimensions[MAX_INPUT_DIMENSIONS];
    int i;

    bchsw.Brightness = Bright;
    bchsw.Contrast   = Contrast;
    bchsw.Hue        = Hue;
    bchsw.Saturation = Saturation;

    cmsWhitePointFromTemp(&WhitePnt, TempSrc );
    cmsxyY2XYZ(&bchsw.WPsrc, &WhitePnt);

    cmsWhitePointFromTemp(&WhitePnt, TempDest);
    cmsxyY2XYZ(&bchsw.WPdest, &WhitePnt);

    hICC = cmsCreateProfilePlaceholder(ContextID);
    if (!hICC)                          // can't allocate
        return NULL;


    cmsSetDeviceClass(hICC,      cmsSigAbstractClass);
    cmsSetColorSpace(hICC,       cmsSigLabData);
    cmsSetPCS(hICC,              cmsSigLabData);

    cmsSetHeaderRenderingIntent(hICC,  INTENT_PERCEPTUAL);

    // Creates a Pipeline with 3D grid only
    Pipeline = cmsPipelineAlloc(ContextID, 3, 3);
    if (Pipeline == NULL) {
        cmsCloseProfile(hICC);
        return NULL;
    }

    for (i=0; i < MAX_INPUT_DIMENSIONS; i++) Dimensions[i] = nLUTPoints;
    CLUT = cmsStageAllocCLut16bitGranular(ContextID, Dimensions, 3, 3, NULL);
    if (CLUT == NULL) return NULL;


    if (!cmsStageSampleCLut16bit(CLUT, bchswSampler, (void*) &bchsw, 0)) {

        // Shouldn't reach here
        goto Error;
    }

    if (!cmsPipelineInsertStage(Pipeline, cmsAT_END, CLUT)) {
        goto Error;
    }

    // Create tags
    if (!SetTextTags(hICC, L"BCHS built-in")) return NULL;

    cmsWriteTag(hICC, cmsSigMediaWhitePointTag, (void*) cmsD50_XYZ());

    cmsWriteTag(hICC, cmsSigAToB0Tag, (void*) Pipeline);

    // Pipeline is already on virtual profile
    cmsPipelineFree(Pipeline);

    // Ok, done
    return hICC;

Error:
    cmsPipelineFree(Pipeline);
    cmsCloseProfile(hICC);
    return NULL;
}