@@ -59,3 +59,58 @@ function LMStoJzazbz(LMS) {
5959 return [ Jz , az , bz ] ;
6060}
6161
62+ function Jzazbz_to_XYZ ( Jzazbz ) {
63+ // convert an array of JzAzBz to D65 XYZ
64+ // such that [0,0,0] is black and
65+ // media white is [0.2220, -0.00016, -0.0001]
66+
67+ const b = 1.15 ;
68+ const g = 0.66 ;
69+ const M = [
70+ [ 1.9242264357876067 , - 1.0047923125953657 , 0.037651404030618 ] ,
71+ [ 0.35031676209499907 , 0.7264811939316552 , - 0.06538442294808501 ] ,
72+ [ - 0.09098281098284752 , - 0.3127282905230739 , 1.5227665613052603 ] ,
73+ ] ;
74+
75+ let LMS = Jzazbz_to_LMS ( Jzazbz ) ;
76+ // modified absolute XYZ
77+ let [ Xm , Ym , Za ] = multiplyMatrices ( LMS , M ) ;
78+
79+ // un-modify X and Y to get D65 XYZ, relative to media white
80+ let Xa = ( Xm + ( b - 1 ) * Za ) / b ;
81+ let Ya = ( Ym + ( g - 1 ) * Xa ) / g ;
82+ return [ Xa , Ya , Za ] ;
83+ }
84+
85+ function Jzazbz_to_LMS ( Jzazbz ) {
86+
87+ const d = - 0.56 ;
88+ const d0 = 1.6295499532821566e-11 ;
89+ const c1 = 3424 / 2 ** 12 ;
90+ const c2 = 2413 / 2 ** 7 ;
91+ const c3 = 2392 / 2 ** 7 ;
92+ const pinv = 2 ** 5 / ( 1.7 * 2523 ) ;
93+ const M = [
94+ [ 1 , 0.13860504327153927 , 0.05804731615611883 ] ,
95+ [ 1 , - 0.1386050432715393 , - 0.058047316156118904 ] ,
96+ [ 1 , - 0.09601924202631895 , - 0.81189189605603900 ] ,
97+ ] ;
98+
99+ let [ Jz , az , bz ] = Jzazbz ;
100+ let Iz = ( Jz + d0 ) / ( 1 + d - d * ( Jz + d0 ) ) ;
101+
102+ // bring into LMS cone domain
103+ let PQLMS = multiplyMatrices ( [ Iz , az , bz ] , M ) ;
104+
105+ // convert from PQ-coded to linear-light LMS
106+ let LMS = (
107+ PQLMS . map ( function ( val ) {
108+ let num = c1 - spow ( val , pinv ) ;
109+ let denom = c3 * spow ( val , pinv ) - c2 ;
110+ let x = 10000 * spow ( num / denom , ninv ) ;
111+
112+ return x ; // luminance relative to diffuse white, [0, 70 or so].
113+ } )
114+ ) ;
115+ return LMS ;
116+ }
0 commit comments