# The MASM Forum

## Miscellaneous => The Orphanage => Topic started by: guga on January 21, 2019, 09:00:28 AM

Post by: guga on January 21, 2019, 09:00:28 AM
Hi Guys

I´m trying to create a app to convert the different iluminants models but i´m failing to undersdtand the math on this.

Accordlying to http://brucelindbloom.com/index.html?Eqn_ChromAdapt.html, the convertion method from XYZ Scaling, Bradford and Von Kries is :

Method    [MA]
XYZ Scaling

1.0000000  0.0000000  0.0000000
0.0000000  1.0000000  0.0000000
0.0000000  0.0000000  1.0000000

0.8951000  0.2664000 -0.1614000
-0.7502000  1.7135000  0.0367000
0.0389000 -0.0685000  1.0296000

Von Kries

0.4002400  0.7076000 -0.0808100
-0.2263000  1.1653200  0.0457000
0.0000000  0.0000000  0.9182200

Followed by the inverted matrices
____________________________________________________________

And the illuminants are given by:

Illuminant    X    Y    Z
A    1.09850    1.00000    0.35585
B    0.99072    1.00000    0.85223
C    0.98074    1.00000    1.18232
D50    0.96422    1.00000    0.82521
D55    0.95682    1.00000    0.92149
D65    0.95047    1.00000    1.08883
D75    0.94972    1.00000    1.22638
E    1.00000    1.00000    1.00000
F2    0.99186    1.00000    0.67393
F7    0.95041    1.00000    1.08747
F11    1.00962    1.00000    0.64350

____________________________________________________________

From the site, the convertion from Illuminat A to B using XYZ Scaling is (From the direct matrix and not the inverted one):

0.9018844  0.0000000  0.0000000
0.0000000  1.0000000  0.0000000
0.0000000  0.0000000  2.3949136

So, the 1st element 0.901884 was achieved from: 0.99072/1.09850 ?

But, on Bradfor, how did it achieved the value of ?

0.8905163 -0.0829136  0.2680945
-0.0971524  1.0754262  0.0879463
0.0538970 -0.0908558  2.4838553
Post by: guga on January 22, 2019, 02:24:17 AM
Ok, guys. I suceeded to make it work. and shows the exact same result :)

I was forgetting to multiply the inverted  matrix for each array of 3x1.

The steps are these:

1) Multiply the matrix Bradford (3x3) with the 3x1 matrix related to the white refereces from source and destionation (destination is the colorspace you want to convert to). Like:

From Source we have:

Code: [Select]
`Illuminant X Y ZA 1.09850 1.00000 0.35585`
Code: [Select]
`Bradford: 0.8951000  0.2664000 -0.1614000-0.7502000  1.7135000  0.0367000 0.0389000 -0.0685000  1.0296000`
So... Bradford *  Source = [0.8951, 0.2664, -0.1614, -0.7502......] * [1.09850, 1, 0.35585]

Then do the same for the destination:

Code: [Select]
`Illuminant X Y ZB 0.99072 1.00000 0.85223`
Code: [Select]
`Bradford: 0.8951000  0.2664000 -0.1614000-0.7502000  1.7135000  0.0367000 0.0389000 -0.0685000  1.0296000`
So... Bradford *  Destination = [0.8951, 0.2664, -0.1614, -0.7502......] * [0.99072, 1.00000, 0.85223]

2) Put the resultant valuues of source and destination on a matrix 3x3 dividing destination from source, like:

Scaled = Destination/Source

Ex:
Destination = 0.5, 0.6, 0.3
Source = 0.9, 0.8, 0.7

Scaled = 0.5/0.9, 0.6/0.8, 0.3/0.7

Put the results on a matrix to become like this:

Code: [Select]
`MatrixNew = (0.5/0.9)   0                  00              (0.6/0.8)       00              0                  (0.3/0.7)`
3) Multiply the inverted matrix of Bradford to the new Matrix and the resultant matrix multiply by the normal Bradford matrix. Like:

The Inverted Bradford matrix is already given in the site, but i´ll later create a routine to compute it better, since the values on the site ar not accurated. So:

0.9869929 -0.1470543  0.1599627
0.4323053  0.5183603  0.0492912
-0.0085287  0.0400428  0.9684867

Code: [Select]
`MatrixNew2 = | 0.9869929 -0.1470543  0.1599627 |          | (0.5/0.9)    0                  0         || 0.4323053  0.5183603  0.0492912 |     *    | 0             (0.6/0.8)         0         ||-0.0085287  0.0400428  0.9684867 |          | 0              0                (0.3/0.7) |`

3a) And finally, multiply this resultant 3x3 matrix to the normal bradford. Like this:

Say, Matrixnew2 results in:

| 0.521238 -0.12567489  0.102345    |
| 0.777777  0.5183603  0.01012341  |
| -0.012554  0.156459  0.914265478 |

Then the final matrix will result from the multiplication of:

| 0.521238 -0.12567489  0.102345   |          |  0.8951000  0.2664000 -0.1614000 |
| 0.777777  0.5183603  0.01012341  |    *    |-0.7502000  1.7135000  0.0367000 |
| -0.012554  0.156459  0.914265478 |         | 0.0389000 -0.0685000  1.0296000 |

Now, i need to figure it out a way to adapt the resultant matrix to the vertex martix on a regular ColorSpaces, Ex:

Transform a D65 Observer2 Adobe Matrix

Code: [Select]
` FloatAdobe_RGB_1998_D65_Red_M1: R\$ 0.5767309  FloatAdobe_RGB_1998_D65_Green_M2: R\$ 0.185554     FloatAdobe_RGB_1998_D65_Blue_M3: R\$ 0.1881852 FloatAdobe_RGB_1998_D65_Red_M4: R\$ 0.2973769  FloatAdobe_RGB_1998_D65_Green_M5: R\$ 0.6273491    FloatAdobe_RGB_1998_D65_Blue_M6: R\$ 0.0752741 FloatAdobe_RGB_1998_D65_Red_M7: R\$ 0.0270343  FloatAdobe_RGB_1998_D65_Green_M8: R\$ 0.0706872    FloatAdobe_RGB_1998_D65_Blue_M9: R\$ 0.9911085`

Onto the new adapted matrix using those resultant values. Ex: Transforming the above values onto D50, C, A, B, D75, F, observer10 or 2 etc etc using whatever method needed (XYZ Scaling, Bradford or Von Kries). My plan is to make a huge table containing all the matrix values already adapted, rather then computing it on each time i need to use a function to convert RGB to CieLab or RGB to CieLCH etc. Making a huge table is better in terms of speed computation. So, i can make a vertex matrix for Adobe1998 on all adaptations, D50, A, B, etc etc on all methods....and also do the same for others, like; NTSC, Pal, Secam, WideGamut, sRGB, HDTV etc etc etc

If you want the function i made is this. (Not optimized. Written for RosAsm syntax)

Code: [Select]
`;;; http://brucelindbloom.com/index.html?Eqn_ChromAdapt.html; Transformed values to convert from one illuminant to anotherhttp://www.easyrgb.com/en/math.phphttps://www.mathworks.com/matlabcentral/fileexchange/40640-computational-colour-science-using-matlab-2eWHITE_SPACE_A_OBS2;;[ADAPT_XYZ_SCALING 0][ADAPT_BRADFORD 1][ADAPT_VON_KRIES 2][FloatXYZAdaptMatrices: Adapt_XYZ_Scaling_Red_M1: R\$ 1.0            Adapt_XYZ_Scaling_Green_M2: R\$ 0.0               Adapt_XYZ_Scaling_Blue_M3: R\$ 0.0 Adapt_XYZ_Scaling_Red_M4: R\$ 0.0            Adapt_XYZ_Scaling_Green_M5: R\$ 1.0               Adapt_XYZ_Scaling_Blue_M6: R\$ 0.0 Adapt_XYZ_Scaling_Red_M7: R\$ 0.0            Adapt_XYZ_Scaling_Green_M8: R\$ 0.0               Adapt_XYZ_Scaling_Blue_M9: R\$ 1.0 Adapt_Bradford_Red_M1: R\$ 0.8951            Adapt_Bradford_Green_M2: R\$ 0.2664               Adapt_Bradford_Blue_M3: R\$ -0.1614 Adapt_Bradford_Red_M4: R\$ -0.7502           Adapt_Bradford_Green_M5: R\$ 1.7135               Adapt_Bradford_Blue_M6: R\$ 0.0367 Adapt_Bradford_Red_M7: R\$ 0.0389            Adapt_Bradford_Green_M8: R\$ -0.0685              Adapt_Bradford_Blue_M9: R\$ 1.0296 Adapt_Von_Kries_Red_M1: R\$ 0.40024          Adapt_Von_Kries_Green_M2: R\$ 0.7076              Adapt_Von_Kries_Blue_M3: R\$ -0.08081 Adapt_Von_Kries_Red_M4: R\$ -0.2263          Adapt_Von_Kries_Green_M5: R\$ 1.16532             Adapt_Von_Kries_Blue_M6: R\$ 0.0457 Adapt_Von_Kries_Red_M7: R\$ 0.0              Adapt_Von_Kries_Green_M8: R\$ 0.0                 Adapt_Von_Kries_Blue_M9: R\$ 0.91822][Float_XYZ_RGB_Inverted_AdaptMatrices: Adapt_Inverted_XYZScaling_Red_M1: R\$ 1.0       Adapt_Inverted_XYZScaling_Green_M2: R\$ 0.0          Adapt_Inverted_XYZScaling_Blue_M3: R\$ 0.0 Adapt_Inverted_XYZScaling_Red_M4: R\$ 0.0       Adapt_Inverted_XYZScaling_Green_M5: R\$ 1.0          Adapt_Inverted_XYZScaling_Blue_M6: R\$ 0.0 Adapt_Inverted_XYZScaling_Red_M7: R\$ 0.0       Adapt_Inverted_XYZScaling_Green_M8: R\$ 0.0          Adapt_Inverted_XYZScaling_Blue_M9: R\$ 1.0; Adapt_Inverted_Bradford_Red_M1: R\$ 0.9869929    Adapt_Inverted_Bradford_Green_M2: R\$ -0.1470543     Adapt_Inverted_Bradford_Blue_M3: R\$ 0.1599627; Adapt_Inverted_Bradford_Red_M4: R\$ 0.4323053    Adapt_Inverted_Bradford_Green_M5: R\$ 0.5183603      Adapt_Inverted_Bradford_Blue_M6: R\$ 0.0492912; Adapt_Inverted_Bradford_Red_M7: R\$ -0.0085287   Adapt_Inverted_Bradford_Green_M8: R\$ 0.0400428     Adapt_Inverted_Bradford_Blue_M9: R\$ 0.9684867 Adapt_Inverted_Bradford_Red_M1: R\$ 0.9869929054667121899       Adapt_Inverted_Bradford_Green_M2: R\$ -0.14705425642099010066     Adapt_Inverted_Bradford_Blue_M3: R\$ 0.15996265166373123948 Adapt_Inverted_Bradford_Red_M4: R\$ 0.43230526972339451002      Adapt_Inverted_Bradford_Green_M5: R\$ 0.51836027153677753834      Adapt_Inverted_Bradford_Blue_M6: R\$ 0.049291228212855612148 Adapt_Inverted_Bradford_Red_M7: R\$ -0.0085286645751773312464   Adapt_Inverted_Bradford_Green_M8: R\$ 0.040042821654084864313     Adapt_Inverted_Bradford_Blue_M9: R\$ 0.96848669578754998478 Adapt_Inverted_Von_Kries_Red_M1: R\$ 1.8599363874558397422      Adapt_Inverted_Von_Kries_Green_M2: R\$ -1.1293816185800914784    Adapt_Inverted_Von_Kries_Blue_M3: R\$ 0.21989740959619327624 Adapt_Inverted_Von_Kries_Red_M4: R\$ 0.36119143624176752624     Adapt_Inverted_Von_Kries_Green_M5: R\$ 0.63881246328504213303    Adapt_Inverted_Von_Kries_Blue_M6: R\$ -0.0000063705968386570599758 Adapt_Inverted_Von_Kries_Red_M7: R\$ 0.0                        Adapt_Inverted_Von_Kries_Green_M8: R\$ 0.0                       Adapt_Inverted_Von_Kries_Blue_M9: R\$ 1.0890636230968613186][ScaledFactor: ScaledFactor_Red_M1: R\$ 0  ScaledFactor_Green_M2: R\$ 0 ScaledFactor_Blue_M3: R\$ 0 ScaledFactor_Red_M4: R\$ 0  ScaledFactor_Green_M5: R\$ 0 ScaledFactor_Blue_M6: R\$ 0 ScaledFactor_Red_M7: R\$ 0  ScaledFactor_Green_M8: R\$ 0 ScaledFactor_Blue_M9: R\$ 0][TmpScaledFactor: TmpScaledFactor_Red_M1: R\$ 0  TmpScaledFactor_Green_M2: R\$ 0 TmpScaledFactor_Blue_M3: R\$ 0 TmpScaledFactor_Red_M4: R\$ 0  TmpScaledFactor_Green_M5: R\$ 0 TmpScaledFactor_Blue_M6: R\$ 0 TmpScaledFactor_Red_M7: R\$ 0  TmpScaledFactor_Green_M8: R\$ 0 TmpScaledFactor_Blue_M9: R\$ 0]; call ChromaticAdaptation_XYXtoLab WHITE_SPACE_A_OBS2, WHITE_SPACE_C_OBS2, ADAPT_XYZ_SCALING, ScaledFactor; http://lclevy.free.fr/cr2/srgbd50_xyz.txt; https://player.slideplayer.com/24/7368067/; http://etsitpab.github.io/JSM/doc/html/source/CIE.html; Inverted Matrix calculated from: https://matrix.reshish.com/inverCalculation.php; https://home.kpn.nl/vanadovv/color/ColorMath.html; http://brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html#WSMatrices; https://github.com/jkl1337/go-chromath/blob/master/chromath.go[SigmaFrom: R\$ 0 #3][Sigmato: R\$ 0 #3]Proc ChromaticAdaptation_XYXtoLab:    Arguments @WhiteRefFrom, @WhiteRefTo, @Method, @pOutMatrix    Structure @Reference 72, @pRefXFromDis 0, @pRefYFromDis 8, @pRefZFromDis 16, @pRefXtoDis, 24, @pRefYtoDis 32, @pRefZtoDis 40, @XScaledDis 48, @YScaledDis 56, @ZScaledDis 64    Uses ebx, ecx, edx    lea edx D@pRefZFromDis    lea ebx D@pRefYFromDis    lea eax D@pRefXFromDis    call FindWhiteRef D@WhiteRefFrom, eax, ebx, edx    lea edx D@pRefZtoDis    lea ebx D@pRefYtoDis    lea eax D@pRefXtoDis    call FindWhiteRef D@WhiteRefto, eax, ebx, edx   ; calculate SigmaFrom https://github.com/jkl1337/go-chromath/blob/master/chromath.go    mov ebx D@Method | imul ebx Size_Of_FloatMatrices | add ebx FloatXYZAdaptMatrices    mov edi SigmaFrom    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    mov edi SigmaTo    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    fld R\$SigmaTo+FloatMatrices.M1Dis | fdiv R\$SigmaFrom+FloatMatrices.M1Dis | fstp R@XScaledDis    fld R\$SigmaTo+FloatMatrices.M2Dis | fdiv R\$SigmaFrom+FloatMatrices.M2Dis | fstp R@YScaledDis    fld R\$SigmaTo+FloatMatrices.M3Dis | fdiv R\$SigmaFrom+FloatMatrices.M3Dis | fstp R@ZScaledDis    ; get the from method    mov ebx D@Method | imul ebx Size_Of_FloatMatrices | add ebx Float_XYZ_RGB_Inverted_AdaptMatrices;FloatXYZAdaptMatrices    mov edi TmpScaledFactor;D@pOutMatrix    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    mov ebx D@Method | imul ebx Size_Of_FloatMatrices | add ebx FloatXYZAdaptMatrices    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.M9DisEndP`
Example of usage (I´ll later change the function name, because it is not a XYZ to Lab converted ;) but a matrix adaptation to be used later on XYZ (and lab):
Code: [Select]
`[ADAPT_XYZ_SCALING 0][ADAPT_BRADFORD 1][ADAPT_VON_KRIES 2][ScaledFactor: ScaledFactor_Red_M1: R\$ 0  ScaledFactor_Green_M2: R\$ 0 ScaledFactor_Blue_M3: R\$ 0 ScaledFactor_Red_M4: R\$ 0  ScaledFactor_Green_M5: R\$ 0 ScaledFactor_Blue_M6: R\$ 0 ScaledFactor_Red_M7: R\$ 0  ScaledFactor_Green_M8: R\$ 0 ScaledFactor_Blue_M9: R\$ 0]; Create a adaptative matrix from WhiteRef A to C using XYZ Scaling methodcall ChromaticAdaptation_XYXtoLab WHITE_SPACE_A_OBS2, WHITE_SPACE_C_OBS2, ADAPT_XYZ_SCALING, ScaledFactor; Create a adaptative matrix from WhiteRef A to C using Bradford methodcall ChromaticAdaptation_XYXtoLab WHITE_SPACE_A_OBS2, WHITE_SPACE_C_OBS2, ADAPT_BRADFORD, ScaledFactoror...using Von Kries Method; Create a adaptative matrix from WhiteRef A to C using Von Kries methodcall ChromaticAdaptation_XYXtoLab WHITE_SPACE_A_OBS2, WHITE_SPACE_C_OBS2, ADAPT_VON_KRIES, ScaledFactor`
:t :t :t :t
Post by: guga on January 22, 2019, 02:33:40 AM
The function FindWhiteRef , i wrote it as:

Code: [Select]
`__________________________________________________________________________________________________; To Find the white reference correspondencies[WHITE_SPACE_A_OBS2 0 WHITE_SPACE_C_OBS2 1 WHITE_SPACE_D50_OBS2 2 WHITE_SPACE_D55_OBS2 3 WHITE_SPACE_D65_OBS2 4 WHITE_SPACE_D75_OBS2 5 WHITE_SPACE_F2_OBS2 6 WHITE_SPACE_F7_OBS2 7 WHITE_SPACE_F11_OBS2 8 WHITE_SPACE_A_OBS10 9 WHITE_SPACE_C_OBS10 10 WHITE_SPACE_D50_OBS10 11 WHITE_SPACE_D55_OBS10 12 WHITE_SPACE_D65_OBS10 13 WHITE_SPACE_D75_OBS10 14 WHITE_SPACE_F2_OBS10 15 WHITE_SPACE_F7_OBS10 16 WHITE_SPACE_F11_OBS10 17][WHITE_SPACE_A_X2: R\$ 109.850 WHITE_SPACE_A_Y2: R\$ 100 WHITE_SPACE_A_Z2: R\$ 35.585 WHITE_SPACE_C_X2: R\$ 98.074 WHITE_SPACE_C_Y2: R\$ 100 WHITE_SPACE_C_Z2: R\$ 118.232 WHITE_SPACE_D50_X2: R\$ 96.422 WHITE_SPACE_D50_Y2: R\$ 100 WHITE_SPACE_D50_Z2: R\$ 82.521 WHITE_SPACE_D55_X2: R\$ 95.682 WHITE_SPACE_D55_Y2: R\$ 100 WHITE_SPACE_D55_Z2: R\$ 92.149 WHITE_SPACE_D65_X2: R\$ 95.047 WHITE_SPACE_D65_Y2: R\$ 100 WHITE_SPACE_D65_Z2: R\$ 108.883 WHITE_SPACE_D75_X2: R\$ 94.972 WHITE_SPACE_D75_Y2: R\$ 100 WHITE_SPACE_D75_Z2: R\$ 122.638 WHITE_SPACE_F2_X2: R\$ 99.187 WHITE_SPACE_F2_Y2: R\$ 100 WHITE_SPACE_F2_Z2: R\$ 67.395 WHITE_SPACE_F7_X2: R\$ 95.044 WHITE_SPACE_F7_Y2: R\$ 100 WHITE_SPACE_F7_Z2: R\$ 108.755 WHITE_SPACE_F11_X2: R\$ 100.966 WHITE_SPACE_F11_Y2: R\$ 100 WHITE_SPACE_F11_Z2: R\$ 64.370 WHITE_SPACE_A_X10: R\$ 111.144 WHITE_SPACE_A_Y10: R\$ 100 WHITE_SPACE_A_Z10: R\$ 35.200 WHITE_SPACE_C_X10: R\$ 97.285 WHITE_SPACE_C_Y10: R\$ 100 WHITE_SPACE_C_Z10: R\$ 116.145 WHITE_SPACE_D50_X10: R\$ 96.720 WHITE_SPACE_D50_Y10: R\$ 100 WHITE_SPACE_D50_Z10: R\$ 81.427 WHITE_SPACE_D55_X10: R\$ 95.799 WHITE_SPACE_D55_Y10: R\$ 100 WHITE_SPACE_D55_Z10: R\$ 90.926 WHITE_SPACE_D65_X10: R\$ 94.811 WHITE_SPACE_D65_Y10: R\$ 100 WHITE_SPACE_D65_Z10: R\$ 107.304 WHITE_SPACE_D75_X10: R\$  94.416 WHITE_SPACE_D75_Y10: R\$ 100 WHITE_SPACE_D75_Z10: R\$ 120.641 WHITE_SPACE_F2_X10: R\$ 103.280 WHITE_SPACE_F2_Y10: R\$ 100 WHITE_SPACE_F2_Z10: R\$ 69.026 WHITE_SPACE_F7_X10: R\$ 95.792 WHITE_SPACE_F7_Y10: R\$ 100 WHITE_SPACE_F7_Z10: R\$ 107.687 WHITE_SPACE_F11_X10: R\$ 103.866 WHITE_SPACE_F11_Y10: R\$ 100 WHITE_SPACE_F11_Z10: R\$ 65.627];;http://www.easyrgb.com/en/math.phphttps://www.mathworks.com/matlabcentral/fileexchange/40640-computational-colour-science-using-matlab-2ehttps://en.wikipedia.org/wiki/Standard_illuminantXYZ (Tristimulus) Reference values of a perfect reflecting diffuserObserver                2°(CIE 1931)                   10° (CIE 1964)               NoteIlluminant  X2          Y2          Z2          X10         Y10         Z10  __________________________________________________________________________________________________________________A           109.850     100.000     35.585      111.144     100.000     35.200      Incandescent/tungstenB           99.0927     100.000     85.313      99.178      100.000     84.3493     Old direct sunlight at noonC           98.074      100.000     118.232     97.285      100.000     116.145     Old daylightD50         96.422      100.000     82.521      96.720      100.000     81.427      ICC profile PCSD55         95.682      100.000     92.149      95.799      100.000     90.926      Mid-morning daylightD65         95.047      100.000     108.883     94.811      100.000     107.304     Daylight, sRGB, Adobe-RGBD75         94.972      100.000     122.638     94.416      100.000     120.641     North sky daylightE           100.000     100.000     100.000     100.000     100.000     100.000     Equal energyF1          92.834      100.000     103.665     94.791      100.000     103.191     Daylight FluorescentF2          99.187      100.000     67.395      103.280     100.000     69.026      Cool fluorescentF3          103.754     100.000     49.861      108.968     100.000     51.965      White FluorescentF4          109.147     100.000     38.813      114.961     100.000     40.963      Warm White FluorescentF5          90.872      100.000     98.723      93.369      100.000     98.636      Daylight FluorescentF6          97.309      100.000     60.191      102.148     100.000     62.074      Lite White FluorescentF7          95.044      100.000     108.755     95.792      100.000     107.687     Daylight fluorescent, D65 simulatorF8          96.413      100.000     82.333      97.115      100.000     81.135      Sylvania F40, D50 simulatorF9          100.365     100.000     67.868      102.116     100.000     67.826      Cool White FluorescentF10         96.174      100.000     81.712      99.001      100.000     83.134      Ultralume 50, Philips TL85F11         100.966     100.000     64.370      103.866     100.000     65.627      Ultralume 40, Philips TL84F12         108.046     100.000     39.228      111.428     100.000     40.353      Ultralume 30, Philips TL83;;Proc FindWhiteRef:    Arguments @Flag, @pRefx, @pRefy, @pRefz    Uses ebx, ecx, esi    mov ebx D@pRefx, ecx D@pRefy, esi D@pRefz    .If D@Flag = WHITE_SPACE_A_OBS2        move D\$ebx D\$WHITE_SPACE_A_X2 | move D\$ebx+4 D\$WHITE_SPACE_A_X2+4        move D\$ecx D\$WHITE_SPACE_A_Y2 | move D\$ecx+4 D\$WHITE_SPACE_A_Y2+4        move D\$esi D\$WHITE_SPACE_A_Z2 | move D\$esi+4 D\$WHITE_SPACE_A_Z2+4    .Else_If D@Flag = WHITE_SPACE_C_OBS2        move D\$ebx D\$WHITE_SPACE_C_X2 | move D\$ebx+4 D\$WHITE_SPACE_C_X2+4        move D\$ecx D\$WHITE_SPACE_C_Y2 | move D\$ecx+4 D\$WHITE_SPACE_C_Y2+4        move D\$esi D\$WHITE_SPACE_C_Z2 | move D\$esi+4 D\$WHITE_SPACE_C_Z2+4    .Else_If D@Flag = WHITE_SPACE_D50_OBS2        move D\$ebx D\$WHITE_SPACE_D50_X2 | move D\$ebx+4 D\$WHITE_SPACE_D50_X2+4        move D\$ecx D\$WHITE_SPACE_D50_Y2 | move D\$ecx+4 D\$WHITE_SPACE_D50_Y2+4        move D\$esi D\$WHITE_SPACE_D50_Z2 | move D\$esi+4 D\$WHITE_SPACE_D50_Z2+4    .Else_If D@Flag = WHITE_SPACE_D55_OBS2        move D\$ebx D\$WHITE_SPACE_D55_X2 | move D\$ebx+4 D\$WHITE_SPACE_D55_X2+4        move D\$ecx D\$WHITE_SPACE_D55_Y2 | move D\$ecx+4 D\$WHITE_SPACE_D55_Y2+4        move D\$esi D\$WHITE_SPACE_D55_Z2 | move D\$esi+4 D\$WHITE_SPACE_D55_Z2+4    .Else_If D@Flag = WHITE_SPACE_D65_OBS2        move D\$ebx D\$WHITE_SPACE_D65_X2 | move D\$ebx+4 D\$WHITE_SPACE_D65_X2+4        move D\$ecx D\$WHITE_SPACE_D65_Y2 | move D\$ecx+4 D\$WHITE_SPACE_D65_Y2+4        move D\$esi D\$WHITE_SPACE_D65_Z2 | move D\$esi+4 D\$WHITE_SPACE_D65_Z2+4    .Else_If D@Flag = WHITE_SPACE_D75_OBS2        move D\$ebx D\$WHITE_SPACE_D75_X2 | move D\$ebx+4 D\$WHITE_SPACE_D75_X2+4        move D\$ecx D\$WHITE_SPACE_D75_Y2 | move D\$ecx+4 D\$WHITE_SPACE_D75_Y2+4        move D\$esi D\$WHITE_SPACE_D75_Z2 | move D\$esi+4 D\$WHITE_SPACE_D75_Z2+4    .Else_If D@Flag = WHITE_SPACE_F2_OBS2        move D\$ebx D\$WHITE_SPACE_F2_X2 | move D\$ebx+4 D\$WHITE_SPACE_F2_X2+4        move D\$ecx D\$WHITE_SPACE_F2_Y2 | move D\$ecx+4 D\$WHITE_SPACE_F2_Y2+4        move D\$esi D\$WHITE_SPACE_F2_Z2 | move D\$esi+4 D\$WHITE_SPACE_F2_Z2+4    .Else_If D@Flag = WHITE_SPACE_F7_OBS2        move D\$ebx D\$WHITE_SPACE_F7_X2 | move D\$ebx+4 D\$WHITE_SPACE_F7_X2+4        move D\$ecx D\$WHITE_SPACE_F7_Y2 | move D\$ecx+4 D\$WHITE_SPACE_F7_Y2+4        move D\$esi D\$WHITE_SPACE_F7_Z2 | move D\$esi+4 D\$WHITE_SPACE_F7_Z2+4    .Else_If D@Flag = WHITE_SPACE_F11_OBS2        move D\$ebx D\$WHITE_SPACE_F11_X2 | move D\$ebx+4 D\$WHITE_SPACE_F11_X2+4        move D\$ecx D\$WHITE_SPACE_F11_Y2 | move D\$ecx+4 D\$WHITE_SPACE_F11_Y2+4        move D\$esi D\$WHITE_SPACE_F11_Z2 | move D\$esi+4 D\$WHITE_SPACE_F11_Z2+4    .Else_If D@Flag = WHITE_SPACE_A_OBS10        move D\$ebx D\$WHITE_SPACE_A_X10 | move D\$ebx+4 D\$WHITE_SPACE_A_X10+4        move D\$ecx D\$WHITE_SPACE_A_Y10 | move D\$ecx+4 D\$WHITE_SPACE_A_Y10+4        move D\$esi D\$WHITE_SPACE_A_Z10 | move D\$esi+4 D\$WHITE_SPACE_A_Z10+4    .Else_If D@Flag = WHITE_SPACE_C_OBS10        move D\$ebx D\$WHITE_SPACE_C_X10 | move D\$ebx+4 D\$WHITE_SPACE_C_X10+4        move D\$ecx D\$WHITE_SPACE_C_Y10 | move D\$ecx+4 D\$WHITE_SPACE_C_Y10+4        move D\$esi D\$WHITE_SPACE_C_Z10 | move D\$esi+4 D\$WHITE_SPACE_C_Z10+4    .Else_If D@Flag = WHITE_SPACE_D50_OBS10        move D\$ebx D\$WHITE_SPACE_D50_X10 | move D\$ebx+4 D\$WHITE_SPACE_D50_X10+4        move D\$ecx D\$WHITE_SPACE_D50_Y10 | move D\$ecx+4 D\$WHITE_SPACE_D50_Y10+4        move D\$esi D\$WHITE_SPACE_D50_Z10 | move D\$esi+4 D\$WHITE_SPACE_D50_Z10+4    .Else_If D@Flag = WHITE_SPACE_D55_OBS10        move D\$ebx D\$WHITE_SPACE_D55_X10 | move D\$ebx+4 D\$WHITE_SPACE_D55_X10+4        move D\$ecx D\$WHITE_SPACE_D55_Y10 | move D\$ecx+4 D\$WHITE_SPACE_D55_Y10+4        move D\$esi D\$WHITE_SPACE_D55_Z10 | move D\$esi+4 D\$WHITE_SPACE_D55_Z10+4    .Else_If D@Flag = WHITE_SPACE_D65_OBS10        move D\$ebx D\$WHITE_SPACE_D65_X10 | move D\$ebx+4 D\$WHITE_SPACE_D65_X10+4        move D\$ecx D\$WHITE_SPACE_D65_Y10 | move D\$ecx+4 D\$WHITE_SPACE_D65_Y10+4        move D\$esi D\$WHITE_SPACE_D65_Z10 | move D\$esi+4 D\$WHITE_SPACE_D65_Z10+4    .Else_If D@Flag = WHITE_SPACE_D75_OBS10        move D\$ebx D\$WHITE_SPACE_D75_X10 | move D\$ebx+4 D\$WHITE_SPACE_D75_X10+4        move D\$ecx D\$WHITE_SPACE_D75_Y10 | move D\$ecx+4 D\$WHITE_SPACE_D75_Y10+4        move D\$esi D\$WHITE_SPACE_D75_Z10 | move D\$esi+4 D\$WHITE_SPACE_D75_Z10+4    .Else_If D@Flag = WHITE_SPACE_F2_OBS10        move D\$ebx D\$WHITE_SPACE_F2_X10 | move D\$ebx+4 D\$WHITE_SPACE_F2_X10+4        move D\$ecx D\$WHITE_SPACE_F2_Y10 | move D\$ecx+4 D\$WHITE_SPACE_F2_Y10+4        move D\$esi D\$WHITE_SPACE_F2_Z10 | move D\$esi+4 D\$WHITE_SPACE_F2_Z10+4    .Else_If D@Flag = WHITE_SPACE_F7_OBS10        move D\$ebx D\$WHITE_SPACE_F7_X10 | move D\$ebx+4 D\$WHITE_SPACE_F7_X10+4        move D\$ecx D\$WHITE_SPACE_F7_Y10 | move D\$ecx+4 D\$WHITE_SPACE_F7_Y10+4        move D\$esi D\$WHITE_SPACE_F7_Z10 | move D\$esi+4 D\$WHITE_SPACE_F7_Z10+4    .Else_If D@Flag = WHITE_SPACE_F11_OBS10        move D\$ebx D\$WHITE_SPACE_F11_X10 | move D\$ebx+4 D\$WHITE_SPACE_F11_X10+4        move D\$ecx D\$WHITE_SPACE_F11_Y10 | move D\$ecx+4 D\$WHITE_SPACE_F11_Y10+4        move D\$esi D\$WHITE_SPACE_F11_Z10 | move D\$esi+4 D\$WHITE_SPACE_F11_Z10+4    .End_IfEndP`
Post by: Siekmanski on January 22, 2019, 03:38:13 AM
Interesting.  :t
Post by: guga on January 22, 2019, 04:13:45 AM
Hi Siekmanski. Thanks :)

This is part of the routines i´m making to create a converter for Black and White Images (or movie) to Colored. During my studies i found out some very interesting properties regarding Luminance from CieLab (Or CieLCH which i prefer to use). For example, we can have more then 16 millions colors but, in fact,  a huge amount of them are exactly the same. I mean, they are perceptually the same. During my tests i found that a gray value can result on a very limited amount of Luminance and grey is pratically only related to Luminance rather then color itself.

I built some routines to generate the proper luminance from a gray color, so, whenever a coloured image have XX value as Luminance, no matter what is the RGB combinations, they will always result on th same gray. So i built a table for that containing only a range of 256 luminance values that results on 256 gray colors.

I suceeded to make a test app to transport the colors form a reference image onto a gray image, but the results using the regular CieLab was bogus, because the values were being clipped someway. Since the RGBtoCielab (and the reverted one CieLabtoRGB) uses Whitereference. it is easy to some pixels result the wrong values since the actual formulas used only clip the exceeeding values. Ex. If the resultang Blue is more then 255 it is clipped to 255 etc etc.. Thios is inaccurate since, there shouldn´t be clipping at all in the 1st place :)

So, i faced this great Chromatic adaptation algortihms froim where i can try to use to create a better RGBtoCieLCH and CieLCHtoRGb functions without the needs of clipping anything. As you see on the attached image, the resultant colored values are clipped. The colorized image produces the same gray leves as the input, but during the convertion onto colors some pixels were clipped due to the actual failure of CieLab convertions.

My main problem while reading some publications on color convert is my lack of knowledge of complex math notations :(  All the algorithms i read so far are way over my head and i can´t understand all those signs, so i´m making some of my own trying to interpret what the papers are actually trying to do. :greensml: :greensml: :greensml: :icon_mrgreen:

(https://i.imgur.com/aZmGsIF.jpg)

The actual algorithm colorizes an image on an unordered way. Ie, i made it simple as possible just trying to find the pixel from the reference that most match to the source (gray). Once i succeed to fix this adaptation algorithms i´ll try to create a way to organize the pixels, so when the colored image is being scanned it will correctly transfer a bunch of pixels that macthes exactly to the ones in the gray image.

In theory, this is not so hard to achieve since we have limited possibility of an error while trying to find the match but, still...i need to suceed to finish this adaptation algorithm before i go further on the colorization tests.

When i started creating this algorithm, the test image i posted for example, was taking something around 20 minutes to render depending on the size of the reference image (some tests took almost 50 minutes to conclude). Now, with my new routines, i could built up a table and convert to color in runtime. So, it takes less then a second to color a image of 960x480. (Still a bit slow, since i did not optimized it yet), but way better then the looooong time it was tooking when i started :)

My goal is make the convertion works in a few miliseconds per image, so i can be able to convert a full video (with, let´s say 45 minutes of duration) in less then 20 minutes :)

CieLCH colorspaace is particulary interesting using my modified method, since i found out also, that we can have a perfect limit on the relation between Chroma and Hue. Since all Luminance is specific to a certain range of gray, the formula i made up also, showed me that we have Chroma and Hue are related to each other, so it is easier to avoid clipping when knowing the proper Luma related to a pixel.

So, for example, when converting back from CieLCH to RGB, we can simply check the Luma range for the fractions (limits) of hue x chroma and, on this way we can avoid clipping. Ex: Say on Luma = 100 we have this formula for hue anc chroma. Hue = X*Chroma+Y*Luma.  Once we know the proper Luma, we can simply see if the inputed Chroma macthes the maximum result when Luma is used. So, for luma = 100, the maximum relation between chroma and hue is===> Hue = X*Chroma+Y*100 and so on.....

This is to say that, each Hue have a specifi range of crhoma and vice-versa.

So, if our pixel have a Luminance of 100, we can create a routine to convert it back from Chroma and Hue properly and also allow shifting or not. For example, say that when Luma = 100 and the pixel have a Hue of 65º and we also inputed a Chroma of 80, but...if for Hue =  65º the maximum chroma is 30, we can easily clip the chroma to it fits the limit to that hue or...the other way we can keep the chroma to80 and see what is the hue that fit´s for it. In both cases, even if we clipp hue or chroma to it fits the limit, it will never result on bad RGB since we will never clip RGB whatsoever during the convertion backwards
Post by: daydreamer on January 22, 2019, 05:58:09 AM
Interesting and great work guga
I think you might be the right person to ask about an idea I have
Maybe it would be more efficient + more possibilities if I choose to work with cmyk color system with SIMD packed SSE
1 maybe can use the faster reciprocal sqrt instead
2 separate scalar use of k channel for darkness/ (brightness)
Post by: guga on January 22, 2019, 06:56:13 AM
Tks Daydreamer

I did not used CMYK yet for the tests i´m making. For what i saw so far, the best colorspace is still CieLCH since it isolates almost completelly Luminance from chroma and hue. The main problem with all those algorithms XYZ, CieLab, HSI, HSV, CMYK etc etc, is that all of them works on a innacurate way, since they allows clipping on the converting back to RGB which is not desirable.

I tried several colorspaces from different apps, since gimp, photoshop, paintshoo pro etc etc, and almost all of them uses the same algorithms that on many cases does not uses white reference or even gamma adjust internally which tends to produce vbad results when converting back to RGB.

I´m not sure if using SSE for CMYK will fix those kind of problems, although it may be faster. The best would give a try on CieLCH functions and try to optimize it and then, convert to CMYK (If this colorspace is used).

I made a routine to convert RGB to LCH as bellow. It is not optimized yet, but produces an accurate result. (Dispites this small problems on the white reference adaptations i´m still working on). I can gain some speed if i suceed to fix this adaptation algorithm since i´ll no longer need to use another function to retrieve the values of White Reference, but still...i need to finish it before test to check if it is clipping or not. I´m prety sure that we can overcome the needs of 2 threshold checking on the function, but i´ll need to see if i can find those with only 1 single equation rather then those 2 routines used to check. And latrer, if suceed to make all of thiss works on a single equation, then can use a SSE to speed up a little bit (specially because it uses at the end the atan2 function which is kinda slow, though) and i don´t know a way to compute the atan of an angle with SSE to make it faster)

Anyway, try using CieLCH colorspace rather then CMYK. Dispites some minor speed problems, it is really worthfull.

Code: [Select]
`Proc RGBtoCieLCH:    Arguments @Red, @Green, @Blue, @pLuminance, @pChroma, @pHue, @Flag, @WhiteRef    Local @MyPixelSrc    Structure @TempStorage 64, @pXDis 0, @pYDis 8, @pZDis 16, @TmpRedDis, 24, @TmpGreenDis 32, @TmpBlueDis 40, @pAFactorDis 48, @pBFactorDis 56    Uses esi, ebx, ecx, edx, edi    finit    If D@Flag > XYZ_Matrice_sRGB_D65_HDTV        mov D@Flag XYZ_Matrice_sRGB_D65_HDTV    End_If    ;1st convert to XYZ colorspace. Same as RGBtoXYZ3    ; double r = (double)((src & 0xff0000) >> 16)/255; RED    lea ecx D@TmpRedDis | fild F@Red | fmul R\$FloatOne_255 | fstp R\$ecx    ; double g = (double)((src & 0xff00) >> 8)/255; GREEN    lea ecx D@TmpGreenDis | fild F@Green | fmul R\$FloatOne_255 | fstp R\$ecx    ; double b = (double)(src & 0xff)/255; BLUE    lea ecx D@TmpBlueDis | fild F@Blue | fmul R\$FloatOne_255 | fstp R\$ecx    call GammaLinearEncodingEx F_gamma, F_Offset, F_Slope, F_Treshold, F_OffsetPlusOne, D@Flag    ; newColorRed = ((R@Red+0.055)/1.055)^2.4 ; where2.4 = gamma, 0.055 = Offset, 1.055 = Offset+1. Better precalculating them as i did.    lea ecx D@TmpRedDis    .Fpu_If R\$ecx > R\$F_Treshold        fld R\$F_gamma | fld R\$F_Offset | fadd R\$ecx | fmul R\$F_OffsetPlusOne | fyl2x | fld1 | fld ST1 | fprem | f2xm1 | faddp ST1 ST0 | fscale | fxch | fstp ST0    .Fpu_Else        fld R\$ecx | fdiv R\$F_Slope    .Fpu_End_If    fmul R\$Float100 | fstp R\$ecx    ; newColorGreen = ((R@Green+0.055)/1.055)^2.4    lea ecx D@TmpGreenDis    .Fpu_If R\$ecx > R\$F_Treshold        fld R\$F_gamma | fld R\$F_Offset | fadd R\$ecx | fmul R\$F_OffsetPlusOne | fyl2x | fld1 | fld ST1 | fprem | f2xm1 | faddp ST1 ST0 | fscale | fxch | fstp ST0    .Fpu_Else        fld R\$ecx | fdiv R\$F_Slope    .Fpu_End_If    fmul R\$Float100 | fstp R\$ecx    ; newColorBlue = ((R@Blue+0.055)/1.055)^2.4    lea ecx D@TmpBlueDis    .Fpu_If R\$ecx > R\$F_Treshold        fld R\$F_gamma | fld R\$F_Offset | fadd R\$ecx | fmul R\$F_OffsetPlusOne | fyl2x | fld1 | fld ST1 | fprem | f2xm1 | faddp ST1 ST0 | fscale | fxch | fstp ST0    .Fpu_Else        fld R\$ecx | fdiv R\$F_Slope    .Fpu_End_If    fmul R\$Float100 | fstp R\$ecx    ; probably mising the Normalize for D65 white point because the sum of FloatMatrices on X and Z does not lead to 1. See RGB2Lab4 and CieLabtoCieLCH. Hue for this varyes from 292 to 293 when RGB = 0 and RGB = 255 when it should be a fixed value    ; Observer. = 2°, Illuminant = D65    xor edx edx    mov eax Size_Of_FloatMatrices    mul D@Flag    mov esi FloatXYZWorkSpacesMatrices    add esi eax    lea ecx D@pXDis | fld R@TmpRedDis | fmul R\$esi+FloatMatrices.M1Dis | fld R@TmpGreenDis | fmul R\$esi+FloatMatrices.M2Dis | faddp ST1 ST0 | fld R@TmpBlueDis | fmul R\$esi+FloatMatrices.M3Dis | faddp ST1 ST0 | fstp R\$ecx    lea ecx D@pYDis | fld R@TmpRedDis | fmul R\$esi+FloatMatrices.M4Dis | fld R@TmpGreenDis | fmul R\$esi+FloatMatrices.M5Dis | faddp ST1 ST0 | fld R@TmpBlueDis | fmul R\$esi+FloatMatrices.M6Dis | faddp ST1 ST0 | fstp R\$ecx    lea ecx D@pZDis | fld R@TmpRedDis | fmul R\$esi+FloatMatrices.M7Dis | fld R@TmpGreenDis | fmul R\$esi+FloatMatrices.M8Dis | faddp ST1 ST0 | fld R@TmpBlueDis | fmul R\$esi+FloatMatrices.M9Dis | faddp ST1 ST0 | fstp R\$ecx    ; 2nd convert XYZ to Cielab as in XYZtoCieLab3    ; Whiteref is the Yn term from https://en.wikipedia.org/wiki/Lab_color_space    call FindWhiteRef D@WhiteRef, Ref_X, Ref_Y, Ref_Z    ; must be within the limits    lea ebx D@pXDis | fld R\$ebx | fdiv R\$Ref_X | fst R\$ebx | fstp R\$FPU_TempResult    Fpu_If R\$FPU_TempResult > R\$Float_One        fld R\$Float_One | fstp R\$ebx    Fpu_End_If    lea ebx D@pYDis | fld R\$ebx | fdiv R\$Ref_Y | fst R\$ebx | fstp R\$FPU_TempResult    Fpu_If R\$FPU_TempResult > R\$Float_One        fld R\$Float_One | fstp R\$ebx    Fpu_End_If    lea ebx D@pZDis | fld R\$ebx | fdiv R\$Ref_Z | fst R\$ebx | fstp R\$FPU_TempResult    Fpu_If R\$FPU_TempResult > R\$Float_One        fld R\$Float_One | fstp R\$ebx    Fpu_End_If    ; We know that X+Y+Z = 1, therefore: Z  = 1-(X+Y)    ;  var_X = var_X ^ ( 1/3 )    .Fpu_If R@pXDis > R\$Float8856        fld R\$FloatOneThird | fld R@pXDis | fyl2x | fld1 | fld ST1 | fprem | f2xm1 | faddp ST1 ST0 | fscale | fxch | fstp ST0    .Fpu_Else        fld R@pXDis | fmul R\$Float_7787 | fadd R\$Float_16_116    .Fpu_End_If    lea eax D@pXDis | fstp R\$eax    ;  var_Y = var_Y ^ ( 1/3 )    .Fpu_If R@pYDis > R\$Float8856        fld R\$FloatOneThird | fld R@pYDis | fyl2x | fld1 | fld ST1 | fprem | f2xm1 | faddp ST1 ST0 | fscale | fxch | fstp ST0    .Fpu_Else        fld R@pYDis | fmul R\$Float_7787 | fadd R\$Float_16_116    .Fpu_End_If    lea eax D@pYDis | fstp R\$eax    ;  var_Z = var_Z ^ ( 1/3 )    .Fpu_If R@pZDis > R\$Float8856        fld R\$FloatOneThird | fld R@pZDis | fyl2x | fld1 | fld ST1 | fprem | f2xm1 | faddp ST1 ST0 | fscale | fxch | fstp ST0    .Fpu_Else        fld R@pZDis | fmul R\$Float_7787 | fadd R\$Float_16_116    .Fpu_End_If    lea eax D@pZDis | fstp R\$eax    mov eax D@pLuminance | fld R@pYDis | fmul R\$Float_116 | fsub R\$Float_16 | fabs | fstp R\$eax ; luminance is always positive. we must be sure this result is >= 0. Same as in GraytoLuma    lea eax D@pAFactorDis | fld R@pXDis | fsub R@pYDis | fmul R\$Float_500 | fstp R\$eax    lea eax D@pBFactorDis | fld R@pYDis | fsub R@pZDis | fmul R\$Float_200 | fstp R\$eax    ; 3rd finally convert to chroma and hue as in CieLabtoCieLCH    mov edi D@pChroma    lea eax D@pAFactorDis    lea ebx D@pBFactorDis    fld R\$eax | fst St1 | fmulp ST1 ST0    fld R\$ebx | fmul ST0 ST0 | faddp ST1 ST0 | fsqrt    fstp R\$edi    ;call atan2 D@bFactor, D@aFactor, &TRUE    call atan2 ebx, eax, &TRUE    mov eax D@pHue | fstp R\$eaxEndP`
Post by: daydreamer on January 23, 2019, 05:41:02 AM
I dont know if atan taylor series should make it or LUT?
well its looks like an alternative,either K=blackness or L=luminance
Check my Rossler attractor thread in workshop, to see what I am working on
Looks like your pic example,it could be possible to add some psychedelic colors to a boring greyscale object