Ejemplo n.º 1
0
static
cmsHPROFILE OpenProfile(const char* File)
{
	cmsHPROFILE h;

       if (!File) 
            return cmsCreate_sRGBProfile();    
       
       if (stricmp(File, "*Lab") == 0)
                return cmsCreateLabProfile(NULL);
       
       if (stricmp(File, "*XYZ") == 0)
                return cmsCreateXYZProfile();
         
	   if (stricmp(File, "*srgb") == 0)
				return cmsCreate_sRGBProfile();

       
	   if (stricmp(File, "*Gray22") == 0) {
		   LPGAMMATABLE Gamma = cmsBuildGamma(256, 2.2);
		   cmsHPROFILE hProfile = cmsCreateGrayProfile(cmsD50_xyY(), Gamma);
		   cmsFreeGamma(Gamma);
		   return hProfile;

	   }
       
       if (stricmp(File, "*Lin2222") == 0) {

            LPGAMMATABLE Gamma = cmsBuildGamma(256, 2.2);
            LPGAMMATABLE Gamma4[4];
            cmsHPROFILE hProfile; 

            Gamma4[0] = Gamma4[1] = Gamma4[2] = Gamma4[3] = Gamma;
            hProfile = cmsCreateLinearizationDeviceLink(icSigCmykData, Gamma4);
		    cmsFreeGamma(Gamma);
		    return hProfile;

	   }


       h = cmsOpenProfileFromFile(File, "r");

	   
       if (cmsGetDeviceClass(h) == icSigNamedColorClass)
			FatalError("ERROR: Cannot make devicelink of named color profiles!");
       

	   return h;
}
Ejemplo n.º 2
0
static cmsHPROFILE
gimp_color_profile_new_d65_gray_linear_internal (void)
{
  cmsHPROFILE profile;

  /* white point is D65 from the sRGB specs */
  cmsCIExyY whitepoint = { 0.3127, 0.3290, 1.0 };

  cmsToneCurve *curve = cmsBuildGamma (NULL, 1.0);

  profile = cmsCreateGrayProfile (&whitepoint, curve);

  cmsFreeToneCurve (curve);

  gimp_color_profile_set_tag (profile, cmsSigProfileDescriptionTag,
                              "GIMP built-in D65 Linear Grayscale");
  gimp_color_profile_set_tag (profile, cmsSigDeviceMfgDescTag,
                              "GIMP");
  gimp_color_profile_set_tag (profile, cmsSigDeviceModelDescTag,
                              "D65 Linear Grayscale");
  gimp_color_profile_set_tag (profile, cmsSigCopyrightTag,
                              "Public Domain");

  return profile;
}
Ejemplo n.º 3
0
JNIEXPORT jlong JNICALL Java_com_lightcrafts_utils_LCMS_cmsCreateRGBProfile
  (JNIEnv *env, jclass clazz, jdoubleArray jWhitePoint, jdoubleArray jPrimaries, jdouble gamma)
{
      double *WhitePoint = (double *) (*env)->GetPrimitiveArrayCritical(env, jWhitePoint, 0);
      double *Primaries = (double *) (*env)->GetPrimitiveArrayCritical(env, jPrimaries, 0);
      int i;
      cmsHPROFILE result;

      cmsCIExyY w = { WhitePoint[0], WhitePoint[1], WhitePoint[2] };
      
      cmsCIExyYTRIPLE p = {
        {Primaries[0], Primaries[1], Primaries[2]},
        {Primaries[3], Primaries[4], Primaries[5]},
        {Primaries[6], Primaries[7], Primaries[8]}
      };

      cmsToneCurve* gammaTable[3];
      const int context = 1337;

      gammaTable[0] = gammaTable[1] = gammaTable[2] = cmsBuildGamma(gamma == 1 ? (cmsContext) &context : 0, gamma);

      result = cmsCreateRGBProfile(&w, &p, gammaTable);
      
      // _cmsSaveProfile( result, "/Stuff/matrixRGB.icc" );
      
      // cmsFreeToneCurve(gammaTable[0]);
      
      (*env)->ReleasePrimitiveArrayCritical(env, jWhitePoint, WhitePoint, 0);
      (*env)->ReleasePrimitiveArrayCritical(env, jPrimaries, Primaries, 0);

      return (jlong)(intptr_t) result;
}
Ejemplo n.º 4
0
/* This profile corresponds to babl_model ("RGB") */
static cmsHPROFILE
create_lcms_linear_rgb_profile (void)
{
  cmsHPROFILE ret;

  /* white point is D65 from the sRGB specs */
  cmsCIExyY whitepoint = {0.3127, 0.3290, 1.0};

  /* primaries are ITU‐R BT.709‐5 (xYY),
   * which are also the primaries from the sRGB specs,
   * modified to properly account for hexadecimal quantization
   * during the profile making process.
   */
  cmsCIExyYTRIPLE primaries = {
    /*R {0.6400, 0.3300, 1.0},*/
    /*G {0.3000, 0.6000, 1.0},*/
    /*B {0.1500, 0.0600, 1.0} */
    /*R*/ {0.639998686, 0.330010138, 1.0},
    /*G*/ {0.300003784, 0.600003357, 1.0},
    /*B*/ {0.150002046, 0.059997204, 1.0}
  };

  /* linear light */
  cmsToneCurve* linear[3];
  linear[0] = linear[1] = linear[2] = cmsBuildGamma (NULL, 1.0); 

  /* create the profile, cleanup, and return */
  ret = cmsCreateRGBProfile (&whitepoint, &primaries, linear);
  cmsFreeToneCurve (linear[0]);
  return ret;
}
Ejemplo n.º 5
0
static
cmsHPROFILE OpenProfile(const char* File)
{   
    
    if (!File) 
        return cmsCreate_sRGBProfile();    
    
	if (stricmp(File, "*sRGB") == 0)
        return cmsCreate_sRGBProfile(NULL);
    
    if (stricmp(File, "*Lab") == 0)
        return cmsCreateLabProfile(NULL);
    
    if (stricmp(File, "*LabD65") == 0) {
        
        cmsCIExyY D65xyY;
        
        cmsWhitePointFromTemp(6504, &D65xyY);           
        return cmsCreateLabProfile(&D65xyY);
    }
    
    if (stricmp(File, "*XYZ") == 0)
        return cmsCreateXYZProfile();
    
     if (stricmp(File, "*Gray22") == 0) {
           LPGAMMATABLE Gamma = cmsBuildGamma(256, 2.2);
           cmsHPROFILE hProfile = cmsCreateGrayProfile(cmsD50_xyY(), Gamma);
           cmsFreeGamma(Gamma);
           return hProfile;

    }

    return cmsOpenProfileFromFile(File, "r");
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
static
void CreateLabPrelinearization(LPGAMMATABLE LabTable[])
{
    int i;

    LabTable[0] = cmsAllocGamma(257);
    LabTable[1] = cmsBuildGamma(257, 1.0);
    LabTable[2] = cmsBuildGamma(257, 1.0);

    // L* uses 257 entries. Entry 256 holds 0xFFFF, so, the effective range
    // is 0..0xFF00. Last entry (257) is also collapsed to 0xFFFF

    // From 0 to 0xFF00
    for (i=0; i < 256; i++) 
        LabTable[0]->GammaTable[i] = RGB_8_TO_16(i);

    // Repeat last for 0xFFFF
    LabTable[0] ->GammaTable[256] = 0xFFFF;        
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
0
Archivo: lcmsgen.c Proyecto: AltGr/gg
static void init(void)
{
   cmsCIEXYZ D65_XYZ = {0.95047, 1.0, 1.08883 };
   cmsCIExyY D65;
   cmsXYZ2xyY(&D65, &D65_XYZ);

   cmsToneCurve *linear = cmsBuildGamma(NULL, 1.0);
   cmsToneCurve *linrgb[3] = {linear,linear,linear};
   cmsCIExyYTRIPLE primaries = {
       {0.64, 0.33, 1.0},
       {0.30, 0.60, 1.0},
       {0.15, 0.06, 1.0}
   };

   cmsFloat64Number P[5] = { 2.4, 1. / 1.055, 0.055 / 1.055, 1. / 12.92, 0.04045 };
   cmsToneCurve *srgb = cmsBuildParametricToneCurve(NULL, 4, P);
   cmsToneCurve *srgbcurve[3] = {srgb,srgb,srgb};
   cmsHPROFILE hsRGB = cmsCreateRGBProfile(&D65, &primaries, srgbcurve);
   cmsHPROFILE hLab = cmsCreateLab4Profile(NULL);
   cmsHPROFILE hlRGB = cmsCreateRGBProfile(&D65, &primaries, linrgb);
   cmsHPROFILE hlGray = cmsCreateGrayProfile(cmsD50_xyY(), linear);

   cmsSetHeaderFlags(hlGray, cmsEmbeddedProfileTrue);
   cmsSaveProfileToFile(hlGray,"lgray.icc");
   cmsSetHeaderFlags(hlRGB, cmsEmbeddedProfileTrue);
   cmsSaveProfileToFile(hlRGB,"lrgb.icc");

   xform_srgb_to_lrgb = cmsCreateTransform(hsRGB, TYPE_RGB_DBL,
                                           hlRGB, TYPE_RGB_DBL,
                                           INTENT_RELATIVE_COLORIMETRIC,
                                           cmsFLAGS_NOOPTIMIZE  /* preserve precision */
                                         );
   xform_srgb_to_lab = cmsCreateTransform(hsRGB, TYPE_RGB_DBL, hLab,
                                          TYPE_Lab_DBL, INTENT_RELATIVE_COLORIMETRIC,
                                          cmsFLAGS_NOOPTIMIZE);
   xform_srgb_to_lgray = cmsCreateTransform(hsRGB, TYPE_RGB_DBL, hlGray,
                                           TYPE_GRAY_DBL, INTENT_RELATIVE_COLORIMETRIC,
                                           cmsFLAGS_NOOPTIMIZE);
   cmsCloseProfile(hsRGB);
   cmsCloseProfile(hlRGB);
   cmsCloseProfile(hLab);
   cmsCloseProfile(hlGray);
   cmsFreeToneCurve(linear);
   cmsFreeToneCurve(srgb);
   cmsSetLogErrorHandler(errlog);
   /* sRGB, RGB, Lab, Gray */
   printf("R',G',B',R,G,B,L,a,b,Gray\n");
}
Ejemplo n.º 10
0
static cmsHPROFILE *
gimp_color_profile_new_rgb_adobe_internal (void)
{
  cmsHPROFILE profile;

  /* white point is D65 from the sRGB specs */
  cmsCIExyY whitepoint = { 0.3127, 0.3290, 1.0 };

  /* AdobeRGB1998 and sRGB have the same white point.
   *
   * The primaries below are technically correct, but because of
   * hexadecimal rounding these primaries don't make a profile that
   * matches the original.
   *
   *  cmsCIExyYTRIPLE primaries = {
   *    { 0.6400, 0.3300, 1.0 },
   *    { 0.2100, 0.7100, 1.0 },
   *    { 0.1500, 0.0600, 1.0 }
   *  };
   */
  cmsCIExyYTRIPLE primaries =
    {
      { 0.639996511, 0.329996864, 1.0 },
      { 0.210005295, 0.710004866, 1.0 },
      { 0.149997606, 0.060003644, 1.0 }
    };

  cmsToneCurve *curve[3];

  /* gamma 2.2 */
  curve[0] = curve[1] = curve[2] = cmsBuildGamma (NULL, 2.19921875);

  profile = cmsCreateRGBProfile (&whitepoint, &primaries, curve);

  cmsFreeToneCurve (curve[0]);

  gimp_color_profile_set_tag (profile, cmsSigProfileDescriptionTag,
                              "Compatible with Adobe RGB (1998)");
  gimp_color_profile_set_tag (profile, cmsSigDeviceMfgDescTag,
                              "GIMP");
  gimp_color_profile_set_tag (profile, cmsSigDeviceModelDescTag,
                              "Compatible with Adobe RGB (1998)");
  gimp_color_profile_set_tag (profile, cmsSigCopyrightTag,
                              "Public Domain");

  return profile;
}
Ejemplo n.º 11
0
static PyObject *
pycms_CreateGrayProfile(PyObject *self, PyObject *args) {

	cmsHPROFILE hProfile;
	cmsToneCurve *tonecurve;

	tonecurve = cmsBuildGamma(NULL, 2.2);
	hProfile = cmsCreateGrayProfile(0, tonecurve);
	cmsFreeToneCurve(tonecurve);

	if(hProfile==NULL) {
		Py_INCREF(Py_None);
		return Py_None;
	}

	return Py_BuildValue("O", PyCObject_FromVoidPtr((void *)hProfile, (void *)cmsCloseProfile));
}
Ejemplo n.º 12
0
mng_cmsprof mnglcms_createsrgbprofile (void)
{
  cmsCIExyY       D65;
  cmsCIExyYTRIPLE Rec709Primaries = {
                                      {0.6400, 0.3300, 1.0},
                                      {0.3000, 0.6000, 1.0},
                                      {0.1500, 0.0600, 1.0}
                                    };
  LPGAMMATABLE    Gamma24[3];
  mng_cmsprof     hsRGB;

  cmsWhitePointFromTemp(6504, &D65);
  Gamma24[0] = Gamma24[1] = Gamma24[2] = cmsBuildGamma(256, 2.4);
  hsRGB = cmsCreateRGBProfile(&D65, &Rec709Primaries, Gamma24);
  cmsFreeGamma(Gamma24[0]);

  return hsRGB;
}
Ejemplo n.º 13
0
static PyObject *
pycms_CreateGrayProfile(PyObject *self, PyObject *args) {

	cmsHPROFILE hProfile;
	LPGAMMATABLE gamma;

	cmsErrorAction(LCMS_ERROR_IGNORE);

	gamma = cmsBuildGamma(256, 2.2);
	hProfile = cmsCreateGrayProfile(cmsD50_xyY(), gamma);
	cmsFreeGamma(gamma);

	if(hProfile==NULL) {
		Py_INCREF(Py_None);
		return Py_None;
	}

	return Py_BuildValue("O", PyCObject_FromVoidPtr((void *)hProfile, (void *)cmsCloseProfile));
}
Ejemplo n.º 14
0
static
cmsHPROFILE CreateRGBSpace(void)
{
	cmsHPROFILE hProfile;
	
	LPGAMMATABLE Gamma3[3];
	cmsCIExyYTRIPLE CIEPrimaries = {    {0.7355,0.2645 },
										{0.2658,0.7243 },
										{0.1669,0.0085}};


	Gamma3[0] = Gamma3[1] = Gamma3[2] = cmsBuildGamma(4096, 4.5);

	hProfile = cmsCreateRGBProfile(&Cus, &CIEPrimaries, Gamma3);

	cmsFreeGamma(Gamma3[0]);

	return hProfile;
}
Ejemplo n.º 15
0
static cmsHPROFILE
gimp_color_profile_new_rgb_srgb_linear_internal (void)
{
  cmsHPROFILE profile;

  /* white point is D65 from the sRGB specs */
  cmsCIExyY whitepoint = { 0.3127, 0.3290, 1.0 };

  /* primaries are ITU‐R BT.709‐5 (xYY), which are also the primaries
   * from the sRGB specs, modified to properly account for hexadecimal
   * quantization during the profile making process.
   */
  cmsCIExyYTRIPLE primaries =
    {
      /* R { 0.6400, 0.3300, 1.0 }, */
      /* G { 0.3000, 0.6000, 1.0 }, */
      /* B { 0.1500, 0.0600, 1.0 }  */
      /* R */ { 0.639998686, 0.330010138, 1.0 },
      /* G */ { 0.300003784, 0.600003357, 1.0 },
      /* B */ { 0.150002046, 0.059997204, 1.0 }
    };

  cmsToneCurve *curve[3];

  /* linear light */
  curve[0] = curve[1] = curve[2] = cmsBuildGamma (NULL, 1.0);

  profile = cmsCreateRGBProfile (&whitepoint, &primaries, curve);

  cmsFreeToneCurve (curve[0]);

  gimp_color_profile_set_tag (profile, cmsSigProfileDescriptionTag,
                              "GIMP built-in Linear sRGB");
  gimp_color_profile_set_tag (profile, cmsSigDeviceMfgDescTag,
                              "GIMP");
  gimp_color_profile_set_tag (profile, cmsSigDeviceModelDescTag,
                              "Linear sRGB");
  gimp_color_profile_set_tag (profile, cmsSigCopyrightTag,
                              "Public Domain");

  return profile;
}
Ejemplo n.º 16
0
PyObject *
load_png_fast_progressive (char *filename,
                           PyObject *get_buffer_callback)
{
  // Note: we are not using the method that libpng calls "Reading PNG
  // files progressively". That method would involve feeding the data
  // into libpng piece by piece, which is not necessary if we can give
  // libpng a simple FILE pointer.

  png_structp png_ptr = NULL;
  png_infop info_ptr = NULL;
  PyObject * result = NULL;
  FILE *fp = NULL;
  uint32_t width, height;
  uint32_t rows_left;
  png_byte color_type;
  png_byte bit_depth;
  bool have_alpha;
  char *cm_processing = NULL;

  // ICC profile-based colour conversion data.
  png_charp icc_profile_name = NULL;
  int icc_compression_type = 0;
#if PNG_LIBPNG_VER < 10500    // 1.5.0beta36, according to libpng CHANGES
  png_charp icc_profile = NULL;
#else
  png_bytep icc_profile = NULL;
#endif
  png_uint_32 icc_proflen = 0;

  // The sRGB flag has an intent field, which we ignore - 
  // the target gamut is sRGB already.
  int srgb_intent = 0;

  // Generic RGB space conversion params.
  // The assumptions we're making are those of sRGB,
  // but they'll be overridden by gammas or primaries in the file if used.
  bool generic_rgb_have_gAMA = false;
  bool generic_rgb_have_cHRM = false;
  double generic_rgb_file_gamma = 45455 / PNG_gAMA_scale;
  double generic_rgb_white_x = 31270 / PNG_cHRM_scale;
  double generic_rgb_white_y = 32900 / PNG_cHRM_scale;
  double generic_rgb_red_x   = 64000 / PNG_cHRM_scale;
  double generic_rgb_red_y   = 33000 / PNG_cHRM_scale;
  double generic_rgb_green_x = 30000 / PNG_cHRM_scale;
  double generic_rgb_green_y = 60000 / PNG_cHRM_scale;
  double generic_rgb_blue_x  = 15000 / PNG_cHRM_scale;
  double generic_rgb_blue_y  =  6000 / PNG_cHRM_scale;

  // Indicates the case where no CM information was present in the file and we
  // treated it as sRGB.
  bool possible_legacy_png = false;

  // LCMS stuff
  cmsHPROFILE input_buffer_profile = NULL;
  cmsHPROFILE nparray_data_profile = cmsCreate_sRGBProfile();
  cmsHTRANSFORM input_buffer_to_nparray = NULL;
  cmsToneCurve *gamma_transfer_func = NULL;
  cmsUInt32Number input_buffer_format = 0;

  cmsSetLogErrorHandler(log_lcms2_error);

  fp = fopen(filename, "rb");
  if (!fp) {
    PyErr_SetFromErrno(PyExc_IOError);
    //PyErr_Format(PyExc_IOError, "Could not open PNG file for writing: %s",
    //             filename);
    goto cleanup;
  }

  png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
                                    png_read_error_callback, NULL);
  if (!png_ptr) {
    PyErr_SetString(PyExc_MemoryError, "png_create_write_struct() failed");
    goto cleanup;
  }

  info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr) {
    PyErr_SetString(PyExc_MemoryError, "png_create_info_struct() failed");
    goto cleanup;
  }

  if (setjmp(png_jmpbuf(png_ptr))) {
    goto cleanup;
  }

  png_init_io(png_ptr, fp);

  png_read_info(png_ptr, info_ptr);

  // If there's an embedded ICC profile, use it in preference to any other
  // colour management information present.
  if (png_get_iCCP (png_ptr, info_ptr, &icc_profile_name,
                    &icc_compression_type, &icc_profile,
                    &icc_proflen))
  {
    input_buffer_profile = cmsOpenProfileFromMem(icc_profile, icc_proflen);
    if (! input_buffer_profile) {
      PyErr_SetString(PyExc_MemoryError, "cmsOpenProfileFromMem() failed");
      goto cleanup;
    }
    cm_processing = "iCCP (use embedded colour profile)";
  }

  // Shorthand for sRGB.
  else if (png_get_sRGB (png_ptr, info_ptr, &srgb_intent)) {
    input_buffer_profile = cmsCreate_sRGBProfile();
    cm_processing = "sRGB (explicit sRGB chunk)";
  }

  else {
    // We might have generic RGB transformation information in the form of
    // the chromaticities for R, G and B and a generic gamma curve.

    if (png_get_cHRM (png_ptr, info_ptr,
                      &generic_rgb_white_x, &generic_rgb_white_y,
                      &generic_rgb_red_x, &generic_rgb_red_y,
                      &generic_rgb_green_x, &generic_rgb_green_y,
                      &generic_rgb_blue_x, &generic_rgb_blue_y))
    {
      generic_rgb_have_cHRM = true;
    }
    if (png_get_gAMA(png_ptr, info_ptr, &generic_rgb_file_gamma)) {
      generic_rgb_have_gAMA = true;
    }
    if (generic_rgb_have_gAMA || generic_rgb_have_cHRM) {
      cmsCIExyYTRIPLE primaries = {{generic_rgb_red_x, generic_rgb_red_y},
                                   {generic_rgb_green_x, generic_rgb_green_y},
                                   {generic_rgb_blue_x, generic_rgb_blue_y}};
      cmsCIExyY white_point = {generic_rgb_white_x, generic_rgb_white_y};
      gamma_transfer_func = cmsBuildGamma(NULL, 1.0/generic_rgb_file_gamma);
      cmsToneCurve *transfer_funcs[3] = {gamma_transfer_func,
                                         gamma_transfer_func,
                                         gamma_transfer_func };
      input_buffer_profile = cmsCreateRGBProfile(&white_point, &primaries,
                                                transfer_funcs);
      cm_processing = "cHRM and/or gAMA (generic RGB space)";
    }

    // Possible legacy PNG, or rather one which might have been written with an
    // old version of MyPaint. Treat as sRGB, but flag the strangeness because
    // it might be important for PNGs in old OpenRaster files.
    else {
      possible_legacy_png = true;
      input_buffer_profile = cmsCreate_sRGBProfile();
      cm_processing = "sRGB (no CM chunks present)";
    }
  }

  if (png_get_interlace_type (png_ptr, info_ptr) != PNG_INTERLACE_NONE) {
    PyErr_SetString(PyExc_RuntimeError,
                    "Interlaced PNG files are not supported!");
    goto cleanup;
  }

  color_type = png_get_color_type(png_ptr, info_ptr);
  bit_depth = png_get_bit_depth(png_ptr, info_ptr);
  have_alpha = color_type & PNG_COLOR_MASK_ALPHA;

  if (color_type == PNG_COLOR_TYPE_PALETTE) {
    png_set_palette_to_rgb(png_ptr);
  }

  if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
    png_set_expand_gray_1_2_4_to_8(png_ptr);
  }

  if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
    png_set_tRNS_to_alpha(png_ptr);
    have_alpha = true;
  }

  if (bit_depth < 8) {
    png_set_packing(png_ptr);
  }

  if (!have_alpha) {
    png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER);
  }

  if (color_type == PNG_COLOR_TYPE_GRAY ||
      color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
    png_set_gray_to_rgb(png_ptr);
  }

  png_read_update_info(png_ptr, info_ptr);

  // Verify what we have done
  bit_depth = png_get_bit_depth(png_ptr, info_ptr);
  if (! (bit_depth == 8 || bit_depth == 16)) {
    PyErr_SetString(PyExc_RuntimeError, "Failed to convince libpng to convert "
                                        "to 8 or 16 bits per channel");
    goto cleanup;
  }
  if (png_get_color_type(png_ptr, info_ptr) != PNG_COLOR_TYPE_RGB_ALPHA) {
    PyErr_SetString(PyExc_RuntimeError, "Failed to convince libpng to convert "
                                        "to RGBA (wrong color_type)");
    goto cleanup;
  }
  if (png_get_channels(png_ptr, info_ptr) != 4) {
    PyErr_SetString(PyExc_RuntimeError, "Failed to convince libpng to convert "
                                        "to RGBA (wrong number of channels)");
    goto cleanup;
  }

  // PNGs use network byte order, i.e. big-endian in descending order
  // of bit significance. LittleCMS uses whatever's detected for the compiler.
  // ref: http://www.w3.org/TR/2003/REC-PNG-20031110/#7Integers-and-byte-order
  if (bit_depth == 16) {
#ifdef CMS_USE_BIG_ENDIAN
    input_buffer_format = TYPE_RGBA_16;
#else
    input_buffer_format = TYPE_RGBA_16_SE;
#endif
  }
  else {
    input_buffer_format = TYPE_RGBA_8;
  }

  input_buffer_to_nparray = cmsCreateTransform
        (input_buffer_profile, input_buffer_format,
         nparray_data_profile, TYPE_RGBA_8,
         INTENT_PERCEPTUAL, 0);

  width = png_get_image_width(png_ptr, info_ptr);
  height = png_get_image_height(png_ptr, info_ptr);
  rows_left = height;

  while (rows_left) {
    PyObject *pyarr = NULL;
    uint32_t rows = 0;
    uint32_t row = 0;
    const uint8_t input_buf_bytes_per_pixel = (bit_depth==8) ? 4 : 8;
    const uint32_t input_buf_row_stride = sizeof(png_byte) * width
                                          * input_buf_bytes_per_pixel;
    png_byte *input_buffer = NULL;
    png_bytep *input_buf_row_pointers = NULL;

    pyarr = PyObject_CallFunction(get_buffer_callback, "ii", width, height);
    if (! pyarr) {
      PyErr_Format(PyExc_RuntimeError, "Get-buffer callback failed");
      goto cleanup;
    }
#ifdef HEAVY_DEBUG
    //assert(PyArray_ISCARRAY(arr));
    assert(PyArray_NDIM(pyarr) == 3);
    assert(PyArray_DIM(pyarr, 1) == width);
    assert(PyArray_DIM(pyarr, 2) == 4);
    assert(PyArray_TYPE(pyarr) == NPY_UINT8);
    assert(PyArray_ISBEHAVED(pyarr));
    assert(PyArray_STRIDE(pyarr, 1) == 4*sizeof(uint8_t));
    assert(PyArray_STRIDE(pyarr, 2) ==   sizeof(uint8_t));
#endif
    rows = PyArray_DIM(pyarr, 0);

    if (rows > rows_left) {
      PyErr_Format(PyExc_RuntimeError,
                   "Attempt to read %d rows from the PNG, "
                   "but only %d are left",
                   rows, rows_left);
      goto cleanup;
    }

    input_buffer = (png_byte *) malloc(rows * input_buf_row_stride);
    input_buf_row_pointers = (png_bytep *)malloc(rows * sizeof(png_bytep));
    for (row=0; row<rows; row++) {
      input_buf_row_pointers[row] = input_buffer + (row * input_buf_row_stride);
    }

    png_read_rows(png_ptr, input_buf_row_pointers, NULL, rows);
    rows_left -= rows;

    for (row=0; row<rows; row++) {
      uint8_t *pyarr_row = (uint8_t *)PyArray_DATA(pyarr)
                         + row*PyArray_STRIDE(pyarr, 0);
      uint8_t *input_row = input_buf_row_pointers[row];
      // Really minimal fake colour management. Just remaps to sRGB.
      cmsDoTransform(input_buffer_to_nparray, input_row, pyarr_row, width);
      // lcms2 ignores alpha, so copy that verbatim
      // If it's 8bpc RGBA, use A.
      // If it's 16bpc RrGgBbAa, use A.
      for (uint32_t i=0; i<width; ++i) {
        const uint32_t pyarr_alpha_byte = (i*4) + 3;
        const uint32_t buf_alpha_byte = (i*input_buf_bytes_per_pixel)
                                       + ((bit_depth==8) ? 3 : 6);
        pyarr_row[pyarr_alpha_byte] = input_row[buf_alpha_byte];
      }
    }

    free(input_buf_row_pointers);
    free(input_buffer);

    Py_DECREF(pyarr);
  }

  png_read_end(png_ptr, NULL);

  result = Py_BuildValue("{s:b,s:i,s:i,s:s}",
                         "possible_legacy_png", possible_legacy_png,
                         "width", width,
                         "height", height,
                         "cm_conversions_applied", cm_processing);

 cleanup:
  if (info_ptr) png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
  // libpng's style is to free internally allocated stuff like the icc
  // tables in png_destroy_*(). I think.
  if (fp) fclose(fp);
  if (input_buffer_profile) cmsCloseProfile(input_buffer_profile);
  if (nparray_data_profile) cmsCloseProfile(nparray_data_profile);
  if (input_buffer_to_nparray) cmsDeleteTransform(input_buffer_to_nparray);
  if (gamma_transfer_func) cmsFreeToneCurve(gamma_transfer_func);

  return result;
}
Ejemplo n.º 17
0
static
BOOL CreateLUTS(LPMONITORPROFILERDATA sys, LPLUT* A2B, LPLUT* B2A)
{
    LPLUT AToB0 = cmsAllocLUT();
    LPLUT BToA0 = cmsAllocLUT();
    LPGAMMATABLE LabG;
    cmsCIExyY xyY;


        cmsAlloc3DGrid(AToB0, sys->hdr.CLUTPoints, 3, 3);
        cmsAlloc3DGrid(BToA0, sys->hdr.CLUTPoints, 3, 3);

        /* cmsAllocLinearTable(AToB0, sys -> Prelinearization, 1);     */

        sys->ReverseTables[0] = cmsReverseGamma(4096, sys ->Prelinearization[0]);
        sys->ReverseTables[1] = cmsReverseGamma(4096, sys ->Prelinearization[1]);
        sys->ReverseTables[2] = cmsReverseGamma(4096, sys ->Prelinearization[2]);

        /* Prelinearization */

        LabG = cmsBuildGamma(4096, 3.0);

        sys -> PreLab[0] = cmsJoinGammaEx(LabG, sys ->Prelinearization[0], 4096);
        sys -> PreLab[1] = cmsJoinGammaEx(LabG, sys ->Prelinearization[1], 4096);
        sys -> PreLab[2] = cmsJoinGammaEx(LabG, sys ->Prelinearization[2], 4096);

        sys -> PreLabRev[0] = cmsJoinGammaEx(sys ->Prelinearization[0], LabG, 4096);
        sys -> PreLabRev[1] = cmsJoinGammaEx(sys ->Prelinearization[1], LabG, 4096);
        sys -> PreLabRev[2] = cmsJoinGammaEx(sys ->Prelinearization[2], LabG, 4096);


        cmsFreeGamma(LabG);


        cmsAllocLinearTable(AToB0, sys->PreLabRev, 1);
        cmsAllocLinearTable(BToA0, sys->PreLab,    2);


        /* Set CIECAM97s parameters */

        sys -> hdr.device.whitePoint.X = sys -> hdr.WhitePoint.X * 100.;
        sys -> hdr.device.whitePoint.Y = sys -> hdr.WhitePoint.Y * 100.;
        sys -> hdr.device.whitePoint.Z = sys -> hdr.WhitePoint.Z * 100.;


        /* Normalize White point for CIECAM97s model */
        cmsXYZ2xyY(&xyY,  &sys -> hdr.device.whitePoint);
        xyY.Y = 100.;
        cmsxyY2XYZ(&sys -> hdr.device.whitePoint, &xyY);


        sys->hdr.hDevice = cmsCIECAM97sInit(&sys->hdr.device);
        sys->hdr.hPCS    = cmsCIECAM97sInit(&sys->hdr.PCS);


        cmsSample3DGrid(AToB0, RegressionSamplerA2B, sys, 0);
        cmsSample3DGrid(BToA0, RegressionSamplerB2A, sys, 0);

        cmsCIECAM97sDone(sys->hdr.hDevice);
        cmsCIECAM97sDone(sys->hdr.hPCS);

       cmsAddTag(sys->hdr.hProfile, icSigAToB0Tag, AToB0);
       cmsAddTag(sys->hdr.hProfile, icSigBToA0Tag, BToA0);

       /* This is the 0xff00 trick to map white at lattice point */
       BToA0 ->Matrix.v[0].n[0] = DOUBLE_TO_FIXED((65535.0 / 65280.0));

       *A2B  = AToB0;
       *B2A  = BToA0;

        cmsFreeGammaTriple(sys->ReverseTables);
        cmsFreeGammaTriple(sys->PreLab);
        cmsFreeGammaTriple(sys->PreLabRev);
        return true;
}
Ejemplo n.º 18
0
/**
 * cd_util_create_standard_space:
 **/
static gboolean
cd_util_create_standard_space (CdUtilPrivate *priv,
			       CdDom *dom,
			       const GNode *root,
			       GError **error)
{
	CdColorYxy yxy;
	cmsCIExyYTRIPLE primaries;
	cmsCIExyY white;
	cmsToneCurve *transfer[3] = { NULL, NULL, NULL};
	const gchar *data;
	const GNode *tmp;
	gboolean ret;
	gdouble curve_gamma;

	/* parse gamma */
	tmp = cd_dom_get_node (dom, root, "gamma");
	if (tmp == NULL) {
		ret = FALSE;
		g_set_error_literal (error, 1, 0, "XML error, expected gamma");
		goto out;
	}
	data = cd_dom_get_node_data (tmp);
	if (g_strcmp0 (data, "sRGB") == 0) {
		transfer[0] = cd_util_build_srgb_gamma ();
		transfer[1] = transfer[0];
		transfer[2] = transfer[0];
	} else if (g_strcmp0 (data, "L*") == 0) {
		transfer[0] = cd_util_build_lstar_gamma ();
		transfer[1] = transfer[0];
		transfer[2] = transfer[0];
	} else if (g_strcmp0 (data, "Rec709") == 0) {
		transfer[0] = cd_util_build_rec709_gamma ();
		transfer[1] = transfer[0];
		transfer[2] = transfer[0];
	} else {
		curve_gamma = cd_dom_get_node_data_as_double (tmp);
		if (curve_gamma == G_MAXDOUBLE) {
			ret = FALSE;
			g_set_error (error, 1, 0,
				     "failed to parse gamma: '%s'",
				     data);
			goto out;
		}
		transfer[0] = cmsBuildGamma (NULL, curve_gamma);
		transfer[1] = transfer[0];
		transfer[2] = transfer[0];
	}

	/* values taken from https://en.wikipedia.org/wiki/Standard_illuminant */
	tmp = cd_dom_get_node (dom, root, "whitepoint");
	if (tmp == NULL) {
		ret = FALSE;
		g_set_error_literal (error, 1, 0, "XML error, expected whitepoint");
		goto out;
	}
	data = cd_dom_get_node_data (tmp);
	white.Y = 1.0f;
	if (g_strcmp0 (data, "C") == 0) {
		white.x = 0.31006;
		white.y = 0.31616;
	} else if (g_strcmp0 (data, "E") == 0) {
		white.x = 0.33333;
		white.y = 0.33333;
	} else if (g_strcmp0 (data, "D50") == 0) {
		white.x = 0.345703;
		white.y = 0.358539;
	} else if (g_strcmp0 (data, "D65") == 0) {
		cmsWhitePointFromTemp (&white, 6504);
	} else {
		ret = FALSE;
		g_set_error_literal (error, 1, 0,
				     "unknown illuminant, expected C, E, D50 or D65");
		goto out;
	}

	/* get red primary */
	tmp = cd_dom_get_node (dom, root, "primaries/red");
	if (tmp == NULL) {
		ret = FALSE;
		g_set_error_literal (error, 1, 0, "XML error, expected primaries/red");
		goto out;
	}
	ret = cd_dom_get_node_yxy (tmp, &yxy);
	if (!ret) {
		g_set_error_literal (error, 1, 0, "XML error, invalid primaries/red");
		goto out;
	}
	primaries.Red.x = yxy.x;
	primaries.Red.y = yxy.y;
	primaries.Red.Y = yxy.Y;

	/* get green primary */
	tmp = cd_dom_get_node (dom, root, "primaries/green");
	if (tmp == NULL) {
		ret = FALSE;
		g_set_error_literal (error, 1, 0, "XML error, expected primaries/green");
		goto out;
	}
	ret = cd_dom_get_node_yxy (tmp, &yxy);
	if (!ret) {
		g_set_error_literal (error, 1, 0, "XML error, invalid primaries/green");
		goto out;
	}
	primaries.Green.x = yxy.x;
	primaries.Green.y = yxy.y;
	primaries.Green.Y = yxy.Y;

	/* get blue primary */
	tmp = cd_dom_get_node (dom, root, "primaries/blue");
	if (tmp == NULL) {
		ret = FALSE;
		g_set_error_literal (error, 1, 0, "XML error, expected primaries/blue");
		goto out;
	}
	ret = cd_dom_get_node_yxy (tmp, &yxy);
	if (!ret) {
		g_set_error_literal (error, 1, 0, "XML error, invalid primaries/blue");
		goto out;
	}
	primaries.Blue.x = yxy.x;
	primaries.Blue.y = yxy.y;
	primaries.Blue.Y = yxy.Y;

	/* create profile */
	priv->lcms_profile = cmsCreateRGBProfileTHR (cd_icc_get_context (priv->icc),
						     &white,
						     &primaries,
						     transfer);
	ret = TRUE;
out:
	cmsFreeToneCurve (transfer[0]);
	return ret;
}
Ejemplo n.º 19
0
// Virtual profiles are handled here.
cmsHPROFILE OpenStockProfile(cmsContext ContextID, const char* File)
{   
       if (!File) 
            return cmsCreate_sRGBProfileTHR(ContextID);    
       
       if (cmsstrcasecmp(File, "*Lab2") == 0)
                return cmsCreateLab2ProfileTHR(ContextID, NULL);

       if (cmsstrcasecmp(File, "*Lab4") == 0)
                return cmsCreateLab4ProfileTHR(ContextID, NULL);

       if (cmsstrcasecmp(File, "*Lab") == 0)
                return cmsCreateLab4ProfileTHR(ContextID, NULL);
       
       if (cmsstrcasecmp(File, "*LabD65") == 0) {

           cmsCIExyY D65xyY;
           
           cmsWhitePointFromTemp( &D65xyY, 6504);           
           return cmsCreateLab4ProfileTHR(ContextID, &D65xyY);
       }

       if (cmsstrcasecmp(File, "*XYZ") == 0)
                return cmsCreateXYZProfileTHR(ContextID);

       if (cmsstrcasecmp(File, "*Gray22") == 0) {

           cmsToneCurve* Curve = cmsBuildGamma(ContextID, 2.2);
           cmsHPROFILE hProfile = cmsCreateGrayProfileTHR(ContextID, cmsD50_xyY(), Curve);
           cmsFreeToneCurve(Curve);
           return hProfile;
       }

        if (cmsstrcasecmp(File, "*Gray30") == 0) {

           cmsToneCurve* Curve = cmsBuildGamma(ContextID, 3.0);
           cmsHPROFILE hProfile = cmsCreateGrayProfileTHR(ContextID, cmsD50_xyY(), Curve);
           cmsFreeToneCurve(Curve);
           return hProfile;
       }

       if (cmsstrcasecmp(File, "*srgb") == 0)
                return cmsCreate_sRGBProfileTHR(ContextID);

       if (cmsstrcasecmp(File, "*null") == 0)
                return cmsCreateNULLProfileTHR(ContextID);

       
       if (cmsstrcasecmp(File, "*Lin2222") == 0) {

            cmsToneCurve*  Gamma = cmsBuildGamma(0, 2.2);
            cmsToneCurve*  Gamma4[4];
            cmsHPROFILE hProfile; 

            Gamma4[0] = Gamma4[1] = Gamma4[2] = Gamma4[3] = Gamma;
            hProfile = cmsCreateLinearizationDeviceLink(cmsSigCmykData, Gamma4);
            cmsFreeToneCurve(Gamma);
            return hProfile;
       }

           
        return cmsOpenProfileFromFileTHR(ContextID, File, "r");
}
Ejemplo n.º 20
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;
}
Ejemplo n.º 21
0
mng_retcode mng_init_full_cms (mng_datap pData,
                               mng_bool  bGlobal,
                               mng_bool  bObject,
                               mng_bool  bRetrobj)
{
  mng_cmsprof    hProf;
  mng_cmstrans   hTrans;
  mng_imagep     pImage = MNG_NULL;
  mng_imagedatap pBuf   = MNG_NULL;

#ifdef MNG_SUPPORT_TRACE
  MNG_TRACE (pData, MNG_FN_INIT_FULL_CMS, MNG_LC_START);
#endif

  if (bObject)                         /* use object if present ? */
  {                                    /* current object ? */
    if ((mng_imagep)pData->pCurrentobj)
      pImage = (mng_imagep)pData->pCurrentobj;
    else                               /* if not; use object 0 */
      pImage = (mng_imagep)pData->pObjzero;
  }

  if (bRetrobj)                        /* retrieving from an object ? */
    pImage = (mng_imagep)pData->pRetrieveobj;

  if (pImage)                          /* are we using an object ? */
    pBuf = pImage->pImgbuf;            /* then address the buffer */

  if ((!pBuf) || (!pBuf->bCorrected))  /* is the buffer already corrected ? */
  {
#ifndef MNG_SKIPCHUNK_iCCP
    if (((pBuf) && (pBuf->bHasICCP)) || ((bGlobal) && (pData->bHasglobalICCP)))
    {
      if (!pData->hProf2)              /* output profile not defined ? */
      {                                /* then assume sRGB !! */
        pData->hProf2 = mnglcms_createsrgbprofile ();

        if (!pData->hProf2)            /* handle error ? */
          MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);
      }

      if ((pBuf) && (pBuf->bHasICCP))  /* generate a profile handle */
        hProf = cmsOpenProfileFromMem (pBuf->pProfile, pBuf->iProfilesize);
      else
        hProf = cmsOpenProfileFromMem (pData->pGlobalProfile, pData->iGlobalProfilesize);

      pData->hProf1 = hProf;           /* save for future use */

      if (!hProf)                      /* handle error ? */
        MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);

#ifndef MNG_NO_16BIT_SUPPORT
      if (pData->bIsRGBA16)            /* 16-bit intermediates ? */
        hTrans = cmsCreateTransform (hProf,         TYPE_RGBA_16_SE,
                                     pData->hProf2, TYPE_RGBA_16_SE,
                                     INTENT_PERCEPTUAL, MNG_CMS_FLAGS);
      else
#endif
        hTrans = cmsCreateTransform (hProf,         TYPE_RGBA_8,
                                     pData->hProf2, TYPE_RGBA_8,
                                     INTENT_PERCEPTUAL, MNG_CMS_FLAGS);

      pData->hTrans = hTrans;          /* save for future use */

      if (!hTrans)                     /* handle error ? */
        MNG_ERRORL (pData, MNG_LCMS_NOTRANS);
                                       /* load color-correction routine */
      pData->fCorrectrow = (mng_fptr)mng_correct_full_cms;

      return MNG_NOERROR;              /* and done */
    }
    else
#endif
    if (((pBuf) && (pBuf->bHasSRGB)) || ((bGlobal) && (pData->bHasglobalSRGB)))
    {
      mng_uint8 iIntent;

      if (pData->bIssRGB)              /* sRGB system ? */
        return MNG_NOERROR;            /* no conversion required */

      if (!pData->hProf3)              /* sRGB profile not defined ? */
      {                                /* then create it implicitly !! */
        pData->hProf3 = mnglcms_createsrgbprofile ();

        if (!pData->hProf3)            /* handle error ? */
          MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);
      }

      hProf = pData->hProf3;           /* convert from sRGB profile */

      if ((pBuf) && (pBuf->bHasSRGB))  /* determine rendering intent */
        iIntent = pBuf->iRenderingintent;
      else
        iIntent = pData->iGlobalRendintent;

      if (pData->bIsRGBA16)            /* 16-bit intermediates ? */
        hTrans = cmsCreateTransform (hProf,         TYPE_RGBA_16_SE,
                                     pData->hProf2, TYPE_RGBA_16_SE,
                                     iIntent, MNG_CMS_FLAGS);
      else
        hTrans = cmsCreateTransform (hProf,         TYPE_RGBA_8,
                                     pData->hProf2, TYPE_RGBA_8,
                                     iIntent, MNG_CMS_FLAGS);

      pData->hTrans = hTrans;          /* save for future use */

      if (!hTrans)                     /* handle error ? */
        MNG_ERRORL (pData, MNG_LCMS_NOTRANS);
                                       /* load color-correction routine */
      pData->fCorrectrow = (mng_fptr)mng_correct_full_cms;

      return MNG_NOERROR;              /* and done */
    }
    else
    if ( (((pBuf) && (pBuf->bHasCHRM)) || ((bGlobal) && (pData->bHasglobalCHRM))) &&
         ( ((pBuf) && (pBuf->bHasGAMA) && (pBuf->iGamma > 0)) ||
           ((bGlobal) && (pData->bHasglobalGAMA) && (pData->iGlobalGamma > 0))  )    )
    {
      mng_CIExyY       sWhitepoint;
      mng_CIExyYTRIPLE sPrimaries;
      mng_gammatabp    pGammatable[3];
      mng_float        dGamma;

      if (!pData->hProf2)              /* output profile not defined ? */
      {                                /* then assume sRGB !! */
        pData->hProf2 = mnglcms_createsrgbprofile ();

        if (!pData->hProf2)            /* handle error ? */
          MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);
      }

#ifndef MNG_SKIPCHUNK_cHRM
      if ((pBuf) && (pBuf->bHasCHRM))  /* local cHRM ? */
      {
        sWhitepoint.x      = (mng_float)pBuf->iWhitepointx   / 100000;
        sWhitepoint.y      = (mng_float)pBuf->iWhitepointy   / 100000;
        sPrimaries.Red.x   = (mng_float)pBuf->iPrimaryredx   / 100000;
        sPrimaries.Red.y   = (mng_float)pBuf->iPrimaryredy   / 100000;
        sPrimaries.Green.x = (mng_float)pBuf->iPrimarygreenx / 100000;
        sPrimaries.Green.y = (mng_float)pBuf->iPrimarygreeny / 100000;
        sPrimaries.Blue.x  = (mng_float)pBuf->iPrimarybluex  / 100000;
        sPrimaries.Blue.y  = (mng_float)pBuf->iPrimarybluey  / 100000;
      }
      else
      {
        sWhitepoint.x      = (mng_float)pData->iGlobalWhitepointx   / 100000;
        sWhitepoint.y      = (mng_float)pData->iGlobalWhitepointy   / 100000;
        sPrimaries.Red.x   = (mng_float)pData->iGlobalPrimaryredx   / 100000;
        sPrimaries.Red.y   = (mng_float)pData->iGlobalPrimaryredy   / 100000;
        sPrimaries.Green.x = (mng_float)pData->iGlobalPrimarygreenx / 100000;
        sPrimaries.Green.y = (mng_float)pData->iGlobalPrimarygreeny / 100000;
        sPrimaries.Blue.x  = (mng_float)pData->iGlobalPrimarybluex  / 100000;
        sPrimaries.Blue.y  = (mng_float)pData->iGlobalPrimarybluey  / 100000;
      }
#endif

      sWhitepoint.Y      =             /* Y component is always 1.0 */
      sPrimaries.Red.Y   =
      sPrimaries.Green.Y =
      sPrimaries.Blue.Y  = 1.0;

      if ((pBuf) && (pBuf->bHasGAMA))  /* get the gamma value */
        dGamma = (mng_float)pBuf->iGamma / 100000;
      else
        dGamma = (mng_float)pData->iGlobalGamma / 100000;

      dGamma = pData->dViewgamma / dGamma;

      pGammatable [0] =                /* and build the lookup tables */
      pGammatable [1] =
      pGammatable [2] = cmsBuildGamma (256, dGamma);

      if (!pGammatable [0])            /* enough memory ? */
        MNG_ERRORL (pData, MNG_LCMS_NOMEM);
                                       /* create the profile */
      hProf = cmsCreateRGBProfile (&sWhitepoint, &sPrimaries, pGammatable);

      cmsFreeGamma (pGammatable [0]);  /* free the temporary gamma tables ? */
                                       /* yes! but just the one! */

      pData->hProf1 = hProf;           /* save for future use */

      if (!hProf)                      /* handle error ? */
        MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);

      if (pData->bIsRGBA16)            /* 16-bit intermediates ? */
        hTrans = cmsCreateTransform (hProf,         TYPE_RGBA_16_SE,
                                     pData->hProf2, TYPE_RGBA_16_SE,
                                     INTENT_PERCEPTUAL, MNG_CMS_FLAGS);
      else
        hTrans = cmsCreateTransform (hProf,         TYPE_RGBA_8,
                                     pData->hProf2, TYPE_RGBA_8,
                                     INTENT_PERCEPTUAL, MNG_CMS_FLAGS);

      pData->hTrans = hTrans;          /* save for future use */

      if (!hTrans)                     /* handle error ? */
        MNG_ERRORL (pData, MNG_LCMS_NOTRANS);
                                       /* load color-correction routine */
      pData->fCorrectrow = (mng_fptr)mng_correct_full_cms;

      return MNG_NOERROR;              /* and done */
    }
  }

#ifdef MNG_SUPPORT_TRACE
  MNG_TRACE (pData, MNG_FN_INIT_FULL_CMS, MNG_LC_END);
#endif
                                       /* if we get here, we'll only do gamma */
  return mng_init_gamma_only (pData, bGlobal, bObject, bRetrobj);
}
Ejemplo n.º 22
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;
}