예제 #1
0
void LcmsColorProfileContainer::DelinearizeFloatValue(QVector <double> & Value) const
{
    QVector <double> TRCtriplet(3);
    TRCtriplet[0] = Value[0];
    TRCtriplet[1] = Value[1];
    TRCtriplet[2] = Value[2];
    if (cmsIsTag(d->profile, cmsSigRedTRCTag)) {
        if (cmsIsToneCurveLinear(d->redTRC)) {
            TRCtriplet[0] = Value[0];
        } else {
            TRCtriplet[0] = cmsEvalToneCurveFloat(d->redTRCReverse, Value[0]);
        }
        if (cmsIsToneCurveLinear(d->greenTRC)) {
            TRCtriplet[1] = Value[1];
        } else {
            TRCtriplet[1] = cmsEvalToneCurveFloat(d->greenTRCReverse, Value[1]);
        }
        if (cmsIsToneCurveLinear(d->blueTRC)) {
            TRCtriplet[2] = Value[2];
        } else {
            TRCtriplet[2] = cmsEvalToneCurveFloat(d->blueTRCReverse, Value[2]);
        }
            
    } else {
        if (cmsIsTag(d->profile, cmsSigGrayTRCTag)) {
            TRCtriplet.fill(cmsEvalToneCurveFloat(d->grayTRCReverse, Value[0]));
        }
    }

    Value = TRCtriplet;
}
예제 #2
0
/**
 * cd_util_extract_vcgt:
 **/
static gboolean
cd_util_extract_vcgt (CdUtilPrivate *priv, gchar **values, GError **error)
{
	cmsFloat32Number in;
	cmsHPROFILE lcms_profile;
	const cmsToneCurve **vcgt;
	guint i;
	guint size;

	/* check arguments */
	if (g_strv_length (values) != 2) {
		g_set_error_literal (error, 1, 0,
				     "invalid input, expect 'filename' size'");
		return FALSE;
	}

	/* invalid size */
	size = atoi (values[1]);
	if (size <= 1 || size > 1024) {
		g_set_error_literal (error, 1, 0,
				     "invalid size,expected 2-1024");
		return FALSE;
	}

	/* does profile have VCGT */
	lcms_profile = cd_icc_get_handle (priv->icc);
	vcgt = cmsReadTag (lcms_profile, cmsSigVcgtTag);
	if (vcgt == NULL || vcgt[0] == NULL) {
		g_set_error_literal (error, 1, 0,
				     "profile does not have any VCGT data");
		return FALSE;
	}

	/* output data */
	g_print ("idx,red,green,blue\n");
	for (i = 0; i < size; i++) {
		in = (gdouble) i / (gdouble) (size - 1);
		g_print ("%u,", i);
		g_print ("%f,", cmsEvalToneCurveFloat(vcgt[0], in));
		g_print ("%f,", cmsEvalToneCurveFloat(vcgt[1], in));
		g_print ("%f\n", cmsEvalToneCurveFloat(vcgt[2], in));
	}

	/* success */
	priv->rewrite_file = FALSE;
	return TRUE;
}
예제 #3
0
void LcmsColorProfileContainer::DelinearizeFloatValue(QVector <double> & Value) const
{
    if (d->hasColorants) {
        if (!cmsIsToneCurveLinear(d->redTRC)) {
            Value[0] = cmsEvalToneCurveFloat(d->redTRCReverse, Value[0]);
        }
        if (!cmsIsToneCurveLinear(d->greenTRC)) {
            Value[1] = cmsEvalToneCurveFloat(d->greenTRCReverse, Value[1]);
        }
        if (!cmsIsToneCurveLinear(d->blueTRC)) {
            Value[2] = cmsEvalToneCurveFloat(d->blueTRCReverse, Value[2]);
        }

    } else {
        if (cmsIsTag(d->profile, cmsSigGrayTRCTag)) {
            Value[0] = cmsEvalToneCurveFloat(d->grayTRCReverse, Value[0]);
        }
    }
}
예제 #4
0
void
weston_cms_set_color_profile(struct weston_output *o,
			     struct weston_color_profile *p)
{
#ifdef HAVE_LCMS
	cmsFloat32Number in;
	const cmsToneCurve **vcgt;
	int i;
	int size;
	uint16_t *red = NULL;
	uint16_t *green = NULL;
	uint16_t *blue = NULL;

	if (!o->set_gamma)
		return;
	if (!p) {
		weston_cms_gamma_clear(o);
		return;
	}

	weston_log("Using ICC profile %s\n", p->filename);
	vcgt = cmsReadTag (p->lcms_handle, cmsSigVcgtTag);
	if (vcgt == NULL || vcgt[0] == NULL) {
		weston_cms_gamma_clear(o);
		return;
	}

	size = o->gamma_size;
	red = calloc(size, sizeof(uint16_t));
	green = calloc(size, sizeof(uint16_t));
	blue = calloc(size, sizeof(uint16_t));
	for (i = 0; i < size; i++) {
		in = (cmsFloat32Number) i / (cmsFloat32Number) (size - 1);
		red[i] = cmsEvalToneCurveFloat(vcgt[0], in) * (double) 0xffff;
		green[i] = cmsEvalToneCurveFloat(vcgt[1], in) * (double) 0xffff;
		blue[i] = cmsEvalToneCurveFloat(vcgt[2], in) * (double) 0xffff;
	}
	o->set_gamma(o, size, red, green, blue);
	free(red);
	free(green);
	free(blue);
#endif
}
예제 #5
0
파일: cmsgamma.c 프로젝트: Samangan/mpc-hc
// Joins two curves for X and Y. Curves should be monotonic.
// We want to get 
//
//      y = Y^-1(X(t)) 
//
cmsToneCurve* CMSEXPORT cmsJoinToneCurve(cmsContext ContextID, 
                                      const cmsToneCurve* X,
                                      const cmsToneCurve* Y, cmsUInt32Number nResultingPoints)
{
    cmsToneCurve* out = NULL;
    cmsToneCurve* Yreversed = NULL;
    cmsFloat32Number t, x;
    cmsFloat32Number* Res = NULL;
    cmsUInt32Number i;


    _cmsAssert(X != NULL);
    _cmsAssert(Y != NULL);

    Yreversed = cmsReverseToneCurveEx(nResultingPoints, Y);
    if (Yreversed == NULL) goto Error;

    Res = (cmsFloat32Number*) _cmsCalloc(ContextID, nResultingPoints, sizeof(cmsFloat32Number));
    if (Res == NULL) goto Error;
    
    //Iterate
    for (i=0; i <  nResultingPoints; i++) {

        t = (cmsFloat32Number) i / (nResultingPoints-1);
        x = cmsEvalToneCurveFloat(X,  t);
        Res[i] = cmsEvalToneCurveFloat(Yreversed, x);
    }

    // Allocate space for output
    out = cmsBuildTabulatedToneCurveFloat(ContextID, nResultingPoints, Res);
    
Error:

    if (Res != NULL) _cmsFree(ContextID, Res);
    if (Yreversed != NULL) cmsFreeToneCurve(Yreversed);

    return out;
}
예제 #6
0
파일: cmsgamma.c 프로젝트: Samangan/mpc-hc
cmsFloat64Number CMSEXPORT cmsEstimateGamma(const cmsToneCurve* t, cmsFloat64Number Precision)
{
    cmsFloat64Number gamma, sum, sum2;
    cmsFloat64Number n, x, y, Std;
    cmsUInt32Number i;

    _cmsAssert(t != NULL);

    sum = sum2 = n = 0;

    // Excluding endpoints   
    for (i=1; i < (MAX_NODES_IN_CURVE-1); i++) {

        x = (cmsFloat64Number) i / (MAX_NODES_IN_CURVE-1);
        y = (cmsFloat64Number) cmsEvalToneCurveFloat(t, (cmsFloat32Number) x);

        // Avoid 7% on lower part to prevent 
        // artifacts due to linear ramps

        if (y > 0. && y < 1. && x > 0.07) {

            gamma = log(y) / log(x);
            sum  += gamma;
            sum2 += gamma * gamma;
            n++;
        }
    }

    // Take a look on SD to see if gamma isn't exponential at all
    Std = sqrt((n * sum2 - sum * sum) / (n*(n-1)));

    if (Std > Precision)
        return -1.0;

    return (sum / n);   // The mean
}
예제 #7
0
// The CLUT will be stored at 16 bits, but calculations are performed at cmsFloat32Number precision
static
int BlackPreservingSampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo)
{
    int i;
    cmsFloat32Number Inf[4], Outf[4];
    cmsFloat32Number LabK[4];
    cmsFloat64Number SumCMY, SumCMYK, Error, Ratio;
    cmsCIELab ColorimetricLab, BlackPreservingLab;
    PreserveKPlaneParams* bp = (PreserveKPlaneParams*) Cargo;

    // Convert from 16 bits to floating point
    for (i=0; i < 4; i++)
        Inf[i] = (cmsFloat32Number) (In[i] / 65535.0);

    // Get the K across Tone curve
    LabK[3] = cmsEvalToneCurveFloat(bp ->KTone, Inf[3]);

    // If going across black only, keep black only
    if (In[0] == 0 && In[1] == 0 && In[2] == 0) {

        Out[0] = Out[1] = Out[2] = 0;
        Out[3] = _cmsQuickSaturateWord(LabK[3] * 65535.0);
        return TRUE;
    }

    // Try the original transform,
    cmsPipelineEvalFloat( Inf, Outf, bp ->cmyk2cmyk);

    // Store a copy of the floating point result into 16-bit
    for (i=0; i < 4; i++)
            Out[i] = _cmsQuickSaturateWord(Outf[i] * 65535.0);

    // Maybe K is already ok (mostly on K=0)
    if ( fabs(Outf[3] - LabK[3]) < (3.0 / 65535.0) ) {
        return TRUE;
    }

    // K differ, mesure and keep Lab measurement for further usage
    // this is done in relative colorimetric intent
    cmsDoTransform(bp->hProofOutput, Out, &ColorimetricLab, 1);

    // Is not black only and the transform doesn't keep black.
    // Obtain the Lab of output CMYK. After that we have Lab + K
    cmsDoTransform(bp ->cmyk2Lab, Outf, LabK, 1);

    // Obtain the corresponding CMY using reverse interpolation
    // (K is fixed in LabK[3])
    if (!cmsPipelineEvalReverseFloat(LabK, Outf, Outf, bp ->LabK2cmyk)) {

        // Cannot find a suitable value, so use colorimetric xform
        // which is already stored in Out[]
        return TRUE;
    }

    // Make sure to pass thru K (which now is fixed)
    Outf[3] = LabK[3];

    // Apply TAC if needed
    SumCMY   = Outf[0]  + Outf[1] + Outf[2];
    SumCMYK  = SumCMY + Outf[3];

    if (SumCMYK > bp ->MaxTAC) {

        Ratio = 1 - ((SumCMYK - bp->MaxTAC) / SumCMY);
        if (Ratio < 0)
            Ratio = 0;
    }
    else
       Ratio = 1.0;

    Out[0] = _cmsQuickSaturateWord(Outf[0] * Ratio * 65535.0);     // C
    Out[1] = _cmsQuickSaturateWord(Outf[1] * Ratio * 65535.0);     // M
    Out[2] = _cmsQuickSaturateWord(Outf[2] * Ratio * 65535.0);     // Y
    Out[3] = _cmsQuickSaturateWord(Outf[3] * 65535.0);

    // Estimate the error (this goes 16 bits to Lab DBL)
    cmsDoTransform(bp->hProofOutput, Out, &BlackPreservingLab, 1);
    Error = cmsDeltaE(&ColorimetricLab, &BlackPreservingLab);
    if (Error > bp -> MaxError)
        bp->MaxError = Error;

    return TRUE;
}
예제 #8
0
static int
dt_colorspaces_get_matrix_from_profile (cmsHPROFILE prof, float *matrix, float *lutr, float *lutg, float* lutb, const int lutsize, const int input)
{
  // create an OpenCL processable matrix + tone curves from an cmsHPROFILE:

  // check this first:
  if(!cmsIsMatrixShaper(prof)) return 1;

  cmsToneCurve* red_curve   = cmsReadTag(prof, cmsSigRedTRCTag);
  cmsToneCurve* green_curve = cmsReadTag(prof, cmsSigGreenTRCTag);
  cmsToneCurve* blue_curve  = cmsReadTag(prof, cmsSigBlueTRCTag);

  cmsCIEXYZ *red_color   = cmsReadTag(prof, cmsSigRedColorantTag);
  cmsCIEXYZ *green_color = cmsReadTag(prof, cmsSigGreenColorantTag);
  cmsCIEXYZ *blue_color  = cmsReadTag(prof, cmsSigBlueColorantTag);

  if(!red_curve || !green_curve || !blue_curve || !red_color || !green_color || !blue_color) return 2;

  matrix[0] = red_color->X;
  matrix[1] = green_color->X;
  matrix[2] = blue_color->X;
  matrix[3] = red_color->Y;
  matrix[4] = green_color->Y;
  matrix[5] = blue_color->Y;
  matrix[6] = red_color->Z;
  matrix[7] = green_color->Z;
  matrix[8] = blue_color->Z;

  // some camera ICC profiles claim to have color locations for red, green and blue base colors defined, 
  // but in fact these are all set to zero. we catch this case here.
  float sum = 0.0f;
  for(int k=0; k<9; k++) sum += matrix[k];
  if(sum == 0.0f) return 3;

  if(input)
  {
    // mark as linear, if they are:
    if(cmsIsToneCurveLinear(red_curve))   lutr[0] = -1.0f;
    else for(int k=0; k<lutsize; k++)     lutr[k] = cmsEvalToneCurveFloat(red_curve,   k/(lutsize-1.0f));
    if(cmsIsToneCurveLinear(green_curve)) lutg[0] = -1.0f;
    else for(int k=0; k<lutsize; k++)     lutg[k] = cmsEvalToneCurveFloat(green_curve, k/(lutsize-1.0f));
    if(cmsIsToneCurveLinear(blue_curve))  lutb[0] = -1.0f;
    else for(int k=0; k<lutsize; k++)     lutb[k] = cmsEvalToneCurveFloat(blue_curve,  k/(lutsize-1.0f));
  }
  else
  {
    // invert profile->XYZ matrix for output profiles
    float tmp[9];
    memcpy(tmp, matrix, sizeof(float)*9);
    if(mat3inv (matrix, tmp)) return 3;
    // also need to reverse gamma, to apply reverse before matrix multiplication:
    cmsToneCurve* rev_red   = cmsReverseToneCurveEx(0x8000, red_curve);
    cmsToneCurve* rev_green = cmsReverseToneCurveEx(0x8000, green_curve);
    cmsToneCurve* rev_blue  = cmsReverseToneCurveEx(0x8000, blue_curve);
    if(!rev_red || !rev_green || !rev_blue)
    {
      cmsFreeToneCurve(rev_red);
      cmsFreeToneCurve(rev_green);
      cmsFreeToneCurve(rev_blue);
      return 4;
    }
    // pass on tonecurves, in case lutsize > 0:
    if(cmsIsToneCurveLinear(red_curve))   lutr[0] = -1.0f;
    else for(int k=0; k<lutsize; k++)     lutr[k] = cmsEvalToneCurveFloat(rev_red,   k/(lutsize-1.0f));
    if(cmsIsToneCurveLinear(green_curve)) lutg[0] = -1.0f;
    else for(int k=0; k<lutsize; k++)     lutg[k] = cmsEvalToneCurveFloat(rev_green, k/(lutsize-1.0f));
    if(cmsIsToneCurveLinear(blue_curve))  lutb[0] = -1.0f;
    else for(int k=0; k<lutsize; k++)     lutb[k] = cmsEvalToneCurveFloat(rev_blue,  k/(lutsize-1.0f));
    cmsFreeToneCurve(rev_red);
    cmsFreeToneCurve(rev_green);
    cmsFreeToneCurve(rev_blue);
  }
  return 0;
}