Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
M
Molstar
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Michal Malý
Molstar
Commits
421bb9a8
Commit
421bb9a8
authored
5 years ago
by
Alexander Rose
Browse files
Options
Downloads
Patches
Plain Diff
added lab and hcl color spaces
parent
4a788d2d
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
src/mol-util/color/color.ts
+24
-2
24 additions, 2 deletions
src/mol-util/color/color.ts
src/mol-util/color/spaces/hcl.ts
+107
-0
107 additions, 0 deletions
src/mol-util/color/spaces/hcl.ts
src/mol-util/color/spaces/lab.ts
+164
-0
164 additions, 0 deletions
src/mol-util/color/spaces/lab.ts
with
295 additions
and
2 deletions
src/mol-util/color/color.ts
+
24
−
2
View file @
421bb9a8
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018
-2019
mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import
{
NumberArray
}
from
'
mol-util/type-helpers
'
;
import
{
Vec3
}
from
'
mol-math/linear-algebra
'
;
import
{
Hcl
}
from
'
./spaces/hcl
'
;
import
{
Lab
}
from
'
./spaces/lab
'
;
/** RGB color triplet expressed as a single number */
export
type
Color
=
{
readonly
'
@type
'
:
'
color
'
}
&
number
...
...
@@ -81,7 +83,7 @@ export namespace Color {
return
out
}
/** Linear interpolation between two colors */
/** Linear interpolation between two colors
in rgb space
*/
export
function
interpolate
(
c1
:
Color
,
c2
:
Color
,
t
:
number
):
Color
{
const
r1
=
c1
>>
16
&
255
const
g1
=
c1
>>
8
&
255
...
...
@@ -96,6 +98,26 @@ export namespace Color {
return
((
r
<<
16
)
|
(
g
<<
8
)
|
b
)
as
Color
}
const
tmpSaturateHcl
=
[
0
,
0
,
0
]
as
Hcl
export
function
saturate
(
c
:
Color
,
amount
:
number
):
Color
{
Hcl
.
fromColor
(
tmpSaturateHcl
,
c
)
return
Hcl
.
toColor
(
Hcl
.
saturate
(
tmpSaturateHcl
,
tmpSaturateHcl
,
amount
))
}
export
function
desaturate
(
c
:
Color
,
amount
:
number
):
Color
{
return
saturate
(
c
,
-
amount
)
}
const
tmpDarkenLab
=
[
0
,
0
,
0
]
as
Lab
export
function
darken
(
c
:
Color
,
amount
:
number
):
Color
{
Lab
.
fromColor
(
tmpDarkenLab
,
c
)
return
Lab
.
toColor
(
Lab
.
darken
(
tmpDarkenLab
,
tmpDarkenLab
,
amount
))
}
export
function
lighten
(
c
:
Color
,
amount
:
number
):
Color
{
return
darken
(
c
,
-
amount
)
}
}
export
type
ColorTable
<
T
extends
{
[
k
:
string
]:
number
[]
}
>
=
{
[
k
in
keyof
T
]:
Color
[]
}
...
...
This diff is collapsed.
Click to expand it.
src/mol-util/color/spaces/hcl.ts
0 → 100644
+
107
−
0
View file @
421bb9a8
/**
* Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*
* Color conversion code adapted from chroma.js (https://github.com/gka/chroma.js)
* Copyright (c) 2011-2018, Gregor Aisch, BSD license
*/
import
{
Color
}
from
'
../color
'
;
import
{
degToRad
}
from
'
mol-math/misc
'
;
import
{
Lab
}
from
'
./lab
'
;
export
{
Hcl
}
interface
Hcl
extends
Array
<
number
>
{
[
d
:
number
]:
number
,
'
@type
'
:
'
hcl
'
,
length
:
3
}
/**
* CIE HCL (Hue-Chroma-Luminance) color
*
* - H [0..360]
* - C [0..100]
* - L [0..100]
*
* Cylindrical representation of CIELUV (see https://en.wikipedia.org/wiki/CIELUV)
*/
function
Hcl
()
{
return
Hcl
.
zero
()
}
namespace
Hcl
{
export
function
zero
():
Hcl
{
const
out
=
[
0.1
,
0.0
,
0.0
]
out
[
0
]
=
0
return
out
as
Hcl
;
}
export
function
create
(
h
:
number
,
c
:
number
,
l
:
number
):
Hcl
{
const
out
=
zero
()
out
[
0
]
=
h
out
[
1
]
=
c
out
[
2
]
=
l
return
out
}
const
tmpFromColorLab
=
[
0
,
0
,
0
]
as
Lab
export
function
fromColor
(
out
:
Hcl
,
color
:
Color
):
Hcl
{
return
Lab
.
toHcl
(
out
,
Lab
.
fromColor
(
tmpFromColorLab
,
color
))
}
export
function
fromLab
(
hcl
:
Hcl
,
lab
:
Lab
):
Hcl
{
return
Lab
.
toHcl
(
hcl
,
lab
)
}
const
tmpToColorLab
=
[
0
,
0
,
0
]
as
Lab
export
function
toColor
(
hcl
:
Hcl
):
Color
{
return
Lab
.
toColor
(
toLab
(
tmpToColorLab
,
hcl
))
}
/**
* Convert from a qualitative parameter h and a quantitative parameter l to a 24-bit pixel.
*
* These formulas were invented by David Dalrymple to obtain maximum contrast without going
* out of gamut if the parameters are in the range 0-1.
* A saturation multiplier was added by Gregor Aisch
*/
export
function
toLab
(
out
:
Lab
,
hcl
:
Hcl
):
Lab
{
let
[
h
,
c
,
l
]
=
hcl
if
(
isNaN
(
h
))
h
=
0
h
=
degToRad
(
h
)
out
[
0
]
=
l
out
[
1
]
=
Math
.
cos
(
h
)
*
c
out
[
2
]
=
Math
.
sin
(
h
)
*
c
return
out
}
export
function
copy
(
out
:
Hcl
,
c
:
Hcl
):
Hcl
{
out
[
0
]
=
c
[
0
]
out
[
1
]
=
c
[
1
]
out
[
2
]
=
c
[
2
]
return
out
}
export
function
saturate
(
out
:
Hcl
,
c
:
Hcl
,
amount
:
number
):
Hcl
{
out
[
0
]
=
c
[
0
]
out
[
1
]
=
Math
.
max
(
0
,
c
[
1
]
+
Kn
*
amount
)
out
[
2
]
=
c
[
2
]
return
out
}
export
function
desaturate
(
out
:
Hcl
,
c
:
Hcl
,
amount
:
number
):
Hcl
{
return
saturate
(
out
,
c
,
-
amount
)
}
const
tmpDarkenLab
=
[
0
,
0
,
0
]
as
Lab
export
function
darken
(
out
:
Hcl
,
c
:
Hcl
,
amount
:
number
):
Hcl
{
toLab
(
tmpDarkenLab
,
c
)
return
Lab
.
toHcl
(
out
,
Lab
.
darken
(
tmpDarkenLab
,
tmpDarkenLab
,
amount
))
}
export
function
lighten
(
out
:
Hcl
,
c
:
Hcl
,
amount
:
number
):
Hcl
{
return
darken
(
out
,
c
,
-
amount
)
}
// Corresponds roughly to RGB brighter/darker
const
Kn
=
18
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
src/mol-util/color/spaces/lab.ts
0 → 100644
+
164
−
0
View file @
421bb9a8
/**
* Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*
* Color conversion code adapted from chroma.js (https://github.com/gka/chroma.js)
* Copyright (c) 2011-2018, Gregor Aisch, BSD license
*/
import
{
Color
}
from
'
../color
'
;
import
{
Hcl
}
from
'
./hcl
'
;
import
{
radToDeg
}
from
'
mol-math/misc
'
;
import
{
clamp
}
from
'
mol-math/interpolate
'
;
export
{
Lab
}
interface
Lab
extends
Array
<
number
>
{
[
d
:
number
]:
number
,
'
@type
'
:
'
lab
'
,
length
:
3
}
/**
* CIE LAB color
*
* - L* [0..100] - lightness from black to white
* - a [-100..100] - green (-) to red (+)
* - b [-100..100] - blue (-) to yellow (+)
*
* see https://en.wikipedia.org/wiki/CIELAB_color_space
*/
function
Lab
()
{
return
Lab
.
zero
()
}
namespace
Lab
{
export
function
zero
():
Lab
{
const
out
=
[
0.1
,
0.0
,
0.0
]
out
[
0
]
=
0
return
out
as
Lab
;
}
export
function
create
(
l
:
number
,
a
:
number
,
b
:
number
):
Lab
{
const
out
=
zero
()
out
[
0
]
=
l
out
[
1
]
=
a
out
[
2
]
=
b
return
out
}
export
function
fromColor
(
out
:
Lab
,
color
:
Color
):
Lab
{
const
[
r
,
g
,
b
]
=
Color
.
toRgb
(
color
)
const
[
x
,
y
,
z
]
=
rgbToXyz
(
r
,
g
,
b
)
const
l
=
116
*
y
-
16
out
[
0
]
=
l
<
0
?
0
:
l
out
[
1
]
=
500
*
(
x
-
y
)
out
[
2
]
=
200
*
(
y
-
z
)
return
out
}
export
function
fromHcl
(
out
:
Lab
,
hcl
:
Hcl
):
Lab
{
return
Hcl
.
toLab
(
out
,
hcl
)
}
export
function
toColor
(
lab
:
Lab
):
Color
{
let
y
=
(
lab
[
0
]
+
16
)
/
116
let
x
=
isNaN
(
lab
[
1
])
?
y
:
y
+
lab
[
1
]
/
500
let
z
=
isNaN
(
lab
[
2
])
?
y
:
y
-
lab
[
2
]
/
200
y
=
Yn
*
lab_xyz
(
y
)
x
=
Xn
*
lab_xyz
(
x
)
z
=
Zn
*
lab_xyz
(
z
)
const
r
=
xyz_rgb
(
3.2404542
*
x
-
1.5371385
*
y
-
0.4985314
*
z
)
// D65 -> sRGB
const
g
=
xyz_rgb
(
-
0.9692660
*
x
+
1.8760108
*
y
+
0.0415560
*
z
)
const
b
=
xyz_rgb
(
0.0556434
*
x
-
0.2040259
*
y
+
1.0572252
*
z
)
return
Color
.
fromRgb
(
Math
.
round
(
clamp
(
r
,
0
,
255
)),
Math
.
round
(
clamp
(
g
,
0
,
255
)),
Math
.
round
(
clamp
(
b
,
0
,
255
))
)
}
export
function
toHcl
(
out
:
Hcl
,
lab
:
Lab
):
Hcl
{
const
[
l
,
a
,
b
]
=
lab
const
c
=
Math
.
sqrt
(
a
*
a
+
b
*
b
)
let
h
=
(
radToDeg
(
Math
.
atan2
(
b
,
a
))
+
360
)
%
360
if
(
Math
.
round
(
c
*
10000
)
===
0
)
h
=
Number
.
NaN
out
[
0
]
=
h
out
[
1
]
=
c
out
[
2
]
=
l
return
out
}
export
function
copy
(
out
:
Lab
,
c
:
Lab
):
Lab
{
out
[
0
]
=
c
[
0
]
out
[
1
]
=
c
[
1
]
out
[
2
]
=
c
[
2
]
return
out
}
export
function
darken
(
out
:
Lab
,
c
:
Lab
,
amount
:
number
):
Lab
{
out
[
0
]
=
c
[
0
]
-
Kn
*
amount
out
[
1
]
=
c
[
1
]
out
[
2
]
=
c
[
2
]
return
out
}
export
function
lighten
(
out
:
Lab
,
c
:
Lab
,
amount
:
number
):
Lab
{
return
darken
(
out
,
c
,
-
amount
)
}
const
tmpSaturateHcl
=
[
0
,
0
,
0
]
as
Hcl
export
function
saturate
(
out
:
Lab
,
c
:
Lab
,
amount
:
number
):
Lab
{
toHcl
(
tmpSaturateHcl
,
c
)
return
Hcl
.
toLab
(
out
,
Hcl
.
saturate
(
tmpSaturateHcl
,
tmpSaturateHcl
,
amount
))
}
export
function
desaturate
(
out
:
Lab
,
c
:
Lab
,
amount
:
number
):
Lab
{
return
saturate
(
out
,
c
,
-
amount
)
}
// Corresponds roughly to RGB brighter/darker
const
Kn
=
18
/** D65 standard referent */
const
Xn
=
0.950470
const
Yn
=
1
const
Zn
=
1.088830
const
T0
=
0.137931034
// 4 / 29
const
T1
=
0.206896552
// 6 / 29
const
T2
=
0.12841855
// 3 * t1 * t1
const
T3
=
0.008856452
// t1 * t1 * t1
/** convert component from xyz to rgb */
function
xyz_rgb
(
c
:
number
)
{
return
255
*
(
c
<=
0.00304
?
12.92
*
c
:
1.055
*
Math
.
pow
(
c
,
1
/
2.4
)
-
0.055
)
}
/** convert component from lab to xyz */
function
lab_xyz
(
t
:
number
)
{
return
t
>
T1
?
t
*
t
*
t
:
T2
*
(
t
-
T0
)
}
/** convert component from rgb to xyz */
function
rgb_xyz
(
c
:
number
)
{
if
((
c
/=
255
)
<=
0.04045
)
return
c
/
12.92
return
Math
.
pow
((
c
+
0.055
)
/
1.055
,
2.4
)
}
/** convert component from xyz to lab */
function
xyz_lab
(
t
:
number
)
{
if
(
t
>
T3
)
return
Math
.
pow
(
t
,
1
/
3
)
return
t
/
T2
+
T0
}
function
rgbToXyz
(
r
:
number
,
g
:
number
,
b
:
number
)
{
r
=
rgb_xyz
(
r
)
g
=
rgb_xyz
(
g
)
b
=
rgb_xyz
(
b
)
const
x
=
xyz_lab
((
0.4124564
*
r
+
0.3575761
*
g
+
0.1804375
*
b
)
/
Xn
)
const
y
=
xyz_lab
((
0.2126729
*
r
+
0.7151522
*
g
+
0.0721750
*
b
)
/
Yn
)
const
z
=
xyz_lab
((
0.0193339
*
r
+
0.1191920
*
g
+
0.9503041
*
b
)
/
Zn
)
return
[
x
,
y
,
z
]
}
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment