Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_tone_curve_widget.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2015 Wolthera van Hövell tot Westerflier <griffinvalley@gmail.com>
3 *
4 * Based on the Digikam CIE Tongue widget
5 * SPDX-FileCopyrightText: 2006-2013 Gilles Caulier <caulier dot gilles at gmail dot com>
6 *
7 * Any source code are inspired from lprof project and
8 * SPDX-FileCopyrightText: 1998-2001 Marti Maria
9 *
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 **/
12#include <QPointF>
13#include <QPolygonF>
14#include <QPainter>
15#include <QPainterPath>
16#include <QPaintEvent>
17#include <QTextStream>
18#include <cmath>
19#include <klocalizedstring.h>
20
21
23
24class Q_DECL_HIDDEN KisToneCurveWidget::Private
25{
26public:
27
28 bool profileDataAvailable {false};
29 bool needUpdatePixmap {false};
30 bool TRCGray {true};
31 bool TRCRGB {false};
32
33 int xBias {0};
34 int yBias {0};
35 int pxcols {0};
36 int pxrows {0};
37
38 QPolygonF ToneCurveGray;
39 QPolygonF ToneCurveRed;
40 QPolygonF ToneCurveGreen;
41 QPolygonF ToneCurveBlue;
42
43 double gridside {0.0};
44
45 QPainter painter;
46 QPainter painter2;
47 QPixmap pixmap;
48 QPixmap curvemap;
49};
50
52 QWidget(parent), d(new Private)
53{
54 /*this is a tone curve widget*/
55}
56
61
63{
64 d->ToneCurveGray = poly;
65 d->TRCGray = true;
66 d->TRCRGB = false;
67 d->profileDataAvailable = true;
68 d->needUpdatePixmap = true;
69}
70
71void KisToneCurveWidget::setRGBCurve(QPolygonF red, QPolygonF green, QPolygonF blue)
72{
73 d->ToneCurveRed = red;
74 d->ToneCurveGreen = green;
75 d->ToneCurveBlue = blue;
76 d->profileDataAvailable = true;
77 d->TRCGray = false;
78 d->TRCRGB = true;
79 d->needUpdatePixmap = true;
80}
81void KisToneCurveWidget::setCMYKCurve(QPolygonF cyan, QPolygonF magenta, QPolygonF yellow, QPolygonF key)
82{
83 d->ToneCurveRed = cyan;
84 d->ToneCurveGreen = magenta;
85 d->ToneCurveBlue = yellow;
86 d->ToneCurveGray = key;
87 d->profileDataAvailable = true;
88 d->TRCGray = false;
89 d->TRCRGB = false;
90 d->needUpdatePixmap = true;
91}
93{
94 d->profileDataAvailable = dataAvailable;
95}
96int KisToneCurveWidget::grids(double val) const
97{
98 return (int) floor(val * d->gridside + 0.5);
99}
100
102{
103 QPointF dummy = xy;
104 xy.setX( (int) floor((dummy.x() * (d->pxcols - 1)) + .5) + d->xBias);
105 xy.setY( (int) floor(((d->pxrows - 1) - dummy.y() * (d->pxrows - 1)) + .5) );
106}
107
108void KisToneCurveWidget::biasedLine(int x1, int y1, int x2, int y2)
109{
110 d->painter.drawLine(x1 + d->xBias, y1, x2 + d->xBias, y2);
111}
112
113void KisToneCurveWidget::biasedText(int x, int y, const QString& txt)
114{
115 d->painter.drawText(QPoint(d->xBias + x, y), txt);
116}
117
119{
120 d->painter.setOpacity(1.0);
121 d->painter.setPen(qRgb(255, 255, 255));
122 biasedLine(0, 0, 0, d->pxrows - 1);
123 biasedLine(0, d->pxrows-1, d->pxcols-1, d->pxrows - 1);
124
125 QFont font;
126 font.setPointSize(6);
127 d->painter.setFont(font);
128
129 for (int y = 1; y <= 9; y += 1)
130 {
131 QString s;
132 int xstart = (y * (d->pxcols - 1)) / 10;
133 int ystart = (y * (d->pxrows - 1)) / 10;
134
135 QTextStream(&s) << y;
136 biasedLine(xstart, d->pxrows - grids(1), xstart, d->pxrows - grids(4));
137 biasedText(xstart - grids(11), d->pxrows + grids(15), s);
138
139 QTextStream(&s) << 10 - y;
140 biasedLine(0, ystart, grids(3), ystart);
141 biasedText(grids(-25), ystart + grids(5), s);
142 }
143
144 d->painter.setPen(qRgb(128, 128, 128));
145 d->painter.setOpacity(0.5);
146
147 for (int y = 1; y <= 9; y += 1)
148 {
149 int xstart = (y * (d->pxcols - 1)) / 10;
150 int ystart = (y * (d->pxrows - 1)) / 10;
151
152 biasedLine(xstart, grids(4), xstart, d->pxrows - grids(4) - 1);
153 biasedLine(grids(7), ystart, d->pxcols-1-grids(7), ystart);
154 }
155 d->painter.setOpacity(1.0);
156 d->painter.setOpacity(1.0);
157}
158
160{
161 d->needUpdatePixmap = false;
162 d->pixmap = QPixmap(size() * devicePixelRatioF());
163 d->pixmap.setDevicePixelRatio(devicePixelRatioF());
164 d->curvemap = QPixmap(size() * devicePixelRatioF());
165 d->curvemap.setDevicePixelRatio(devicePixelRatioF());
166 d->pixmap.fill(Qt::black);
167 d->curvemap.fill(Qt::transparent);
168
169 d->painter.begin(&d->pixmap);
170
171 int pixcols =
172 static_cast<int>(d->pixmap.width() / d->pixmap.devicePixelRatioF());
173 int pixrows =
174 static_cast<int>(d->pixmap.height() / d->pixmap.devicePixelRatioF());
175
176 d->gridside = (qMin(pixcols, pixrows)) / 512.0;
177 d->xBias = grids(32);
178 d->yBias = grids(20);
179 d->pxcols = pixcols - d->xBias;
180 d->pxrows = pixrows - d->yBias;
181
182 d->painter.setBackground(QBrush(qRgb(0, 0, 0)));
183 QPointF start;
184 drawGrid();
185 d->painter.setRenderHint(QPainter::Antialiasing);
186 if (d->TRCGray && d->ToneCurveGray.size()>0){
187 QPainterPath path;
188 start = d->ToneCurveGray.at(0);
189 mapPoint(start);
190 path.moveTo(start);
191 foreach (QPointF Point, d->ToneCurveGray) {
192 mapPoint(Point);
193 path.lineTo(Point);
194 }
195 d->painter.setPen(qRgb(255, 255, 255));
196 d->painter.drawPath(path);
197 } else if (d->TRCRGB && d->ToneCurveRed.size()>0 && d->ToneCurveGreen.size()>0 && d->ToneCurveBlue.size()>0){
198 d->painter.save();
199 d->painter.setCompositionMode(QPainter::CompositionMode_Screen);
200 QPainterPath path;
201 start = d->ToneCurveRed.at(0);
202 mapPoint(start);
203 path.moveTo(start);
204 foreach (QPointF Point, d->ToneCurveRed) {
205 mapPoint(Point);
206 path.lineTo(Point);
207 }
208 d->painter.setPen(qRgb(255, 0, 0));
209 d->painter.drawPath(path);
210 QPainterPath path2;
211 start = d->ToneCurveGreen.at(0);
212 mapPoint(start);
213 path2.moveTo(start);
214 foreach (QPointF Point, d->ToneCurveGreen) {
215 mapPoint(Point);
216 path2.lineTo(Point);
217 }
218 d->painter.setPen(qRgb(0, 255, 0));
219 d->painter.drawPath(path2);
220 QPainterPath path3;
221 start = d->ToneCurveBlue.at(0);
222 mapPoint(start);
223 path3.moveTo(start);
224 foreach (QPointF Point, d->ToneCurveBlue) {
225 mapPoint(Point);
226 path3.lineTo(Point);
227 }
228 d->painter.setPen(qRgb(0, 0, 255));
229 d->painter.drawPath(path3);
230 d->painter.restore();
231 } else {
232 d->painter2.begin(&d->curvemap);
233 d->painter2.setRenderHint(QPainter::Antialiasing);
234 //d->painter2.setCompositionMode(QPainter::CompositionMode_Multiply);
235 QPainterPath path;
236 start = d->ToneCurveRed.at(0);
237 mapPoint(start);
238 path.moveTo(start);
239 foreach (QPointF Point, d->ToneCurveRed) {
240 mapPoint(Point);
241 path.lineTo(Point);
242 }
243 d->painter2.setPen(qRgb(0, 255, 255));
244 d->painter2.drawPath(path);
245 QPainterPath path2;
246 start = d->ToneCurveGreen.at(0);
247 mapPoint(start);
248 path2.moveTo(start);
249 foreach (QPointF Point, d->ToneCurveGreen) {
250 mapPoint(Point);
251 path2.lineTo(Point);
252 }
253 d->painter2.setPen(qRgb(255, 0, 255));
254 d->painter2.drawPath(path2);
255 QPainterPath path3;
256 start = d->ToneCurveBlue.at(0);
257 mapPoint(start);
258 path3.moveTo(start);
259 foreach (QPointF Point, d->ToneCurveBlue) {
260 mapPoint(Point);
261 path3.lineTo(Point);
262 }
263 d->painter2.setPen(qRgb(255, 255, 0));
264 d->painter2.drawPath(path3);
265 QPainterPath path4;
266 start = d->ToneCurveGray.at(0);
267 mapPoint(start);
268 path4.moveTo(start);
269 foreach (QPointF Point, d->ToneCurveGray) {
270 mapPoint(Point);
271 path4.lineTo(Point);
272 }
273 d->painter2.setPen(qRgb(80, 80, 80));
274 d->painter2.drawPath(path4);
275 d->painter2.end();
276 d->painter.drawPixmap(d->xBias, 0, d->curvemap);
277 }
278 d->painter.end();
279}
280
282{
283 QPainter p(this);
284
285 // Widget is disable : drawing grayed frame.
286
287 if ( !isEnabled() )
288 {
289 p.fillRect(0, 0, width(), height(),
290 palette().color(QPalette::Disabled, QPalette::Window));
291
292 QPen pen(palette().color(QPalette::Disabled, QPalette::WindowText));
293 pen.setStyle(Qt::SolidLine);
294 pen.setWidth(1);
295
296 p.setPen(pen);
297 p.drawRect(0, 0, width(), height());
298
299 return;
300 }
301
302
303 // No profile data to show, or RAW file
304
305 if (!d->profileDataAvailable)
306 {
307 p.fillRect(0, 0, width(), height(), palette().color(QPalette::Active, QPalette::Window));
308 QPen pen(palette().color(QPalette::Active, QPalette::Text));
309 pen.setStyle(Qt::SolidLine);
310 pen.setWidth(1);
311
312 p.setPen(pen);
313 p.drawRect(0, 0, width(), height());
314
315 p.setPen(Qt::red);
316 p.drawText(0, 0, width(), height(), Qt::AlignCenter,
317 i18n("No tone curve available..."));
318
319 return;
320 }
321
322 // Create CIE tongue if needed
323 if (d->needUpdatePixmap)
324 {
325 updatePixmap();
326 }
327
328 // draw prerendered tongue
329 p.drawPixmap(0, 0, d->pixmap);
330}
331
332void KisToneCurveWidget::resizeEvent(QResizeEvent* event)
333{
334 QWidget::resizeEvent(event);
335 d->needUpdatePixmap = true;
336}
const Params2D p
void setRGBCurve(QPolygonF red, QPolygonF green, QPolygonF blue)
void paintEvent(QPaintEvent *) override
KisToneCurveWidget(QWidget *parent=nullptr)
void setProfileDataAvailable(bool dataAvailable)
void biasedText(int x, int y, const QString &txt)
void setCMYKCurve(QPolygonF cyan, QPolygonF magenta, QPolygonF yellow, QPolygonF key)
void resizeEvent(QResizeEvent *event) override
int grids(double val) const
void biasedLine(int x1, int y1, int x2, int y2)
void setGreyscaleCurve(QPolygonF poly)
rgba palette[MAX_PALETTE]
Definition palette.c:35