1 /*
2  */
3 
4 /*
5 
6     Copyright (C) 2014 Ferrero Andrea
7 
8     This program is free software: you can redistribute it and/or modify
9     it under the terms of the GNU General Public License as published by
10     the Free Software Foundation, either version 3 of the License, or
11     (at your option) any later version.
12 
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     GNU General Public License for more details.
17 
18     You should have received a copy of the GNU General Public License
19     along with this program. If not, see <http://www.gnu.org/licenses/>.
20 
21 
22  */
23 
24 /*
25 
26     These files are distributed with PhotoFlow - http://aferrero2707.github.io/PhotoFlow/
27 
28  */
29 
30 #ifndef PF_ICCSTORE_H
31 #define PF_ICCSTORE_H
32 
33 #include <string.h>
34 #include <string>
35 #include <lcms2.h>
36 #include <glibmm.h>
37 #include <vips/vips.h>
38 
39 #include "color.hh"
40 #include "../rt/rtengine/LUT.h"
41 
42 namespace PF
43 {
44 
45 enum TRC_type
46 {
47   PF_TRC_STANDARD=0,
48   PF_TRC_PERCEPTUAL=1,
49   PF_TRC_LINEAR=2,
50   PF_TRC_sRGB=3,
51   PF_TRC_GAMMA_22=4,
52   PF_TRC_GAMMA_18=5,
53   PF_TRC_UNKNOWN=1000
54 };
55 
56 
57 enum profile_mode_t {
58   PROF_MODE_NONE,
59   PROF_MODE_DEFAULT,
60   PROF_MODE_EMBEDDED,
61   PROF_MODE_EMBEDDED_sRGB,
62   PROF_MODE_CUSTOM,
63   PROF_MODE_ICC
64 };
65 
66 
67 enum profile_type_t {
68   PROF_TYPE_EMBEDDED,
69   PROF_TYPE_FROM_SETTINGS,
70   PROF_TYPE_FROM_DISK,
71   PROF_TYPE_sRGB,
72   PROF_TYPE_sRGB_D50,
73   PROF_TYPE_REC2020,
74   PROF_TYPE_ADOBE,
75   PROF_TYPE_PROPHOTO,
76   PROF_TYPE_PROPHOTO_D65,
77   PROF_TYPE_ACEScg,
78   PROF_TYPE_ACES,
79   PROF_TYPE_LAB,
80   PROF_TYPE_XYZ,
81   PROF_TYPE_CUSTOM,
82   PROF_TYPE_NONE,
83 };
84 
85 
86 
87 extern cmsToneCurve* Lstar_trc;
88 extern cmsToneCurve* iLstar_trc;
89 
90 
91 struct ICCProfileData
92 {
93   cmsToneCurve* perceptual_trc;
94   cmsToneCurve* perceptual_trc_inv;
95   TRC_type trc_type;
96 
97   //float perceptual_trc_vec[65536];
98   //float perceptual_trc_inv_vec[65536];
99 
100   float Y_R, Y_G, Y_B;
101 };
102 
103 
104 #define PF_GAMUT_MAP_NJZ 500
105 
106 class ICCTransform;
107 
108 class ICCProfile
109 {
110   bool has_colorants;
111   void* profile_data;
112   cmsUInt32Number profile_size;
113   cmsHPROFILE profile;
114   cmsToneCurve* perceptual_trc;
115   cmsToneCurve* perceptual_trc_inv;
116   profile_type_t profile_type;
117   TRC_type trc_type;
118   bool parametric_trc;
119 
120   Glib::ustring filename;
121 
122   //float perceptual_trc_vec[65536];
123   //float perceptual_trc_inv_vec[65536];
124 
125   LUTf p2l_lut, l2p_lut;
126 
127   double colorants[9];
128   float rgb2xyz[3][3];
129   float rgb2xyz100_D65[3][3];
130   float xyz1002rgb_D65[3][3];
131   float Y_R, Y_G, Y_B;
132 
133   void init_trc( cmsToneCurve* trc, cmsToneCurve* trc_inv );
134 
135   int refcount;
136 
137   ICCTransform* to_lab;
138   ICCTransform* from_lab;
139 
140   float** gamut_boundary;
141   float** gamut_boundary_out;
142   float* gamut_Lid_Cmax;
143 
144 
145 public:
146   ICCProfile();
147   virtual ~ICCProfile();
148 
ref()149   void ref() { refcount += 1; }
unref()150   void unref() { refcount -= 1; }
get_ref_count()151   int get_ref_count() { return refcount; }
152 
set_file_name(Glib::ustring name)153   void set_file_name( Glib::ustring name ) { filename = name; }
get_file_name()154   Glib::ustring get_file_name() { return filename; }
155 
156   void init_colorants();
157   void init_trc();
158   void init_Lab_conversions( ICCProfile* plab );
159 
160   bool is_rgb();
161   bool is_grayscale();
162   bool is_lab();
163   bool is_cmyk();
164 
165   bool is_matrix();
get_colorants()166   double* get_colorants() { return colorants; }
167 
set_profile_type(profile_type_t p)168   void set_profile_type(profile_type_t p) { profile_type = p; }
get_profile_type()169   profile_type_t get_profile_type() { return profile_type; }
set_trc_type(TRC_type type)170   void set_trc_type(TRC_type type) { trc_type = type; }
get_trc_type()171   TRC_type get_trc_type() { return trc_type; }
is_linear()172   bool is_linear() { return( get_trc_type() == PF_TRC_LINEAR ); }
is_parametric()173   bool is_parametric() { return( parametric_trc ); }
is_perceptual()174   bool is_perceptual() { return( get_trc_type() == PF_TRC_PERCEPTUAL ); }
is_standard()175   bool is_standard() { return( get_trc_type() == PF_TRC_STANDARD ); }
176 
get_p2l_trc()177   cmsToneCurve* get_p2l_trc() { return perceptual_trc; }
get_l2p_trc()178   cmsToneCurve* get_l2p_trc() { return perceptual_trc_inv; }
179 
180   void set_profile( cmsHPROFILE p );
181   cmsHPROFILE get_profile(); //{ return profile; }
182 
get_profile_size()183   cmsUInt32Number get_profile_size() { return profile_size; }
get_profile_data()184   void* get_profile_data() { return profile_data; }
185 
186   cmsFloat32Number linear2perceptual( cmsFloat32Number val );
187   cmsFloat32Number perceptual2linear( cmsFloat32Number val );
188 
189   //float* get_linear2perceptual_vec() { return perceptual_trc_inv_vec; }
190   //float* get_perceptual2linear_vec() { return perceptual_trc_vec; }
191 
get_luminance(const float & R,const float & G,const float & B)192   float get_luminance( const float& R, const float& G, const float& B )
193   {
194     return( (has_colorants) ? Y_R*R + Y_G*G + Y_B*B : 0.0f );
195   }
196   //void get_luminance( float* RGBv, float* Lv, size_t size );
197 
198   float get_lightness( const float& R, const float& G, const float& B );
199   void get_lightness( float* RGBv, float* Lv, size_t size );
200 
201   void to_Jzazbz( const float& R, const float& G, const float& B, float& Jz, float& az, float& bz );
202   void from_Jzazbz( const float& Jz, const float& az, const float& bz, float& R, float& G, float& B );
203 
204   void init_gamut_mapping();
205   void set_destination_gamut(ICCProfile* pout);
get_gamut_boundary()206   float** get_gamut_boundary() { return gamut_boundary; }
get_gamut_Lid_Cmax()207   float* get_gamut_Lid_Cmax() { return gamut_Lid_Cmax; }
208   void gamut_mapping( float& R, float& G, float& B, float** gamut_boundary_out, float* gamut_Lid_Cmax_out, float saturation );
209   bool chroma_compression( float& J, float& C, float& H, float** gamut_boundary_out, float* gamut_Lid_Cmax_out, float saturation );
210 
211   bool equals_to( PF::ICCProfile* prof);
212 
get_data()213   ICCProfileData* get_data()
214   {
215     ICCProfileData* data = new ICCProfileData;
216     data->trc_type = trc_type;
217     //memcpy( data->perceptual_trc_vec, perceptual_trc_vec, sizeof(perceptual_trc_vec) );
218     //memcpy( data->perceptual_trc_inv_vec, perceptual_trc_inv_vec, sizeof(perceptual_trc_inv_vec) );
219     data->perceptual_trc =  cmsDupToneCurve( perceptual_trc );
220     data->perceptual_trc_inv =  cmsDupToneCurve( perceptual_trc_inv );
221     data->Y_R = Y_R;
222     data->Y_G = Y_G;
223     data->Y_B = Y_B;
224 
225     return data;
226   }
227 };
228 
229 
230 //ICCProfileData* get_icc_profile_data( VipsImage* img );
231 //void free_icc_profile_data( ICCProfileData* data );
232 void set_icc_profile( VipsImage* img, ICCProfile* prof );
233 ICCProfile* get_icc_profile( VipsImage* img );
234 void iccprofile_unref( void* prof );
235 
236 //cmsFloat32Number linear2perceptual( ICCProfileData* data, cmsFloat32Number val );
237 //cmsFloat32Number perceptual2linear( ICCProfileData* data, cmsFloat32Number val );
238 
239 
240 class DiskProfile: public ICCProfile
241 {
242 public:
243   DiskProfile();
244 };
245 
246 
247 class ACESProfile: public ICCProfile
248 {
249 public:
250   ACESProfile(TRC_type type);
251 };
252 
253 
254 class Rec2020Profile: public ICCProfile
255 {
256 public:
257   Rec2020Profile(TRC_type type);
258 };
259 
260 
261 class sRGBProfile: public ICCProfile
262 {
263 public:
264   sRGBProfile(TRC_type type);
265 };
266 
267 
268 class sRGBProfileD50: public ICCProfile
269 {
270 public:
271   sRGBProfileD50(TRC_type type);
272 };
273 
274 
275 class ProPhotoProfile: public ICCProfile
276 {
277 public:
278   ProPhotoProfile(TRC_type type);
279 };
280 
281 
282 class ProPhotoProfileD65: public ICCProfile
283 {
284 public:
285   ProPhotoProfileD65(TRC_type type);
286 };
287 
288 
289 class LabProfile: public ICCProfile
290 {
291 public:
292   LabProfile(TRC_type type);
293 };
294 
295 
296 class XYZProfile: public ICCProfile
297 {
298 public:
299   XYZProfile(TRC_type type);
300 };
301 
302 
303 class ICCTransform
304 {
305   ICCProfile* in_profile;
306   ICCProfile* out_profile;
307   cmsUInt32Number intent;
308   bool bpc;
309   float adaptation_state;
310   cmsHTRANSFORM transform;
311 
312   LUTf trc_lut, itrc_lut;
313 
314   bool is_rgb2rgb;
315   float rgb2rgb[3][3];
316 
317   cmsColorSpaceSignature input_cs_type;
318   cmsColorSpaceSignature output_cs_type;
319 
320 public:
ICCTransform()321   ICCTransform(): in_profile(NULL), out_profile(NULL), transform(NULL) {}
~ICCTransform()322   ~ICCTransform() {
323     if( transform ) {
324       cmsDeleteTransform( transform );
325     }
326   }
valid()327   bool valid() { return( transform!=NULL || is_rgb2rgb ); }
328   void init(ICCProfile* in_profile, ICCProfile* out_profile, VipsBandFormat band_fmt,
329       cmsUInt32Number intent=INTENT_RELATIVE_COLORIMETRIC,
330       bool bpc=true, float adaptation_state=0);
331   void apply(float* in, float* out, int n=1);
332 };
333 
334 
335 class ICCStore
336 {
337   ICCProfile* srgb_profiles[6];
338   ICCProfile* srgb_d50_profiles[6];
339   ICCProfile* rec2020_profiles[6];
340   ICCProfile* aces_profiles[6];
341   ICCProfile* acescg_profiles[6];
342   ICCProfile* adobe_profiles[6];
343   ICCProfile* prophoto_profiles[6];
344   ICCProfile* prophoto_d65_profiles[6];
345   ICCProfile* system_monitor_profile;
346   std::vector<ICCProfile*> profiles;
347 
348   ICCProfile* Lab_profile;
349   ICCProfile* XYZ_profile;
350 
351   static ICCStore* instance;
352 
353   Glib::ustring    defaultMonitorProfile;  // Main monitors standard profile name, from OS
354 public:
355   ICCStore();
356 
357   static ICCStore& Instance();
358 
get_srgb_profile(TRC_type type)359   ICCProfile* get_srgb_profile(TRC_type type) { return srgb_profiles[type]; }
360   ICCProfile* get_profile(profile_type_t ptype, TRC_type trc_type);
361   ICCProfile* get_profile( Glib::ustring pname );
362   ICCProfile* get_profile( void* pdata, cmsUInt32Number psize );
363   ICCProfile* get_profile( cmsHPROFILE profile );
364 
get_Lab_profile()365   ICCProfile* get_Lab_profile() { return Lab_profile; }
get_XYZ_profile()366   ICCProfile* get_XYZ_profile() { return XYZ_profile; }
367 
get_Lstar_trc()368   cmsToneCurve* get_Lstar_trc() {return Lstar_trc; }
get_iLstar_trc()369   cmsToneCurve* get_iLstar_trc() {return iLstar_trc; }
370 
371   void set_system_monitor_profile( cmsHPROFILE profile );
get_system_monitor_profile()372   ICCProfile* get_system_monitor_profile() { return system_monitor_profile; }
373 };
374 }
375 
376 
377 #endif
378 
379 
380