diff options
author | Allan Sandfeld Jensen <[email protected]> | 2019-12-09 13:44:31 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <[email protected]> | 2020-01-31 11:04:06 +0100 |
commit | a6e661d25bf7ebeb8f4e58925aa9375f5ca10ef3 (patch) | |
tree | eff5daac853cbc4d6e75a25a71b89a19141d21e0 /src | |
parent | 276d00cff956cb54612ec425b7c40eb50a20d78a (diff) |
Image ColorSpace bindings for Quick/QML
Adds a ColorSpace type mapped to QColorSpace, and adds a property to
Image nodes to read and change it, converting the image if necessary
on read.
Fixes: QTBUG-80616
Change-Id: Ie80c8bc045f66de01de3a5d2c4a9974f07d2871d
Reviewed-by: Andy Nichols <[email protected]>
Diffstat (limited to 'src')
-rw-r--r-- | src/quick/items/qquickimagebase.cpp | 20 | ||||
-rw-r--r-- | src/quick/items/qquickimagebase_p.h | 6 | ||||
-rw-r--r-- | src/quick/items/qquickimagebase_p_p.h | 1 | ||||
-rw-r--r-- | src/quick/util/qquickglobal.cpp | 60 | ||||
-rw-r--r-- | src/quick/util/qquickimageprovider.cpp | 18 | ||||
-rw-r--r-- | src/quick/util/qquickpixmapcache.cpp | 14 | ||||
-rw-r--r-- | src/quick/util/qquickpixmapcache_p.h | 5 | ||||
-rw-r--r-- | src/quick/util/qquickvaluetypes.cpp | 42 | ||||
-rw-r--r-- | src/quick/util/qquickvaluetypes_p.h | 52 |
9 files changed, 217 insertions, 1 deletions
diff --git a/src/quick/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp index 2118f67387..8849c2005c 100644 --- a/src/quick/items/qquickimagebase.cpp +++ b/src/quick/items/qquickimagebase.cpp @@ -396,6 +396,10 @@ void QQuickImageBase::requestFinished() d->frameCount = d->pix.frameCount(); emit frameCountChanged(); } + if (d->colorSpace != d->pix.colorSpace()) { + d->colorSpace = d->pix.colorSpace(); + emit colorSpaceChanged(); + } update(); } @@ -488,6 +492,22 @@ void QQuickImageBase::setAutoTransform(bool transform) emitAutoTransformBaseChanged(); } +QColorSpace QQuickImageBase::colorSpace() const +{ + Q_D(const QQuickImageBase); + return d->colorSpace; +} + +void QQuickImageBase::setColorSpace(const QColorSpace &colorSpace) +{ + Q_D(QQuickImageBase); + if (d->colorSpace == colorSpace) + return; + d->colorSpace = colorSpace; + d->providerOptions.setTargetColorSpace(colorSpace); + emit colorSpaceChanged(); +} + QT_END_NAMESPACE #include "moc_qquickimagebase_p.cpp" diff --git a/src/quick/items/qquickimagebase_p.h b/src/quick/items/qquickimagebase_p.h index 238b31b2e5..095547a2cf 100644 --- a/src/quick/items/qquickimagebase_p.h +++ b/src/quick/items/qquickimagebase_p.h @@ -53,6 +53,7 @@ #include "qquickimplicitsizeitem_p.h" #include <private/qtquickglobal_p.h> +#include <QtGui/qcolorspace.h> QT_BEGIN_NAMESPACE @@ -70,6 +71,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickImageBase : public QQuickImplicitSizeItem Q_PROPERTY(bool mirror READ mirror WRITE setMirror NOTIFY mirrorChanged) Q_PROPERTY(int currentFrame READ currentFrame WRITE setCurrentFrame NOTIFY currentFrameChanged REVISION 14) Q_PROPERTY(int frameCount READ frameCount NOTIFY frameCountChanged REVISION 14) + Q_PROPERTY(QColorSpace colorSpace READ colorSpace WRITE setColorSpace NOTIFY colorSpaceChanged REVISION 15) QML_NAMED_ELEMENT(ImageBase); QML_ADDED_IN_MINOR_VERSION(14) @@ -122,6 +124,9 @@ public: virtual void setAutoTransform(bool transform); bool autoTransform() const; + QColorSpace colorSpace() const; + virtual void setColorSpace(const QColorSpace &colorSpace); + static void resolve2xLocalFile(const QUrl &url, qreal targetDevicePixelRatio, QUrl *sourceUrl, qreal *sourceDevicePixelRatio); // Use a virtual rather than a signal->signal to avoid the huge @@ -139,6 +144,7 @@ Q_SIGNALS: Q_REVISION(14) void currentFrameChanged(); Q_REVISION(14) void frameCountChanged(); Q_REVISION(15) void sourceClipRectChanged(); + Q_REVISION(15) void colorSpaceChanged(); protected: void loadEmptyUrl(); diff --git a/src/quick/items/qquickimagebase_p_p.h b/src/quick/items/qquickimagebase_p_p.h index 00a9295ef0..ebb7568caf 100644 --- a/src/quick/items/qquickimagebase_p_p.h +++ b/src/quick/items/qquickimagebase_p_p.h @@ -88,6 +88,7 @@ public: qreal devicePixelRatio; QRectF sourceClipRect; QQuickImageProviderOptions providerOptions; + QColorSpace colorSpace; int currentFrame; int frameCount; bool async : 1; diff --git a/src/quick/util/qquickglobal.cpp b/src/quick/util/qquickglobal.cpp index bc5b8c4f3e..70256e202e 100644 --- a/src/quick/util/qquickglobal.cpp +++ b/src/quick/util/qquickglobal.cpp @@ -273,6 +273,52 @@ public: return QMatrix4x4(); } + static QColorSpace colorSpaceFromObject(const QV4::Value &object, QV4::ExecutionEngine *v4, bool *ok) + { + if (ok) + *ok = false; + QColorSpace retn; + QV4::Scope scope(v4); + QV4::ScopedObject obj(scope, object); + if (!obj) { + if (ok) + *ok = false; + return retn; + } + + QV4::ScopedString s(scope); + + QV4::ScopedValue vName(scope, obj->get((s = v4->newString(QStringLiteral("namedColorSpace"))))); + if (vName->isInt32()) { + if (ok) + *ok = true; + return QColorSpace((QColorSpace::NamedColorSpace)vName->toInt32()); + } + + QV4::ScopedValue vPri(scope, obj->get((s = v4->newString(QStringLiteral("primaries"))))); + QV4::ScopedValue vTra(scope, obj->get((s = v4->newString(QStringLiteral("transferFunction"))))); + if (!vPri->isInt32() || !vTra->isInt32()) { + if (ok) + *ok = false; + return retn; + } + + QColorSpace::Primaries pri = static_cast<QColorSpace::Primaries>(vPri->integerValue()); + QColorSpace::TransferFunction tra = static_cast<QColorSpace::TransferFunction>(vTra->integerValue()); + float gamma = 0.0f; + if (tra == QColorSpace::TransferFunction::Gamma) { + QV4::ScopedValue vGam(scope, obj->get((s = v4->newString(QStringLiteral("gamma"))))); + if (!vGam->isNumber()) { + if (ok) + *ok = false; + return retn; + } + gamma = vGam->toNumber(); + } + if (ok) *ok = true; + return QColorSpace(pri, tra, gamma); + } + static QFont fontFromObject(const QV4::Value &object, QV4::ExecutionEngine *v4, bool *ok) { if (ok) @@ -402,6 +448,8 @@ public: switch (type) { case QMetaType::QColor: return &QQuickColorValueType::staticMetaObject; + case QMetaType::QColorSpace: + return &QQuickColorSpaceValueType::staticMetaObject; case QMetaType::QFont: return &QQuickFontValueType::staticMetaObject; case QMetaType::QVector2D: @@ -427,6 +475,9 @@ public: case QMetaType::QColor: dst.setValue<QColor>(QColor()); return true; + case QMetaType::QColorSpace: + dst.setValue<QColorSpace>(QColorSpace()); + return true; case QMetaType::QFont: dst.setValue<QFont>(QFont()); return true; @@ -647,6 +698,9 @@ public: #endif bool ok = false; switch (type) { + case QMetaType::QColorSpace: + *v = QVariant::fromValue(colorSpaceFromObject(object, v4, &ok)); + break; case QMetaType::QFont: *v = QVariant::fromValue(fontFromObject(object, v4, &ok)); break; @@ -669,6 +723,8 @@ public: switch (type) { case QMetaType::QColor: return typedEqual<QColor>(lhs, rhs); + case QMetaType::QColorSpace: + return typedEqual<QColorSpace>(lhs, rhs); case QMetaType::QFont: return typedEqual<QFont>(lhs, rhs); case QMetaType::QVector2D: @@ -732,6 +788,8 @@ public: switch (dstType) { case QMetaType::QColor: return typedRead<QColor>(src, dstType, dst); + case QMetaType::QColorSpace: + return typedRead<QColorSpace>(src, dstType, dst); case QMetaType::QFont: return typedRead<QFont>(src, dstType, dst); case QMetaType::QVector2D: @@ -766,6 +824,8 @@ public: switch (type) { case QMetaType::QColor: return typedWrite<QColor>(src, dst); + case QMetaType::QColorSpace: + return typedWrite<QColorSpace>(src, dst); case QMetaType::QFont: return typedWrite<QFont>(src, dst); case QMetaType::QVector2D: diff --git a/src/quick/util/qquickimageprovider.cpp b/src/quick/util/qquickimageprovider.cpp index db82b2d807..80873e2ad5 100644 --- a/src/quick/util/qquickimageprovider.cpp +++ b/src/quick/util/qquickimageprovider.cpp @@ -43,6 +43,7 @@ #include "qquickpixmapcache_p.h" #include <QtQuick/private/qsgcontext_p.h> #include <private/qqmlglobal_p.h> +#include <QtGui/qcolorspace.h> QT_BEGIN_NAMESPACE @@ -510,6 +511,7 @@ public: { } + QColorSpace targetColorSpace; QQuickImageProviderOptions::AutoTransform autoTransform = QQuickImageProviderOptions::UsePluginDefaultTransform; bool preserveAspectRatioCrop = false; bool preserveAspectRatioFit = false; @@ -558,7 +560,8 @@ bool QQuickImageProviderOptions::operator==(const QQuickImageProviderOptions &ot { return d->autoTransform == other.d->autoTransform && d->preserveAspectRatioCrop == other.d->preserveAspectRatioCrop && - d->preserveAspectRatioFit == other.d->preserveAspectRatioFit; + d->preserveAspectRatioFit == other.d->preserveAspectRatioFit && + d->targetColorSpace == other.d->targetColorSpace; } /*! @@ -602,6 +605,19 @@ void QQuickImageProviderOptions::setPreserveAspectRatioFit(bool preserveAspectRa d->preserveAspectRatioFit = preserveAspectRatioFit; } +/*! + Returns the color space the image provider should return the image in. +*/ +QColorSpace QQuickImageProviderOptions::targetColorSpace() const +{ + return d->targetColorSpace; +} + +void QQuickImageProviderOptions::setTargetColorSpace(const QColorSpace &colorSpace) +{ + d->targetColorSpace = colorSpace; +} + QQuickImageProviderWithOptions::QQuickImageProviderWithOptions(ImageType type, Flags flags) : QQuickAsyncImageProvider() { diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp index bdd1e2c514..2ae9debbc9 100644 --- a/src/quick/util/qquickpixmapcache.cpp +++ b/src/quick/util/qquickpixmapcache.cpp @@ -318,6 +318,7 @@ public: QSize requestSize; QQuickImageProviderOptions providerOptions; QQuickImageProviderOptions::AutoTransform appliedTransform; + QColorSpace targetColorSpace; QQuickTextureFactory *textureFactory; @@ -436,6 +437,12 @@ static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *e maybeRemoveAlpha(image); if (impsize && impsize->width() < 0) *impsize = image->size(); + if (providerOptions.targetColorSpace().isValid()) { + if (image->colorSpace().isValid()) + image->convertToColorSpace(providerOptions.targetColorSpace()); + else + image->setColorSpace(providerOptions.targetColorSpace()); + } return true; } else { if (errorString) @@ -1763,6 +1770,13 @@ bool QQuickPixmap::connectDownloadProgress(QObject *object, int method) return QMetaObject::connect(d->reply, QQuickPixmapReply::downloadProgressIndex, object, method); } +QColorSpace QQuickPixmap::colorSpace() const +{ + if (!d || !d->textureFactory) + return QColorSpace(); + return d->textureFactory->image().colorSpace(); +} + QT_END_NAMESPACE #include <qquickpixmapcache.moc> diff --git a/src/quick/util/qquickpixmapcache_p.h b/src/quick/util/qquickpixmapcache_p.h index 01c99cdbb6..93dec63e94 100644 --- a/src/quick/util/qquickpixmapcache_p.h +++ b/src/quick/util/qquickpixmapcache_p.h @@ -117,6 +117,9 @@ public: bool preserveAspectRatioFit() const; void setPreserveAspectRatioFit(bool preserveAspectRatioFit); + QColorSpace targetColorSpace() const; + void setTargetColorSpace(const QColorSpace &colorSpace); + private: QSharedDataPointer<QQuickImageProviderOptionsPrivate> d; }; @@ -156,6 +159,8 @@ public: void setImage(const QImage &); void setPixmap(const QQuickPixmap &other); + QColorSpace colorSpace() const; + QQuickTextureFactory *textureFactory() const; QRect rect() const; diff --git a/src/quick/util/qquickvaluetypes.cpp b/src/quick/util/qquickvaluetypes.cpp index b47e1a082d..395385fa0d 100644 --- a/src/quick/util/qquickvaluetypes.cpp +++ b/src/quick/util/qquickvaluetypes.cpp @@ -41,6 +41,7 @@ #include <qtquickglobal.h> #include <private/qqmlvaluetype_p.h> +#include <private/qcolorspace_p.h> #include <private/qfont_p.h> @@ -784,6 +785,47 @@ void QQuickFontValueType::setPreferShaping(bool enable) v.setStyleStrategy(static_cast<QFont::StyleStrategy>(v.styleStrategy() | QFont::PreferNoShaping)); } +QQuickColorSpaceValueType::NamedColorSpace QQuickColorSpaceValueType::namedColorSpace() const noexcept +{ + if (const auto *p = QColorSpacePrivate::get(v)) + return (QQuickColorSpaceValueType::NamedColorSpace)p->namedColorSpace; + return QQuickColorSpaceValueType::Unknown; +} +void QQuickColorSpaceValueType::setNamedColorSpace(QQuickColorSpaceValueType::NamedColorSpace namedColorSpace) +{ + v = { (QColorSpace::NamedColorSpace)namedColorSpace }; +} + +QQuickColorSpaceValueType::Primaries QQuickColorSpaceValueType::primaries() const noexcept +{ + return (QQuickColorSpaceValueType::Primaries)v.primaries(); +} + +void QQuickColorSpaceValueType::setPrimaries(QQuickColorSpaceValueType::Primaries primariesId) +{ + v.setPrimaries((QColorSpace::Primaries)primariesId); +} + +QQuickColorSpaceValueType::TransferFunction QQuickColorSpaceValueType::transferFunction() const noexcept +{ + return (QQuickColorSpaceValueType::TransferFunction)v.transferFunction(); +} + +void QQuickColorSpaceValueType::setTransferFunction(QQuickColorSpaceValueType::TransferFunction transferFunction) +{ + v.setTransferFunction((QColorSpace::TransferFunction)transferFunction, v.gamma()); +} + +float QQuickColorSpaceValueType::gamma() const noexcept +{ + return v.gamma(); +} + +void QQuickColorSpaceValueType::setGamma(float gamma) +{ + v.setTransferFunction(v.transferFunction(), gamma); +} + QT_END_NAMESPACE #include "moc_qquickvaluetypes_p.cpp" diff --git a/src/quick/util/qquickvaluetypes_p.h b/src/quick/util/qquickvaluetypes_p.h index 91e3815d5b..b6cbc37adb 100644 --- a/src/quick/util/qquickvaluetypes_p.h +++ b/src/quick/util/qquickvaluetypes_p.h @@ -56,6 +56,7 @@ #include <private/qqmlvaluetype_p.h> #include <QtGui/QColor> +#include <QtGui/QColorSpace> #include <QtGui/QVector2D> #include <QtGui/QVector3D> #include <QtGui/QVector4D> @@ -408,6 +409,57 @@ public: void setPreferShaping(bool b); }; +class QQuickColorSpaceValueType +{ + QColorSpace v; + Q_GADGET + + Q_PROPERTY(NamedColorSpace namedColorSpace READ namedColorSpace WRITE setNamedColorSpace FINAL) + Q_PROPERTY(Primaries primaries READ primaries WRITE setPrimaries FINAL) + Q_PROPERTY(TransferFunction transferFunction READ transferFunction WRITE setTransferFunction FINAL) + Q_PROPERTY(float gamma READ gamma WRITE setGamma FINAL) + + QML_NAMED_ELEMENT(ColorSpace) + Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + +public: + enum NamedColorSpace { + Unknown = 0, + SRgb, + SRgbLinear, + AdobeRgb, + DisplayP3, + ProPhotoRgb + }; + Q_ENUM(NamedColorSpace) + + enum class Primaries { + Custom = 0, + SRgb, + AdobeRgb, + DciP3D65, + ProPhotoRgb + }; + Q_ENUM(Primaries) + enum class TransferFunction { + Custom = 0, + Linear, + Gamma, + SRgb, + ProPhotoRgb + }; + Q_ENUM(TransferFunction) + + NamedColorSpace namedColorSpace() const noexcept; + void setNamedColorSpace(NamedColorSpace namedColorSpace); + Primaries primaries() const noexcept; + void setPrimaries(Primaries primariesId); + TransferFunction transferFunction() const noexcept; + void setTransferFunction(TransferFunction transferFunction); + float gamma() const noexcept; + void setGamma(float gamma); +}; + QT_END_NAMESPACE #endif // QQUICKVALUETYPES_P_H |