Hi Guys, i created a function able to transform from one illuminant model to another. You can use this function to convert between D65 to F12, A Observer2º degree to C observer10º, using whatever method you want such as: Bradford, Bianco, Von Kries, Estevez, Sharp, CAT02 etc etc.
This is usefull when convertng a RGB pixel to CieLab, XYZ or CieLCH colorspaces and you want to change between the difference illuminance references on the image. Currently, the function supports 40 different illuminant models with 18 different methods to be used.
So, you maybe able to transform/adapt 720 different ways a given colorspace matrix. For example, if you are converting RGB to CieLab using the D65 tristimulus matrix (D65 observer 2º):
[0.4124564, 0.3575761, 0.1804375
0.2126729, 0.7151522, 0.0721750
0.0193339, 0.1191920, 0.9503041]
It means that with GetChromaticAdaptationMatrix you can create 720 new matrixes derived from the D65 one ;)
The current function only generates the necessary matrix to perform those kind of convertions, and not the convertion of the tristimulus itself. To convert the tristimulus directly i´ll later try to create another function.
The text i used is kind big for the post, so i attached the full file containing the complete function and data used.
Basically the function looks like this:
Proc GetChromaticAdaptationMatrix:
Arguments @pOutMatrix, @WhiteRefFrom, @WhiteRefTo, @Method
Local @pCurMatrixFrom
Structure @Reference 264, @pRefXFromDis 0, @pRefYFromDis 8, @pRefZFromDis 16, @pRefXtoDis 24, @pRefYtoDis 32, @pRefZtoDis 40, @XScaledDis 48, @YScaledDis 56, @ZScaledDis 64,
@SigmaFromDis 72, @SigmaToDis 96, @TmpInvertedMatrixDis 120, @TmpScaledMatrixDis 192
Uses ebx, ecx, edx, edi
finit
mov eax 0-2
On D@Method > ADAPT_LIE, ExitP
; The very 1st thing to do is get the actual pointer to the inputed matrix and calculate its ínverse. If matrix is invertible we can continue
mov ebx D@Method | imul ebx Size_Of_FloatMatrices | add ebx FloatXYZAdaptMatrices | mov D@pCurMatrixFrom ebx
; get the inverted matrix from where you want to compute from
lea ebx D@TmpInvertedMatrixDis
call InvertMatrix_3x3_Double D@pCurMatrixFrom, ebx
If eax = 0 ; Squared Matrix is not inversible, exit
mov eax 0-1 ; Put the proper error value on return
ExitP
End_If
; 2nd - Get the white references to we compute the fraction after dividing the RefFrom to RefTo
lea edx D@pRefZFromDis
lea ebx D@pRefYFromDis
lea eax D@pRefXFromDis
call FindWhiteRefEx eax, ebx, edx, D@WhiteRefFrom
On eax = 0, ExitP ; the inputed illumination modle does not exists
lea edx D@pRefZtoDis
lea ebx D@pRefYtoDis
lea eax D@pRefXtoDis
call FindWhiteRefEx eax, ebx, edx, D@WhiteRefto
On eax = 0, ExitP ; the inputed illumination modle does not exists
; 3rd = Multiply [Matrix3x3] [3x1]. So, multiply matrix calculated from input with the referece (From and To)
; [Matrix3x1] is simply the references of white displayed on a 3x1 vertex as [X, Y, Z] (vertical order: X top, Z bottom)
mov ebx D@pCurMatrixFrom
lea edi D@SigmaFromDis
fld R$ebx+FloatMatrices.M1Dis | fmul R@pRefXFromDis | fld R$ebx+FloatMatrices.M2Dis | fmul R@pRefYFromDis | faddp ST1 ST0 | fld R$ebx+FloatMatrices.M3Dis | fmul R@pRefZFromDis | faddp ST1 ST0 | fstp R$edi+FloatMatrices.M1Dis
fld R$ebx+FloatMatrices.M4Dis | fmul R@pRefXFromDis | fld R$ebx+FloatMatrices.M5Dis | fmul R@pRefYFromDis | faddp ST1 ST0 | fld R$ebx+FloatMatrices.M6Dis | fmul R@pRefZFromDis | faddp ST1 ST0 | fstp R$edi+FloatMatrices.M2Dis
fld R$ebx+FloatMatrices.M7Dis | fmul R@pRefXFromDis | fld R$ebx+FloatMatrices.M8Dis | fmul R@pRefYFromDis | faddp ST1 ST0 | fld R$ebx+FloatMatrices.M9Dis | fmul R@pRefZFromDis | faddp ST1 ST0 | fstp R$edi+FloatMatrices.M3Dis
; do the same with Refto
lea edi D@SigmaToDis
fld R$ebx+FloatMatrices.M1Dis | fmul R@pRefXtoDis | fld R$ebx+FloatMatrices.M2Dis | fmul R@pRefYtoDis | faddp ST1 ST0 | fld R$ebx+FloatMatrices.M3Dis | fmul R@pRefZtoDis | faddp ST1 ST0 | fstp R$edi+FloatMatrices.M1Dis
fld R$ebx+FloatMatrices.M4Dis | fmul R@pRefXtoDis | fld R$ebx+FloatMatrices.M5Dis | fmul R@pRefYtoDis | faddp ST1 ST0 | fld R$ebx+FloatMatrices.M6Dis | fmul R@pRefZtoDis | faddp ST1 ST0 | fstp R$edi+FloatMatrices.M2Dis
fld R$ebx+FloatMatrices.M7Dis | fmul R@pRefXtoDis | fld R$ebx+FloatMatrices.M8Dis | fmul R@pRefYtoDis | faddp ST1 ST0 | fld R$ebx+FloatMatrices.M9Dis | fmul R@pRefZtoDis | faddp ST1 ST0 | fstp R$edi+FloatMatrices.M3Dis
; divide the generated results from XRefto with XRefFrom to we get a fraction. So, Scaled=Refto/RefFrom
lea eax D@SigmaFromDis
fld R$edi+FloatMatrices.M1Dis | fdiv R$eax+FloatMatrices.M1Dis | fstp R@XScaledDis
fld R$edi+FloatMatrices.M2Dis | fdiv R$eax+FloatMatrices.M2Dis | fstp R@YScaledDis
fld R$edi+FloatMatrices.M3Dis | fdiv R$eax+FloatMatrices.M3Dis | fstp R@ZScaledDis
; 4th put the generated Scaled Fractions on a matrix on the form of:
; XScaled, 0 0
; 0 YScaled 0
; 0 0 ZScaled
; and multiply the inverted matrix achieved on input with the new 3x3 caled filled with zeroes like that.
;;
lea ebx D@TmpInvertedMatrixDis
lea edi D@TmpScaledMatrixDis
fld R$ebx+FloatMatrices.M1Dis | fmul R@XScaledDis | fld R$ebx+FloatMatrices.M2Dis | fmul R$FloatZero | faddp ST1 ST0 | fld R$ebx+FloatMatrices.M3Dis | fmul R$FloatZero | faddp ST1 ST0 | fstp R$edi+FloatMatrices.M1Dis
fld R$ebx+FloatMatrices.M1Dis | fmul R$FloatZero | fld R$ebx+FloatMatrices.M2Dis | fmul R@YScaledDis | faddp ST1 ST0 | fld R$ebx+FloatMatrices.M3Dis | fmul R$FloatZero | faddp ST1 ST0 | fstp R$edi+FloatMatrices.M2Dis
fld R$ebx+FloatMatrices.M1Dis | fmul R$FloatZero | fld R$ebx+FloatMatrices.M2Dis | fmul R$FloatZero | faddp ST1 ST0 | fld R$ebx+FloatMatrices.M3Dis | fmul R@ZScaledDis | faddp ST1 ST0 | fstp R$edi+FloatMatrices.M3Dis
fld R$ebx+FloatMatrices.M4Dis | fmul R@XScaledDis | fld R$ebx+FloatMatrices.M5Dis | fmul R$FloatZero | faddp ST1 ST0 | fld R$ebx+FloatMatrices.M6Dis | fmul R$FloatZero | faddp ST1 ST0 | fstp R$edi+FloatMatrices.M4Dis
fld R$ebx+FloatMatrices.M4Dis | fmul R$FloatZero | fld R$ebx+FloatMatrices.M5Dis | fmul R@YScaledDis | faddp ST1 ST0 | fld R$ebx+FloatMatrices.M6Dis | fmul R$FloatZero | faddp ST1 ST0 | fstp R$edi+FloatMatrices.M5Dis
fld R$ebx+FloatMatrices.M4Dis | fmul R$FloatZero | fld R$ebx+FloatMatrices.M5Dis | fmul R$FloatZero | faddp ST1 ST0 | fld R$ebx+FloatMatrices.M6Dis | fmul R@ZScaledDis | faddp ST1 ST0 | fstp R$edi+FloatMatrices.M6Dis
fld R$ebx+FloatMatrices.M7Dis | fmul R@XScaledDis | fld R$ebx+FloatMatrices.M8Dis | fmul R$FloatZero | faddp ST1 ST0 | fld R$ebx+FloatMatrices.M9Dis | fmul R$FloatZero | faddp ST1 ST0 | fstp R$edi+FloatMatrices.M7Dis
fld R$ebx+FloatMatrices.M7Dis | fmul R$FloatZero | fld R$ebx+FloatMatrices.M8Dis | fmul R@YScaledDis | faddp ST1 ST0 | fld R$ebx+FloatMatrices.M9Dis | fmul R$FloatZero | faddp ST1 ST0 | fstp R$edi+FloatMatrices.M8Dis
fld R$ebx+FloatMatrices.M7Dis | fmul R$FloatZero | fld R$ebx+FloatMatrices.M8Dis | fmul R$FloatZero | faddp ST1 ST0 | fld R$ebx+FloatMatrices.M9Dis | fmul R@ZScaledDis | faddp ST1 ST0 | fstp R$edi+FloatMatrices.M9Dis
;;
; Since we are multiplying with zeroes we can make it faster, avoiding the zero multplications after all X*0 = 0. So the commented multplication above results on this 3x3 matrix:
lea ebx D@TmpInvertedMatrixDis
lea edi D@TmpScaledMatrixDis
fld R$ebx+FloatMatrices.M1Dis | fmul R@XScaledDis | fstp R$edi+FloatMatrices.M1Dis
fld R$ebx+FloatMatrices.M2Dis | fmul R@YScaledDis | fstp R$edi+FloatMatrices.M2Dis
fld R$ebx+FloatMatrices.M3Dis | fmul R@ZScaledDis | fstp R$edi+FloatMatrices.M3Dis
fld R$ebx+FloatMatrices.M4Dis | fmul R@XScaledDis | fstp R$edi+FloatMatrices.M4Dis
fld R$ebx+FloatMatrices.M5Dis | fmul R@YScaledDis | fstp R$edi+FloatMatrices.M5Dis
fld R$ebx+FloatMatrices.M6Dis | fmul R@ZScaledDis | fstp R$edi+FloatMatrices.M6Dis
fld R$ebx+FloatMatrices.M7Dis | fmul R@XScaledDis | fstp R$edi+FloatMatrices.M7Dis
fld R$ebx+FloatMatrices.M8Dis | fmul R@YScaledDis | fstp R$edi+FloatMatrices.M8Dis
fld R$ebx+FloatMatrices.M9Dis | fmul R@ZScaledDis | fstp R$edi+FloatMatrices.M9Dis
; 4th. Finally we can simply multiply the resultant inverted 3x3 matrix above with the one achieved from input
mov ebx D@pCurMatrixFrom
mov edx D@pOutMatrix
fld R$edi+FloatMatrices.M1Dis | fmul R$ebx+FloatMatrices.M1Dis | fld R$edi+FloatMatrices.M2Dis | fmul R$ebx+FloatMatrices.M4Dis | faddp ST1 ST0 | fld R$edi+FloatMatrices.M3Dis | fmul R$ebx+FloatMatrices.M7Dis | faddp ST1 ST0 | fstp R$edx+FloatMatrices.M1Dis
fld R$edi+FloatMatrices.M1Dis | fmul R$ebx+FloatMatrices.M2Dis | fld R$edi+FloatMatrices.M2Dis | fmul R$ebx+FloatMatrices.M5Dis | faddp ST1 ST0 | fld R$edi+FloatMatrices.M3Dis | fmul R$ebx+FloatMatrices.M8Dis | faddp ST1 ST0 | fstp R$edx+FloatMatrices.M2Dis
fld R$edi+FloatMatrices.M1Dis | fmul R$ebx+FloatMatrices.M3Dis | fld R$edi+FloatMatrices.M2Dis | fmul R$ebx+FloatMatrices.M6Dis | faddp ST1 ST0 | fld R$edi+FloatMatrices.M3Dis | fmul R$ebx+FloatMatrices.M9Dis | faddp ST1 ST0 | fstp R$edx+FloatMatrices.M3Dis
fld R$edi+FloatMatrices.M4Dis | fmul R$ebx+FloatMatrices.M1Dis | fld R$edi+FloatMatrices.M5Dis | fmul R$ebx+FloatMatrices.M4Dis | faddp ST1 ST0 | fld R$edi+FloatMatrices.M6Dis | fmul R$ebx+FloatMatrices.M7Dis | faddp ST1 ST0 | fstp R$edx+FloatMatrices.M4Dis
fld R$edi+FloatMatrices.M4Dis | fmul R$ebx+FloatMatrices.M2Dis | fld R$edi+FloatMatrices.M5Dis | fmul R$ebx+FloatMatrices.M5Dis | faddp ST1 ST0 | fld R$edi+FloatMatrices.M6Dis | fmul R$ebx+FloatMatrices.M8Dis | faddp ST1 ST0 | fstp R$edx+FloatMatrices.M5Dis
fld R$edi+FloatMatrices.M4Dis | fmul R$ebx+FloatMatrices.M3Dis | fld R$edi+FloatMatrices.M5Dis | fmul R$ebx+FloatMatrices.M6Dis | faddp ST1 ST0 | fld R$edi+FloatMatrices.M6Dis | fmul R$ebx+FloatMatrices.M9Dis | faddp ST1 ST0 | fstp R$edx+FloatMatrices.M6Dis
fld R$edi+FloatMatrices.M7Dis | fmul R$ebx+FloatMatrices.M1Dis | fld R$edi+FloatMatrices.M8Dis | fmul R$ebx+FloatMatrices.M4Dis | faddp ST1 ST0 | fld R$edi+FloatMatrices.M9Dis | fmul R$ebx+FloatMatrices.M7Dis | faddp ST1 ST0 | fstp R$edx+FloatMatrices.M7Dis
fld R$edi+FloatMatrices.M7Dis | fmul R$ebx+FloatMatrices.M2Dis | fld R$edi+FloatMatrices.M8Dis | fmul R$ebx+FloatMatrices.M5Dis | faddp ST1 ST0 | fld R$edi+FloatMatrices.M9Dis | fmul R$ebx+FloatMatrices.M8Dis | faddp ST1 ST0 | fstp R$edx+FloatMatrices.M8Dis
fld R$edi+FloatMatrices.M7Dis | fmul R$ebx+FloatMatrices.M3Dis | fld R$edi+FloatMatrices.M8Dis | fmul R$ebx+FloatMatrices.M6Dis | faddp ST1 ST0 | fld R$edi+FloatMatrices.M9Dis | fmul R$ebx+FloatMatrices.M9Dis | faddp ST1 ST0 | fstp R$edx+FloatMatrices.M9Dis
mov eax &TRUE
EndP