Ejemplo n.º 1
0
static
void ComputeChromaticAdaptation(LPMAT3 Conversion,
                                LPcmsCIEXYZ SourceWhitePoint,
                                LPcmsCIEXYZ DestWhitePoint,
                                LPMAT3 Chad)

{
      
        MAT3 Chad_Inv;
        VEC3 ConeSourceXYZ, ConeSourceRGB;
        VEC3 ConeDestXYZ, ConeDestRGB;
        MAT3 Cone, Tmp;


        Tmp = *Chad;
        MAT3inverse(&Tmp, &Chad_Inv);

        VEC3init(&ConeSourceXYZ, SourceWhitePoint -> X,
                                 SourceWhitePoint -> Y,
                                 SourceWhitePoint -> Z);

        VEC3init(&ConeDestXYZ,   DestWhitePoint -> X,
                                 DestWhitePoint -> Y,
                                 DestWhitePoint -> Z);

        MAT3eval(&ConeSourceRGB, Chad, &ConeSourceXYZ);
        MAT3eval(&ConeDestRGB,   Chad, &ConeDestXYZ);

        // Build matrix

        VEC3init(&Cone.v[0], ConeDestRGB.n[0]/ConeSourceRGB.n[0],    0.0,  0.0);
        VEC3init(&Cone.v[1], 0.0,   ConeDestRGB.n[1]/ConeSourceRGB.n[1],   0.0);
        VEC3init(&Cone.v[2], 0.0,   0.0,   ConeDestRGB.n[2]/ConeSourceRGB.n[2]);


        // Normalize
        MAT3per(&Tmp, &Cone, Chad);
        MAT3per(Conversion, &Chad_Inv, &Tmp);

}
Ejemplo n.º 2
0
static
void ComputeBlackPointCompensationFactors(LPcmsCIEXYZ BlackPointIn,
                      LPcmsCIEXYZ WhitePointIn,
                      LPcmsCIEXYZ IlluminantIn,
                      LPcmsCIEXYZ BlackPointOut,
                      LPcmsCIEXYZ WhitePointOut,
                      LPcmsCIEXYZ IlluminantOut,
                      LPMAT3 m, LPVEC3 of)
{
    

   cmsCIEXYZ RelativeBlackPointIn, RelativeBlackPointOut;
   double ax, ay, az, bx, by, bz, tx, ty, tz;
   
   // At first, convert both black points to relative.

   cmsAdaptToIlluminant(&RelativeBlackPointIn,  WhitePointIn, IlluminantIn, BlackPointIn);
   cmsAdaptToIlluminant(&RelativeBlackPointOut, WhitePointOut, IlluminantOut, BlackPointOut);
   
   // Now we need to compute a matrix plus an offset m and of such of
   // [m]*bpin + off = bpout
   // [m]*D50  + off = D50
   //
   // This is a linear scaling in the form ax+b, where
   // a = (bpout - D50) / (bpin - D50)
   // b = - D50* (bpout - bpin) / (bpin - D50)


   tx = RelativeBlackPointIn.X - IlluminantIn ->X;
   ty = RelativeBlackPointIn.Y - IlluminantIn ->Y;
   tz = RelativeBlackPointIn.Z - IlluminantIn ->Z;

   ax = (RelativeBlackPointOut.X - IlluminantOut ->X) / tx;
   ay = (RelativeBlackPointOut.Y - IlluminantOut ->Y) / ty;
   az = (RelativeBlackPointOut.Z - IlluminantOut ->Z) / tz;

   bx = - IlluminantOut -> X * (RelativeBlackPointOut.X - RelativeBlackPointIn.X) / tx;
   by = - IlluminantOut -> Y * (RelativeBlackPointOut.Y - RelativeBlackPointIn.Y) / ty;
   bz = - IlluminantOut -> Z * (RelativeBlackPointOut.Z - RelativeBlackPointIn.Z) / tz;


   MAT3identity(m);

   m->v[VX].n[0] = ax;
   m->v[VY].n[1] = ay;
   m->v[VZ].n[2] = az;

   VEC3init(of, bx, by, bz);

}
Ejemplo n.º 3
0
BOOL LCMSEXPORT cmsBuildRGB2XYZtransferMatrix(LPMAT3 r, LPcmsCIExyY WhitePt,
                                            LPcmsCIExyYTRIPLE Primrs)
{
        VEC3 WhitePoint, Coef;
        MAT3 Result, Primaries;
        double xn, yn;
        double xr, yr;
        double xg, yg;
        double xb, yb;


        xn = WhitePt -> x;
        yn = WhitePt -> y;
        xr = Primrs -> Red.x;
        yr = Primrs -> Red.y;
        xg = Primrs -> Green.x;
        yg = Primrs -> Green.y;
        xb = Primrs -> Blue.x;
        yb = Primrs -> Blue.y;


        // Build Primaries matrix

        VEC3init(&Primaries.v[0], xr,        xg,         xb);
        VEC3init(&Primaries.v[1], yr,        yg,         yb);
        VEC3init(&Primaries.v[2], (1-xr-yr), (1-xg-yg),  (1-xb-yb));


        // Result = Primaries ^ (-1) inverse matrix

        if (!MAT3inverse(&Primaries, &Result))
                        return FALSE;


        VEC3init(&WhitePoint, xn/yn, 1.0, (1.0-xn-yn)/yn);

        // Across inverse primaries ...

        MAT3eval(&Coef, &Result, &WhitePoint);

        // Give us the Coefs, then I build transformation matrix

        VEC3init(&r -> v[0], Coef.n[VX]*xr,          Coef.n[VY]*xg,          Coef.n[VZ]*xb);
        VEC3init(&r -> v[1], Coef.n[VX]*yr,          Coef.n[VY]*yg,          Coef.n[VZ]*yb);
        VEC3init(&r -> v[2], Coef.n[VX]*(1.0-xr-yr), Coef.n[VY]*(1.0-xg-yg), Coef.n[VZ]*(1.0-xb-yb));
       

        return TRUE;
}
Ejemplo n.º 4
0
static
void Rel2RelStepAbsCoefs(double AdaptationState,

                         LPcmsCIEXYZ BlackPointIn,
                         LPcmsCIEXYZ WhitePointIn,
                         LPcmsCIEXYZ IlluminantIn,
                         LPMAT3 ChromaticAdaptationMatrixIn,

                         LPcmsCIEXYZ BlackPointOut,
                         LPcmsCIEXYZ WhitePointOut,
                         LPcmsCIEXYZ IlluminantOut,
                         LPMAT3 ChromaticAdaptationMatrixOut,

                         LPMAT3 m, LPVEC3 of)
{
       
       VEC3 WtPtIn, WtPtInAdapted;
       VEC3 WtPtOut, WtPtOutAdapted;
       MAT3 Scale, m1, m2, m3;
       
       VEC3init(&WtPtIn, WhitePointIn->X, WhitePointIn->Y, WhitePointIn->Z);
       MAT3eval(&WtPtInAdapted, ChromaticAdaptationMatrixIn, &WtPtIn);
                  
       VEC3init(&WtPtOut, WhitePointOut->X, WhitePointOut->Y, WhitePointOut->Z);
       MAT3eval(&WtPtOutAdapted, ChromaticAdaptationMatrixOut, &WtPtOut);

       VEC3init(&Scale.v[0], WtPtInAdapted.n[0] / WtPtOutAdapted.n[0], 0, 0);
       VEC3init(&Scale.v[1], 0, WtPtInAdapted.n[1] / WtPtOutAdapted.n[1], 0);
       VEC3init(&Scale.v[2], 0, 0, WtPtInAdapted.n[2] / WtPtOutAdapted.n[2]);


       // Adaptation state

       if (AdaptationState == 1.0) {

           // Observer is fully adapted. Keep chromatic adaptation 

           CopyMemory(m, &Scale, sizeof(MAT3));

       }
       else {

            // Observer is not adapted, undo the chromatic adaptation
            m1 = *ChromaticAdaptationMatrixIn;
            MAT3inverse(&m1, &m2);
       
            MAT3per(&m3, &m2, &Scale);
            MAT3per(m, &m3, ChromaticAdaptationMatrixOut);
       }

            
       VEC3init(of, 0.0, 0.0, 0.0);
                    
}
Ejemplo n.º 5
0
BOOL LCMSEXPORT cmsAdaptToIlluminant(LPcmsCIEXYZ Result, 
                                     LPcmsCIEXYZ SourceWhitePt, 
                                     LPcmsCIEXYZ Illuminant, 
                                     LPcmsCIEXYZ Value)
{
        MAT3 Bradford;
        VEC3 In, Out;
    
        // BradfordLamRiggChromaticAdaptation(&Bradford, SourceWhitePt, Illuminant);

        cmsAdaptationMatrix(&Bradford, NULL, SourceWhitePt, Illuminant);

        VEC3init(&In, Value -> X, Value -> Y, Value -> Z);
        MAT3eval(&Out, &Bradford, &In);

        Result -> X = Out.n[0];
        Result -> Y = Out.n[1];
        Result -> Z = Out.n[2];

        return TRUE;
}
Ejemplo n.º 6
0
BOOL cmsxComputeMatrixShaper(const char* ReferenceSheet,
                             const char* MeasurementSheet,
                             int Medium,
                             LPGAMMATABLE TransferCurves[3],
                             LPcmsCIEXYZ WhitePoint,
                             LPcmsCIEXYZ BlackPoint,
                             LPcmsCIExyYTRIPLE Primaries)
{

    MEASUREMENT Linearized;
    cmsCIEXYZ Black, White;
    cmsCIExyYTRIPLE  PrimarySet;
    LPPATCH PatchWhite, PatchBlack;
    LPPATCH PatchRed, PatchGreen, PatchBlue;
    double Distance;

    /* Load sheets */

    if (!cmsxPCollBuildMeasurement(&Linearized,
                             ReferenceSheet,
                             MeasurementSheet,
                             PATCH_HAS_XYZ|PATCH_HAS_RGB)) return false;



    /* Any patch to deal of? */
    if (cmsxPCollCountSet(&Linearized, Linearized.Allowed) <= 0) return false;


    /* Try to see if proper primaries, white and black already present */
    PatchWhite = cmsxPCollFindWhite(&Linearized, Linearized.Allowed, &Distance);
    if (Distance != 0)
        PatchWhite = NULL;

    PatchBlack = cmsxPCollFindBlack(&Linearized, Linearized.Allowed, &Distance);
    if (Distance != 0)
        PatchBlack = NULL;

    PatchRed = cmsxPCollFindPrimary(&Linearized, Linearized.Allowed, 0, &Distance);
    if (Distance != 0)
        PatchRed = NULL;

    PatchGreen = cmsxPCollFindPrimary(&Linearized, Linearized.Allowed, 1, &Distance);
    if (Distance != 0)
        PatchGreen = NULL;

    PatchBlue = cmsxPCollFindPrimary(&Linearized, Linearized.Allowed, 2, &Distance);
    if (Distance != 0)
        PatchBlue= NULL;

    /* If we got primaries, then we can also get prelinearization */
    /* by  Levenberg-Marquardt. This applies on monitor profiles */

    if (PatchWhite && PatchRed && PatchGreen && PatchBlue) {

        /* Build matrix with primaries */

        MAT3 Mat, MatInv;
        LPSAMPLEDCURVE Xr,Yr, Xg, Yg, Xb, Yb;
        int i, nRes, cnt;

        VEC3init(&Mat.v[0], PatchRed->XYZ.X, PatchGreen->XYZ.X, PatchBlue->XYZ.X);
        VEC3init(&Mat.v[1], PatchRed->XYZ.Y, PatchGreen->XYZ.Y, PatchBlue->XYZ.Y);
        VEC3init(&Mat.v[2], PatchRed->XYZ.Z, PatchGreen->XYZ.Z, PatchBlue->XYZ.Z);

        /* Invert matrix */
        MAT3inverse(&Mat, &MatInv);

        nRes = cmsxPCollCountSet(&Linearized, Linearized.Allowed);

        Xr = cmsAllocSampledCurve(nRes);
        Yr = cmsAllocSampledCurve(nRes);
        Xg = cmsAllocSampledCurve(nRes);
        Yg = cmsAllocSampledCurve(nRes);
        Xb = cmsAllocSampledCurve(nRes);
        Yb = cmsAllocSampledCurve(nRes);

        /* Convert XYZ of all patches to RGB */
        cnt = 0;
        for (i=0; i < Linearized.nPatches; i++) {

            if (Linearized.Allowed[i]) {

                VEC3 RGBprime, XYZ;
                LPPATCH p;

                p = Linearized.Patches + i;
                XYZ.n[0] = p -> XYZ.X;
                XYZ.n[1] = p -> XYZ.Y;
                XYZ.n[2] = p -> XYZ.Z;

                MAT3eval(&RGBprime, &MatInv, &XYZ);

                Xr ->Values[cnt] = p ->Colorant.RGB[0];
                Yr ->Values[cnt] = Clip(RGBprime.n[0]);

                Xg ->Values[cnt] = p ->Colorant.RGB[1];
                Yg ->Values[cnt] = Clip(RGBprime.n[1]);

                Xb ->Values[cnt] = p ->Colorant.RGB[2];
                Yb ->Values[cnt] = Clip(RGBprime.n[2]);

                cnt++;

            }
        }

        TransferCurves[0] = cmsxEstimateGamma(Xr, Yr, 1024);
        TransferCurves[1] = cmsxEstimateGamma(Xg, Yg, 1024);
        TransferCurves[2] = cmsxEstimateGamma(Xb, Yb, 1024);

        if (WhitePoint) {

            WhitePoint->X = PatchWhite->XYZ.X;
            WhitePoint->Y= PatchWhite ->XYZ.Y;
            WhitePoint->Z= PatchWhite ->XYZ.Z;
        }

        if (BlackPoint && PatchBlack) {

            BlackPoint->X = PatchBlack ->XYZ.X;
            BlackPoint->Y = PatchBlack ->XYZ.Y;
            BlackPoint->Z = PatchBlack ->XYZ.Z;
        }

        if (Primaries) {

            cmsXYZ2xyY(&Primaries->Red,   &PatchRed ->XYZ);
            cmsXYZ2xyY(&Primaries->Green, &PatchGreen ->XYZ);
            cmsXYZ2xyY(&Primaries->Blue,  &PatchBlue ->XYZ);

        }


        cmsFreeSampledCurve(Xr);
        cmsFreeSampledCurve(Yr);
        cmsFreeSampledCurve(Xg);
        cmsFreeSampledCurve(Yg);
        cmsFreeSampledCurve(Xb);
        cmsFreeSampledCurve(Yb);

        cmsxPCollFreeMeasurements(&Linearized);

        return true;
    }




    /* Compute prelinearization */
    cmsxComputeLinearizationTables(&Linearized, PT_XYZ, TransferCurves, 1024, Medium);

    /* Linearize measurements */
    cmsxPCollLinearizePatches(&Linearized, Linearized.Allowed, TransferCurves);


    /* Endpoints */
    ComputeWhiteAndBlackPoints(&Linearized, TransferCurves, &Black, &White);

    /* Primaries */
    ComputePrimary(&Linearized, TransferCurves, 0, &PrimarySet.Red);
    ComputePrimary(&Linearized, TransferCurves, 1, &PrimarySet.Green);
    ComputePrimary(&Linearized, TransferCurves, 2, &PrimarySet.Blue);


    if (BlackPoint) {
        *BlackPoint = Black;
        Div100(BlackPoint);
    }

    if (WhitePoint) {
        *WhitePoint = White;
        Div100(WhitePoint);
    }


    if (Primaries) {
        *Primaries = PrimarySet;
    }

    cmsxPCollFreeMeasurements(&Linearized);

    return true;
}
Ejemplo n.º 7
0
int cmsChooseCnvrt(int Absolute,
                  int Phase1, LPcmsCIEXYZ BlackPointIn,
                              LPcmsCIEXYZ WhitePointIn,
                              LPcmsCIEXYZ IlluminantIn,
                              LPMAT3 ChromaticAdaptationMatrixIn,

                  int Phase2, LPcmsCIEXYZ BlackPointOut,
                              LPcmsCIEXYZ WhitePointOut,
                              LPcmsCIEXYZ IlluminantOut,
                              LPMAT3 ChromaticAdaptationMatrixOut,

                  int DoBlackPointCompensation,
                  double AdaptationState,
                  _cmsADJFN *fn1,
                  LPWMAT3 wm, LPWVEC3 wof)
{

       int rc;
       MAT3 m;
       VEC3 of;


       MAT3identity(&m);
       VEC3init(&of, 0, 0, 0);

       switch (Phase1) {

       // Input LUT is giving XYZ relative values.

       case XYZRel:  rc = FromXYZRelLUT(Absolute,
                                          BlackPointIn,
                                          WhitePointIn,
                                          IlluminantIn,
                                          ChromaticAdaptationMatrixIn,
                                          Phase2,
                                          BlackPointOut,
                                          WhitePointOut,
                                          IlluminantOut,
                                          ChromaticAdaptationMatrixOut,
                                          DoBlackPointCompensation,
                                          AdaptationState,
                                          fn1, &m, &of);
                     break;

       

       // Input LUT is giving Lab relative values

       case LabRel:  rc =  FromLabRelLUT(Absolute,
                                          BlackPointIn,
                                          WhitePointIn,
                                          IlluminantIn,
                                          ChromaticAdaptationMatrixIn,
                                          Phase2,
                                          BlackPointOut,
                                          WhitePointOut,
                                          IlluminantOut,
                                          ChromaticAdaptationMatrixOut,
                                          DoBlackPointCompensation,
                                          AdaptationState,
                                          fn1, &m, &of);
                     break;


       

       // Unrecognized combination

       default:    cmsSignalError(LCMS_ERRC_ABORTED, "(internal) Phase error");
                   return FALSE;

       }

       MAT3toFix(wm, &m);
       VEC3toFix(wof, &of);

       // Do some optimization -- discard conversion if identity parameters.

       if (*fn1 == XYZ2XYZ || *fn1 == Lab2XYZ2Lab) {

           if (IdentityParameters(wm, wof))
               *fn1 = NULL;
       }

       
       return rc;
}
Ejemplo n.º 8
0
static
int FromXYZRelLUT(int Absolute,
                             LPcmsCIEXYZ BlackPointIn,
                             LPcmsCIEXYZ WhitePointIn,
                             LPcmsCIEXYZ IlluminantIn,
                             LPMAT3 ChromaticAdaptationMatrixIn,

                 int Phase2, LPcmsCIEXYZ BlackPointOut,
                             LPcmsCIEXYZ WhitePointOut,
                             LPcmsCIEXYZ IlluminantOut,
                             LPMAT3 ChromaticAdaptationMatrixOut,

                 int DoBlackPointCompensation,
                 double AdaptationState,
                 _cmsADJFN *fn1,
                 LPMAT3 m, LPVEC3 of)

{
              switch (Phase2) {

                     // From relative XYZ to Relative XYZ.

                     case XYZRel:

                            if (Absolute)
                            {
                                   // From input relative to absolute, and then
                                   // back to output relative

                                   Rel2RelStepAbsCoefs(AdaptationState,
                                                       BlackPointIn,
                                                       WhitePointIn,
                                                       IlluminantIn,
                                                       ChromaticAdaptationMatrixIn,
                                                       BlackPointOut,
                                                       WhitePointOut,
                                                       IlluminantOut,
                                                       ChromaticAdaptationMatrixOut,
                                                       m, of);
                                   *fn1 = XYZ2XYZ;

                            }
                            else
                            {
                                   // XYZ Relative to XYZ relative, no op required                                   
                                   *fn1 = NULL;
                                   if (DoBlackPointCompensation) {

                                      *fn1 = XYZ2XYZ;
                                      ComputeBlackPointCompensationFactors(BlackPointIn,
                                                                      WhitePointIn,
                                                                      IlluminantIn,
                                                                      BlackPointOut,
                                                                      WhitePointOut,
                                                                      IlluminantOut,
                                                                      m, of);

                                   }
                            }
                            break;

                    
                     // From relative XYZ to Relative Lab

                     case LabRel:

                            // First pass XYZ to absolute, then to relative and
                            // finally to Lab. I use here D50 for output in order
                            // to prepare the "to Lab" conversion.

                            if (Absolute)
                            {   

                                Rel2RelStepAbsCoefs(AdaptationState,
                                                    BlackPointIn,
                                                    WhitePointIn,
                                                    IlluminantIn,
                                                    ChromaticAdaptationMatrixIn,
                                                    BlackPointOut,
                                                    WhitePointOut,
                                                    IlluminantOut,
                                                    ChromaticAdaptationMatrixOut,
                                                    m, of);
                                
                                *fn1 = XYZ2Lab;

                            }
                            else
                            {
                                   // Just Convert to Lab

                                   MAT3identity(m);
                                   VEC3init(of, 0, 0, 0);
                                   *fn1 = XYZ2Lab;

                                   if (DoBlackPointCompensation) {

                                    ComputeBlackPointCompensationFactors(BlackPointIn,
                                                                          WhitePointIn,
                                                                          IlluminantIn,
                                                                          BlackPointOut,
                                                                          WhitePointOut,
                                                                          IlluminantOut,
                                                                          m, of);
                                   }
                            }
                            break;

                    
                     default: return FALSE;
                     }

              return TRUE;
}