diff --git a/libs/pigment/KoColorDisplayRendererInterface.cpp b/libs/pigment/KoColorDisplayRendererInterface.cpp index fb6b0a9165..d79a815795 100644 --- a/libs/pigment/KoColorDisplayRendererInterface.cpp +++ b/libs/pigment/KoColorDisplayRendererInterface.cpp @@ -1,85 +1,92 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * 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 "KoColorDisplayRendererInterface.h" #include #include #include +#include +#include Q_GLOBAL_STATIC(KoDumbColorDisplayRenderer, s_instance) KoColorDisplayRendererInterface::KoColorDisplayRendererInterface() { } KoColorDisplayRendererInterface::~KoColorDisplayRendererInterface() { } +QImage KoDumbColorDisplayRenderer::convertToQImage(const KoColorSpace *srcColorSpace, const quint8 *data, qint32 width, qint32 height) const +{ + return srcColorSpace->convertToQImage(data, width, height, 0, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); +} + QColor KoDumbColorDisplayRenderer::toQColor(const KoColor &c) const { return c.toQColor(); } KoColor KoDumbColorDisplayRenderer::approximateFromRenderedQColor(const QColor &c) const { KoColor color; color.fromQColor(c); return color; } KoColor KoDumbColorDisplayRenderer::fromHsv(int h, int s, int v, int a) const { h = qBound(0, h, 359); s = qBound(0, s, 255); v = qBound(0, v, 255); a = qBound(0, a, 255); QColor qcolor(QColor::fromHsv(h, s, v, a)); return KoColor(qcolor, KoColorSpaceRegistry::instance()->rgb8()); } void KoDumbColorDisplayRenderer::getHsv(const KoColor &srcColor, int *h, int *s, int *v, int *a) const { QColor qcolor = toQColor(srcColor); qcolor.getHsv(h, s, v, a); } KoColorDisplayRendererInterface* KoDumbColorDisplayRenderer::instance() { return s_instance; } qreal KoDumbColorDisplayRenderer::minVisibleFloatValue(const KoChannelInfo *chaninfo) const { Q_ASSERT(chaninfo); return chaninfo->getUIMin(); } qreal KoDumbColorDisplayRenderer::maxVisibleFloatValue(const KoChannelInfo *chaninfo) const { Q_ASSERT(chaninfo); return chaninfo->getUIMax(); } const KoColorSpace* KoDumbColorDisplayRenderer::getPaintingColorSpace() const { return KoColorSpaceRegistry::instance()->rgb8(); } diff --git a/libs/pigment/KoColorDisplayRendererInterface.h b/libs/pigment/KoColorDisplayRendererInterface.h index 2e974767cc..fb8f07937c 100644 --- a/libs/pigment/KoColorDisplayRendererInterface.h +++ b/libs/pigment/KoColorDisplayRendererInterface.h @@ -1,117 +1,129 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * 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_COLOR_DISPLAY_RENDERER_INTERFACE_H #define __KO_COLOR_DISPLAY_RENDERER_INTERFACE_H #include #include #include #include "KoColor.h" class KoChannelInfo; +class KoColorSpace; /** * A special interface class provided by pigment to let widgets render * a KoColor on screen using custom profiling provided by the user. * * If you want to provide your own rendering of the KoColor on screen, * reimplement this class and provide its instance to a supporting * widget. */ class KRITAPIGMENT_EXPORT KoColorDisplayRendererInterface : public QObject { Q_OBJECT public: KoColorDisplayRendererInterface(); virtual ~KoColorDisplayRendererInterface(); + /** + * @brief KoColorSpace::convertToQImage converts a whole row of colors in one go + * @param srcColorSpace the colorspace the pixel data is in + * @param data a pointer to a byte array with colors + * @param width of the resulting image + * @param height of the resulting image + * @return a QImage that can be displayed + */ + virtual QImage convertToQImage(const KoColorSpace *srcColorSpace, const quint8 *data, qint32 width, qint32 height) const = 0; + /** * Convert the color \p c to a custom QColor that will be * displayed by the widget on screen. Please note, that the * reverse conversion may simply not exist. */ virtual QColor toQColor(const KoColor &c) const = 0; /** * This tries to approximate a rendered QColor into the KoColor * of the painting color space. Please note, that in most of the * cases the exact reverse transformation does not exist, so the * resulting color will be only a rough approximation. Never try * to do a round trip like that: * * // r will never be equal to c! * r = approximateFromRenderedQColor(toQColor(c)); */ virtual KoColor approximateFromRenderedQColor(const QColor &c) const = 0; virtual KoColor fromHsv(int h, int s, int v, int a = 255) const = 0; virtual void getHsv(const KoColor &srcColor, int *h, int *s, int *v, int *a = 0) const = 0; /** * \return the minimum value of a floating point channel that can * be seen on screen */ virtual qreal minVisibleFloatValue(const KoChannelInfo *chaninfo) const = 0; /** * \return the maximum value of a floating point channel that can * be seen on screen. In normal situation it is 1.0. When * the user changes exposure the value varies. */ virtual qreal maxVisibleFloatValue(const KoChannelInfo *chaninfo) const = 0; /** * @brief getColorSpace * @return the painting color space, this is useful for determining the transform. */ virtual const KoColorSpace* getPaintingColorSpace() const = 0; Q_SIGNALS: void displayConfigurationChanged(); private: Q_DISABLE_COPY(KoColorDisplayRendererInterface) }; /** * The default conversion class that just calls KoColor::toQColor() * conversion implementation which efectively renders the color into * sRGB color space. */ class KRITAPIGMENT_EXPORT KoDumbColorDisplayRenderer : public KoColorDisplayRendererInterface { public: + QImage convertToQImage(const KoColorSpace *srcColorSpace, const quint8 *data, qint32 width, qint32 height) const; QColor toQColor(const KoColor &c) const; KoColor approximateFromRenderedQColor(const QColor &c) const; KoColor fromHsv(int h, int s, int v, int a = 255) const; void getHsv(const KoColor &srcColor, int *h, int *s, int *v, int *a = 0) const; virtual qreal minVisibleFloatValue(const KoChannelInfo *chaninfo) const; virtual qreal maxVisibleFloatValue(const KoChannelInfo *chaninfo) const; virtual const KoColorSpace* getPaintingColorSpace() const; static KoColorDisplayRendererInterface* instance(); }; #endif /* __KO_COLOR_DISPLAY_RENDERER_INTERFACE_H */ diff --git a/libs/ui/canvas/kis_display_color_converter.cpp b/libs/ui/canvas/kis_display_color_converter.cpp index b05e5dd1f2..5c57a0d324 100644 --- a/libs/ui/canvas/kis_display_color_converter.cpp +++ b/libs/ui/canvas/kis_display_color_converter.cpp @@ -1,635 +1,641 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_display_color_converter.h" #include #include #include #include #include #include #include #include #include #include "kis_config_notifier.h" #include "kis_canvas_resource_provider.h" #include "kis_canvas2.h" #include "KisViewManager.h" #include "kis_image.h" #include "kis_node.h" #include "kundo2command.h" #include "kis_config.h" #include "kis_paint_device.h" #include "kis_iterator_ng.h" Q_GLOBAL_STATIC(KisDisplayColorConverter, s_instance) struct KisDisplayColorConverter::Private { Private(KisDisplayColorConverter *_q, KoCanvasResourceManager *_resourceManager) : q(_q), resourceManager(_resourceManager), nodeColorSpace(0), paintingColorSpace(0), monitorColorSpace(0), monitorProfile(0), renderingIntent(KoColorConversionTransformation::internalRenderingIntent()), conversionFlags(KoColorConversionTransformation::internalConversionFlags()), displayFilter(0), intermediateColorSpace(0), displayRenderer(new DisplayRenderer(_q, _resourceManager)) { } KisDisplayColorConverter *const q; KoCanvasResourceManager *resourceManager; const KoColorSpace *nodeColorSpace; const KoColorSpace *paintingColorSpace; const KoColorSpace *monitorColorSpace; const KoColorProfile *monitorProfile; KoColorConversionTransformation::Intent renderingIntent; KoColorConversionTransformation::ConversionFlags conversionFlags; QSharedPointer displayFilter; const KoColorSpace *intermediateColorSpace; KoColor intermediateFgColor; KisNodeSP connectedNode; inline KoColor approximateFromQColor(const QColor &qcolor); inline QColor approximateToQColor(const KoColor &color); void slotCanvasResourceChanged(int key, const QVariant &v); void slotUpdateCurrentNodeColorSpace(); void selectPaintingColorSpace(); void updateIntermediateFgColor(const KoColor &color); void setCurrentNode(KisNodeSP node); bool useOcio() const; bool finalIsRgba(const KoColorSpace *cs) const; template QColor floatArrayToQColor(const float *p); template QImage convertToQImageDirect(KisPaintDeviceSP device); class DisplayRenderer : public KoColorDisplayRendererInterface { public: DisplayRenderer(KisDisplayColorConverter *displayColorConverter, KoCanvasResourceManager *resourceManager) : m_displayColorConverter(displayColorConverter), m_resourceManager(resourceManager) { displayColorConverter->connect(displayColorConverter, SIGNAL(displayConfigurationChanged()), this, SIGNAL(displayConfigurationChanged())); } + QImage convertToQImage(const KoColorSpace *srcColorSpace, const quint8 *data, qint32 width, qint32 height) const { + KisPaintDeviceSP dev = new KisPaintDevice(srcColorSpace); + dev->writeBytes(data, 0, 0, width, height); + return m_displayColorConverter->toQImage(dev); + } + QColor toQColor(const KoColor &c) const override { return m_displayColorConverter->toQColor(c); } KoColor approximateFromRenderedQColor(const QColor &c) const override { return m_displayColorConverter->approximateFromRenderedQColor(c); } KoColor fromHsv(int h, int s, int v, int a) const override { return m_displayColorConverter->fromHsv(h, s, v, a); } void getHsv(const KoColor &srcColor, int *h, int *s, int *v, int *a) const override { m_displayColorConverter->getHsv(srcColor, h, s, v, a); } qreal minVisibleFloatValue(const KoChannelInfo *chaninfo) const override { return chaninfo->getUIMin(); } qreal maxVisibleFloatValue(const KoChannelInfo *chaninfo) const override { qreal maxValue = chaninfo->getUIMax(); if (m_resourceManager) { qreal exposure = m_resourceManager->resource(KisCanvasResourceProvider::HdrExposure).value(); // not sure if *= is what we want maxValue *= std::pow(2.0, -exposure); } return maxValue; } const KoColorSpace* getPaintingColorSpace() const override { return m_displayColorConverter->paintingColorSpace(); } private: KisDisplayColorConverter *m_displayColorConverter; QPointer m_resourceManager; }; QScopedPointer displayRenderer; }; KisDisplayColorConverter::KisDisplayColorConverter(KoCanvasResourceManager *resourceManager, QObject *parent) : QObject(parent), m_d(new Private(this, resourceManager)) { connect(m_d->resourceManager, SIGNAL(canvasResourceChanged(int, const QVariant&)), SLOT(slotCanvasResourceChanged(int, const QVariant&))); connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(selectPaintingColorSpace())); m_d->setCurrentNode(0); setMonitorProfile(0); setDisplayFilter(QSharedPointer(0)); } KisDisplayColorConverter::KisDisplayColorConverter() : m_d(new Private(this, 0)) { setDisplayFilter(QSharedPointer(0)); m_d->paintingColorSpace = KoColorSpaceRegistry::instance()->rgb8(); m_d->setCurrentNode(0); setMonitorProfile(0); } KisDisplayColorConverter::~KisDisplayColorConverter() { } KisDisplayColorConverter* KisDisplayColorConverter::dumbConverterInstance() { return s_instance; } KoColorDisplayRendererInterface* KisDisplayColorConverter::displayRendererInterface() const { return m_d->displayRenderer.data(); } bool KisDisplayColorConverter::Private::useOcio() const { return displayFilter && paintingColorSpace->colorModelId() == RGBAColorModelID; } void KisDisplayColorConverter::Private::updateIntermediateFgColor(const KoColor &srcColor) { KIS_ASSERT_RECOVER_RETURN(displayFilter); KoColor color = srcColor; color.convertTo(intermediateColorSpace); displayFilter->approximateForwardTransformation(color.data(), 1); intermediateFgColor = color; } void KisDisplayColorConverter::Private::slotCanvasResourceChanged(int key, const QVariant &v) { if (key == KisCanvasResourceProvider::CurrentKritaNode) { KisNodeSP currentNode = v.value(); setCurrentNode(currentNode); } else if (useOcio() && key == KoCanvasResourceManager::ForegroundColor) { updateIntermediateFgColor(v.value()); } } void KisDisplayColorConverter::Private::slotUpdateCurrentNodeColorSpace() { setCurrentNode(connectedNode); } inline KisPaintDeviceSP findValidDevice(KisNodeSP node) { return node->paintDevice() ? node->paintDevice() : node->original(); } void KisDisplayColorConverter::Private::setCurrentNode(KisNodeSP node) { if (connectedNode) { KisPaintDeviceSP device = findValidDevice(connectedNode); if (device) { q->disconnect(device, 0); } } if (node) { KisPaintDeviceSP device = findValidDevice(node); nodeColorSpace = device ? device->compositionSourceColorSpace() : node->colorSpace(); KIS_ASSERT_RECOVER_NOOP(nodeColorSpace); if (device) { q->connect(device, SIGNAL(profileChanged(const KoColorProfile*)), SLOT(slotUpdateCurrentNodeColorSpace()), Qt::UniqueConnection); q->connect(device, SIGNAL(colorSpaceChanged(const KoColorSpace*)), SLOT(slotUpdateCurrentNodeColorSpace()), Qt::UniqueConnection); } } else { nodeColorSpace = KoColorSpaceRegistry::instance()->rgb8(); } connectedNode = node; selectPaintingColorSpace(); } void KisDisplayColorConverter::Private::selectPaintingColorSpace() { KisConfig cfg; paintingColorSpace = cfg.customColorSelectorColorSpace(); if (!paintingColorSpace || displayFilter) { paintingColorSpace = nodeColorSpace; } emit q->displayConfigurationChanged(); } const KoColorSpace* KisDisplayColorConverter::paintingColorSpace() const { KIS_ASSERT_RECOVER(m_d->paintingColorSpace) { return KoColorSpaceRegistry::instance()->rgb8(); } return m_d->paintingColorSpace; } void KisDisplayColorConverter::setMonitorProfile(const KoColorProfile *monitorProfile) { m_d->monitorColorSpace = KoColorSpaceRegistry::instance()->rgb8(monitorProfile); m_d->monitorProfile = monitorProfile; m_d->renderingIntent = renderingIntent(); m_d->conversionFlags = conversionFlags(); emit displayConfigurationChanged(); } void KisDisplayColorConverter::setDisplayFilter(QSharedPointer displayFilter) { if (m_d->displayFilter && displayFilter && displayFilter->lockCurrentColorVisualRepresentation()) { KoColor color(m_d->intermediateFgColor); displayFilter->approximateInverseTransformation(color.data(), 1); color.convertTo(m_d->paintingColorSpace); m_d->resourceManager->setForegroundColor(color); } m_d->displayFilter = displayFilter; m_d->intermediateColorSpace = 0; if (m_d->displayFilter) { // choosing default profile, which is scRGB const KoColorProfile *intermediateProfile = 0; m_d->intermediateColorSpace = KoColorSpaceRegistry::instance()-> colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id(), intermediateProfile); KIS_ASSERT_RECOVER(m_d->intermediateColorSpace) { m_d->intermediateColorSpace = m_d->monitorColorSpace; } m_d->updateIntermediateFgColor( m_d->resourceManager->foregroundColor()); } { // sanity check KisConfig cfg; //KIS_ASSERT_RECOVER_NOOP(cfg.useOcio() == (bool) m_d->displayFilter); } m_d->selectPaintingColorSpace(); } KoColorConversionTransformation::Intent KisDisplayColorConverter::renderingIntent() { KisConfig cfg; return (KoColorConversionTransformation::Intent)cfg.monitorRenderIntent(); } KoColorConversionTransformation::ConversionFlags KisDisplayColorConverter::conversionFlags() { KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::HighQuality; KisConfig cfg; if (cfg.useBlackPointCompensation()) conversionFlags |= KoColorConversionTransformation::BlackpointCompensation; if (!cfg.allowLCMSOptimization()) conversionFlags |= KoColorConversionTransformation::NoOptimization; return conversionFlags; } QSharedPointer KisDisplayColorConverter::displayFilter() const { return m_d->displayFilter; } const KoColorProfile* KisDisplayColorConverter::monitorProfile() const { return m_d->monitorProfile; } bool KisDisplayColorConverter::Private::finalIsRgba(const KoColorSpace *cs) const { /** * In Krita RGB color spaces differ: 8/16bit are BGRA, 16f/32f-bit RGBA */ KoID colorDepthId = cs->colorDepthId(); return colorDepthId == Float16BitsColorDepthID || colorDepthId == Float32BitsColorDepthID; } template QColor KisDisplayColorConverter::Private::floatArrayToQColor(const float *p) { if (flipToBgra) { return QColor(KoColorSpaceMaths::scaleToA(p[0]), KoColorSpaceMaths::scaleToA(p[1]), KoColorSpaceMaths::scaleToA(p[2]), KoColorSpaceMaths::scaleToA(p[3])); } else { return QColor(KoColorSpaceMaths::scaleToA(p[2]), KoColorSpaceMaths::scaleToA(p[1]), KoColorSpaceMaths::scaleToA(p[0]), KoColorSpaceMaths::scaleToA(p[3])); } } QColor KisDisplayColorConverter::toQColor(const KoColor &srcColor) const { KoColor c(srcColor); c.convertTo(m_d->paintingColorSpace); if (!m_d->useOcio()) { // we expect the display profile is rgb8, which is BGRA here KIS_ASSERT_RECOVER(m_d->monitorColorSpace->pixelSize() == 4) { return Qt::red; }; c.convertTo(m_d->monitorColorSpace, m_d->renderingIntent, m_d->conversionFlags); const quint8 *p = c.data(); return QColor(p[2], p[1], p[0], p[3]); } else { const KoColorSpace *srcCS = c.colorSpace(); if (m_d->displayFilter->useInternalColorManagement()) { srcCS = KoColorSpaceRegistry::instance()->colorSpace( RGBAColorModelID.id(), Float32BitsColorDepthID.id(), m_d->monitorProfile); c.convertTo(srcCS, m_d->renderingIntent, m_d->conversionFlags); } int numChannels = srcCS->channelCount(); QVector normalizedChannels(numChannels); srcCS->normalisedChannelsValue(c.data(), normalizedChannels); m_d->displayFilter->filter((quint8*)normalizedChannels.data(), 1); const float *p = (const float *)normalizedChannels.constData(); return m_d->finalIsRgba(srcCS) ? m_d->floatArrayToQColor(p) : m_d->floatArrayToQColor(p); } } KoColor KisDisplayColorConverter::approximateFromRenderedQColor(const QColor &c) const { return m_d->approximateFromQColor(c); } template QImage KisDisplayColorConverter::Private::convertToQImageDirect(KisPaintDeviceSP device) { QRect bounds = device->exactBounds(); if (bounds.isEmpty()) return QImage(); QImage image(bounds.size(), QImage::Format_ARGB32); KisSequentialConstIterator it(device, bounds); quint8 *dstPtr = image.bits(); const KoColorSpace *cs = device->colorSpace(); int numChannels = cs->channelCount(); QVector normalizedChannels(numChannels); do { cs->normalisedChannelsValue(it.rawDataConst(), normalizedChannels); displayFilter->filter((quint8*)normalizedChannels.data(), 1); const float *p = normalizedChannels.constData(); if (flipToBgra) { dstPtr[0] = KoColorSpaceMaths::scaleToA(p[2]); dstPtr[1] = KoColorSpaceMaths::scaleToA(p[1]); dstPtr[2] = KoColorSpaceMaths::scaleToA(p[0]); dstPtr[3] = KoColorSpaceMaths::scaleToA(p[3]); } else { dstPtr[0] = KoColorSpaceMaths::scaleToA(p[0]); dstPtr[1] = KoColorSpaceMaths::scaleToA(p[1]); dstPtr[2] = KoColorSpaceMaths::scaleToA(p[2]); dstPtr[3] = KoColorSpaceMaths::scaleToA(p[3]); } dstPtr += 4; } while (it.nextPixel()); return image; } QImage KisDisplayColorConverter::toQImage(KisPaintDeviceSP srcDevice) const { KisPaintDeviceSP device = srcDevice; if (*device->colorSpace() != *m_d->paintingColorSpace) { device = new KisPaintDevice(*srcDevice); KUndo2Command *cmd = device->convertTo(m_d->paintingColorSpace); delete cmd; } if (!m_d->useOcio()) { return device->convertToQImage(m_d->monitorProfile, m_d->renderingIntent, m_d->conversionFlags); } else { if (m_d->displayFilter->useInternalColorManagement()) { if (device == srcDevice) { device = new KisPaintDevice(*srcDevice); } const KoColorSpace *srcCS = KoColorSpaceRegistry::instance()->colorSpace( RGBAColorModelID.id(), Float32BitsColorDepthID.id(), m_d->monitorProfile); KUndo2Command *cmd = device->convertTo(srcCS, m_d->renderingIntent, m_d->conversionFlags); delete cmd; } return m_d->finalIsRgba(device->colorSpace()) ? m_d->convertToQImageDirect(device) : m_d->convertToQImageDirect(device); } return QImage(); } KoColor KisDisplayColorConverter::Private::approximateFromQColor(const QColor &qcolor) { if (!useOcio()) { return KoColor(qcolor, paintingColorSpace); } else { KoColor color(qcolor, intermediateColorSpace); displayFilter->approximateInverseTransformation(color.data(), 1); color.convertTo(paintingColorSpace); return color; } qFatal("Must not be reachable"); return KoColor(); } QColor KisDisplayColorConverter::Private::approximateToQColor(const KoColor &srcColor) { KoColor color(srcColor); if (useOcio()) { color.convertTo(intermediateColorSpace); displayFilter->approximateForwardTransformation(color.data(), 1); } return color.toQColor(); } KoColor KisDisplayColorConverter::fromHsv(int h, int s, int v, int a) const { // generate HSV from sRGB! QColor qcolor(QColor::fromHsv(h, s, v, a)); return m_d->approximateFromQColor(qcolor); } void KisDisplayColorConverter::getHsv(const KoColor &srcColor, int *h, int *s, int *v, int *a) const { // we are going through sRGB here! QColor color = m_d->approximateToQColor(srcColor); color.getHsv(h, s, v, a); } KoColor KisDisplayColorConverter::fromHsvF(qreal h, qreal s, qreal v, qreal a) { // generate HSV from sRGB! QColor qcolor(QColor::fromHsvF(h, s, v, a)); return m_d->approximateFromQColor(qcolor); } void KisDisplayColorConverter::getHsvF(const KoColor &srcColor, qreal *h, qreal *s, qreal *v, qreal *a) { // we are going through sRGB here! QColor color = m_d->approximateToQColor(srcColor); color.getHsvF(h, s, v, a); } KoColor KisDisplayColorConverter::fromHslF(qreal h, qreal s, qreal l, qreal a) { // generate HSL from sRGB! QColor qcolor(QColor::fromHslF(h, s, l, a)); if (!qcolor.isValid()) { warnKrita << "Could not construct valid color from h" << h << "s" << s << "l" << l << "a" << a; qcolor = Qt::black; } return m_d->approximateFromQColor(qcolor); } void KisDisplayColorConverter::getHslF(const KoColor &srcColor, qreal *h, qreal *s, qreal *l, qreal *a) { // we are going through sRGB here! QColor color = m_d->approximateToQColor(srcColor); color.getHslF(h, s, l, a); } KoColor KisDisplayColorConverter::fromHsiF(qreal h, qreal s, qreal i) { // generate HSI from sRGB! qreal r=0.0; qreal g=0.0; qreal b=0.0; qreal a=1.0; HSIToRGB(h, s, i, &r, &g, &b); QColor qcolor; qcolor.setRgbF(qBound(0.0,r,1.0), qBound(0.0,g,1.0), qBound(0.0,b,1.0), a); return m_d->approximateFromQColor(qcolor); } void KisDisplayColorConverter::getHsiF(const KoColor &srcColor, qreal *h, qreal *s, qreal *i) { // we are going through sRGB here! QColor color = m_d->approximateToQColor(srcColor); qreal r=color.redF(); qreal g=color.greenF(); qreal b=color.blueF(); RGBToHSI(r, g, b, h, s, i); } KoColor KisDisplayColorConverter::fromHsyF(qreal h, qreal s, qreal y, qreal R, qreal G, qreal B, qreal gamma) { // generate HSL from sRGB! QVector channelValues(3); y = pow(y, gamma); HSYToRGB(h, s, y, &channelValues[0], &channelValues[1], &channelValues[2], R, G, B); KoColorSpaceRegistry::instance()->rgb8()->profile()->delinearizeFloatValueFast(channelValues); QColor qcolor; qcolor.setRgbF(qBound(0.0,channelValues[0],1.0), qBound(0.0,channelValues[1],1.0), qBound(0.0,channelValues[2],1.0), 1.0); return m_d->approximateFromQColor(qcolor); } void KisDisplayColorConverter::getHsyF(const KoColor &srcColor, qreal *h, qreal *s, qreal *y, qreal R, qreal G, qreal B, qreal gamma) { // we are going through sRGB here! QColor color = m_d->approximateToQColor(srcColor); QVector channelValues(3); channelValues[0]=color.redF(); channelValues[1]=color.greenF(); channelValues[2]=color.blueF(); //TODO: if we're going to have KoColor here, remember to check whether the TRC of the profile exists... KoColorSpaceRegistry::instance()->rgb8()->profile()->linearizeFloatValueFast(channelValues); RGBToHSY(channelValues[0], channelValues[1], channelValues[2], h, s, y, R, G, B); *y = pow(*y, 1/gamma); } #include "moc_kis_display_color_converter.cpp"