#### guga

• Member
• Posts: 1074
• Assembly is a state of art.
« 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
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

#### guga

• Member
• Posts: 1074
• Assembly is a state of art.
« Reply #1 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 Z
A 1.09850 1.00000 0.35585

Code: [Select]
-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 Z
B 0.99072 1.00000 0.85223

Code: [Select]
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                  0
0              (0.6/0.8)       0
0              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]

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]
;;
; Transformed values to convert from one illuminant to another

http://www.easyrgb.com/en/math.php
https://www.mathworks.com/matlabcentral/fileexchange/40640-computational-colour-science-using-matlab-2e

WHITE_SPACE_A_OBS2
;;

[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]

; http://lclevy.free.fr/cr2/srgbd50_xyz.txt
; http://etsitpab.github.io/JSM/doc/html/source/CIE.html
; Inverted Matrix calculated from: https://matrix.reshish.com/inverCalculation.php
; 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]

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 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 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 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

EndP

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]

[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 method

; Create a adaptative matrix from WhiteRef A to C using Bradford method

or...using Von Kries Method

; Create a adaptative matrix from WhiteRef A to C using Von Kries method

:t :t :t :t
« Last Edit: January 22, 2019, 03:41:10 AM by guga »
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

#### guga

• Member
• Posts: 1074
• Assembly is a state of art.
« Reply #2 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.php
https://www.mathworks.com/matlabcentral/fileexchange/40640-computational-colour-science-using-matlab-2e
https://en.wikipedia.org/wiki/Standard_illuminant

XYZ (Tristimulus) Reference values of a perfect reflecting diffuser

Observer                2°(CIE 1931)                   10° (CIE 1964)               Note
Illuminant  X2          Y2          Z2          X10         Y10         Z10
__________________________________________________________________________________________________________________
A           109.850     100.000     35.585      111.144     100.000     35.200      Incandescent/tungsten
B           99.0927     100.000     85.313      99.178      100.000     84.3493     Old direct sunlight at noon
C           98.074      100.000     118.232     97.285      100.000     116.145     Old daylight
D50         96.422      100.000     82.521      96.720      100.000     81.427      ICC profile PCS
D55         95.682      100.000     92.149      95.799      100.000     90.926      Mid-morning daylight
D65         95.047      100.000     108.883     94.811      100.000     107.304     Daylight, sRGB, Adobe-RGB
D75         94.972      100.000     122.638     94.416      100.000     120.641     North sky daylight
E           100.000     100.000     100.000     100.000     100.000     100.000     Equal energy
F1          92.834      100.000     103.665     94.791      100.000     103.191     Daylight Fluorescent
F2          99.187      100.000     67.395      103.280     100.000     69.026      Cool fluorescent
F3          103.754     100.000     49.861      108.968     100.000     51.965      White Fluorescent
F4          109.147     100.000     38.813      114.961     100.000     40.963      Warm White Fluorescent
F5          90.872      100.000     98.723      93.369      100.000     98.636      Daylight Fluorescent
F6          97.309      100.000     60.191      102.148     100.000     62.074      Lite White Fluorescent
F7          95.044      100.000     108.755     95.792      100.000     107.687     Daylight fluorescent, D65 simulator
F8          96.413      100.000     82.333      97.115      100.000     81.135      Sylvania F40, D50 simulator
F9          100.365     100.000     67.868      102.116     100.000     67.826      Cool White Fluorescent
F10         96.174      100.000     81.712      99.001      100.000     83.134      Ultralume 50, Philips TL85
F11         100.966     100.000     64.370      103.866     100.000     65.627      Ultralume 40, Philips TL84
F12         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_If

EndP

Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

#### Siekmanski

• Member
• Posts: 1955
« Reply #3 on: January 22, 2019, 03:38:13 AM »
Interesting.  :t
Creative coders use backward thinking techniques as a strategy.

#### guga

• Member
• Posts: 1074
• Assembly is a state of art.
« Reply #4 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. :icon_mrgreen:

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
« Last Edit: January 22, 2019, 06:24:46 AM by guga »
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

#### daydreamer

• Member
• Posts: 1001
• I also want a stargate
« Reply #5 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)
Quote from Flashdance
Nick  :  When you give up your dream, you die
*wears a flameproof asbestos suit*
Gone serverside programming p:  :D
I love assembly,because its legal to write
princess:lea eax,luke
:)

#### guga

• Member
• Posts: 1074
• Assembly is a state of art.
« Reply #6 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

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\$eax

EndP
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

#### daydreamer

• Member
• Posts: 1001
• I also want a stargate
« Reply #7 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
« Last Edit: January 23, 2019, 09:20:21 AM by daydreamer »
Quote from Flashdance
Nick  :  When you give up your dream, you die
*wears a flameproof asbestos suit*
Gone serverside programming p:  :D
I love assembly,because its legal to write
princess:lea eax,luke
:)

#### guga

• Member
• Posts: 1074
• Assembly is a state of art.
« Reply #8 on: January 23, 2019, 06:18:58 AM »
A taylor series for atan ? Hmm..maybe it wil speed up a little bit. I´ll give a try later when finishing it. :t :t :t

About LUT...i´m not sure. LUT filters are good for Sony Vegas for example or Premiere, or even VirtualDub but, at the end, it seems that they are only a array of Luminance Data and the main app (Vegas, etc etc) only uses them to replace the original luminance of a given image/video rather then fix the internal problems with the current CieLab functions they uses.

I suceeeded to make a function to adapt the different white references from the tristimulus values to convert from D65 to D50, to HD etc etc....but still needs to make the convertier works on their own Matrixes rather then only on Bradford . I´m struggling to understand how to use the Chromatic Adaptation in order to properly convert all those white references. Probably i need only a multipllication of a matrix by another one, but didn´t tested yet. Yesterday i got stuck trying to make the proper invert matrix 3x3 to use for example on the backwards computation from CieLab to RGB.

And yes..CieLCH is an alternative but needs to be fixed 1st as i told.  The good thing for the CieLab and other perceptual colorspaces is that they can represent the colors correclty. Last year i started developing a new colorspace biased on the TSL one (Not HSL...the TSL - I made some fixes and adaptations of that on wiki: https://en.wikipedia.org/wiki/TSL_color_space) that is in short, a spherical colorspace that also can separate completelly the luminance from chroma and hue.  I suceeded to create the algo for converting from RGB to it...but got stuck on the backwards computation. Once i have time, i´ll give a try again on the algorithm.

The good thing i notice is that, on  the preliminary tests on my algo, there was no such a thing as a true black color, since the 3 points of the space coordinates (R, G, B) can never all be 0 at the same time meaning that even if only one of thhem reaches 0 it means absolutelly nothing except a bad pixels since 0 is not a isolated starting value for R, G, B but only a starting point of all of them. So a colorspace to be a bit more accurate can never consider 0 as a valid value for a pixel. And from the adjustements i´m making on the CieLCH/CieLab formulas, this assumption seems to be true meaning that whenever a pixel have value of 0, 0, 0 (or perhaps, even for the pure white 255,255,255) we are dealing, in fact with a bad pixel.

Btw...if you want a way to get the tristimulus values for the white reference, i made a function for it and posted on the RosAsm subforum. It is easy to follow.  I named it as "FindWhiteRefEx"
« Last Edit: January 23, 2019, 07:53:45 AM by guga »
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com