Tools for color research.
All color spaces implement the two methods
vals = colorspace.from_xyz100(xyz)
xyz = colorspace.to_xyz100(vals)
for conversion from and to XYZ100. Adding new color spaces is as easy as writing a class that provides those two methods.
colorspace.to_rgb_linear(vals)
colorspace.to_rgb1(vals)
colorspace.to_rgb255(vals)
# same for from_rgb*
The following color spaces are implemented:
-
XYZ (
colorio.cs.XYZ(100)
, the parameter determining the scaling) -
xyY (
colorio.cs.XYY(100)
, the paramter determining the scaling ofY
) -
Linear sRGB (
colorio.SrgbLinear()
) This class has the two additional methodsfrom_rgb1() to_rgb1()
for conversion from and to standard RGB.
-
HSL and HSV (
colorio.cs.HSL()
,colorio.cs.HSV()
) These classes have the two methodsfrom_srgb1() to_srgb1()
for conversion from and to standard RGB.
-
OSA-UCS (
colorio.cs.OsaUcs()
) -
CIELAB (
colorio.cs.CIELAB()
) -
CIELUV (
colorio.cs.CIELUV()
) -
RLAB (
colorio.cs.RLAB()
) -
DIN99 and its variants DIN99{b,c,d} (
colorio.cs.DIN99()
) -
ICtCp (
colorio.cs.ICtCp()
) -
IPT (
colorio.cs.IPT()
) -
import math import colorio ciecam02 = colorio.cs.CIECAM02(0.69, 20, 100) cam02 = colorio.cs.CAM02("UCS", 0.69, 20, 100)
The implementation contains a few improvements over the CIECAM02 specification (see here).
-
import math import colorio cam16 = colorio.cs.CAM16(0.69, 20, 100) cam16ucs = colorio.cs.CAM16UCS(0.69, 20, 100)
The implementation contains a few improvements over the CAM16 specification (see here).
-
Jzazbz (
colorio.cs.JzAzBz()
) -
Oklab (
colorio.cs.OKLAB()
) -
proLab (
colorio.cs.PROLAB()
) -
SRLAB2 (
colorio.cs.SRLAB2()
)
All methods in colorio are fully vectorized, i.e., computation is really fast.
colorio implements the following color difference formulas:
- CIE76
colorio.diff.cie76(lab1, lab2)
- CIE94
colorio.diff.cie94(lab1, lab2)
- CIEDE2000
colorio.diff.ciede2000(lab1, lab2)
- CMC l:c
colorio.diff.cmc(lab1, lab2)
colorio implements the following CATs:
- von Kries
cat, cat_inv = colorio.cat.von_kries(whitepoint_source, whitepoint_destination) xyz1 = cat @ xyz0
- CMCCAT2000
cat, cat_inv = colorio.cat.cmccat2000( whitepoint_source, whitepoint_destination, F, L_A1, L_A2 ) xyz1 = cat @ xyz0
- CAT02
cat, cat_inv = colorio.cat.cat02(whitepoint_source, whitepoint_destination, F, L_A) xyz1 = cat @ xyz0
- CAT16
cat, cat_inv = colorio.cat.cat16(whitepoint_source, whitepoint_destination, F, L_A) xyz1 = cat @ xyz0
colorio provides a number of useful tools for analyzing and visualizing color spaces.
CIELAB | CAM16-UCS | Oklab |
---|---|---|
The sRGB gamut is a perfect cube in sRGB space, and takes curious shapes when translated into other color spaces. The above images show the sRGB gamut in different color spaces.
import colorio
colorspace = colorio.cs.CIELAB()
p = colorio.plot_rgb_gamut(colorspace, n=51, show_grid=True)
p.show()
For more visualization options, you can store the sRGB data in a file
import colorio
colorspace = colorio.cs.CIELAB()
colorio.save_rgb_gamut("srgb.vtk", colorspace, n=51)
# all formats supported by https://github.com/nschloe/meshio
an open it with a tool of your choice. See here for how to open the file in ParaView.
For lightness slices of the sRGB gamut, use
import colorio
colorspace = colorio.cs.CIELAB()
p = colorio.plot_rgb_slice(colorspace, lightness=50.0, n=51)
p.show()
# or
# p.screenshot("screenshot.png")
XYZ | CIELAB | CAM16-UCS |
Same as above, but with the surface color gamut visible under a given illuminant.
import colorio
illuminant = colorio.illuminants.d65()
observer = colorio.observers.cie_1931_2()
colorspace = colorio.cs.XYZ(100)
colorio.save_surface_gamut("surface.vtk", colorspace, observer, illuminant)
p = colorio.plot_surface_gamut(colorspace, observer, illuminant)
p.show()
The gamut is shown in grey since sRGB screens are not able to display the colors anyway.
xyY | JzAzBz | Oklab |
---|---|---|
Same as above, but with the gamut of visible colors up to a given lightness Y
.
import colorio
observer = colorio.observers.cie_1931_2()
colorspace = colorio.cs.XYZ(100)
p = colorio.plot_visible_gamut(colorspace, observer, max_Y1=1)
p.show()
The gamut is shown in grey since sRGB screens are not able to display the colors anyway.
For slices, use
import colorio
colorspace = colorio.cs.CIELAB()
plt = colorio.plot_visible_slice(colorspace, lightness=0.5)
plt.show()
With colorio, you can easily visualize the basic color gradients of any color space. This may make defects in color spaces obvious, e.g., the well-known blue-distortion of CIELAB and related spaces. (Compare with the hue linearity data below.)
import colorio
lab = colorio.cs.CIELAB()
plt = colorio.plot_primary_srgb_gradients(lab)
plt.show()
CIELAB | DIN99 | OKLAB |
colorio contains lots of experimental data sets some of which can be used to assess certain properties of color spaces. Most data sets can also be visualized.
xyY | CIELAB | CAM16 |
Color difference data from MacAdam (1974). The above plots show the 43 color pairs that are of comparable lightness. The data is matched perfectly if the facing line stubs meet in one point.
import colorio
data = colorio.data.MacAdam1974()
cs = colorio.cs.CIELAB
plt = data.plot(cs)
plt.show()
print(colorio.data.MacAdam1974().stress(cs))
24.54774029343344
The same is available for
colorio.data.BfdP()
colorio.data.Leeds()
colorio.data.RitDupont()
colorio.data.Witt()
colorio.data.COMBVD() # a weighted combination of the above
xyY | CIELAB | CAM16 |
Munsell color data is visualized with
import colorio
cs = colorio.cs.CIELUV
plt = colorio.data.Munsell().plot(cs, V=5)
plt.show()
To retrieve the Munsell data in xyY format, use
import colorio
munsell = colorio.data.Munsell()
# munsell.h
# munsell.V
# munsell.C
# munsell.xyy
xyY (at Y=0.4) | CIELAB (at L=50) | CAM16 (at L=50) |
The famous MacAdam ellipses (from this article) can be plotted with
import colorio
cs = colorio.cs.CIELUV
plt = colorio.data.MacAdam1942(50.0).plot(cs)
plt.show()
The better the colorspace matches the data, the closer the ellipses are to circles of the same size.
xyY | CIELAB | CAM16 |
Likewise for Luo-Rigg.
import colorio
# xyy = colorio.cs.XYY(100)
# colorio.data.LuoRigg(8).show(xyy, 0.4)
# colorio.data.LuoRigg(8).savefig("luo-rigg-xyy.png", xyy, 0.4)
cieluv = colorio.cs.CIELUV()
plt = colorio.data.LuoRigg(8).plot(cieluv, 50)
plt.show()
xyY | CIELAB | CAM16 |
For example
import colorio
colorspace = colorio.cs.JzAzBz
plt = colorio.data.EbnerFairchild().plot(colorspace)
plt.show()
shows constant-hue data from the Ebner-Fairchild experiments in the hue-plane of some color spaces. (Ideally, all colors in one set sit on a line.)
Likewise for Hung-Berns:
xyY | CIELAB | CAM16 |
Note the dark blue distortion in CIELAB and CAM16.
import colorio
colorspace = colorio.cs.JzAzBz
plt = colorio.data.HungBerns().plot(colorspace)
plt.show()
Likewise for Xiao et al.:
xyY | CIELAB | CAM16 |
import colorio
colorspace = colorio.cs.CIELAB
plt = colorio.data.Xiao().plot(colorspace)
plt.show()
xyY | CIELAB | CAM16 |
Lightness experiment by Fairchild-Chen.
import colorio
cs = colorio.cs.CIELAB
plt = colorio.data.FairchildChen("SL2").plot(cs)
plt.show()
- Algorithmic improvements for the CIECAM02 and CAM16 color appearance models, Nico Schlömer, 2018
- On the conversion from OSA-UCS to CIEXYZ, Nico Schlömer, 2019
colorio is available from the Python Package Index, so just use
pip install colorio
to install.
To run the tests, simply check out this repository and run
tox
This software is published under the GPLv3 license.