Esempio n. 1
0
def test_speed(N=2):
    numpy.random.seed(1)
    osa = colorio.OsaUcs()
    cielab = colorio.CIELAB()
    # cam16 = colorio.CAM16(0.69, 20, L_A=64 / numpy.pi / 5)
    ciecam02 = colorio.CIECAM02(0.69, 20, L_A=64 / numpy.pi / 5)

    # This close probably means that another figure hasn't been properly closed.
    import matplotlib.pyplot as plt

    plt.close()

    perfplot.show(
        # Don't use numpy.random.rand(3, n) to avoid the CIECAM breakdown
        setup=lambda n: numpy.outer(numpy.random.rand(3), numpy.ones(n)) * 10,
        equality_check=None,
        kernels=[
            osa.to_xyz100,
            cielab.to_xyz100,
            # cam16.to_xyz100,
            lambda Jsh: ciecam02.to_xyz100(Jsh, "Jsh"),
            numpy.cbrt,
        ],
        labels=["OSA-UCS", "CIELAB", "CIECAM02", "cbrt"],
        n_range=[2 ** n for n in range(N)],
        logx=True,
        logy=True,
        # relative_to=3
    )
Esempio n. 2
0
def test_reference_xyz_d50(xyz100, ref):
    cielab = colorio.CIELAB(
        whitepoint=colorio.illuminants.whitepoints_cie1931["D50"])
    xyz100 = numpy.array(xyz100)
    assert numpy.all(
        abs(cielab.from_xyz100(xyz100) - ref) < 1.0e-4 * abs(numpy.array(ref)))
    return
Esempio n. 3
0
def test_reference_xyz(xyz100, ref):
    cielab = colorio.CIELAB()
    xyz100 = numpy.array(xyz100)
    assert numpy.all(
        abs(cielab.from_xyz100(xyz100) - ref) < 1.0e-4 * abs(numpy.array(ref))
        )
    return
Esempio n. 4
0
def test_speed(N=2):
    numpy.random.seed(1)
    osa = colorio.OsaUcs()
    cielab = colorio.CIELAB()
    # cam16 = colorio.CAM16(0.69, 20, L_A=64 / numpy.pi / 5)
    ciecam02 = colorio.CIECAM02(0.69, 20, L_A=64 / numpy.pi / 5)

    perfplot.plot(
        # Don't use numpy.random.rand(3, n) to avoid the CIECAM breakdown
        setup=lambda n: numpy.outer(numpy.random.rand(3), numpy.ones(n)) * 10,
        equality_check=None,
        kernels=[
            osa.to_xyz100,
            cielab.to_xyz100,
            # cam16.to_xyz100,
            lambda Jsh: ciecam02.to_xyz100(Jsh, "Jsh"),
            numpy.cbrt,
        ],
        labels=["OSA-UCS", "CIELAB", "CIECAM02", "cbrt"],
        n_range=[2**n for n in range(N)],
        logx=True,
        logy=True,
        # relative_to=3
    )
Esempio n. 5
0
def test_show_straights(cs=colorio.CIELAB()):
    colorio.show_straights(cs)
    return
Esempio n. 6
0
import numpy
import pytest

import colorio


@pytest.mark.parametrize(
    "colorspace, cut_000",
    [
        (colorio.CIELAB(), False),
        # (colorio.XYY(), True),
        (colorio.CAM02("UCS", 0.69, 20, 64 / numpy.pi / 5), False),
    ],
)
def test_srgb_gamut(colorspace, cut_000, n=10):
    colorspace.save_srgb_gamut("srgb.vtu", n=n, cut_000=cut_000)
    return


@pytest.mark.parametrize(
    "colorspace",
    [
        colorio.CIELAB(),
        colorio.XYY(),
        colorio.CAM02("UCS", 0.69, 20, 64 / numpy.pi / 5),
    ],
)
def test_cone_gamut(colorspace, n=10):
    observer = colorio.observers.cie_1931_2()
    colorspace.save_cone_gamut("cone.vtu", observer, max_Y=1)
    return
Esempio n. 7
0

@pytest.mark.parametrize(
    'colorspace, cut_000',
    [
        # colorio.CIELAB(),
        (colorio.XYY(), True),
        (colorio.CAM02('UCS', 0.69, 20, 64 / numpy.pi / 5), False),
    ])
def test_srgb_gamut(colorspace, cut_000, n=10):
    colorio.show_srgb_gamut(colorspace, 'srgb.vtu', n=n, cut_000=cut_000)
    return


@pytest.mark.parametrize('colorspace', [
    colorio.CIELAB(),
    colorio.CAM02('UCS', 0.69, 20, 64 / numpy.pi / 5),
])
def test_hdr_gamut(colorspace, n=10):
    colorio.show_hdr_gamut(colorspace, 'hdr.vtu', n=n)
    return


@pytest.mark.parametrize(
    'colorspace,cut_000',
    [
        # (colorio.CIELAB(), False),
        (colorio.XYY(), True),
        (colorio.CAM02('UCS', 0.69, 20, 64 / numpy.pi / 5), False),
    ])
def test_visible_gamut(colorspace, cut_000):
Esempio n. 8
0
def test_conversion(xyz):
    cielab = colorio.CIELAB()
    out = cielab.to_xyz100(cielab.from_xyz100(xyz))
    assert numpy.all(abs(xyz - out) < 1.0e-14)
    return
Esempio n. 9
0
import pytest

import colorio


@pytest.mark.parametrize(
    "cs,k0,level",
    [
        [colorio.XYY(), 2, 0.4],
        [colorio.CIELAB(), 0, 50],
        [colorio.CAM16UCS(0.69, 20, 4.074), 0, 50],
    ],
)
def test_visible_slice(cs, k0, level):
    cs.show_visible_slice(k0, level)
    # cs.save_visible_slice("visible-slice.png", k0, level)
    return


@pytest.mark.parametrize(
    "cs,k0,level",
    [[colorio.XYY(), 2, 0.4], [colorio.CIELUV(), 0, 50],
     [colorio.JzAzBz(), 0, 0.5]],
)
def test_macadam(cs, k0, level):
    cs.show_macadam(k0, level)
    cs.save_macadam("macadam.png", k0, level)
    return


@pytest.mark.parametrize(
Esempio n. 10
0
def get_srgb1(z, alpha=1, colorspace="CAM16"):
    assert alpha >= 0

    # A number of scalings f that map the magnitude [0, infty] to [0, 1] are possible.
    # One desirable property is
    # (1)  f(1/r) = 1 - f(r).
    # This makes sure that the representation of the inverse of a function is exactly as
    # light as the original function is dark. The function g_a(r) = 1 - a^|r| (with some
    # 0 < a < 1), as it is sometimes suggested (e.g., on Wikipedia
    # <https://en.wikipedia.org/wiki/Domain_coloring>) does _not_ fulfill (1).  The
    # function 2/pi * arctan(r) is _very_ close to g_(1/2) between 0 and 1 and has that
    # property, so this is good alternative. Here, we are using the simple r^a / r^a+1
    # with a configurable parameter a.

    def abs_scaling(r):
        # Fulfills (1) for any alpha >= 0
        return r**alpha / (r**alpha + 1)

    # def abs_scaling(r):
    #     # Fulfills (1).
    #    return 2 / numpy.pi * numpy.arctan(r)

    angle = numpy.arctan2(z.imag, z.real)
    absval_scaled = abs_scaling(numpy.abs(z))

    # We may have NaNs, so don't be too strict here.
    # assert numpy.all(absval_scaled >= 0)
    # assert numpy.all(absval_scaled <= 1)

    # It'd be lovely if one could claim that the grayscale of the cplot represents
    # exactly the absolute value of the complex number. The grayscale is computed as the
    # Y component of the XYZ-representation of the color, for linear SRGB values as
    #
    #     0.2126 * r + 0.7152 * g + 0.722 * b.
    #
    # Unfortunately, there is no perceptually uniform color space yet that uses
    # Y-luminance. CIELAB, CIECAM02, and CAM16 have their own values.
    if colorspace.upper() == "CAM16":
        L_A = 64 / numpy.pi / 5
        cam = colorio.CAM16UCS(0.69, 20, L_A)
        srgb = colorio.SrgbLinear()
        # The max radius is about 21.7, but crank up colors a little bit to make the
        # images more saturated. This leads to SRGB-cut-off of course.
        # r0 = find_max_srgb_radius(cam, srgb, L=50)
        # r0 = 21.65824845433235
        r0 = 25.0
        # Rotate the angles such a "green" color represents positive real values. The
        # rotation is chosen such that the ratio g/(r+b) (in rgb) is the largest for the
        # point 1.0.
        offset = 0.916_708 * numpy.pi
        # Map (r, angle) to a point in the color space; bicone mapping similar to what
        # HSL looks like <https://en.wikipedia.org/wiki/HSL_and_HSV>.
        rd = r0 - r0 * 2 * abs(absval_scaled - 0.5)
        cam_pts = numpy.array([
            100 * absval_scaled,
            rd * numpy.cos(angle + offset),
            rd * numpy.sin(angle + offset),
        ])
        # now just translate to srgb
        srgb_vals = srgb.to_srgb1(srgb.from_xyz100(cam.to_xyz100(cam_pts)))
        # Cut off the outliers. This restriction makes the representation less perfect,
        # but that's what it is with the SRGB color space.
        srgb_vals[srgb_vals > 1] = 1.0
        srgb_vals[srgb_vals < 0] = 0.0
    elif colorspace.upper() == "CIELAB":
        cielab = colorio.CIELAB()
        srgb = colorio.SrgbLinear()
        # The max radius is about 29.5, but crank up colors a little bit to make the
        # images more saturated. This leads to SRGB-cut-off of course.
        # r0 = find_max_srgb_radius(cielab, srgb, L=50)
        # r0 = 29.488203674554825
        r0 = 45.0
        # Rotate the angles such a "green" color represents positive real values. The
        # rotation is chosen such that the ratio g/(r+b) (in rgb) is the largest for the
        # point 1.0.
        offset = 0.893_686_8 * numpy.pi
        # Map (r, angle) to a point in the color space; bicone mapping similar to what
        # HSL looks like <https://en.wikipedia.org/wiki/HSL_and_HSV>.
        rd = r0 - r0 * 2 * abs(absval_scaled - 0.5)
        lab_pts = numpy.array([
            100 * absval_scaled,
            rd * numpy.cos(angle + offset),
            rd * numpy.sin(angle + offset),
        ])
        # now just translate to srgb
        srgb_vals = srgb.to_srgb1(srgb.from_xyz100(cielab.to_xyz100(lab_pts)))
        # Cut off the outliers. This restriction makes the representation less perfect,
        # but that's what it is with the SRGB color space.
        srgb_vals[srgb_vals > 1] = 1.0
        srgb_vals[srgb_vals < 0] = 0.0
    else:
        assert (
            colorspace.upper() == "HSL"
        ), f"Illegal colorspace {colorspace}. Pick one of CAM16, CIELAB, HSL."
        hsl = colorio.HSL()
        # rotate by 120 degrees to have green (0, 1, 0) for real positive numbers
        offset = 120
        hsl_vals = numpy.array([
            numpy.mod(angle / (2 * numpy.pi) * 360 + offset, 360),
            numpy.ones(angle.shape),
            absval_scaled,
        ])
        srgb_vals = hsl.to_srgb1(hsl_vals)
        # iron out the -1.82131e-17 round-offs
        srgb_vals[srgb_vals < 0] = 0

    return numpy.moveaxis(srgb_vals, 0, -1)
Esempio n. 11
0
''' Save the visible gamut of CIELAB D65 2° in a vtk file. '''

import colorio

illuminant = colorio.illuminants.d65()
observer = colorio.observers.cie_1931_2()

colorspace = colorio.CIELAB()
colorspace.save_visible_gamut(observer, illuminant, "cielab_d65_2_visible.vtk")