File indexing completed on 2024-05-26 04:32:15

0001 /*
0002  *  SPDX-FileCopyrightText: 2003 Patrick Julien <freak@codepimps.org>
0003  *  SPDX-FileCopyrightText: 2004, 2010 Cyrille Berger <cberger@cberger.net>
0004  *  SPDX-FileCopyrightText: 2011 Srikanth Tiyyagura <srikanth.tulasiram@gmail.com>
0005  *
0006  * SPDX-License-Identifier: LGPL-2.1-or-later
0007 */
0008 #include "LcmsEnginePlugin.h"
0009 
0010 #include <QApplication>
0011 #include <QDebug>
0012 #include <QDir>
0013 #include <QHash>
0014 #include <QStringList>
0015 
0016 #include <klocalizedstring.h>
0017 #include <kpluginfactory.h>
0018 
0019 #include <KoBasicHistogramProducers.h>
0020 #include <KoColorSpace.h>
0021 #include <KoColorSpaceEngine.h>
0022 #include <KoColorSpaceRegistry.h>
0023 #include <KoResourcePaths.h>
0024 #include <kis_assert.h>
0025 #include <kis_debug.h>
0026 
0027 #include "IccColorSpaceEngine.h"
0028 #include "colorprofiles/LcmsColorProfileContainer.h"
0029 
0030 #include "colorspaces/cmyk_u8/CmykU8ColorSpace.h"
0031 #include "colorspaces/cmyk_u16/CmykU16ColorSpace.h"
0032 #include "colorspaces/cmyk_f32/CmykF32ColorSpace.h"
0033 
0034 #include "colorspaces/gray_u8/GrayU8ColorSpace.h"
0035 #include "colorspaces/gray_u16/GrayU16ColorSpace.h"
0036 #include "colorspaces/gray_f32/GrayF32ColorSpace.h"
0037 
0038 #include "colorspaces/lab_u8/LabU8ColorSpace.h"
0039 #include "colorspaces/lab_u16/LabColorSpace.h"
0040 #include "colorspaces/lab_f32/LabF32ColorSpace.h"
0041 
0042 #include "colorspaces/xyz_u8/XyzU8ColorSpace.h"
0043 #include "colorspaces/xyz_u16/XyzU16ColorSpace.h"
0044 #include "colorspaces/xyz_f32/XyzF32ColorSpace.h"
0045 
0046 #include "colorspaces/rgb_u8/RgbU8ColorSpace.h"
0047 #include "colorspaces/rgb_u16/RgbU16ColorSpace.h"
0048 #include "colorspaces/rgb_f32/RgbF32ColorSpace.h"
0049 
0050 #include "colorspaces/ycbcr_u8/YCbCrU8ColorSpace.h"
0051 #include "colorspaces/ycbcr_u16/YCbCrU16ColorSpace.h"
0052 #include "colorspaces/ycbcr_f32/YCbCrF32ColorSpace.h"
0053 
0054 #include "LcmsRGBP2020PQColorSpace.h"
0055 
0056 #include <KoConfig.h>
0057 
0058 #ifdef HAVE_OPENEXR
0059 #   include <half.h>
0060 #   ifdef HAVE_LCMS24
0061 #       include "colorspaces/gray_f16/GrayF16ColorSpace.h"
0062 #       include "colorspaces/xyz_f16/XyzF16ColorSpace.h"
0063 #       include "colorspaces/rgb_f16/RgbF16ColorSpace.h"
0064 #   endif
0065 #endif
0066 
0067 #if defined(HAVE_LCMS_FAST_FLOAT_PLUGIN)
0068 #include <lcms2_fast_float.h>
0069 #endif 
0070 
0071 void lcms2LogErrorHandlerFunction(cmsContext /*ContextID*/, cmsUInt32Number ErrorCode, const char *Text)
0072 {
0073     errorPigment << "Lcms2 error: " << ErrorCode << Text;
0074 }
0075 
0076 K_PLUGIN_FACTORY_WITH_JSON(PluginFactory, "kolcmsengine.json", registerPlugin<LcmsEnginePlugin>();)
0077 
0078 LcmsEnginePlugin::LcmsEnginePlugin(QObject *parent, const QVariantList &)
0079     : QObject(parent)
0080 {
0081     KoResourcePaths::addAssetType("icc_profiles", "data", "/color/icc");
0082     KoResourcePaths::addAssetType("icc_profiles", "data", "/profiles/");
0083 
0084     // Set the lmcs error reporting function
0085     cmsSetLogErrorHandler(&lcms2LogErrorHandlerFunction);
0086 
0087     KoColorSpaceRegistry *registry = KoColorSpaceRegistry::instance();
0088 
0089     // Initialise color engine
0090     KoColorSpaceEngineRegistry::instance()->add(new IccColorSpaceEngine);
0091 
0092     QStringList profileFilenames;
0093     profileFilenames += KoResourcePaths::findAllAssets("icc_profiles", "*.icm",  KoResourcePaths::Recursive);
0094     profileFilenames += KoResourcePaths::findAllAssets("icc_profiles", "*.ICM",  KoResourcePaths::Recursive);
0095     profileFilenames += KoResourcePaths::findAllAssets("icc_profiles", "*.ICC",  KoResourcePaths::Recursive);
0096     profileFilenames += KoResourcePaths::findAllAssets("icc_profiles", "*.icc",  KoResourcePaths::Recursive);
0097 
0098     QStringList iccProfileDirs;
0099 
0100 #ifdef Q_OS_MAC
0101     iccProfileDirs.append(QDir::homePath() + "/Library/ColorSync/Profiles/");
0102     iccProfileDirs.append("/System/Library/ColorSync/Profiles/");
0103     iccProfileDirs.append("/Library/ColorSync/Profiles/");
0104 #endif
0105 #ifdef Q_OS_WIN
0106     QString winPath = QString::fromUtf8(qgetenv("windir"));
0107     winPath.replace('\\','/');
0108     iccProfileDirs.append(winPath + "/System32/Spool/Drivers/Color/");
0109 
0110 #endif
0111 #ifdef Q_OS_LINUX
0112     iccProfileDirs.append(QDir::homePath() + "./share/color/icc");
0113 #endif
0114 
0115     QStringList blackList = QStringList() << "panhexro.icm"
0116                                           << "ctpctdmed.icc";
0117 
0118 
0119     Q_FOREACH(const QString &iccProfiledir, iccProfileDirs) {
0120         QDir profileDir(iccProfiledir);
0121         Q_FOREACH(const QString &entry, profileDir.entryList(QStringList() << "*.icm" << "*.icc" << "*.ICM" << "*.ICC", QDir::NoDotAndDotDot | QDir::Files | QDir::Readable)) {
0122             if (blackList.contains(entry.toLower())) continue;
0123             profileFilenames << iccProfiledir + "/" + entry;
0124         }
0125     }
0126 
0127     // Load the profiles
0128     if (!profileFilenames.empty()) {
0129         for (QStringList::Iterator it = profileFilenames.begin(); it != profileFilenames.end(); ++it) {
0130 
0131             KoColorProfile *profile = new IccColorProfile(*it);
0132             Q_CHECK_PTR(profile);
0133 
0134             profile->load();
0135             if (profile->valid()) {
0136                 //qDebug() << "Valid profile : " << profile->fileName() << profile->name();
0137                 registry->addProfileToMap(profile);
0138             } else {
0139                 qDebug() << "Invalid profile : " << *it;
0140                 delete profile;
0141             }
0142         }
0143     }
0144 
0145     // ------------------- LAB ---------------------------------
0146 
0147     KoColorProfile *labProfile = LcmsColorProfileContainer::createFromLcmsProfile(cmsCreateLab4Profile(0));
0148     registry->addProfile(labProfile);
0149 
0150     registry->add(new LabU8ColorSpaceFactory());
0151     registry->add(new LabU16ColorSpaceFactory());
0152     registry->add(new LabF32ColorSpaceFactory());
0153 
0154     KoHistogramProducerFactoryRegistry::instance()->add(
0155         new KoBasicHistogramProducerFactory<KoBasicU8HistogramProducer>
0156             (KoID("LABAU8HISTO", i18n("L*a*b*/8 Histogram")), LABAColorModelID.id(), Integer8BitsColorDepthID.id()));
0157 
0158     KoHistogramProducerFactoryRegistry::instance()->add(
0159         new KoBasicHistogramProducerFactory<KoBasicU16HistogramProducer>
0160             (KoID("LABAU16HISTO", i18n("L*a*b*/16 Histogram")), LABAColorModelID.id(), Integer16BitsColorDepthID.id()));
0161 
0162     KoHistogramProducerFactoryRegistry::instance()->add(
0163         new KoBasicHistogramProducerFactory<KoBasicF32HistogramProducer>
0164             (KoID("LABAF32HISTO", i18n("L*a*b*/32 Histogram")), LABAColorModelID.id(), Float32BitsColorDepthID.id()));
0165 
0166     // ------------------- RGB ---------------------------------
0167 
0168     KoColorProfile *rgbProfile = LcmsColorProfileContainer::createFromLcmsProfile(cmsCreate_sRGBProfile());
0169     registry->addProfile(rgbProfile);
0170 
0171     registry->add(new LcmsRGBP2020PQColorSpaceFactoryWrapper<RgbU8ColorSpaceFactory>());
0172     registry->add(new LcmsRGBP2020PQColorSpaceFactoryWrapper<RgbU16ColorSpaceFactory>());
0173 #ifdef HAVE_LCMS24
0174 #ifdef HAVE_OPENEXR
0175     registry->add(new LcmsRGBP2020PQColorSpaceFactoryWrapper<RgbF16ColorSpaceFactory>());
0176 #endif
0177 #endif
0178     registry->add(new LcmsRGBP2020PQColorSpaceFactoryWrapper<RgbF32ColorSpaceFactory>());
0179 
0180     KoHistogramProducerFactoryRegistry::instance()->add(
0181         new KoBasicHistogramProducerFactory<KoBasicU8HistogramProducer>
0182             (KoID("RGBU8HISTO", i18n("RGBA/8 Histogram")), RGBAColorModelID.id(), Integer8BitsColorDepthID.id()));
0183 
0184     KoHistogramProducerFactoryRegistry::instance()->add(
0185         new KoBasicHistogramProducerFactory<KoBasicU16HistogramProducer>
0186             (KoID("RGBU16HISTO", i18n("RGBA/16 Histogram")), RGBAColorModelID.id(), Integer16BitsColorDepthID.id()));
0187 
0188 #ifdef HAVE_LCMS24
0189 #ifdef HAVE_OPENEXR
0190     KoHistogramProducerFactoryRegistry::instance()->add(
0191         new KoBasicHistogramProducerFactory<KoBasicF16HalfHistogramProducer>
0192             (KoID("RGBF16HISTO", i18n("RGBA/F16 Histogram")), RGBAColorModelID.id(), Float16BitsColorDepthID.id()));
0193 #endif
0194 #endif
0195 
0196     KoHistogramProducerFactoryRegistry::instance()->add(
0197         new KoBasicHistogramProducerFactory<KoBasicF32HistogramProducer>
0198             (KoID("RGF328HISTO", i18n("RGBA/F32 Histogram")), RGBAColorModelID.id(), Float32BitsColorDepthID.id()));
0199 
0200     // ------------------- GRAY ---------------------------------
0201 
0202     cmsToneCurve *Gamma = cmsBuildGamma(0, 2.2);
0203     cmsHPROFILE hProfile = cmsCreateGrayProfile(cmsD50_xyY(), Gamma);
0204     cmsFreeToneCurve(Gamma);
0205     KoColorProfile *defProfile = LcmsColorProfileContainer::createFromLcmsProfile(hProfile);
0206     registry->addProfile(defProfile);
0207 
0208     registry->add(new GrayAU8ColorSpaceFactory());
0209     registry->add(new GrayAU16ColorSpaceFactory());
0210 #ifdef HAVE_LCMS24
0211 #ifdef HAVE_OPENEXR
0212     registry->add(new GrayF16ColorSpaceFactory());
0213 #endif
0214 #endif
0215     registry->add(new GrayF32ColorSpaceFactory());
0216 
0217     KoHistogramProducerFactoryRegistry::instance()->add(
0218         new KoBasicHistogramProducerFactory<KoBasicU8HistogramProducer>
0219             (KoID("GRAYA8HISTO", i18n("GRAY/8 Histogram")), GrayAColorModelID.id(), Integer8BitsColorDepthID.id()));
0220 
0221     KoHistogramProducerFactoryRegistry::instance()->add(
0222         new KoBasicHistogramProducerFactory<KoBasicU16HistogramProducer>
0223             (KoID("GRAYA16HISTO", i18n("GRAY/16 Histogram")), GrayAColorModelID.id(), Integer16BitsColorDepthID.id()));
0224 #ifdef HAVE_LCMS24
0225 #ifdef HAVE_OPENEXR
0226     KoHistogramProducerFactoryRegistry::instance()->add(
0227         new KoBasicHistogramProducerFactory<KoBasicF16HalfHistogramProducer>
0228             (KoID("GRAYF16HISTO", i18n("GRAYF/F16 Histogram")), GrayAColorModelID.id(), Float16BitsColorDepthID.id()));
0229 #endif
0230 #endif
0231 
0232     KoHistogramProducerFactoryRegistry::instance()->add(
0233         new KoBasicHistogramProducerFactory<KoBasicF32HistogramProducer>
0234             (KoID("GRAYAF32HISTO", i18n("GRAY/F32 float Histogram")), GrayAColorModelID.id(), Float32BitsColorDepthID.id()));
0235 
0236     // ------------------- CMYK ---------------------------------
0237 
0238     registry->add(new CmykU8ColorSpaceFactory());
0239     registry->add(new CmykU16ColorSpaceFactory());
0240     registry->add(new CmykF32ColorSpaceFactory());
0241 
0242     KoHistogramProducerFactoryRegistry::instance()->add(
0243         new KoBasicHistogramProducerFactory<KoBasicU8HistogramProducer>
0244             (KoID("CMYK8HISTO", i18n("CMYK/8 Histogram")), CMYKAColorModelID.id(), Integer8BitsColorDepthID.id()));
0245 
0246     KoHistogramProducerFactoryRegistry::instance()->add(
0247         new KoBasicHistogramProducerFactory<KoBasicU16HistogramProducer>
0248             (KoID("CMYK16HISTO", i18n("CMYK/16 Histogram")), CMYKAColorModelID.id(), Integer16BitsColorDepthID.id()));
0249 
0250     KoHistogramProducerFactoryRegistry::instance()->add(
0251         new KoBasicHistogramProducerFactory<KoBasicF32HistogramProducer>
0252             (KoID("CMYKF32HISTO", i18n("CMYK/F32 Histogram")), CMYKAColorModelID.id(), Float32BitsColorDepthID.id()));
0253 
0254     // ------------------- XYZ ---------------------------------
0255 
0256     KoColorProfile *xyzProfile = LcmsColorProfileContainer::createFromLcmsProfile(cmsCreateXYZProfile());
0257     registry->addProfile(xyzProfile);
0258 
0259     registry->add(new XyzU8ColorSpaceFactory());
0260     registry->add(new XyzU16ColorSpaceFactory());
0261 #ifdef HAVE_LCMS24
0262 #ifdef HAVE_OPENEXR
0263     registry->add(new XyzF16ColorSpaceFactory());
0264 #endif
0265 #endif
0266     registry->add(new XyzF32ColorSpaceFactory());
0267 
0268     KoHistogramProducerFactoryRegistry::instance()->add(
0269         new KoBasicHistogramProducerFactory<KoBasicU8HistogramProducer>
0270             (KoID("XYZ8HISTO", i18n("XYZ/8 Histogram")), XYZAColorModelID.id(), Integer8BitsColorDepthID.id()));
0271 
0272     KoHistogramProducerFactoryRegistry::instance()->add(
0273         new KoBasicHistogramProducerFactory<KoBasicU16HistogramProducer>
0274             (KoID("XYZ16HISTO", i18n("XYZ/16 Histogram")), XYZAColorModelID.id(), Integer16BitsColorDepthID.id()));
0275 
0276 #ifdef HAVE_LCMS24
0277 #ifdef HAVE_OPENEXR
0278     KoHistogramProducerFactoryRegistry::instance()->add(
0279         new KoBasicHistogramProducerFactory<KoBasicF32HistogramProducer>
0280             (KoID("XYZF16HISTO", i18n("XYZ/F16 Histogram")), XYZAColorModelID.id(), Float16BitsColorDepthID.id()));
0281 #endif
0282 #endif
0283 
0284     KoHistogramProducerFactoryRegistry::instance()->add(
0285         new KoBasicHistogramProducerFactory<KoBasicF32HistogramProducer>
0286             (KoID("XYZF32HISTO", i18n("XYZF32 Histogram")), XYZAColorModelID.id(), Float32BitsColorDepthID.id()));
0287 
0288     // ------------------- YCBCR ---------------------------------
0289 
0290     //    KoColorProfile *yCbCrProfile = LcmsColorProfileContainer::createFromLcmsProfile(cmsCreateYCBCRProfile());
0291     //    registry->addProfile(yCbCrProfile);
0292 
0293     registry->add(new YCbCrU8ColorSpaceFactory());
0294     registry->add(new YCbCrU16ColorSpaceFactory());
0295     registry->add(new YCbCrF32ColorSpaceFactory());
0296 
0297     KoHistogramProducerFactoryRegistry::instance()->add(
0298         new KoBasicHistogramProducerFactory<KoBasicU8HistogramProducer>
0299             (KoID("YCBCR8HISTO", i18n("YCbCr/8 Histogram")), YCbCrAColorModelID.id(), Integer8BitsColorDepthID.id()));
0300 
0301     KoHistogramProducerFactoryRegistry::instance()->add(
0302         new KoBasicHistogramProducerFactory<KoBasicU16HistogramProducer>
0303             (KoID("YCBCR16HISTO", i18n("YCbCr/16 Histogram")), YCbCrAColorModelID.id(), Integer16BitsColorDepthID.id()));
0304 
0305     KoHistogramProducerFactoryRegistry::instance()->add(
0306         new KoBasicHistogramProducerFactory<KoBasicF32HistogramProducer>
0307             (KoID("YCBCRF32HISTO", i18n("YCbCr/F32 Histogram")), YCbCrAColorModelID.id(), Float32BitsColorDepthID.id()));
0308 
0309     // Add profile alias for default profile from lcms1
0310     registry->addProfileAlias("sRGB built-in - (lcms internal)", "sRGB built-in");
0311     registry->addProfileAlias("gray built-in - (lcms internal)", "gray built-in");
0312     registry->addProfileAlias("Lab identity built-in - (lcms internal)", "Lab identity built-in");
0313     registry->addProfileAlias("XYZ built-in - (lcms internal)", "XYZ identity built-in");
0314 
0315 #if defined(HAVE_LCMS_FAST_FLOAT_PLUGIN)
0316     cmsPlugin(cmsFastFloatExtensions());
0317 #endif
0318 }
0319 
0320 #include <LcmsEnginePlugin.moc>