6#include "chromahueimageparameters.h"
8#include "asyncimagerendercallback.h"
9#include "cielchd50values.h"
10#include "helperconstants.h"
11#include "helperimage.h"
12#include "helpermath.h"
13#include "helperqttypes.h"
14#include "interlacingpass.h"
15#include "rgbcolorspace.h"
20#include <qnamespace.h>
23#include <qsharedpointer.h>
34bool ChromaHueImageParameters::operator==(
const ChromaHueImageParameters &other)
const
37 (borderPhysical == other.borderPhysical)
38 && (devicePixelRatioF == other.devicePixelRatioF)
39 && (imageSizePhysical == other.imageSizePhysical)
40 && (lightness == other.lightness)
41 && (rgbColorSpace == other.rgbColorSpace)
50bool ChromaHueImageParameters::operator!=(
const ChromaHueImageParameters &other)
const
52 return !(*
this == other);
72void ChromaHueImageParameters::render(
const QVariant &variantParameters, AsyncImageRenderCallback &callbackObject)
74 if (!variantParameters.
canConvert<ChromaHueImageParameters>()) {
77 const ChromaHueImageParameters parameters =
78 variantParameters.
value<ChromaHueImageParameters>();
87 if (callbackObject.shouldAbort()) {
93 QSize(parameters.imageSizePhysical, parameters.imageSizePhysical),
99 const qreal circleRadius =
100 (parameters.imageSizePhysical - 2 * parameters.borderPhysical) / 2.;
101 if ((circleRadius <= 0) || parameters.rgbColorSpace.isNull()) {
110 myImage.setDevicePixelRatio(parameters.devicePixelRatioF);
111 callbackObject.deliverInterlacingPass(
115 AsyncImageRenderCallback::InterlacingState::Final);
126 cielabD50.L = parameters.lightness;
128 const auto chromaRange =
129 parameters.rgbColorSpace->profileMaximumCielchD50Chroma();
130 const qreal scaleFactor =
static_cast<qreal
>(2 * chromaRange)
134 / (parameters.imageSizePhysical - 2 * parameters.borderPhysical);
145 constexpr qreal pixelOffset = 0.5;
147 const auto shift = pixelOffset - parameters.borderPhysical;
150 constexpr double referenceSizePhysical = 343;
151 const auto factor = parameters.imageSizePhysical / referenceSizePhysical;
153 constexpr int numberOfPassesAtReferenceSize = 5;
154 static_assert(isOdd(numberOfPassesAtReferenceSize));
156 const auto numberOfPasses =
157 numberOfPassesAtReferenceSize
159 + 2 * std::log2(qMax(0.01, factor));
160 InterlacingPass currentPass(numberOfPasses);
162 QPainter myPainter(&myImage);
165 for (
int y = currentPass.lineOffset;
166 y < parameters.imageSizePhysical;
167 y += currentPass.lineFrequency)
169 if (callbackObject.shouldAbort()) {
172 cielabD50.b = chromaRange
173 - (y + shift) * scaleFactor;
174 for (
int x = currentPass.columnOffset;
175 x < parameters.imageSizePhysical;
176 x += currentPass.columnFrequency
179 (x + shift) * scaleFactor
182 (qPow(cielabD50.a, 2) + qPow(cielabD50.b, 2))
183 <= (qPow(chromaRange + overlap, 2))
188 ->fromCielabD50ToQRgbOrTransparent(cielabD50);
189 if (qAlpha(tempColor) != 0) {
195 currentPass.rectangleSize.width(),
196 currentPass.rectangleSize.height(),
200 myPainter.setCompositionMode(
207 currentPass.rectangleSize.width(),
208 currentPass.rectangleSize.height(),
216 myImage.setDevicePixelRatio(parameters.devicePixelRatioF);
217 callbackObject.deliverInterlacingPass(
225 AsyncImageRenderCallback::InterlacingState::Intermediate);
226 myImage.setDevicePixelRatio(1);
228 if (currentPass.countdown > 1) {
229 currentPass.switchToNextPass();
236 if (callbackObject.shouldAbort()) {
261 QList<QPoint> antiAliasCoordinates =
findBoundary(myImage);
264 if (callbackObject.shouldAbort()) {
268 const auto myColorFunction = [parameters, shift, scaleFactor, chromaRange](
const double x,
const double y) -> QRgb {
269 cmsCIELab myCielabD50;
270 myCielabD50.L = parameters.lightness;
271 myCielabD50.b = chromaRange - (y + shift) * scaleFactor;
272 myCielabD50.a = (x + shift) * scaleFactor - chromaRange;
273 return parameters.rgbColorSpace->fromCielabD50ToQRgbOrTransparent(
276 doAntialias(myImage, antiAliasCoordinates, myColorFunction);
278 if (callbackObject.shouldAbort()) {
282 myImage.setDevicePixelRatio(parameters.devicePixelRatioF);
283 callbackObject.deliverInterlacingPass(
287 AsyncImageRenderCallback::InterlacingState::Final);
290static_assert(std::is_standard_layout_v<ChromaHueImageParameters>);
The namespace of this library.
void doAntialias(QImage &image, const QList< QPoint > &antiAliasCoordinates, const std::function< QRgb(const double x, const double y)> &colorFunction)
Calculates anti-alias for gamut diagrams.
QList< QPoint > findBoundary(const QImage &image)
Find boundaries between fully opaque and fully transparent pixels.
bool canConvert() const const