diff --git a/plugins/color/lcms2engine/colorprofiles/IccColorProfile.cpp b/plugins/color/lcms2engine/colorprofiles/IccColorProfile.cpp index f463f52438..819c2320eb 100644 --- a/plugins/color/lcms2engine/colorprofiles/IccColorProfile.cpp +++ b/plugins/color/lcms2engine/colorprofiles/IccColorProfile.cpp @@ -1,389 +1,381 @@ /* * Copyright (c) 2007 Cyrille Berger * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "IccColorProfile.h" #include #include #include #include #include "QDebug" #include "LcmsColorProfileContainer.h" #include "lcms2.h" struct IccColorProfile::Data::Private { QByteArray rawData; }; IccColorProfile::Data::Data() : d(new Private) { } IccColorProfile::Data::Data(const QByteArray &rawData) : d(new Private) { d->rawData = rawData; } IccColorProfile::Data::~Data() { } QByteArray IccColorProfile::Data::rawData() { return d->rawData; } void IccColorProfile::Data::setRawData(const QByteArray &rawData) { d->rawData = rawData; } -IccColorProfile::Container::Container() -{ -} - -IccColorProfile::Container::~Container() -{ -} - struct IccColorProfile::Private { struct Shared { QScopedPointer data; QScopedPointer lcmsProfile; QVector uiMinMaxes; }; QSharedPointer shared; }; IccColorProfile::IccColorProfile(const QString &fileName) : KoColorProfile(fileName), d(new Private) { // QSharedPointer lacks a reset in Qt 4.x d->shared = QSharedPointer(new Private::Shared()); d->shared->data.reset(new Data()); } IccColorProfile::IccColorProfile(const QByteArray &rawData) : KoColorProfile(QString()), d(new Private) { d->shared = QSharedPointer(new Private::Shared()); d->shared->data.reset(new Data()); setRawData(rawData); init(); } IccColorProfile::IccColorProfile(const IccColorProfile &rhs) : KoColorProfile(rhs) , d(new Private(*rhs.d)) { Q_ASSERT(d->shared); } IccColorProfile::~IccColorProfile() { Q_ASSERT(d->shared); } KoColorProfile *IccColorProfile::clone() const { return new IccColorProfile(*this); } QByteArray IccColorProfile::rawData() const { return d->shared->data->rawData(); } void IccColorProfile::setRawData(const QByteArray &rawData) { d->shared->data->setRawData(rawData); } bool IccColorProfile::valid() const { if (d->shared->lcmsProfile) { return d->shared->lcmsProfile->valid(); } return false; } float IccColorProfile::version() const { if (d->shared->lcmsProfile) { return d->shared->lcmsProfile->version(); } return 0.0; } bool IccColorProfile::isSuitableForOutput() const { if (d->shared->lcmsProfile) { return d->shared->lcmsProfile->isSuitableForOutput(); } return false; } bool IccColorProfile::isSuitableForPrinting() const { if (d->shared->lcmsProfile) { return d->shared->lcmsProfile->isSuitableForPrinting(); } return false; } bool IccColorProfile::isSuitableForDisplay() const { if (d->shared->lcmsProfile) { return d->shared->lcmsProfile->isSuitableForDisplay(); } return false; } bool IccColorProfile::supportsPerceptual() const { if (d->shared->lcmsProfile) { return d->shared->lcmsProfile->supportsPerceptual(); } return false; } bool IccColorProfile::supportsSaturation() const { if (d->shared->lcmsProfile) { return d->shared->lcmsProfile->supportsSaturation(); } return false; } bool IccColorProfile::supportsAbsolute() const { if (d->shared->lcmsProfile) { return d->shared->lcmsProfile->supportsAbsolute(); } return false; } bool IccColorProfile::supportsRelative() const { if (d->shared->lcmsProfile) { return d->shared->lcmsProfile->supportsRelative(); } return false; } bool IccColorProfile::hasColorants() const { if (d->shared->lcmsProfile) { return d->shared->lcmsProfile->hasColorants(); } return false; } bool IccColorProfile::hasTRC() const { if (d->shared->lcmsProfile) return d->shared->lcmsProfile->hasTRC(); return false; } bool IccColorProfile::isLinear() const { if (d->shared->lcmsProfile) return d->shared->lcmsProfile->isLinear(); return false; } QVector IccColorProfile::getColorantsXYZ() const { if (d->shared->lcmsProfile) { return d->shared->lcmsProfile->getColorantsXYZ(); } return QVector(9); } QVector IccColorProfile::getColorantsxyY() const { if (d->shared->lcmsProfile) { return d->shared->lcmsProfile->getColorantsxyY(); } return QVector(9); } QVector IccColorProfile::getWhitePointXYZ() const { QVector d50Dummy(3); d50Dummy << 0.9642 << 1.0000 << 0.8249; if (d->shared->lcmsProfile) { return d->shared->lcmsProfile->getWhitePointXYZ(); } return d50Dummy; } QVector IccColorProfile::getWhitePointxyY() const { QVector d50Dummy(3); d50Dummy << 0.34773 << 0.35952 << 1.0; if (d->shared->lcmsProfile) { return d->shared->lcmsProfile->getWhitePointxyY(); } return d50Dummy; } QVector IccColorProfile::getEstimatedTRC() const { QVector dummy(3); dummy.fill(2.2);//estimated sRGB trc. if (d->shared->lcmsProfile) { return d->shared->lcmsProfile->getEstimatedTRC(); } return dummy; } void IccColorProfile::linearizeFloatValue(QVector & Value) const { if (d->shared->lcmsProfile) d->shared->lcmsProfile->LinearizeFloatValue(Value); } void IccColorProfile::delinearizeFloatValue(QVector & Value) const { if (d->shared->lcmsProfile) d->shared->lcmsProfile->DelinearizeFloatValue(Value); } void IccColorProfile::linearizeFloatValueFast(QVector & Value) const { if (d->shared->lcmsProfile) d->shared->lcmsProfile->LinearizeFloatValueFast(Value); } void IccColorProfile::delinearizeFloatValueFast(QVector &Value) const { if (d->shared->lcmsProfile) d->shared->lcmsProfile->DelinearizeFloatValueFast(Value); } QByteArray IccColorProfile::uniqueId() const { QByteArray dummy; if (d->shared->lcmsProfile) { dummy = d->shared->lcmsProfile->getProfileUniqueId(); } return dummy; } bool IccColorProfile::load() { QFile file(fileName()); file.open(QIODevice::ReadOnly); QByteArray rawData = file.readAll(); setRawData(rawData); file.close(); if (init()) { return true; } qWarning() << "Failed to load profile from " << fileName(); return false; } bool IccColorProfile::save() { return false; } bool IccColorProfile::init() { if (!d->shared->lcmsProfile) { d->shared->lcmsProfile.reset(new LcmsColorProfileContainer(d->shared->data.data())); } if (d->shared->lcmsProfile->init()) { setName(d->shared->lcmsProfile->name()); setInfo(d->shared->lcmsProfile->info()); setManufacturer(d->shared->lcmsProfile->manufacturer()); setCopyright(d->shared->lcmsProfile->copyright()); if (d->shared->lcmsProfile->valid()) { calculateFloatUIMinMax(); } return true; } else { return false; } } LcmsColorProfileContainer *IccColorProfile::asLcms() const { Q_ASSERT(d->shared->lcmsProfile); return d->shared->lcmsProfile.data(); } bool IccColorProfile::operator==(const KoColorProfile &rhs) const { const IccColorProfile *rhsIcc = dynamic_cast(&rhs); if (rhsIcc) { return d->shared == rhsIcc->d->shared; } return false; } const QVector &IccColorProfile::getFloatUIMinMax(void) const { Q_ASSERT(!d->shared->uiMinMaxes.isEmpty()); return d->shared->uiMinMaxes; } void IccColorProfile::calculateFloatUIMinMax(void) { QVector &ret = d->shared->uiMinMaxes; cmsHPROFILE cprofile = d->shared->lcmsProfile->lcmsProfile(); Q_ASSERT(cprofile); cmsColorSpaceSignature color_space_sig = cmsGetColorSpace(cprofile); unsigned int num_channels = cmsChannelsOf(color_space_sig); unsigned int color_space_mask = _cmsLCMScolorSpace(color_space_sig); Q_ASSERT(num_channels >= 1 && num_channels <= 4); // num_channels==1 is for grayscale, we need to handle it Q_ASSERT(color_space_mask); // to try to find the max range of float/doubles for this profile, // pass in min/max int and make the profile convert that // this is far from perfect, we need a better way, if possible to get the "bounds" of a profile uint16_t in_min_pixel[4] = {0, 0, 0, 0}; uint16_t in_max_pixel[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}; qreal out_min_pixel[4] = {0, 0, 0, 0}; qreal out_max_pixel[4] = {0, 0, 0, 0}; cmsHTRANSFORM trans = cmsCreateTransform( cprofile, (COLORSPACE_SH(color_space_mask) | CHANNELS_SH(num_channels) | BYTES_SH(2)), cprofile, (COLORSPACE_SH(color_space_mask) | FLOAT_SH(1) | CHANNELS_SH(num_channels) | BYTES_SH(0)), //NOTE THAT 'BYTES' FIELD IS SET TO ZERO ON DLB because 8 bytes overflows the bitfield INTENT_PERCEPTUAL, 0); // does the intent matter in this case? if (trans) { cmsDoTransform(trans, in_min_pixel, out_min_pixel, 1); cmsDoTransform(trans, in_max_pixel, out_max_pixel, 1); cmsDeleteTransform(trans); }//else, we'll just default to [0..1] below ret.resize(num_channels); for (unsigned int i = 0; i < num_channels; ++i) { if (out_min_pixel[i] < out_max_pixel[i]) { ret[i].minVal = out_min_pixel[i]; ret[i].maxVal = out_max_pixel[i]; } else { // apparently we can't even guarantee that converted_to_double(0x0000) < converted_to_double(0xFFFF) // assume [0..1] in such cases // we need to find a really solid way of determining the bounds of a profile, if possible ret[i].minVal = 0; ret[i].maxVal = 1; } } } diff --git a/plugins/color/lcms2engine/colorprofiles/IccColorProfile.h b/plugins/color/lcms2engine/colorprofiles/IccColorProfile.h index 3eb3ace963..efa0aa3e06 100644 --- a/plugins/color/lcms2engine/colorprofiles/IccColorProfile.h +++ b/plugins/color/lcms2engine/colorprofiles/IccColorProfile.h @@ -1,144 +1,118 @@ /* * Copyright (c) 2007 Cyrille Berger * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef _KO_ICC_COLOR_PROFILE_H_ #define _KO_ICC_COLOR_PROFILE_H_ #include "KoColorProfile.h" #include "KoChannelInfo.h" class LcmsColorProfileContainer; /** * This class contains an ICC color profile. */ class IccColorProfile : public KoColorProfile { public: using KoColorProfile::save; /** * Contains the data associated with a profile. This is * shared through internal representation. */ class Data { public: Data(); explicit Data(const QByteArray &rawData); ~Data(); QByteArray rawData(); void setRawData(const QByteArray &); private: struct Private; QScopedPointer const d; }; - /** - * This class should be used to wrap the ICC profile - * representation coming from various CMS engine. - */ - class Container - { - public: - Container(); - virtual ~Container(); - public: - virtual QString name() const = 0; - virtual QString info() const = 0; - virtual QString manufacturer() const = 0; - virtual QString copyright() const = 0; - virtual bool valid() const = 0; - virtual bool isSuitableForOutput() const = 0; - virtual bool isSuitableForPrinting() const = 0; - virtual bool isSuitableForDisplay() const = 0; - virtual bool hasColorants() const = 0; - virtual QVector getColorantsXYZ() const = 0; - virtual QVector getColorantsxyY() const = 0; - virtual QVector getWhitePointXYZ() const = 0; - virtual QVector getWhitePointxyY() const = 0; - virtual QVector getEstimatedTRC() const = 0; - virtual QByteArray getProfileUniqueId() const = 0; - }; public: explicit IccColorProfile(const QString &fileName = QString()); explicit IccColorProfile(const QByteArray &rawData); IccColorProfile(const IccColorProfile &rhs); ~IccColorProfile() override; KoColorProfile *clone() const override; bool load() override; virtual bool save(); /** * @return an array with the raw data of the profile */ QByteArray rawData() const override; bool valid() const override; float version() const override; bool isSuitableForOutput() const override; bool isSuitableForPrinting() const override; bool isSuitableForDisplay() const override; bool supportsPerceptual() const override; bool supportsSaturation() const override; bool supportsAbsolute() const override; bool supportsRelative() const override; bool hasColorants() const override; bool hasTRC() const override; bool isLinear() const override; QVector getColorantsXYZ() const override; QVector getColorantsxyY() const override; QVector getWhitePointXYZ() const override; QVector getWhitePointxyY() const override; QVector getEstimatedTRC() const override; void linearizeFloatValue(QVector & Value) const override; void delinearizeFloatValue(QVector & Value) const override; void linearizeFloatValueFast(QVector & Value) const override; void delinearizeFloatValueFast(QVector & Value) const override; QByteArray uniqueId() const override; bool operator==(const KoColorProfile &) const override; QString type() const override { return "icc"; } /** * Returns the set of min/maxes for each channel in this profile. * These (sometimes approximate) min and maxes are suitable * for UI building. * Furthermore, then only apply to the floating point uses of this profile, * and not the integer variants. */ const QVector &getFloatUIMinMax(void) const; protected: void setRawData(const QByteArray &rawData); public: LcmsColorProfileContainer *asLcms() const; protected: bool init(); void calculateFloatUIMinMax(void); private: struct Private; QScopedPointer d; }; #endif diff --git a/plugins/color/lcms2engine/colorprofiles/LcmsColorProfileContainer.h b/plugins/color/lcms2engine/colorprofiles/LcmsColorProfileContainer.h index ee1d4bcc7f..f71434d7e0 100644 --- a/plugins/color/lcms2engine/colorprofiles/LcmsColorProfileContainer.h +++ b/plugins/color/lcms2engine/colorprofiles/LcmsColorProfileContainer.h @@ -1,120 +1,120 @@ /* * This file is part of the KDE project * Copyright (c) 2000 Matthias Elter * 2004 Boudewijn Rempt * Copyright (c) 2007 Thomas Zander * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef _KO_LCMS_COLORPROFILE_H #define _KO_LCMS_COLORPROFILE_H #include "IccColorProfile.h" #include #include #include /** * This class contains an LCMS color profile. Don't use it outside LcmsColorSpace. */ -class LcmsColorProfileContainer : public IccColorProfile::Container +class LcmsColorProfileContainer { friend class IccColorProfile; protected: LcmsColorProfileContainer(IccColorProfile::Data *); private: /** * Create a byte array from a lcms profile. */ static QByteArray lcmsProfileToByteArray(const cmsHPROFILE profile); public: /** * @param profile lcms memory structure with the profile, it is freed after the call * to this function * @return an ICC profile created from an LCMS profile */ static IccColorProfile *createFromLcmsProfile(const cmsHPROFILE profile); public: - ~LcmsColorProfileContainer() override; + ~LcmsColorProfileContainer(); /** * @return the ICC color space signature */ cmsColorSpaceSignature colorSpaceSignature() const; /** * @return the class of the color space signature */ cmsProfileClassSignature deviceClass() const; /** * @return the name of the manufacturer */ - QString manufacturer() const override; + QString manufacturer() const; /** * @return the embedded copyright */ - QString copyright() const override; + QString copyright() const; /** * @return the structure to use with LCMS functions */ cmsHPROFILE lcmsProfile() const; - bool valid() const override; - virtual float version() const; + bool valid() const; + float version() const; - bool isSuitableForOutput() const override; + bool isSuitableForOutput() const; - bool isSuitableForPrinting() const override; + bool isSuitableForPrinting() const; - bool isSuitableForDisplay() const override; + bool isSuitableForDisplay() const; - virtual bool supportsPerceptual() const; - virtual bool supportsSaturation() const; - virtual bool supportsAbsolute() const; - virtual bool supportsRelative() const; + bool supportsPerceptual() const; + bool supportsSaturation() const; + bool supportsAbsolute() const; + bool supportsRelative() const; - bool hasColorants() const override; - virtual bool hasTRC() const; + bool hasColorants() const; + bool hasTRC() const; bool isLinear() const; - QVector getColorantsXYZ() const override; - QVector getColorantsxyY() const override; - QVector getWhitePointXYZ() const override; - QVector getWhitePointxyY() const override; - QVector getEstimatedTRC() const override; - virtual void LinearizeFloatValue(QVector & Value) const; - virtual void DelinearizeFloatValue(QVector & Value) const; - virtual void LinearizeFloatValueFast(QVector & Value) const; - virtual void DelinearizeFloatValueFast(QVector & Value) const; - QString name() const override; - QString info() const override; - QByteArray getProfileUniqueId() const override; + QVector getColorantsXYZ() const; + QVector getColorantsxyY() const; + QVector getWhitePointXYZ() const; + QVector getWhitePointxyY() const; + QVector getEstimatedTRC() const; + void LinearizeFloatValue(QVector & Value) const; + void DelinearizeFloatValue(QVector & Value) const; + void LinearizeFloatValueFast(QVector & Value) const; + void DelinearizeFloatValueFast(QVector & Value) const; + QString name() const; + QString info() const; + QByteArray getProfileUniqueId() const; protected: LcmsColorProfileContainer(); private: bool init(); class Private; Private *const d; }; #endif // KOCOLORPROFILE_H