Changeset View
Changeset View
Standalone View
Standalone View
src/colortools.cpp
Show All 12 Lines | |||||
13 | #include <QColor> | 13 | #include <QColor> | ||
14 | #include <math.h> | 14 | #include <math.h> | ||
15 | 15 | | |||
16 | //#define DEBUG_CT | 16 | //#define DEBUG_CT | ||
17 | #ifdef DEBUG_CT | 17 | #ifdef DEBUG_CT | ||
18 | #include "kdenlive_debug.h" | 18 | #include "kdenlive_debug.h" | ||
19 | #endif | 19 | #endif | ||
20 | 20 | | |||
21 | namespace { | ||||
22 | double preventOverflow(double value) | ||||
23 | { | ||||
24 | return value < 0 ? 0 | ||||
25 | : value > 255 ? 255 | ||||
26 | : value; | ||||
27 | } | ||||
28 | } | ||||
29 | | ||||
21 | ColorTools::ColorTools(QObject *parent) | 30 | ColorTools::ColorTools(QObject *parent) | ||
22 | : QObject(parent) | 31 | : QObject(parent) | ||
23 | { | 32 | { | ||
24 | } | 33 | } | ||
25 | 34 | | |||
26 | QImage ColorTools::yuvColorWheel(const QSize &size, int Y, float scaling, bool modifiedVersion, bool circleOnly) | 35 | QImage ColorTools::yuvColorWheel(const QSize &size, int Y, float scaling, bool modifiedVersion, bool circleOnly) | ||
27 | { | 36 | { | ||
28 | QImage wheel(size, QImage::Format_ARGB32); | 37 | QImage wheel(size, QImage::Format_ARGB32); | ||
29 | if (size.width() == 0 || size.height() == 0) { | 38 | if (size.width() == 0 || size.height() == 0) { | ||
30 | qCritical("ERROR: Size of the color wheel must not be 0!"); | 39 | qCritical("ERROR: Size of the color wheel must not be 0!"); | ||
31 | return wheel; | 40 | return wheel; | ||
32 | } | 41 | } | ||
33 | if (circleOnly) { | 42 | if (circleOnly) { | ||
34 | wheel.fill(qRgba(0, 0, 0, 0)); | 43 | wheel.fill(qRgba(0, 0, 0, 0)); | ||
35 | } | 44 | } | ||
36 | 45 | | |||
37 | double dr, dg, db, dv, dmax; | 46 | double dr, dg, db, dv; | ||
38 | double ru, rv, rr; | 47 | double ru, rv, rr; | ||
39 | const int w = size.width(); | 48 | const int w = size.width(); | ||
40 | const int h = size.height(); | 49 | const int h = size.height(); | ||
41 | const float w2 = (float)w / 2; | 50 | const float w2 = (float)w / 2; | ||
42 | const float h2 = (float)h / 2; | 51 | const float h2 = (float)h / 2; | ||
43 | 52 | | |||
44 | for (int u = 0; u < w; ++u) { | 53 | for (int u = 0; u < w; ++u) { | ||
45 | // Transform u from {0,...,w} to [-1,1] | 54 | // Transform u from {0,...,w} to [-1,1] | ||
Show All 18 Lines | 58 | for (int v = 0; v < h; ++v) { | |||
64 | 73 | | |||
65 | // Calculate the RGB values from YUV | 74 | // Calculate the RGB values from YUV | ||
66 | dr = Y + 290.8 * dv; | 75 | dr = Y + 290.8 * dv; | ||
67 | dg = Y - 100.6 * du - 148 * dv; | 76 | dg = Y - 100.6 * du - 148 * dv; | ||
68 | db = Y + 517.2 * du; | 77 | db = Y + 517.2 * du; | ||
69 | 78 | | |||
70 | if (modifiedVersion) { | 79 | if (modifiedVersion) { | ||
71 | // Scale the RGB values down, or up, to max 255 | 80 | // Scale the RGB values down, or up, to max 255 | ||
72 | dmax = fabs(dr); | 81 | const double dmax = 255 / std::max({fabs(dr), fabs(dg), fabs(db)}); | ||
73 | if (fabs(dg) > dmax) { | | |||
74 | dmax = fabs(dg); | | |||
75 | } | | |||
76 | if (fabs(db) > dmax) { | | |||
77 | dmax = fabs(db); | | |||
78 | } | | |||
79 | dmax = 255 / dmax; | | |||
80 | 82 | | |||
81 | dr *= dmax; | 83 | dr *= dmax; | ||
82 | dg *= dmax; | 84 | dg *= dmax; | ||
83 | db *= dmax; | 85 | db *= dmax; | ||
84 | } | 86 | } | ||
85 | 87 | | |||
86 | // Avoid overflows (which would generate intersecting patterns). | 88 | // Avoid overflows (which would generate intersecting patterns). | ||
87 | // Note that not all possible (y,u,v) values with u,v \in [-1,1] | 89 | // Note that not all possible (y,u,v) values with u,v \in [-1,1] | ||
88 | // have a correct RGB representation, therefore some RGB values | 90 | // have a correct RGB representation, therefore some RGB values | ||
89 | // may exceed {0,...,255}. | 91 | // may exceed {0,...,255}. | ||
90 | if (dr < 0) { | 92 | dr = preventOverflow(dr); | ||
91 | dr = 0; | 93 | dg = preventOverflow(dg); | ||
92 | } | 94 | db = preventOverflow(db); | ||
93 | if (dg < 0) { | | |||
94 | dg = 0; | | |||
95 | } | | |||
96 | if (db < 0) { | | |||
97 | db = 0; | | |||
98 | } | | |||
99 | if (dr > 255) { | | |||
100 | dr = 255; | | |||
101 | } | | |||
102 | if (dg > 255) { | | |||
103 | dg = 255; | | |||
104 | } | | |||
105 | if (db > 255) { | | |||
106 | db = 255; | | |||
107 | } | | |||
108 | 95 | | |||
109 | wheel.setPixel(u, (h - v - 1), qRgba(dr, dg, db, 255)); | 96 | wheel.setPixel(u, (h - v - 1), qRgba(dr, dg, db, 255)); | ||
110 | } | 97 | } | ||
111 | } | 98 | } | ||
112 | 99 | | |||
113 | emit signalYuvWheelCalculationFinished(); | 100 | emit signalYuvWheelCalculationFinished(); | ||
114 | return wheel; | 101 | return wheel; | ||
115 | } | 102 | } | ||
Show All 15 Lines | 105 | { | |||
131 | for (int uv = 0; uv < w; ++uv) { | 118 | for (int uv = 0; uv < w; ++uv) { | ||
132 | double du = uscaling * ((double)2 * uv / w - 1); //(double)? | 119 | double du = uscaling * ((double)2 * uv / w - 1); //(double)? | ||
133 | double dv = vscaling * ((double)2 * uv / w - 1); | 120 | double dv = vscaling * ((double)2 * uv / w - 1); | ||
134 | 121 | | |||
135 | for (int y = 0; y < h; ++y) { | 122 | for (int y = 0; y < h; ++y) { | ||
136 | Y = (double)255 * y / h; | 123 | Y = (double)255 * y / h; | ||
137 | 124 | | |||
138 | // See yuv2rgb, yuvColorWheel | 125 | // See yuv2rgb, yuvColorWheel | ||
139 | dr = Y + 290.8 * dv; | 126 | dr = preventOverflow(Y + 290.8 * dv); | ||
140 | dg = Y - 100.6 * du - 148 * dv; | 127 | dg = preventOverflow(Y - 100.6 * du - 148 * dv); | ||
141 | db = Y + 517.2 * du; | 128 | db = preventOverflow(Y + 517.2 * du); | ||
142 | if (dr < 0) { | | |||
143 | dr = 0; | | |||
144 | } | | |||
145 | if (dg < 0) { | | |||
146 | dg = 0; | | |||
147 | } | | |||
148 | if (db < 0) { | | |||
149 | db = 0; | | |||
150 | } | | |||
151 | if (dr > 255) { | | |||
152 | dr = 255; | | |||
153 | } | | |||
154 | if (dg > 255) { | | |||
155 | dg = 255; | | |||
156 | } | | |||
157 | if (db > 255) { | | |||
158 | db = 255; | | |||
159 | } | | |||
160 | 129 | | |||
161 | plane.setPixel(uv, (h - y - 1), qRgba(dr, dg, db, 255)); | 130 | plane.setPixel(uv, (h - y - 1), qRgba(dr, dg, db, 255)); | ||
162 | } | 131 | } | ||
163 | } | 132 | } | ||
164 | 133 | | |||
165 | return plane; | 134 | return plane; | ||
166 | } | 135 | } | ||
167 | 136 | | |||
▲ Show 20 Lines • Show All 114 Lines • ▼ Show 20 Line(s) | 248 | if (circleOnly) { | |||
282 | rR = r - double(h2); | 251 | rR = r - double(h2); | ||
283 | rr = rB * rB / (w2 * w2) + rR * rR / (h2 * h2); | 252 | rr = rB * rB / (w2 * w2) + rR * rR / (h2 * h2); | ||
284 | if (rr > 1) { | 253 | if (rr > 1) { | ||
285 | continue; | 254 | continue; | ||
286 | } | 255 | } | ||
287 | } | 256 | } | ||
288 | 257 | | |||
289 | // Calculate the RGB values from YPbPr | 258 | // Calculate the RGB values from YPbPr | ||
290 | dr = Y + 357.5 * dpR; | 259 | dr = preventOverflow(Y + 357.5 * dpR); | ||
291 | dg = Y - 87.75 * dpB - 182.1 * dpR; | 260 | dg = preventOverflow(Y - 87.75 * dpB - 182.1 * dpR); | ||
292 | db = Y + 451.86 * dpB; | 261 | db = preventOverflow(Y + 451.86 * dpB); | ||
293 | | ||||
294 | // Avoid overflows (which would generate intersecting patterns). | | |||
295 | // Note that not all possible (y,u,v) values with u,v \in [-1,1] | | |||
296 | // have a correct RGB representation, therefore some RGB values | | |||
297 | // may exceed {0,...,255}. | | |||
298 | if (dr < 0) { | | |||
299 | dr = 0; | | |||
300 | } | | |||
301 | if (dg < 0) { | | |||
302 | dg = 0; | | |||
303 | } | | |||
304 | if (db < 0) { | | |||
305 | db = 0; | | |||
306 | } | | |||
307 | if (dr > 255) { | | |||
308 | dr = 255; | | |||
309 | } | | |||
310 | if (dg > 255) { | | |||
311 | dg = 255; | | |||
312 | } | | |||
313 | if (db > 255) { | | |||
314 | db = 255; | | |||
315 | } | | |||
316 | 262 | | |||
317 | wheel.setPixel(b, (h - r - 1), qRgba(dr, dg, db, 255)); | 263 | wheel.setPixel(b, (h - r - 1), qRgba(dr, dg, db, 255)); | ||
318 | } | 264 | } | ||
319 | } | 265 | } | ||
320 | 266 | | |||
321 | return wheel; | 267 | return wheel; | ||
322 | } | 268 | } | ||
323 | 269 | | |||
▲ Show 20 Lines • Show All 110 Lines • Show Last 20 Lines |