85
96
g_message( __VA_ARGS__ );\
100
#define DEBUG_MESSAGE_SCISLAC(key, ...)
101
#define DEBUG_MESSAGE(key, ...)
88
102
#endif // DEBUG_LCMS
90
104
static SPObjectClass *cprof_parent_class;
94
cmsHPROFILE ColorProfile::_sRGBProf = 0;
96
cmsHPROFILE ColorProfile::getSRGBProfile() {
106
class ColorProfileImpl {
108
#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
109
static cmsHPROFILE _sRGBProf;
110
static cmsHPROFILE _NullProf;
111
#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
115
#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
116
static cmsUInt32Number _getInputFormat( cmsColorSpaceSignature space );
118
static cmsHPROFILE getNULLProfile();
119
static cmsHPROFILE getSRGBProfile();
121
void _clearProfile();
123
cmsHPROFILE _profHandle;
124
cmsProfileClassSignature _profileClass;
125
cmsColorSpaceSignature _profileSpace;
126
cmsHTRANSFORM _transf;
127
cmsHTRANSFORM _revTransf;
128
cmsHTRANSFORM _gamutTransf;
129
#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
136
#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
137
cmsColorSpaceSignature asICColorSpaceSig(ColorSpaceSig const & sig)
139
return ColorSpaceSigWrapper(sig);
142
cmsProfileClassSignature asICColorProfileClassSig(ColorProfileClassSig const & sig)
144
return ColorProfileClassSigWrapper(sig);
146
#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
148
} // namespace Inkscape
150
ColorProfileImpl::ColorProfileImpl()
151
#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
154
_profileClass(cmsSigInputClass),
155
_profileSpace(cmsSigRgbData),
159
#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
163
#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
165
cmsHPROFILE ColorProfileImpl::_sRGBProf = 0;
167
cmsHPROFILE ColorProfileImpl::getSRGBProfile() {
97
168
if ( !_sRGBProf ) {
98
169
_sRGBProf = cmsCreate_sRGBProfile();
171
return ColorProfileImpl::_sRGBProf;
103
cmsHPROFILE ColorProfile::_NullProf = 0;
174
cmsHPROFILE ColorProfileImpl::_NullProf = 0;
105
cmsHPROFILE ColorProfile::getNULLProfile() {
176
cmsHPROFILE ColorProfileImpl::getNULLProfile() {
106
177
if ( !_NullProf ) {
107
178
_NullProf = cmsCreateNULLProfile();
109
180
return _NullProf;
112
#endif // ENABLE_LCMS
183
#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
115
186
* Register ColorProfile class and return its type.
487
#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
423
icColorSpaceSignature space;
490
cmsColorSpaceSignature space;
491
cmsUInt32Number inForm;
427
DWORD ColorProfile::_getInputFormat( icColorSpaceSignature space )
494
cmsUInt32Number ColorProfileImpl::_getInputFormat( cmsColorSpaceSignature space )
429
496
MapMap possible[] = {
430
{icSigXYZData, TYPE_XYZ_16},
431
{icSigLabData, TYPE_Lab_16},
433
{icSigYCbCrData, TYPE_YCbCr_16},
434
{icSigYxyData, TYPE_Yxy_16},
435
{icSigRgbData, TYPE_RGB_16},
436
{icSigGrayData, TYPE_GRAY_16},
437
{icSigHsvData, TYPE_HSV_16},
438
{icSigHlsData, TYPE_HLS_16},
439
{icSigCmykData, TYPE_CMYK_16},
440
{icSigCmyData, TYPE_CMY_16},
497
{cmsSigXYZData, TYPE_XYZ_16},
498
{cmsSigLabData, TYPE_Lab_16},
500
{cmsSigYCbCrData, TYPE_YCbCr_16},
501
{cmsSigYxyData, TYPE_Yxy_16},
502
{cmsSigRgbData, TYPE_RGB_16},
503
{cmsSigGrayData, TYPE_GRAY_16},
504
{cmsSigHsvData, TYPE_HSV_16},
505
{cmsSigHlsData, TYPE_HLS_16},
506
{cmsSigCmykData, TYPE_CMYK_16},
507
{cmsSigCmyData, TYPE_CMY_16},
496
cmsHPROFILE Inkscape::colorprofile_get_handle( SPDocument* document, guint* intent, gchar const* name )
563
cmsHPROFILE Inkscape::CMSSystem::getHandle( SPDocument* document, guint* intent, gchar const* name )
498
565
cmsHPROFILE prof = 0;
500
567
SPObject* thing = bruteFind( document, name );
502
prof = COLORPROFILE(thing)->profHandle;
569
prof = COLORPROFILE(thing)->impl->_profHandle;
506
573
*intent = thing ? COLORPROFILE(thing)->rendering_intent : (guint)RENDERING_INTENT_UNKNOWN;
510
576
DEBUG_MESSAGE( lcmsThree, "<color-profile> queried for profile of '%s'. Returning %p with intent of %d", name, prof, (intent? *intent:0) );
581
Inkscape::ColorSpaceSig ColorProfile::getColorSpace() const {
582
return ColorSpaceSigWrapper(impl->_profileSpace);
585
Inkscape::ColorProfileClassSig ColorProfile::getProfileClass() const {
586
return ColorProfileClassSigWrapper(impl->_profileClass);
516
589
cmsHTRANSFORM ColorProfile::getTransfToSRGB8()
518
if ( !_transf && profHandle ) {
591
if ( !impl->_transf && impl->_profHandle ) {
519
592
int intent = getLcmsIntent(rendering_intent);
520
_transf = cmsCreateTransform( profHandle, _getInputFormat(_profileSpace), getSRGBProfile(), TYPE_RGBA_8, intent, 0 );
593
impl->_transf = cmsCreateTransform( impl->_profHandle, ColorProfileImpl::_getInputFormat(impl->_profileSpace), ColorProfileImpl::getSRGBProfile(), TYPE_RGBA_8, intent, 0 );
595
return impl->_transf;
525
598
cmsHTRANSFORM ColorProfile::getTransfFromSRGB8()
527
if ( !_revTransf && profHandle ) {
600
if ( !impl->_revTransf && impl->_profHandle ) {
528
601
int intent = getLcmsIntent(rendering_intent);
529
_revTransf = cmsCreateTransform( getSRGBProfile(), TYPE_RGBA_8, profHandle, _getInputFormat(_profileSpace), intent, 0 );
602
impl->_revTransf = cmsCreateTransform( ColorProfileImpl::getSRGBProfile(), TYPE_RGBA_8, impl->_profHandle, ColorProfileImpl::_getInputFormat(impl->_profileSpace), intent, 0 );
604
return impl->_revTransf;
534
607
cmsHTRANSFORM ColorProfile::getTransfGamutCheck()
536
if ( !_gamutTransf ) {
537
_gamutTransf = cmsCreateProofingTransform(getSRGBProfile(), TYPE_RGBA_8, getNULLProfile(), TYPE_GRAY_8, profHandle, INTENT_RELATIVE_COLORIMETRIC, INTENT_RELATIVE_COLORIMETRIC, (cmsFLAGS_GAMUTCHECK|cmsFLAGS_SOFTPROOFING));
609
if ( !impl->_gamutTransf ) {
610
impl->_gamutTransf = cmsCreateProofingTransform(ColorProfileImpl::getSRGBProfile(),
612
ColorProfileImpl::getNULLProfile(),
615
INTENT_RELATIVE_COLORIMETRIC,
616
INTENT_RELATIVE_COLORIMETRIC,
617
(cmsFLAGS_GAMUTCHECK | cmsFLAGS_SOFTPROOFING));
619
return impl->_gamutTransf;
542
bool ColorProfile::GamutCheck(SPColor color){
622
bool ColorProfile::GamutCheck(SPColor color)
545
626
guint32 val = color.toRGBA32(0);
632
cmsGetAlarmCodes(&alarm_r, &alarm_g, &alarm_b);
633
cmsSetAlarmCodes(255, 255, 255);
635
cmsUInt16Number oldAlarmCodes[cmsMAXCHANNELS] = {0};
636
cmsGetAlarmCodes(oldAlarmCodes);
637
cmsUInt16Number newAlarmCodes[cmsMAXCHANNELS] = {0};
638
newAlarmCodes[0] = ~0;
639
cmsSetAlarmCodes(newAlarmCodes);
640
#endif // HAVE_LIBLCMS1
642
cmsUInt8Number outofgamut = 0;
546
643
guchar check_color[4] = {
547
644
SP_RGBA32_R_U(val),
548
645
SP_RGBA32_G_U(val),
549
646
SP_RGBA32_B_U(val),
552
int alarm_r, alarm_g, alarm_b;
553
cmsGetAlarmCodes(&alarm_r, &alarm_g, &alarm_b);
554
cmsSetAlarmCodes(255, 255, 255);
555
648
cmsDoTransform(ColorProfile::getTransfGamutCheck(), &check_color, &outofgamut, 1);
556
651
cmsSetAlarmCodes(alarm_r, alarm_g, alarm_b);
557
return (outofgamut == 255);
653
cmsSetAlarmCodes(oldAlarmCodes);
654
#endif // HAVE_LIBLCMS1
656
result = (outofgamut != 0);
563
661
class ProfileInfo
566
ProfileInfo( cmsHPROFILE, Glib::ustring const & path );
664
ProfileInfo( cmsHPROFILE prof, Glib::ustring const & path );
568
666
Glib::ustring const& getName() {return _name;}
569
667
Glib::ustring const& getPath() {return _path;}
570
icColorSpaceSignature getSpace() {return _profileSpace;}
571
icProfileClassSignature getClass() {return _profileClass;}
668
cmsColorSpaceSignature getSpace() {return _profileSpace;}
669
cmsProfileClassSignature getClass() {return _profileClass;}
574
672
Glib::ustring _path;
575
673
Glib::ustring _name;
576
icColorSpaceSignature _profileSpace;
577
icProfileClassSignature _profileClass;
674
cmsColorSpaceSignature _profileSpace;
675
cmsProfileClassSignature _profileClass;
581
ProfileInfo::ProfileInfo( cmsHPROFILE prof, Glib::ustring const & path )
680
ProfileInfo::ProfileInfo( cmsHPROFILE prof, Glib::ustring const & path ) :
682
_name( getNameFromProfile(prof) ),
683
_profileSpace( cmsGetColorSpace( prof ) ),
684
_profileClass( cmsGetDeviceClass( prof ) )
584
_name = cmsTakeProductDesc(prof);
585
_profileSpace = cmsGetColorSpace( prof );
586
_profileClass = cmsGetDeviceClass( prof );
591
690
static std::vector<ProfileInfo> knownProfiles;
593
std::vector<Glib::ustring> Inkscape::colorprofile_get_display_names()
595
std::vector<Glib::ustring> result;
597
for ( std::vector<ProfileInfo>::iterator it = knownProfiles.begin(); it != knownProfiles.end(); ++it ) {
598
if ( it->getClass() == icSigDisplayClass && it->getSpace() == icSigRgbData ) {
599
result.push_back( it->getName() );
606
std::vector<Glib::ustring> Inkscape::colorprofile_get_softproof_names()
608
std::vector<Glib::ustring> result;
610
for ( std::vector<ProfileInfo>::iterator it = knownProfiles.begin(); it != knownProfiles.end(); ++it ) {
611
if ( it->getClass() == icSigOutputClass ) {
612
result.push_back( it->getName() );
619
Glib::ustring Inkscape::get_path_for_profile(Glib::ustring const& name)
692
std::vector<Glib::ustring> Inkscape::CMSSystem::getDisplayNames()
695
std::vector<Glib::ustring> result;
697
for ( std::vector<ProfileInfo>::iterator it = knownProfiles.begin(); it != knownProfiles.end(); ++it ) {
698
if ( it->getClass() == cmsSigDisplayClass && it->getSpace() == cmsSigRgbData ) {
699
result.push_back( it->getName() );
702
std::sort(result.begin(), result.end());
707
std::vector<Glib::ustring> Inkscape::CMSSystem::getSoftproofNames()
710
std::vector<Glib::ustring> result;
712
for ( std::vector<ProfileInfo>::iterator it = knownProfiles.begin(); it != knownProfiles.end(); ++it ) {
713
if ( it->getClass() == cmsSigOutputClass ) {
714
result.push_back( it->getName() );
717
std::sort(result.begin(), result.end());
722
Glib::ustring Inkscape::CMSSystem::getPathForProfile(Glib::ustring const& name)
621
725
Glib::ustring result;
623
727
for ( std::vector<ProfileInfo>::iterator it = knownProfiles.begin(); it != knownProfiles.end(); ++it ) {
781
static void findThings() {
782
std::list<Glib::ustring> files = ColorProfile::getProfileFiles();
784
for ( std::list<Glib::ustring>::const_iterator it = files.begin(); it != files.end(); ++it ) {
785
cmsHPROFILE prof = cmsOpenProfileFromFile( it->c_str(), "r" );
787
ProfileInfo info( prof, Glib::filename_to_utf8( it->c_str() ) );
788
cmsCloseProfile( prof );
790
bool sameName = false;
791
for ( std::vector<ProfileInfo>::iterator it = knownProfiles.begin(); it != knownProfiles.end(); ++it ) {
792
if ( it->getName() == info.getName() ) {
799
knownProfiles.push_back(info);
919
std::vector<std::pair<Glib::ustring, Glib::ustring> > ColorProfile::getProfileFilesWithNames()
921
std::vector<std::pair<Glib::ustring, Glib::ustring> > result;
923
#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
924
std::vector<Glib::ustring> files = getProfileFiles();
925
for ( std::vector<Glib::ustring>::const_iterator it = files.begin(); it != files.end(); ++it ) {
926
cmsHPROFILE hProfile = cmsOpenProfileFromFile(it->c_str(), "r");
928
Glib::ustring name = getNameFromProfile(hProfile);
929
result.push_back( std::make_pair(*it, name) );
930
cmsCloseProfile(hProfile);
933
std::sort(result.begin(), result.end());
934
#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
939
#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
805
941
int errorHandlerCB(int ErrorCode, const char *ErrorText)
807
943
g_message("lcms: Error %d; %s", ErrorCode, ErrorText);
948
void errorHandlerCB(cmsContext /*contextID*/, cmsUInt32Number errorCode, char const *errorText)
950
g_message("lcms: Error %d", errorCode);
951
g_message(" %p", errorText);
952
//g_message("lcms: Error %d; %s", errorCode, errorText);
959
Glib::ustring getNameFromProfile(cmsHPROFILE profile)
961
Glib::ustring nameStr;
964
gchar const *name = cmsTakeProductDesc(profile);
966
name = cmsTakeProductName(profile);
968
if ( name && !g_utf8_validate(name, -1, NULL) ) {
969
name = _("(invalid UTF-8 string)");
971
nameStr = (name) ? name : _("None");
973
cmsUInt32Number byteLen = cmsGetProfileInfo(profile, cmsInfoDescription, "en", "US", NULL, 0);
975
// TODO investigate wchar_t and cmsGetProfileInfo()
976
std::vector<char> data(byteLen);
977
cmsUInt32Number readLen = cmsGetProfileInfoASCII(profile, cmsInfoDescription,
979
data.data(), data.size());
980
if (readLen < data.size()) {
981
data.resize(readLen);
983
nameStr = Glib::ustring(data.begin(), data.end());
985
if (nameStr.empty()) {
986
nameStr = _("(invalid UTF-8 string)");
994
* This function loads or refreshes data in knownProfiles.
995
* Call it at the start of every call that requires this data.
999
static bool error_handler_set = false;
1000
if (!error_handler_set) {
1002
cmsSetErrorHandler(errorHandlerCB);
1004
//cmsSetLogErrorHandler(errorHandlerCB);
1005
//g_message("LCMS error handler set");
1007
error_handler_set = true;
1010
static bool profiles_searched = false;
1011
if ( !profiles_searched ) {
1012
knownProfiles.clear();
1013
std::vector<Glib::ustring> files = ColorProfile::getProfileFiles();
1015
for ( std::vector<Glib::ustring>::const_iterator it = files.begin(); it != files.end(); ++it ) {
1016
cmsHPROFILE prof = cmsOpenProfileFromFile( it->c_str(), "r" );
1018
ProfileInfo info( prof, Glib::filename_to_utf8( it->c_str() ) );
1019
cmsCloseProfile( prof );
1022
bool sameName = false;
1023
for ( std::vector<ProfileInfo>::iterator it = knownProfiles.begin(); it != knownProfiles.end(); ++it ) {
1024
if ( it->getName() == info.getName() ) {
1031
knownProfiles.push_back(info);
1035
profiles_searched = true;
812
1040
static bool gamutWarn = false;
813
1041
static Gdk::Color lastGamutColor("#808080");