Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
Solved

# Color Conversion Formula Math

Posted on 2007-03-29
Medium Priority
997 Views
I have some color information (RGB values) that I need to convert.  Based on the formulas provided by EasyRGB (www.easyrgb.com), there are some non-language-specific code examples provided that I am trying to convert to VBScript.  I am taking the RGB values, and converting them to XYZ values, and then to CIE-L*ab values.

My conversion from RGB to XYZ seems to be working correctly (based on some calculated checks provided by the EasyRGB website), but it goes wrong when moving from XYZ to CIE-L*ab.  Here is the sample code that I am working from:

**************************************
var_X = X / ref_X          //ref_X =  95.047  Observer= 2°, Illuminant= D65
var_Y = Y / ref_Y          //ref_Y = 100.000
var_Z = Z / ref_Z          //ref_Z = 108.883

if ( var_X > 0.008856 ) var_X = var_X ^ ( 1/3 )
else                    var_X = ( 7.787 * var_X ) + ( 16 / 116 )
if ( var_Y > 0.008856 ) var_Y = var_Y ^ ( 1/3 )
else                    var_Y = ( 7.787 * var_Y ) + ( 16 / 116 )
if ( var_Z > 0.008856 ) var_Z = var_Z ^ ( 1/3 )
else                    var_Z = ( 7.787 * var_Z ) + ( 16 / 116 )

CIE-L* = ( 116 * var_Y ) - 16
CIE-a* = 500 * ( var_X - var_Y )
CIE-b* = 200 * ( var_Y - var_Z )
**************************************
Here's my VBScript-translated code:

'XYZ -> CIE-L*ab
'Observer = 2 degrees, Iluminant = D65

varRefX = 95.047
varRefY = 100
varRefZ = 108.883

varX = varOutX / varRefX
varY = varOutY / varRefY
varZ = varOutZ / varRefZ

If (varX > 0.008856) Then
varX = varX ^ (1 / 3)
Else
varX = (7.787 * varX) + (16 / 116)
End If

If (varY > 0.008856) Then
varY = varY ^ (1 / 3)
Else
varY = (7.787 * varY) + (16 / 116)
End If

If (varZ > 0.008856) Then
varZ = varZ ^ (1 / 3)
Else
varZ = (7.787 * varZ) + (16 / 116)
End If

varOutL = (116 * varY) - 16
varOuta = 500 * (varX - varY)
varOutb = 200 * (varY - varZ)
**************************************
The 'var' variables refer to Variant type.

The problem seems to occur with the 'varOuta' and 'varOutb' calcs.  The resulting values seem to need to be divided by 1000, but the length of the calculated values seem to be truncated to hexidecimal.

To see the various color formulas, go to http://www.easyrgb.com/math.html.

I am using Access 2007, Win XP Pro.

Thanks!
0
Question by:Donovan Moore
[X]
###### Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

• Help others & share knowledge
• Earn cash & points
• 3
• 2

Author Comment

ID: 18817779
For anyone who needs them, here are the test values I'm using to check the results (substitute "real" numbers for the variables):

varOutX = 1.23403722412354
varOutY = 1.2983032342173
varOutZ = 1.41385222206264

The "expected" results (rounded) should be as follows:

varOutL = 11.2636
varOuta = 0.0012
varOutb = -0.0024
0

LVL 28

Expert Comment

ID: 18818430
I created a function in Access 2003 - I converted all your Variant variables to Double data type.  The results are as you expect

Public Function TestRGB()

'XYZ -> CIE-L*ab
'Observer = 2 degrees, Iluminant = D65

Dim dblRefX As Double, dblRefY As Double, dblRefZ As Double
Dim dblOutX As Double, dblOutY As Double, dblOutZ As Double
Dim dblX As Double, dblY As Double, dblZ As Double
Dim dblOutL As Double, dblOuta As Double, dblOutb As Double

dblRefX = 95.047
dblRefY = 100
dblRefZ = 108.883

dblOutX = 1.23403722412354
dblOutY = 1.2983032342173
dblOutZ = 1.41385222206264

dblX = dblOutX / dblRefX
dblY = dblOutY / dblRefY
dblZ = dblOutZ / dblRefZ

If (dblX > 0.008856) Then
dblX = dblX ^ (1 / 3)
Else
dblX = (7.787 * dblX) + (16 / 116)
End If

If (dblY > 0.008856) Then
dblY = dblY ^ (1 / 3)
Else
dblY = (7.787 * dblY) + (16 / 116)
End If

If (dblZ > 0.008856) Then
dblZ = dblZ ^ (1 / 3)
Else
dblZ = (7.787 * dblZ) + (16 / 116)
End If

dblOutL = (116 * dblY) - 16
dblOuta = 500 * (dblX - dblY)
dblOutb = 200 * (dblY - dblZ)

Debug.Print dblX & " -- " & dblOutL
Debug.Print dblY & " -- " & dblOuta
Debug.Print dblZ & " -- " & dblOutb

End Function

Output
0.235033597912027 -- 11.2636105173512
0.235031125149579 -- 1.23638122394298E-03   <----(this is 0.0012363 etc.)
0.235043356386178 -- -2.44624731974841E-03  <----(this is -0.0024462 etc.)

OM Gang
0

Author Comment

ID: 18819266
Excuse my ignorance, but how do I convert the '1.23638122394298E-03 ' and '-2.44624731974841E-03' values into the correct values?
0

LVL 28

Accepted Solution

omgang earned 2000 total points
ID: 18819368
Use the Round function to round the output to the desired number of decimal places.
OM Gang

Public Function TestRGB()

'XYZ -> CIE-L*ab
'Observer = 2 degrees, Iluminant = D65

Dim dblRefX As Double, dblRefY As Double, dblRefZ As Double
Dim dblOutX As Double, dblOutY As Double, dblOutZ As Double
Dim dblX As Double, dblY As Double, dblZ As Double
Dim dblOutL As Double, dblOuta As Double, dblOutb As Double

dblRefX = 95.047
dblRefY = 100
dblRefZ = 108.883

dblOutX = 1.23403722412354
dblOutY = 1.2983032342173
dblOutZ = 1.41385222206264

dblX = dblOutX / dblRefX
dblY = dblOutY / dblRefY
dblZ = dblOutZ / dblRefZ

If (dblX > 0.008856) Then
dblX = dblX ^ (1 / 3)
Else
dblX = (7.787 * dblX) + (16 / 116)
End If

If (dblY > 0.008856) Then
dblY = dblY ^ (1 / 3)
Else
dblY = (7.787 * dblY) + (16 / 116)
End If

If (dblZ > 0.008856) Then
dblZ = dblZ ^ (1 / 3)
Else
dblZ = (7.787 * dblZ) + (16 / 116)
End If

dblOutL = (116 * dblY) - 16
dblOuta = 500 * (dblX - dblY)
dblOutb = 200 * (dblY - dblZ)

Debug.Print dblX & " -- " & dblOutL & " -- " & Round(dblOutL, 4)
Debug.Print dblY & " -- " & dblOuta & " -- " & Round(dblOuta, 4)
Debug.Print dblZ & " -- " & dblOutb & " -- " & Round(dblOutb, 4)

End Function

Output
0.235033597912027 -- 11.2636105173512 -- 11.2636
0.235031125149579 -- 1.23638122394298E-03 -- 0.0012
0.235043356386178 -- -2.44624731974841E-03 -- -0.0024
0

Author Comment

ID: 18819503
Thank you!
0

## Featured Post

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article describes a method of delivering Word templates for use in merging Access data to Word documents, that requires no computer knowledge on the part of the recipient -- the templates are saved in table fields, and are extracted and install…
This article shows how to get a list of available printers for display in a drop-down list, and then to use the selected printer to print an Access report or a Word document filled with Access data, using different syntax as needed for working with …
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…
In Microsoft Access, learn how to “cascade” or have the displayed data of one combo control depend upon what’s entered in another. Base the dependent combo on a query for its row source: Add a reference to the first combo on the form as criteria i…
###### Suggested Courses
Course of the Month6 days, 21 hours left to enroll