LAB,RGB,XYZ颜色转换不正确反之亦然

时间:2018-05-29 10:26:13

标签: vb.net colors xna rgb cielab

我正在为一个项目制作一个自定义颜色选择器,它采用了photoshop风格,我让所有其他转换按预期工作,但我无法使RGBToLAB和LABToRGB正常工作正确。

问题不仅在于颜色没有正确表示,而且转换也不完美。

示例:

  • LAB _ 58:0:0
  • XYZ _ 0.25960986510312:0.25960986510312:0.25960986510312
  • RGB _ {R:10 G:8 B:7 A:255}
  • XYZ _ 0.250358161840588:5.51162077338675:66.3836625496266
  • LAB _ 85.3739502460609:0:0

初始LAB与上一个LAB不同,这表明转换存在缺陷。我不仅得到了错误的颜色,而且还有值的变化,特别是当LAB.L被假定为常量时(在这个例子中,因为滑块当前正在控制的是什么)

上面的LAB-> RGB-> LAB转换是有缺陷的,但XYZ-> RGB-> XYZ转换也是如此。

显然我对转换LABToLAB不感兴趣,但上述内容确实指出了转换中的一个缺陷。

我尝试的事情:

  1. This formula on wikipedia

  2. EasyRGB's code

  3. This javascript code on github

  4. This cginc code intended for unity, which is where i'm at now

       Private Function LABToXYZ(LAB As LAB) As XYZ
        Dim X, Y, Z As New Double
    
        Y = ((LAB.L + 16.0) / 116.0)
        X = ((LAB.A / 500.0) + Y)
        Z = (Y - (LAB.B / 200.0))
    
        Dim Less = 0.206897
    
        If (X > Less) Then
            X = Math.Pow(X, 3)
        Else
            X = ((X - 16.0 / 116.0) / 7.787)
        End If
        If (Y > Less) Then
            Y = Math.Pow(Y, 3)
        Else
            Y = ((Y - 16.0 / 116.0) / 7.787)
        End If
        If (Z > Less) Then
            Z = Math.Pow(Z, 3)
        Else
            Z = ((Z - 16.0 / 116.0) / 7.787)
        End If
    
        Return New XYZ(X, Y, Z)
    End Function
    
    Private Function XYZToRGB(XYZ As XYZ) As Color
        Dim R, G, B As New Double
        Dim X, Y, Z As New Double
    
        X = (XYZ.X / 100)
        Y = (XYZ.Y / 100)
        Z = (XYZ.Z / 100)
    
        R = ((X * 3.2406) + (Y * -1.5372) + (Z * -0.4986))
        G = ((X * -0.9689) + (Y * 1.8758) + (Z * 0.0415))
        B = ((X * 0.0557) + (Y * -0.204) + (Z * 1.057))
    
        Dim Less As Double = 0.0031308
    
        If (R > Less) Then
            X = ((1.055 * Math.Pow(R, (1.0 / 2.4))) - 0.055)
        Else
            X = (R * 12.92)
        End If
        If (G > Less) Then
            Y = ((1.055 * Math.Pow(G, (1.0 / 2.4))) - 0.055)
        Else
            Y = (G * 12.92)
        End If
        If (B > Less) Then
            Z = ((1.055 * Math.Pow(B, (1.0 / 2.4))) - 0.055)
        Else
            Z = (B * 12.92)
        End If
    
        Return New Color(CSng(X), CSng(Y), CSng(Z))
    End Function
    
    Private Function RGBToXYZ(Color As Color) As XYZ
        Dim RGB = ColorToRGB(Color)
        Dim X, Y, Z As New Double
        Dim Less As Double = 0.04045
    
        If (RGB.R > Less) Then
            X = Math.Pow(((RGB.R + 0.055) / 1.055), 2.4)
        Else
            X = (RGB.R / 12.92)
        End If
        If (RGB.G > Less) Then
            Y = Math.Pow(((RGB.G + 0.055) / 1.055), 2.4)
        Else
            Y = (RGB.G / 12.92)
        End If
        If (RGB.B > Less) Then
            Z = Math.Pow(((RGB.B + 0.055) / 1.055), 2.4)
        Else
            Z = (RGB.B / 12.92)
        End If
    
        X = (((X * 0.4124) + (Y * 0.3576) + (Z * 0.1805)) * 100.0)
        Y = (((X * 0.2126) + (Y * 0.7152) + (Z * 0.0722)) * 100.0)
        Z = (((X * 0.0193) + (Y * 0.1192) + (Z * 0.9505)) * 100.0)
    
        Return New XYZ(X, Y, Z)
    End Function
    
    Private Function XYZToLAB(XYZ As XYZ) As LAB
        Dim X, Y, Z As New Double
        Dim L, A, B As New Double
        Dim Less As Double = 0.008856
    
        X = ((XYZ.X / 95.047) + (XYZ.Y / 100) + (XYZ.Z / 108.883))
        Y = ((XYZ.X / 95.047) + (XYZ.Y / 100) + (XYZ.Z / 108.883))
        Z = ((XYZ.X / 95.047) + (XYZ.Y / 100) + (XYZ.Z / 108.883))
    
        If (X > Less) Then
            X = Math.Pow(X, (1.0 / 3.0))
        Else
            X = ((7.787 * X) + (16.0 / 116.0))
        End If
        If (Y > Less) Then
            Y = Math.Pow(Y, (1.0 / 3.0))
        Else
            Y = ((7.787 * Y) + (16.0 / 116.0))
        End If
        If (Z > Less) Then
            Z = Math.Pow(Z, (1.0 / 3.0))
        Else
            Z = ((7.787 * Z) + (16.0 / 116.0))
        End If
    
        L = ((116.0 * Y) - 16.0)
        A = (500.0 * (X - Y))
        B = (200.0 * (Y - Z))
    
        Return New LAB(L, A, B)
    End Function
    
    Function ColorToRGB(Color As Color) As RGB
        Return New RGB((Convert.ToInt32(Color.R) / 255), (Convert.ToInt32(Color.G) / 255), (Convert.ToInt32(Color.B) / 255))
    End Function
    Public Class RGB
    Public ReadOnly Min As Double = 0
    Public ReadOnly Max As Double = 1
    
    Public Sub New()
    End Sub
    
    Public Sub New(R As Double, G As Double, B As Double)
        Me.R = R
        Me.G = G
        Me.B = B
    End Sub
    
    Public Sub New(Color As Color)
        Me.R = (Convert.ToInt32(Color.R) / 255)
        Me.G = (Convert.ToInt32(Color.G) / 255)
        Me.B = (Convert.ToInt32(Color.B) / 255)
    End Sub
    
    Private _R As New Double
    Private _G As New Double
    Private _B As New Double
    
    Public Property R As Double
        Get
            Return _R
        End Get
        Set
            _R = LimitInRange(Value, Min, Max)
        End Set
    End Property
    
    Public Property G As Double
        Get
            Return _G
        End Get
        Set
            _G = LimitInRange(Value, Min, Max)
        End Set
    End Property
    
    Public Property B As Double
        Get
            Return _B
        End Get
        Set
            _B = LimitInRange(Value, Min, Max)
        End Set
    End Property
    
    Overrides Function ToString() As String
        Return (_R.ToString & ":"c & _G.ToString & ":"c & _B.ToString)
    End Function
    End Class
    
    Public Class XYZ
    Public ReadOnly Min As Double = 0
    Public ReadOnly Max As Double = 100
    
    Public Sub New()
    End Sub
    
    Public Sub New(X As Double, Y As Double, Z As Double)
        Me.X = X
        Me.Y = Y
        Me.Z = Z
    End Sub
    
    Private _X As New Double
    Private _Y As New Double
    Private _Z As New Double
    
    Public Property X As Double
        Get
            Return _X
        End Get
        Set
            _X = LimitInRange(Value, Min, Max)
        End Set
    End Property
    
    Public Property Y As Double
        Get
            Return _Y
        End Get
        Set
            _Y = LimitInRange(Value, Min, Max)
        End Set
    End Property
    
    Public Property Z As Double
        Get
            Return _Z
        End Get
        Set
            _Z = LimitInRange(Value, Min, Max)
        End Set
    End Property
    
    Overrides Function ToString() As String
        Return (_X.ToString & ":"c & _Y.ToString & ":"c & _Z.ToString)
    End Function
    End Class
    
    Public Class LAB
    Public ReadOnly Min As Double = -128
    Public ReadOnly Max As Double = 127
    
    Sub New()
    End Sub
    
    Sub New(L As Double, A As Double, B As Double)
        Me.L = L
        Me.A = A
        Me.B = B
    End Sub
    
    Private _L As New Double
    Private _A As New Double
    Private _B As New Double
    
    Property L As Double
        Get
            Return _L
        End Get
        Set
            _L = LimitInRange(Value, 0, 100)
        End Set
    End Property
    
    Property A As Double
        Get
            Return _A
        End Get
        Set
            _A = LimitInRange(Value, Min, Max)
        End Set
    End Property
    
    Property B As Double
        Get
            Return _B
        End Get
        Set
            _B = LimitInRange(Value, Min, Max)
        End Set
    End Property
    
    Overrides Function ToString() As String
        Return (_L.ToString & ":"c & _A.ToString & ":"c & _B.ToString)
    End Function
    End Class
    
    Function LimitInRange(Value As Double, Min As Double, Max As Double) As Double
        Select Case Value
            Case <= Min
                Return Min
            Case >= Max
                Return Max
            Case Else
                Return Value
        End Select
    End Function
    
  5. 我需要VB.Net中的代码,这就是为什么我正在为我的项目转换和调整统一代码,但是我很困难,需要一些帮助。

    如果有人知道我做错了什么,我会很乐意听。

    更新1: 我试图通过使两种转换方法不匹配来更正转换,我越来越接近完美的转换,但是我担心我可能已经从这个问题中获得了隧道视野这么久。

    示例:

    • LAB _ 0:0:0
    • XYZ _ 0.262413383082537:0.262413383082537:0.262413383082537
    • RGB _ {R:10 G:8 B:7 A:255}
    • XYZ _ 0.250358161840588:0.253536089358344:0.236754082437929
    • LAB _ 2.29017121228677:-0.12373260790384:0.261362975778545

    正如您所看到的那样,问题比以前少,但它仍然存在。

        Private Function LABToXYZ(LAB As LAB) As XYZ
            Dim X, Y, Z As New Double
    
            Y = ((LAB.L + 16.0) / 116.0)
            X = ((LAB.A / 500.0) + Y)
            Z = (Y - (LAB.B / 200.0))
    
            Dim Less = 0.008856
    
            If (X > Less) Then
                X = Math.Pow(X, 3)
            Else
                X = ((X - 16.0 / 116.0) / 7.787)
            End If
            If (Y > Less) Then
                Y = Math.Pow(Y, 3)
            Else
                Y = ((Y - 16.0 / 116.0) / 7.787)
            End If
            If (Z > Less) Then
                Z = Math.Pow(Z, 3)
            Else
                Z = ((Z - 16.0 / 116.0) / 7.787)
            End If
    
            Return New XYZ(X * 100, Y * 100, Z * 100)
        End Function
    
        Private Function XYZToRGB(XYZ As XYZ) As Color
            Dim R, G, B As New Double
            Dim X, Y, Z As New Double
    
            X = (XYZ.X / 100)
            Y = (XYZ.Y / 100)
            Z = (XYZ.Z / 100)
    
            R = ((X * 3.2406) + (Y * -1.5372) + (Z * -0.4986))
            G = ((X * -0.9689) + (Y * 1.8758) + (Z * 0.0415))
            B = ((X * 0.0557) + (Y * -0.204) + (Z * 1.057))
    
            Dim Less As Double = 0.0031308
    
            If (R > Less) Then
                R = ((1.055 * Math.Pow(R, (1.0 / 2.4))) - 0.055)
            Else
                R = (R * 12.92)
            End If
            If (G > Less) Then
                G = ((1.055 * Math.Pow(G, (1.0 / 2.4))) - 0.055)
            Else
                G = (G * 12.92)
            End If
            If (B > Less) Then
                B = ((1.055 * Math.Pow(B, (1.0 / 2.4))) - 0.055)
            Else
                B = (B * 12.92)
            End If
    
            Return New Color(CSng(R), CSng(G), CSng(B))
        End Function
    
        Private Function RGBToXYZ(Color As Color) As XYZ
            Dim RGB = ColorToRGB(Color)
            Dim X, Y, Z As New Double
            Dim R, G, B As New Double
            Dim Less As Double = 0.04045
    
            If (RGB.R > Less) Then
                r = Math.Pow(((RGB.R + 0.055) / 1.055), 2.4)
            Else
                R = (RGB.R / 12.92)
            End If
            If (RGB.G > Less) Then
                G = Math.Pow(((RGB.G + 0.055) / 1.055), 2.4)
            Else
                G = (RGB.G / 12.92)
            End If
            If (RGB.B > Less) Then
                B = Math.Pow(((RGB.B + 0.055) / 1.055), 2.4)
            Else
                B = (RGB.B / 12.92)
            End If
    
            R *= 100
            G *= 100
            B *= 100
    
            X = ((R * 0.4124) + (G * 0.3576) + (B * 0.1805))
            Y = ((R * 0.2126) + (G * 0.7152) + (B * 0.0722))
            Z = ((R * 0.0193) + (G * 0.1192) + (B * 0.9505))
    
            Return New XYZ(X, Y, Z)
        End Function
    
        Private Function XYZToLAB(XYZ As XYZ) As LAB
            Dim X, Y, Z As New Double
            Dim L, A, B As New Double
            Dim Less As Double = 0.008856
    
            X = XYZ.X / 100
            Y = XYZ.Y / 100
            Z = XYZ.Z / 100
    
            If (X > Less) Then
                X = Math.Pow(X, (1.0 / 3.0))
            Else
                X = ((7.787 * X) + (16.0 / 116.0))
            End If
            If (Y > Less) Then
                Y = Math.Pow(Y, (1.0 / 3.0))
            Else
                Y = ((7.787 * Y) + (16.0 / 116.0))
            End If
            If (Z > Less) Then
                Z = Math.Pow(Z, (1.0 / 3.0))
            Else
                Z = ((7.787 * Z) + (16.0 / 116.0))
            End If
    
            L = ((116.0 * Y) - 16.0)
            A = (500.0 * (X - Y))
            B = (200.0 * (Y - Z))
    
            Return New LAB(L, A, B)
        End Function
    

    更新2: 进一步测试显示XNA.Framework.Color中出现异常不受欢迎的行为,导致任何分数被解释为%。 这意味着200.10将超过最大颜色值(255)的200%,这会将其限制在最大值(255),因此除非您指定整数,否则最终会得到非常错误的输出。

    我试图使代码from this example as well不匹配。我觉得我正在进步,即使我不得不在转换中使用XNA.Framework.Color类。

    如果找到最终解决方案,我会更新。

    更新3: 在线测试here (source code here)here表明我的LABToXYZ不正确。

    我的结果:

    • Lab _ 100:0:0
    • XYZ _ 95.047:100:100

    他们的结果:

    • Lab _ 100:0:0
    • XYZ _ 95.05:100:108.88

      Public Function LABtoXYZ(LAB As LAB) As XYZ
          Dim X, Y, Z As Double
          Y = ((LAB.L + 16.0) / 116.0)
          X = ((LAB.A / 500.0) + Y)
          Z = (Y - (LAB.B / 200.0))
      
          Dim Pow_X = Math.Pow(X, 3.0)
          Dim Pow_Y = Math.Pow(Y, 3.0)
          Dim Pow_Z = Math.Pow(Z, 3.0)
      
          Dim Less = 216 / 24389
      
          If (Pow_X > Less) Then
              X = Pow_X
          Else
              X = ((X - (16.0 / 116.0)) / 7.787)
          End If
          If (Pow_Y > Less) Then
              Y = Pow_Y
          Else
              Y = ((Y - (16.0 / 116.0)) / 7.787)
          End If
          If (Pow_Z > Less) Then
              Z = Pow_Z
          Else
              Z = ((Z - (16.0 / 116.0)) / 7.787)
          End If
      
          Return New XYZ((X * 95.047), (Y * 100.0), (Z * 108.883))
      End Function
      

    但是使用全0来执行LAB会产生一个全0的XYZ,这是正确的行为,我无法分辨出错误,它的Z是不正确的但是在哪里是我的代码中的错误?

    更多示例here似乎表明我的代码是正确的,但我仍然得到错误的Z.

    更新4: 进一步完善和重新修改所有代码,我发现转换和发现here的示例的适应性,给了我想要的结果,即使这些例子中有一些错误,值得注意^ 2.2应该是^ 2.4。

    我还发现了一些精确的问题,必须将双精度转换成整数才能完美转换,但这可能是最后的更新,除非我遇到任何问题,我会暂时搁置这个问题。我继续在实践中测试代码。 当我确信代码没有缺陷时,我会回来并将其标记为已回答。

    示例: 测试1

    • LAB _ 1:0:0
    • XYZ _ 0.105222895807779:0.110706172533356:0.120540201839494
    • RGB _ 4:4:4:255
    • XYZ _ 0.115400959145268:0.121410793419535:0.132216354033874
    • LAB _ 1:0:0

    测试2

    • LAB _ 10:0:0
    • XYZ _ 1.07024816003116:1.12601992701628:1.22604427713313
    • RGB _ 27:27:27:255
    • XYZ _ 1.04175693531671:1.09600940064882:1.19355423730657
    • LAB _ 10:0:0

    测试3

    • LAB _ 100:0:0
    • XYZ _ 95.047:100:108.883
    • RGB _ 255:255:255:255
    • XYZ _ 95.05:100:108.9
    • LAB _ 100:0:0

    测试4

    • LAB _ 11:0:0
    • XYZ _ 1.19854884694432:1.26100649883144:1.37302170612264
    • RGB _ 29:29:29:255
    • XYZ _ 1.16783071832485:1.22864883569159:1.33799858206814
    • LAB _ 11:0:0

    如上所示,如果不是圆形的话会有一个微小的变化,会导致不完美的转换。

    课程

      Public Class RGB
            Public ReadOnly Min As Double = 0.0
            Public ReadOnly Max As Double = 255.0
    
            Public Sub New()
            End Sub
    
            Public Sub New(R As Integer, G As Integer, B As Integer)
                Me.R = R
                Me.G = G
                Me.B = B
            End Sub
    
            Public Sub New(R As Integer, G As Integer, B As Integer, A As Integer)
                Me.R = R
                Me.G = G
                Me.B = B
                Me.A = A
            End Sub
            Public Sub New(R As Double, G As Double, B As Double, A As Double)
                Me.R = Convert.ToInt32(R)
                Me.G = Convert.ToInt32(G)
                Me.B = Convert.ToInt32(B)
                Me.A = Convert.ToInt32(A)
            End Sub
            Public Sub New(R As Double, G As Double, B As Double)
                Me.R = Convert.ToInt32(R * 255)
                Me.G = Convert.ToInt32(G * 255)
                Me.B = Convert.ToInt32(B * 255)
            End Sub
            Public Sub New(Color As Color)
                Me.R = Convert.ToInt32(Color.R)
                Me.G = Convert.ToInt32(Color.G)
                Me.B = Convert.ToInt32(Color.B)
                Me.A = Convert.ToInt32(Color.A)
            End Sub
    
            Private _R As New Double
            Private _G As New Double
            Private _B As New Double
            Private _A As Double = 255
    
            Public Property R As Double
                Get
                    Return _R
                End Get
                Set
                    _R = LimitInRange(Value, Min, Max)
                End Set
            End Property
    
            Public Property G As Double
                Get
                    Return _G
                End Get
                Set
                    _G = LimitInRange(Value, Min, Max)
                End Set
            End Property
    
            Public Property B As Double
                Get
                    Return _B
                End Get
                Set
                    _B = LimitInRange(Value, Min, Max)
                End Set
            End Property
    
            Public Property A As Double
                Get
                    Return _A
                End Get
                Set
                    _A = LimitInRange(Value, Min, Max)
                End Set
            End Property
    
            Overrides Function ToString() As String
                Return (_R.ToString & ":"c & _G.ToString & ":"c & _B.ToString & ":"c & _A.ToString)
            End Function
    
            Public Shared Operator =(Left As RGB, Right As RGB) As Boolean
                If ((Left.R = Right.R) AndAlso (Left.G = Right.G) AndAlso (Left.B = Right.B) AndAlso (Left.A = Right.A)) Then
                    Return True
                Else
                    Return False
                End If
            End Operator
    
            Public Shared Operator <>(Left As RGB, Right As RGB) As Boolean
                Return (Not (Left = Right))
            End Operator
    
        End Class
    
        Public Class XYZ
            Public ReadOnly Min As Double = 0
    
            Public Sub New()
            End Sub
    
            Public Sub New(X As Double, Y As Double, Z As Double)
                Me.X = X
                Me.Y = Y
                Me.Z = Z
            End Sub
    
            Private _X As New Double
            Private _Y As New Double
            Private _Z As New Double
    
            Public Property X As Double
                Get
                    Return _X
                End Get
                Set
                    _X = LimitInRange(Value, Min, 95.05)
                End Set
            End Property
    
            Public Property Y As Double
                Get
                    Return _Y
                End Get
                Set
                    _Y = LimitInRange(Value, Min, 100)
                End Set
            End Property
    
            Public Property Z As Double
                Get
                    Return _Z
                End Get
                Set
                    _Z = LimitInRange(Value, Min, 108.9)
                End Set
            End Property
    
            Overrides Function ToString() As String
                Return (_X.ToString & ":"c & _Y.ToString & ":"c & _Z.ToString)
            End Function
    
        End Class
    
        Public Class LAB
            Public ReadOnly Min As Double = -128
            Public ReadOnly Max As Double = 127
    
            Sub New()
            End Sub
    
            Sub New(L As Double, A As Double, B As Double)
                Me.L = L
                Me.A = A
                Me.B = B
            End Sub
    
            Private _L As New Double
            Private _A As New Double
            Private _B As New Double
    
            Property L As Double
                Get
                    Return _L
                End Get
                Set
                    _L = LimitInRange(Value, 0, 100)
                End Set
            End Property
    
            Property A As Double
                Get
                    Return _A
                End Get
                Set
                    _A = LimitInRange(Value, Min, Max)
                End Set
            End Property
    
            Property B As Double
                Get
                    Return _B
                End Get
                Set
                    _B = LimitInRange(Value, Min, Max)
                End Set
            End Property
    
            Overrides Function ToString() As String
                Return (_L.ToString & ":"c & _A.ToString & ":"c & _B.ToString)
            End Function
    
        End Class
    

    转换器

    Public Function LABtoXYZ(LAB As LAB) As XYZ
            Dim X, Y, Z As New Double
            Y = ((LAB.L + 16.0) / 116.0)
            X = ((LAB.A / 500.0) + Y)
            Z = (Y - (LAB.B / 200.0))
    
            Dim Pow_X = Math.Pow(X, 3.0)
            Dim Pow_Y = Math.Pow(Y, 3.0)
            Dim Pow_Z = Math.Pow(Z, 3.0)
    
            Dim Less = (216 / 24389)
    
            If (Pow_X > Less) Then
                X = Pow_X
            Else
                X = ((X - (16.0 / 116.0)) / 7.787)
            End If
            If (Pow_Y > Less) Then
                Y = Pow_Y
            Else
                Y = ((Y - (16.0 / 116.0)) / 7.787)
            End If
            If (Pow_Z > Less) Then
                Z = Pow_Z
            Else
                Z = ((Z - (16.0 / 116.0)) / 7.787)
            End If
    
            Return New XYZ((X * 95.047), (Y * 100.0), (Z * 108.883))
        End Function
    
        Private Function XYZToRGB(XYZ As XYZ) As RGB
            Dim X, Y, Z As New Double
            Dim R, G, B As New Double
            Dim Pow As Double = (1.0 / 2.4)
            Dim Less As Double = 0.0031308
    
            X = (XYZ.X / 100)
            Y = (XYZ.Y / 100)
            Z = (XYZ.Z / 100)
    
            R = ((X * 3.24071) + (Y * -1.53726) + (Z * -0.498571))
            G = ((X * -0.969258) + (Y * 1.87599) + (Z * 0.0415557))
            B = ((X * 0.0556352) + (Y * -0.203996) + (Z * 1.05707))
    
            If (R > Less) Then
                R = ((1.055 * Math.Pow(R, Pow)) - 0.055)
            Else
                R *= 12.92
            End If
            If (G > Less) Then
                G = ((1.055 * Math.Pow(G, Pow)) - 0.055)
            Else
                G *= 12.92
            End If
            If (B > Less) Then
                B = ((1.055 * Math.Pow(B, Pow)) - 0.055)
            Else
                B *= 12.92
            End If
    
            Return New RGB(R, G, B)
        End Function
    
        Private Function RGBToXYZ(RGB As RGB) As XYZ
            Dim X, Y, Z As New Double
            Dim R, G, B As New Double
            Dim Less As Double = 0.04045
    
            R = (RGB.R / 255)
            G = (RGB.G / 255)
            B = (RGB.B / 255)
    
            If (R > Less) Then
                R = Math.Pow(((R + 0.055) / 1.055), 2.4)
            Else
                R = (R / 12.92)
            End If
            If (G > Less) Then
                G = Math.Pow(((G + 0.055) / 1.055), 2.4)
            Else
                G = (G / 12.92)
            End If
            If (B > Less) Then
                B = Math.Pow(((B + 0.055) / 1.055), 2.4)
            Else
                B = (B / 12.92)
            End If
    
            X = ((R * 0.4124) + (G * 0.3576) + (B * 0.1805))
            Y = ((R * 0.2126) + (G * 0.7152) + (B * 0.0722))
            Z = ((R * 0.0193) + (G * 0.1192) + (B * 0.9505))
    
            Return New XYZ(X * 100, Y * 100, Z * 100)
        End Function
    
        Private Function XYZToLAB(XYZ As XYZ) As LAB
            Dim X, Y, Z As New Double
            Dim L, A, B As New Double
            Dim Less As Double = 0.008856
            Dim Pow As Double = (1.0 / 3.0)
    
            X = ((XYZ.X / 100) / 0.9505)
            Y = (XYZ.Y / 100)
            Z = ((XYZ.Z / 100) / 1.089)
    
            If (X > Less) Then
                X = Math.Pow(X, Pow)
            Else
                X = ((7.787 * X) + (16.0 / 116.0))
            End If
            If (Y > Less) Then
                Y = Math.Pow(Y, Pow)
            Else
                Y = ((7.787 * Y) + (16.0 / 116.0))
            End If
            If (Z > Less) Then
                Z = Math.Pow(Z, Pow)
            Else
                Z = ((7.787 * Z) + (16.0 / 116.0))
            End If
    
            L = ((116.0 * Y) - 16.0)
            A = (500.0 * (X - Y))
            B = (200.0 * (Y - Z))
    
            'We solve the precision problem by rounding to nearest integer
            'This makes the conversion perfect.
            Return New LAB(CInt(L), CInt(A), CInt(B))
        End Function
    

    在我将此标记为已解决之前,需要进一步测试。

    更新5:到目前为止,Haven还没有任何问题......当只有问题发布时,我不知道如何将其标记为已回答。 可以找到完整的免费代码here

0 个答案:

没有答案