Krita Source Code Documentation
Loading...
Searching...
No Matches
fastcolortransfer.cpp
Go to the documentation of this file.
1/*
2 * This file is part of Krita
3 *
4 * SPDX-FileCopyrightText: 2006 Cyrille Berger <cberger@cberger.net>
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9#include "fastcolortransfer.h"
10
11#include <math.h>
12
13#include <kpluginfactory.h>
14
15#include <kundo2command.h>
16
18#include <KoUpdater.h>
19
21#include <kis_image.h>
22#include <kis_paint_device.h>
23#include <kis_selection.h>
27
29#include "ui_wdgfastcolortransfer.h"
31#include <KoProgressUpdater.h>
32
33
34K_PLUGIN_FACTORY_WITH_JSON(KritaFastColorTransferFactory, "kritafastcolortransfer.json", registerPlugin<FastColorTransferPlugin>();)
35
36
37FastColorTransferPlugin::FastColorTransferPlugin(QObject *parent, const QVariantList &)
38 : QObject(parent)
39{
41
42}
43
47
55
56
58{
59 Q_UNUSED(dev);
60 return new KisWdgFastColorTransfer(parent);
61}
62
64{
65 KisFilterConfigurationSP config = factoryConfiguration(resourcesInterface);
66 config->setProperty("filename", "");
67 return config;
68}
69
70#define CLAMP(x,l,u) ((x)<(l)?(l):((x)>(u)?(u):(x)))
71
73 const QRect& applyRect,
74 const KisFilterConfigurationSP config,
75 KoUpdater* progressUpdater) const
76{
77 Q_ASSERT(device != 0);
78
79 dbgPlugins << "Start transferring color";
80
81 // Convert ref and src to LAB
83 if (!labCS) {
84 dbgPlugins << "The LAB colorspace is not available.";
85 return;
86 }
87
88 dbgPlugins << "convert a copy of src to lab";
89 const KoColorSpace* oldCS = device->colorSpace();
90 KisPaintDeviceSP srcLAB = new KisPaintDevice(*device.data());
91 dbgPlugins << "srcLab : " << srcLAB->extent();
93
94 KoProgressUpdater compositeUpdater(progressUpdater, KoProgressUpdater::Unthreaded);
95 KoUpdater *updaterStats = compositeUpdater.startSubtask(1);
96 KoUpdater *updaterMap = compositeUpdater.startSubtask(2);
97
98 // Compute the means and sigmas of src
99 dbgPlugins << "Compute the means and sigmas of src";
100 double meanL_src = 0., meanA_src = 0., meanB_src = 0.;
101 double sigmaL_src = 0., sigmaA_src = 0., sigmaB_src = 0.;
102
103 {
104 KisSequentialConstIteratorProgress srcIt(srcLAB, applyRect, updaterStats);
105 while (srcIt.nextPixel()) {
106 const quint16* data = reinterpret_cast<const quint16*>(srcIt.oldRawData());
107 quint32 L = data[0];
108 quint32 A = data[1];
109 quint32 B = data[2];
110 meanL_src += L;
111 meanA_src += A;
112 meanB_src += B;
113 sigmaL_src += L * L;
114 sigmaA_src += A * A;
115 sigmaB_src += B * B;
116 }
117 }
118
119 double totalSize = 1. / (applyRect.width() * applyRect.height());
120 meanL_src *= totalSize;
121 meanA_src *= totalSize;
122 meanB_src *= totalSize;
123 sigmaL_src *= totalSize;
124 sigmaA_src *= totalSize;
125 sigmaB_src *= totalSize;
126
127 dbgPlugins << totalSize << "" << meanL_src << "" << meanA_src << "" << meanB_src << "" << sigmaL_src << "" << sigmaA_src << "" << sigmaB_src;
128
129 double meanL_ref = config->getDouble("meanL");
130 double meanA_ref = config->getDouble("meanA");
131 double meanB_ref = config->getDouble("meanB");
132 double sigmaL_ref = config->getDouble("sigmaL");
133 double sigmaA_ref = config->getDouble("sigmaA");
134 double sigmaB_ref = config->getDouble("sigmaB");
135
136 // Transfer colors
137 dbgPlugins << "Transfer colors";
138 {
139 double coefL = sqrt((sigmaL_ref - meanL_ref * meanL_ref) / (sigmaL_src - meanL_src * meanL_src));
140 double coefA = sqrt((sigmaA_ref - meanA_ref * meanA_ref) / (sigmaA_src - meanA_src * meanA_src));
141 double coefB = sqrt((sigmaB_ref - meanB_ref * meanB_ref) / (sigmaB_src - meanB_src * meanB_src));
142
143 quint16 labPixel[4];
144
145 KisSequentialConstIteratorProgress srcLabIt(srcLAB, applyRect, updaterMap);
146 KisSequentialIterator dstIt(device, applyRect);
147 while (srcLabIt.nextPixel() && dstIt.nextPixel()) {
148 const quint16* data = reinterpret_cast<const quint16*>(srcLabIt.oldRawData());
149
150 labPixel[0] = (quint16)CLAMP(((double)data[0] - meanL_src) * coefL + meanL_ref, 0., 65535.);
151 labPixel[1] = (quint16)CLAMP(((double)data[1] - meanA_src) * coefA + meanA_ref, 0., 65535.);
152 labPixel[2] = (quint16)CLAMP(((double)data[2] - meanB_src) * coefB + meanB_ref, 0., 65535.);
153 labPixel[3] = data[3];
154 oldCS->fromLabA16(reinterpret_cast<const quint8*>(labPixel), dstIt.rawData(), 1);
155 }
156 }
157}
158
159#include "fastcolortransfer.moc"
@ FULLY_INDEPENDENT
FastColorTransferPlugin(QObject *parent, const QVariantList &)
void processImpl(KisPaintDeviceSP device, const QRect &applyRect, const KisFilterConfigurationSP config, KoUpdater *progressUpdater) const override
KisFilterConfigurationSP defaultConfiguration(KisResourcesInterfaceSP resourcesInterface) const override
KisConfigWidget * createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev, bool useForMasks) const override
void add(KisFilterSP item)
static KisFilterRegistry * instance()
QRect extent() const
const KoColorSpace * colorSpace() const
void convertTo(const KoColorSpace *dstColorSpace, KoColorConversionTransformation::Intent renderingIntent=KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::ConversionFlags conversionFlags=KoColorConversionTransformation::internalConversionFlags(), KUndo2Command *parentCommand=nullptr, KoUpdater *progressUpdater=nullptr)
ALWAYS_INLINE quint8 * rawData()
ALWAYS_INLINE const quint8 * oldRawData() const
virtual void fromLabA16(const quint8 *src, quint8 *dst, quint32 nPixels) const
QPointer< KoUpdater > startSubtask(int weight=1, const QString &name=QString(), bool isPersistent=false)
#define CLAMP(x, l, h)
K_PLUGIN_FACTORY_WITH_JSON(KritaASCCDLFactory, "kritaasccdl.json", registerPlugin< KritaASCCDL >();) KritaASCCDL
#define dbgPlugins
Definition kis_debug.h:51
const KoID FiltersCategoryColorId("color_filters", ki18nc("The category of color transfer filters, like color to alpha. Noun.", "Colors"))
void setSupportsThreading(bool v)
virtual KisFilterConfigurationSP factoryConfiguration(KisResourcesInterfaceSP resourcesInterface) const
void setSupportsAdjustmentLayers(bool v)
void setSupportsPainting(bool v)
void setColorSpaceIndependence(ColorSpaceIndependence v)
const KoColorSpace * lab16(const QString &profileName=QString())
static KoColorSpaceRegistry * instance()