
from numpy import *
from numpy.linalg import *
from math import *
class XYZ2RGB:
    def __init__(self,red,green,blue,white):
        self.red = red
        self.green = green
        self.blue = blue
        self.white = white
        P=mat([[red[0],green[0],blue[0]],[red[1],green[1],blue[1]],[1-red[0]-red[1],1-green[0]-green[1],1-blue[0]-blue[1]]])
        U=inv(P)*mat([[white[0]],[white[1]],[1-white[0]-white[1]]])/white[1]
        self.Q=P*mat([[U[0,0],0,0],[0,U[1,0],0],[0,0,U[2,0]]])
        self.T=inv(self.Q)
        self.gamma = 2.2
    def rgb(self,XYZ):
        RGB = self.T*mat([[XYZ[0]],[XYZ[1]],[XYZ[2]]])
        return [RGB[0,0],RGB[1,0],RGB[2,0]]
    def xyY2RGB(self,x,y,Y):
        X=x/y*Y
        Z=(1-x-y)/y*Y
        return self.rgb([X,Y,Z])
    def XYZ(self,RGB):
        XYZ0=self.Q*mat([[RGB[0]],[RGB[1]],[RGB[2]]])
        return [XYZ0[0,0],XYZ0[1,0],XYZ0[2,0]]
            
    def rgbN(self,XYZ):
        RGB = self.rgb(XYZ)
        m=max(RGB)
        if m>1.0:
            return [RGB[0]/m,RGB[1]/m,RGB[2]/m]
        else:
            return RGB
                
    def rgbN1(self,XYZ):
        RGB = self.rgb(XYZ)
        m=-min([0,RGB[0],RGB[1],RGB[2]])
        RGB[0] += m
        RGB[1] += m
        RGB[2] += m
        m=max(RGB)
        if m>1.0:
            return [RGB[0]/m,RGB[1]/m,RGB[2]/m]
        else:
            return RGB
            
    def rgbN2(self,XYZ):
        RGB = self.rgb(XYZ)
        for k in range(3):
            if RGB[k]<0:
                RGB[k]=0;
        m=max(RGB)
        if m>1.0:
            return [RGB[0]/m,RGB[1]/m,RGB[2]/m]
        else:
            return RGB
                
    def rgbN2G(self,XYZ):
        RGB = self.rgbN2(XYZ)
        a = 1.0/self.gamma
        RGB[0] = math.pow(RGB[0],a)
        RGB[1] = math.pow(RGB[1],a)
        RGB[2] = math.pow(RGB[2],a) 
        return RGB
    def rgbN1G(self,XYZ):
        RGB = self.rgbN1(XYZ)
        a = 1.0/self.gamma
        RGB[0] = math.pow(RGB[0],a)
        RGB[1] = math.pow(RGB[1],a)
        RGB[2] = math.pow(RGB[2],a) 
        return RGB
        
    def XYZG(self,RGB):
        RGB[0] = math.pow(RGB[0],self.gamma)
        RGB[1] = math.pow(RGB[1],self.gamma)
        RGB[2] = math.pow(RGB[2],self.gamma)
        return self.XYZ(RGB)
        
    def rgbN2G2(self,XYZ):
        RGB = self.rgbN2(XYZ)
        a=1.0/2.4
        for k in range(3):
            if RGB[k]<=0.00304:
                RGB[k] *= 12.92
            else:
                RGB[k] = 1.055*math.pow(RGB[k],a)-0.055
        return RGB
                
    def xyL2rgb(self,x,y,Lu):
        XYZ=[x/y,1,(1-x-y)/y]
        RGB=self.rgbN2G(XYZ)
        return [RGB[0]*Lu,RGB[1]*Lu,RGB[2]*Lu]
                