Skip to content
This repository has been archived by the owner on Nov 22, 2019. It is now read-only.

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
Marie committed May 21, 2015
2 parents 82f832f + 0cb7599 commit 8e92c1f
Show file tree
Hide file tree
Showing 6 changed files with 252 additions and 84 deletions.
59 changes: 30 additions & 29 deletions lutLab/rgb_to_xyz_matrix.py → lutLab/rgb_to_rgb_matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@
.. moduleauthor:: `Marie FETIVEAU <github.com/mfe>`_
"""
__version__ = "0.4"
from utils.colors_helper import get_RGB_to_XYZ_matrix, get_primaries_matrix
__version__ = "0.5"
from utils.colors_helper import get_RGB_to_RGB_matrix, get_colorspace_matrix
from utils.colorspaces import COLORSPACES
from utils.private_colorspaces import PRIVATE_COLORSPACES
from utils.matrix_helper import matrix_to_string, matrix_to_spimtx_string
import argparse
import sys
from utils import debug_helper

XYZ_colorspace = 'XYZ'


class RGBToXYZMatrixException(Exception):
"""Module custom exception
Expand All @@ -25,7 +27,7 @@ class RGBToXYZMatrixException(Exception):
pass


def display_matrix(colorspace, matrix_format, primaries_only=False):
def display_matrix(in_colorspace, out_colorspace, matrix_format, primaries_only=False):
"""Display RGB to XYZ matrix corresponding to colorspace and formatting
as format
Expand All @@ -35,34 +37,28 @@ def display_matrix(colorspace, matrix_format, primaries_only=False):
matrix_format (str): output format. simple, matrix, spimtx.
"""
try:
colorspace_obj = COLORSPACES[colorspace]
except KeyError:
colorspace_obj = PRIVATE_COLORSPACES[colorspace]
if primaries_only:
matrix = get_primaries_matrix(colorspace_obj.get_red_primaries(),
colorspace_obj.get_green_primaries(),
colorspace_obj.get_blue_primaries())
matrix_type = "Primaries"
if in_colorspace == XYZ_colorspace:
if out_colorspace == XYZ_colorspace:
raise AttributeError("In and out colorspaces can't be both XYZ !")
matrix = get_colorspace_matrix(out_colorspace, primaries_only, inv=True)
elif out_colorspace == XYZ_colorspace:
matrix = get_colorspace_matrix(in_colorspace, primaries_only, inv=False)
else:
matrix = get_RGB_to_XYZ_matrix(colorspace_obj.get_red_primaries(),
colorspace_obj.get_green_primaries(),
colorspace_obj.get_blue_primaries(),
colorspace_obj.get_white_point())
matrix_type = "Primaries + white point"
matrix = get_RGB_to_RGB_matrix(in_colorspace, out_colorspace, primaries_only)

if matrix_format == 'simple':
matrix_dump = matrix_to_string(matrix)
inv_matrix_dump = matrix_to_string(matrix.I)
elif matrix_format == 'spimtx':
matrix_dump = matrix_to_spimtx_string(matrix)
inv_matrix_dump = matrix_to_spimtx_string(matrix.I)
else:
matrix_dump = "{0}".format(matrix)
inv_matrix_dump = "{0}".format(matrix.I)
print "{0} to XYZ matrix ({1}, {2} output):\n".format(colorspace, matrix_type, matrix_format)

print "{0} to {1} matrix ({2} {3} output):\n".format(in_colorspace,
out_colorspace,
primaries_only and "primaries" or
"primaries + white point",
matrix_format)
print matrix_dump
print "XYZ to {0} matrix ({1}, {2} output):\n".format(colorspace, matrix_type, matrix_format)
print inv_matrix_dump


def __get_options():
Expand All @@ -73,15 +69,20 @@ def __get_options():
"""
# Define parser
description = 'Print RGB -> XYZ matrix'
description = 'Print RGB -> RGB matrix'
parser = argparse.ArgumentParser(description=description)
# RGB colorspace
parser.add_argument("-c", "--colorspace",
colorspaces = sorted(COLORSPACES.keys() + PRIVATE_COLORSPACES.keys() + [XYZ_colorspace])
parser.add_argument("-in", "--in-colorspace",
help=("Input RGB Colorspace."),
type=str,
choices=sorted(COLORSPACES.keys() +
PRIVATE_COLORSPACES.keys()),
default='Rec709')
choices=colorspaces,
required=True)
parser.add_argument("-out", "--out-colorspace",
help=("Output RGB Colorspace."),
type=str,
choices=colorspaces,
required=True)
# Get primarie matrix only
parser.add_argument("-po", "--primaries-only",
help="Primaries matrix only, doesn't include white point.",
Expand Down Expand Up @@ -109,4 +110,4 @@ def __get_options():

if __name__ == '__main__':
ARGS = __get_options()
display_matrix(ARGS.colorspace, ARGS.format, ARGS.primaries_only)
display_matrix(ARGS.in_colorspace, ARGS.out_colorspace, ARGS.format, ARGS.primaries_only)
60 changes: 56 additions & 4 deletions test/colorspaces_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
"""
import unittest
import numpy
from utils.colorspaces import (REC709, ALEXALOGCV3, WIDEGAMUT, REC2020_12B,
ACESLOG_32f, sRGB, SGAMUTSLOG, SGAMUTSLOG2,
SGAMUTSLOG3,
SGAMUTSLOG3, ACESCC, ACESPROXY_10i
)
from utils.colors_helper import apply_matrix, get_RGB_to_RGB_matrix, get_colorspace_matrix


class ColorspaceTest(unittest.TestCase):
Expand All @@ -16,27 +18,77 @@ def test_gradation(self):
""" Test encode + decode
"""

colorspace_to_test = [REC709,
ALEXALOGCV3,
WIDEGAMUT,
REC2020_12B,
ACESLOG_32f,
ACESCC,
sRGB,
SGAMUTSLOG,
SGAMUTSLOG2,
SGAMUTSLOG3,
]
delta = 0.000000000000001
for space in colorspace_to_test:
name = space.__class__.__name__
for value in [0.0, 1.0, 0.5]:
res = space.decode_gradation(space.encode_gradation(value))
diff = abs(res - value)
message = ("{0} gradations not transparent ! "
"in: {1:8f} out: {2:8f}").format(name,
value,
res)
self.assert_(diff < delta, message)
self.assertTrue(numpy.isclose(res, value, atol=0.00000000000001), message)

def test_aces_proxy(self):
"""Test ACES proxy (matrix + encoding)
"""
ref_colors = [[0.001184464, 64.0, 0.001185417],
[222.875, 940.0, 222.860944204]
]
ACES_to_proxy_matrix = get_RGB_to_RGB_matrix('ACES', 'ACESproxy_10')
proxy_to_ACES_matrix = get_RGB_to_RGB_matrix('ACESproxy_10', 'ACES')
for color in ref_colors:
aces_proxy_lin = apply_matrix(ACES_to_proxy_matrix, [color[0]]*3)[2]
aces_proxy = ACESPROXY_10i._encode_gradation(aces_proxy_lin)
self.assertEqual(aces_proxy, color[1])
aces_proxy_lin = ACESPROXY_10i._decode_gradation(aces_proxy)
aces = apply_matrix(proxy_to_ACES_matrix, [aces_proxy_lin]*3)[0]
message = ("ACESproxy not valid ! "
"in: {0} out: {1}").format(aces, color[2])
self.assertTrue(numpy.isclose(aces, color[2], atol=0.000001), message)

def test_colorspace_matrices(self):
"""Test matrix conversions
"""
ACES_to_XYZ = [[0.95255239593818575, 0.0, 9.3678631660468553e-05],
[0.34396644976507507, 0.72816609661348575, -0.072132546378560786],
[0.0, 0.0, 1.0088251843515859]]

XYZ_to_ACES = [[1.0498110174979742, 0.0, -9.7484540579252874e-05],
[-0.49590302307731976, 1.3733130458157063, 0.098240036057309993],
[0.0, 0.0, 0.99125201820049902]]
self.assertEqual(ACES_to_XYZ, get_colorspace_matrix("ACES").tolist())
self.assertEqual(XYZ_to_ACES, get_colorspace_matrix("ACES", inv=True).tolist())

def test_rgb_to_rgb_matrix(self):
"""Test rgb to rgb matrix
"""
ACES_to_proxy_matrix = get_RGB_to_RGB_matrix('ACES', 'ACEScc')
ref_value = numpy.matrix([[1.4514393161, -0.2365107469, -0.2149285693],
[-0.0765537734, 1.1762296998, -0.0996759264],
[0.0083161484, -0.0060324498, 0.9977163014]])
self.assertTrue(numpy.allclose(ACES_to_proxy_matrix, ref_value),
"Processed ACES to ACEScc matrix is different from reference ! ")
ACES_to_Rec2020_matrix = get_RGB_to_RGB_matrix("ACES", 'Rec2020_12bits')
ref_value = [[1.5128613853114372, -0.2589874063019148, -0.22978603267468098],
[-0.079036464595355627, 1.1770668323294038, -0.10075565571179679],
[0.0020912324769753847, -0.03114411050570343, 0.95350416068074784]]
self.assertTrue(numpy.allclose(ACES_to_Rec2020_matrix, ref_value),
"Processed ACES to Rec2020 matrix is different from reference ! ")


if __name__ == "__main__":
Expand Down
9 changes: 1 addition & 8 deletions test/general_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import os
import tempfile
import shutil
from lutLab import rgb_to_xyz_matrix
from utils.colors_helper import get_colorspace_matrix, get_RGB_to_RGB_matrix


DISPLAY = False
Expand Down Expand Up @@ -45,13 +45,6 @@ def test_lut_3d(self):
# TODO
pass

def test_rgb_to_matrix(self):
"""Display rgb matrix
"""
rgb_to_xyz_matrix.display_matrix('Rec709', 'spimtx')
# TODO test values

def tearDown(self):
# Remove test directory
shutil.rmtree(self.tmp_dir)
Expand Down
66 changes: 60 additions & 6 deletions utils/colors_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
.. moduleauthor:: `Marie FETIVEAU <github.com/mfe>`_
"""
__version__ = "0.3"
__version__ = "0.4"
import math
import numpy

Expand Down Expand Up @@ -121,11 +121,8 @@ def apply_matrix(matrix, triplet):
.[float, float, float]
"""
a, b, c = triplet
ap = matrix.item(0, 0) * a + matrix.item(0, 1) * b + matrix.item(0, 2) * c
bp = matrix.item(1, 0) * a + matrix.item(1, 1) * b + matrix.item(1, 2) * c
cp = matrix.item(2, 0) * a + matrix.item(2, 1) * b + matrix.item(2, 2) * c
return [ap, bp, cp]
values = numpy.matrix(triplet)
return numpy.dot(matrix, values.T).T.tolist()[0]


def clamp_value(value, max_value=1.0, min_value=0.0):
Expand Down Expand Up @@ -307,3 +304,60 @@ def get_XYZ_to_RGB_matrix(xy_red, xy_green, xy_blue, xy_white):
"""
return get_RGB_to_XYZ_matrix(xy_red, xy_green, xy_blue, xy_white).I


def get_colorspace_matrix(colorspace, primaries_only=False, inv=False):
"""Return a colorspace RGB to XYZ matrix.
Args:
colorspace (str): input colorspace.
Kwargs:
primaries_only (bool): primaries matrix only, doesn't include white point.
inv (bool): return XYZ to RGB matrix.
Returns:
.numpy.matrix (3x3)
"""
from utils.colorspaces import COLORSPACES
from utils.private_colorspaces import PRIVATE_COLORSPACES
colorspace_obj = COLORSPACES.get(colorspace) or PRIVATE_COLORSPACES.get(colorspace)

if not colorspace_obj:
raise NotImplementedError("Could not find {0} colorspace".format(colorspace))

if primaries_only:
matrix = get_primaries_matrix(colorspace_obj.get_red_primaries(),
colorspace_obj.get_green_primaries(),
colorspace_obj.get_blue_primaries())
else:
matrix = get_RGB_to_XYZ_matrix(colorspace_obj.get_red_primaries(),
colorspace_obj.get_green_primaries(),
colorspace_obj.get_blue_primaries(),
colorspace_obj.get_white_point())
if inv:
return matrix.I
return matrix


def get_RGB_to_RGB_matrix(in_colorspace, out_colorspace, primaries_only=False):
"""Return RGB to RGB conversion matrix.
Args:
in_colorspace (str): input colorspace.
out_colorspace (str): output colorspace.
Kwargs:
primaries_only (bool): primaries matrix only, doesn't include white point.
Returns:
.numpy.matrix (3x3)
"""
# Get colorspace in to XYZ matrix
in_matrix = get_colorspace_matrix(in_colorspace, primaries_only)
# Get XYZ to colorspace out matrix
out_matrix = get_colorspace_matrix(out_colorspace, primaries_only, inv=True)
# Return scalar product of the 2 matrices
return numpy.dot(out_matrix, in_matrix)
Loading

0 comments on commit 8e92c1f

Please sign in to comment.