From 929c02fa0ec1588a78d42b78fd2d78ef57d036b2 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Thu, 13 Oct 2022 19:39:24 +0200 Subject: [PATCH] colorTable generation added --- src/common/QskRgbValue.cpp | 99 ++++++++++++++++++++++++++++++++++++++ src/common/QskRgbValue.h | 16 ++++++ 2 files changed, 115 insertions(+) diff --git a/src/common/QskRgbValue.cpp b/src/common/QskRgbValue.cpp index fb29be32..1431ddd1 100644 --- a/src/common/QskRgbValue.cpp +++ b/src/common/QskRgbValue.cpp @@ -5,6 +5,13 @@ #include "QskRgbValue.h" +#include +#include + +QSK_QT_PRIVATE_BEGIN +#include +QSK_QT_PRIVATE_END + namespace { inline int value( int from, int to, qreal ratio ) @@ -196,3 +203,95 @@ void QskRgb::debugColor( QDebug debug, QRgb rgb ) } #endif + +QImage QskRgb::colorTable( int size, const QskGradientStops& stops ) +{ + if ( size == 0 || stops.isEmpty() ) + return QImage(); + + QImage image( size, 1, QImage::Format_RGBA8888_Premultiplied ); + + if ( stops.size() == 1 ) + { + const auto rgb = ARGB2RGBA( qPremultiply( stops[0].rgb() ) ); + image.fill( rgb ); + + return image; + } + + auto values = reinterpret_cast< uint* >( image.bits() ); + + int index1, index2; + QRgb rgb1, rgb2; + + index1 = index2 = qRound( stops[0].position() * size ); + rgb1 = rgb2 = qPremultiply( stops[0].rgb() ); + + if ( index1 > 0 ) + { + const auto v = ARGB2RGBA( rgb1 ); + + for ( int i = 0; i < index1; i++ ) + values[i] = v; + } + + for ( int i = 1; i < stops.count(); i++ ) + { + const auto& stop = stops[i]; + + index2 = qRound( stop.position() * size ); + rgb2 = qPremultiply( stop.rgb() ); + + const auto n = index2 - index1; + + for ( int j = 0; j < n; j++ ) + { + const auto rgb = QskRgb::interpolated( rgb1, rgb2, qreal( j ) / ( n - 1 ) ); + values[ index1 + j] = ARGB2RGBA( rgb ); + } + + index1 = index2; + rgb1 = rgb2; + } + + if ( index1 < size - 1 ) + { + const auto v = ARGB2RGBA( rgb1 ); + + for ( int i = index1; i < size ; i++ ) + values[i] = v; + } + + return image; +} + +QImage QskRgb::colorTable( const int size, + QRgb rgb1, QRgb rgb2, const QEasingCurve& curve ) +{ + if ( size == 0 ) + return QImage(); + + rgb1 = qPremultiply( rgb1 ); + rgb2 = qPremultiply( rgb2 ); + + QImage image( size, 1, QImage::Format_RGBA8888_Premultiplied ); + + if ( rgb1 == rgb2 ) + { + image.fill( ARGB2RGBA( rgb1 ) ); + return image; + } + + auto values = reinterpret_cast< uint* >( image.bits() ); + + for ( int i = 0; i < size; i++ ) + { + qreal progress = curve.valueForProgress( qreal( i ) / ( size - 1 ) ); + progress = qBound( 0.0, progress, 1.0 ); + + auto rgb = QskRgb::interpolated( rgb1, rgb2, progress ); + values[i] = ARGB2RGBA( rgb ); + } + + return image; +} diff --git a/src/common/QskRgbValue.h b/src/common/QskRgbValue.h index 39687898..2ff1b55e 100644 --- a/src/common/QskRgbValue.h +++ b/src/common/QskRgbValue.h @@ -7,8 +7,13 @@ #define QSK_RGB_VALUE_H #include "QskGlobal.h" +#include "QskGradientStop.h" + #include +class QEasingCurve; +class QImage; + namespace QskRgb { /* Web colors */ @@ -207,6 +212,17 @@ namespace QskRgb QSK_EXPORT QRgb darker( QRgb, int factor = 200 ) noexcept; } +namespace QskRgb +{ + /* + One dimensional array of colors ( height is always 1 ) of + Format_RGBA8888_Premultiplied + */ + + QSK_EXPORT QImage colorTable( int size, const QskGradientStops& ); + QSK_EXPORT QImage colorTable( int size, QRgb, QRgb, const QEasingCurve& ); +} + #ifndef QT_NO_DEBUG_STREAM class QDebug;