13
13
import numpy as np
14
14
import os
15
15
import re
16
+ from collections import OrderedDict
16
17
from werkzeug .contrib .cache import SimpleCache
17
18
18
- from colour import RGB_COLOURSPACES , RGB_to_XYZ , read_image
19
- from colour .models import (XYZ_to_colourspace_model , XYZ_to_RGB , RGB_to_RGB ,
20
- oetf_reverse_sRGB )
19
+ from colour import (LOG_DECODING_CURVES , OETFS_REVERSE ,
20
+ RGB_COLOURSPACES , RGB_to_RGB , RGB_to_XYZ , XYZ_to_RGB ,
21
+ read_image )
22
+ from colour .models import XYZ_to_colourspace_model , function_gamma
21
23
from colour .plotting import filter_cmfs , filter_RGB_colourspaces
22
24
from colour .utilities import first_item , normalise_maximum , tsplit , tstack
23
25
30
32
31
33
__all__ = [
32
34
'LINEAR_FILE_FORMATS' , 'DEFAULT_FLOAT_DTYPE' , 'COLOURSPACE_MODELS' ,
33
- 'COLOURSPACE_MODELS_LABELS' , 'PRIMARY_COLOURSPACE' ,
34
- 'SECONDARY_COLOURSPACE' , 'IMAGE_COLOURSPACE' , 'COLOURSPACE_MODEL' ,
35
- 'IMAGE_CACHE' , 'load_image' , 'colourspace_model_axis_reorder' ,
36
- 'colourspace_model_faces_reorder' , 'colourspace_models' ,
37
- 'RGB_colourspaces' , 'buffer_geometry' , 'create_plane' , 'create_box' ,
35
+ 'COLOURSPACE_MODELS_LABELS' , 'DECODING_CCTFS' , 'PRIMARY_COLOURSPACE' ,
36
+ 'SECONDARY_COLOURSPACE' , 'IMAGE_COLOURSPACE' , 'IMAGE_DECODING_CCTF' ,
37
+ 'COLOURSPACE_MODEL' , 'IMAGE_CACHE' , 'load_image' ,
38
+ 'colourspace_model_axis_reorder' , 'colourspace_model_faces_reorder' ,
39
+ 'decoding_cctfs' , 'colourspace_models' , 'RGB_colourspaces' ,
40
+ 'buffer_geometry' , 'create_plane' , 'create_box' ,
38
41
'RGB_colourspace_volume_visual' , 'spectral_locus_visual' ,
39
42
'RGB_image_scatter_visual' , 'image_data'
40
43
]
93
96
'hdr-CIELAB', 'hdr-IPT'}**
94
97
"""
95
98
99
+ DECODING_CCTFS = OrderedDict ()
100
+ DECODING_CCTFS .update (
101
+ sorted ({
102
+ 'Gamma 2.2' : lambda x : function_gamma (x , 2.2 ),
103
+ 'Gamma 2.4' : lambda x : function_gamma (x , 2.4 ),
104
+ 'Gamma 2.6' : lambda x : function_gamma (x , 2.6 )
105
+ }.items ()))
106
+ DECODING_CCTFS .update (sorted (OETFS_REVERSE .items ()))
107
+ DECODING_CCTFS .update (sorted (LOG_DECODING_CURVES .items ()))
108
+ """
109
+ Decoding colour component transfer functions.
110
+
111
+ DECODING_CCTFS : OrderedDict
112
+ """
113
+
96
114
PRIMARY_COLOURSPACE = 'sRGB'
97
115
"""
98
116
Primary analysis RGB colourspace.
114
132
IMAGE_COLOURSPACE : unicode
115
133
"""
116
134
135
+ IMAGE_DECODING_CCTF = 'sRGB'
136
+ """
137
+ Analysed image RGB colourspace decoding colour component transfer function.
138
+
139
+ IMAGE_DECODING_CCTF : unicode
140
+ """
141
+
117
142
COLOURSPACE_MODEL = 'CIE xyY'
118
143
"""
119
144
Analysis colour model.
132
157
"""
133
158
134
159
135
- def load_image (path ):
160
+ def load_image (path , decoding_cctf = 'sRGB' ):
136
161
"""
137
162
Loads the image at given path and caches it in `IMAGE_CACHE` cache. If the
138
163
image is already cached, it is returned directly.
@@ -141,21 +166,28 @@ def load_image(path):
141
166
----------
142
167
path : unicode
143
168
Image path.
169
+ decoding_cctf : unicode, optional
170
+ Decoding colour component transfer function (Decoding CCTF) /
171
+ electro-optical transfer function (EOTF / EOCF) that maps an
172
+ :math:`R'G'B'` video component signal value to tristimulus values at
173
+ the display.
144
174
145
175
Returns
146
176
-------
147
177
ndarray
148
178
Image as a ndarray.
149
179
"""
150
180
151
- RGB = IMAGE_CACHE .get (path )
181
+ key = '{0}-{1}' .format (path , decoding_cctf )
182
+
183
+ RGB = IMAGE_CACHE .get (key )
152
184
if RGB is None :
153
185
RGB = read_image (path )
154
186
155
187
if os .path .splitext (path )[- 1 ].lower () not in LINEAR_FILE_FORMATS :
156
- RGB = oetf_reverse_sRGB (RGB )
188
+ RGB = DECODING_CCTFS [ decoding_cctf ] (RGB )
157
189
158
- IMAGE_CACHE .set (path , RGB )
190
+ IMAGE_CACHE .set (key , RGB )
159
191
160
192
return RGB
161
193
@@ -220,6 +252,20 @@ def colourspace_model_faces_reorder(a, model=None):
220
252
return a
221
253
222
254
255
+ def decoding_cctfs ():
256
+ """
257
+ Returns the decoding colour component transfer functions formatted as
258
+ *JSON*.
259
+
260
+ Returns
261
+ -------
262
+ unicode
263
+ Decoding colour component transfer functions formatted as *JSON*.
264
+ """
265
+
266
+ return json .dumps (DECODING_CCTFS .keys ())
267
+
268
+
223
269
def colourspace_models ():
224
270
"""
225
271
Returns the colourspace models formatted as *JSON*.
@@ -608,6 +654,7 @@ def RGB_image_scatter_visual(path,
608
654
primary_colourspace = PRIMARY_COLOURSPACE ,
609
655
secondary_colourspace = SECONDARY_COLOURSPACE ,
610
656
image_colourspace = IMAGE_COLOURSPACE ,
657
+ image_decoding_cctf = IMAGE_DECODING_CCTF ,
611
658
colourspace_model = COLOURSPACE_MODEL ,
612
659
out_of_primary_colourspace_gamut = False ,
613
660
out_of_secondary_colourspace_gamut = False ,
@@ -628,6 +675,11 @@ def RGB_image_scatter_visual(path,
628
675
image_colourspace: unicode, optional
629
676
**{'Primary', 'Secondary'}**,
630
677
Analysed image RGB colourspace.
678
+ image_decoding_cctf : unicode, optional
679
+ Analysed image decoding colour component transfer function
680
+ (Decoding CCTF) / electro-optical transfer function (EOTF / EOCF) that
681
+ maps an :math:`R'G'B'` video component signal value to tristimulus
682
+ values at the display.
631
683
colourspace_model : unicode, optional
632
684
Colourspace model used to generate the visual geometry.
633
685
out_of_primary_colourspace_gamut : bool, optional
@@ -659,7 +711,7 @@ def RGB_image_scatter_visual(path,
659
711
colourspace = (primary_colourspace if image_colourspace == 'Primary' else
660
712
secondary_colourspace )
661
713
662
- RGB = load_image (path )
714
+ RGB = load_image (path , image_decoding_cctf )
663
715
664
716
if saturate :
665
717
RGB = np .clip (RGB , 0 , 1 )
@@ -698,6 +750,7 @@ def image_data(path,
698
750
primary_colourspace = PRIMARY_COLOURSPACE ,
699
751
secondary_colourspace = SECONDARY_COLOURSPACE ,
700
752
image_colourspace = IMAGE_COLOURSPACE ,
753
+ image_decoding_cctf = IMAGE_DECODING_CCTF ,
701
754
out_of_primary_colourspace_gamut = False ,
702
755
out_of_secondary_colourspace_gamut = False ,
703
756
saturate = False ):
@@ -716,6 +769,11 @@ def image_data(path,
716
769
image_colourspace: unicode, optional
717
770
**{'Primary', 'Secondary'}**,
718
771
Analysed image RGB colourspace.
772
+ image_decoding_cctf : unicode, optional
773
+ Analysed image decoding colour component transfer function
774
+ (Decoding CCTF) / electro-optical transfer function (EOTF / EOCF) that
775
+ maps an :math:`R'G'B'` video component signal value to tristimulus
776
+ values at the display.
719
777
out_of_primary_colourspace_gamut : bool, optional
720
778
Whether to only generate the out of primary RGB colourspace gamut
721
779
values.
@@ -738,7 +796,7 @@ def image_data(path,
738
796
filter_RGB_colourspaces ('^{0}$' .format (
739
797
re .escape (secondary_colourspace ))))
740
798
741
- RGB = load_image (path )
799
+ RGB = load_image (path , image_decoding_cctf )
742
800
743
801
if saturate :
744
802
RGB = np .clip (RGB , 0 , 1 )
0 commit comments