File: | /home/gilles/devel/GIT/8.x/core/libs/dimg/filters/nr/nrestimate.cpp |
Warning: | line 196, column 28 The left operand of '>' is a garbage value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* ============================================================ | ||||
2 | * | ||||
3 | * This file is a part of digiKam project | ||||
4 | * https://www.digikam.org | ||||
5 | * | ||||
6 | * Date : 2012-10-18 | ||||
7 | * Description : Wavelets YCrCb Noise Reduction settings estimation by image content analys. | ||||
8 | * Wavelets theory is based on "À Trous" Discrete Wavelet Transform | ||||
9 | * described into "The Handbook of Astronomical Image Processing" book | ||||
10 | * from Richard Berry and James Burnell, chapter 18. | ||||
11 | * See this wiki page for details: | ||||
12 | * community.kde.org/Digikam/SoK2012/AutoNR | ||||
13 | * | ||||
14 | * SPDX-FileCopyrightText: 2012-2013 by Sayantan Datta <sayantan dot knz at gmail dot com> | ||||
15 | * SPDX-FileCopyrightText: 2012-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> | ||||
16 | * | ||||
17 | * SPDX-License-Identifier: GPL-2.0-or-later | ||||
18 | * | ||||
19 | * ============================================================ */ | ||||
20 | |||||
21 | #include "nrestimate.h" | ||||
22 | |||||
23 | // C++ includes | ||||
24 | |||||
25 | #include <cmath> | ||||
26 | #include <cfloat> | ||||
27 | |||||
28 | // OpenCV includes | ||||
29 | |||||
30 | #include "digikam_opencv.h" | ||||
31 | |||||
32 | // Qt includes | ||||
33 | |||||
34 | #include <QTextStream> | ||||
35 | #include <QFile> | ||||
36 | |||||
37 | // Local includes | ||||
38 | |||||
39 | #include "digikam_debug.h" | ||||
40 | |||||
41 | namespace Digikam | ||||
42 | { | ||||
43 | |||||
44 | class Q_DECL_HIDDEN__attribute__((visibility("hidden"))) NREstimate::Private | ||||
45 | { | ||||
46 | public: | ||||
47 | |||||
48 | Private() = default; | ||||
49 | |||||
50 | NRContainer prm; | ||||
51 | |||||
52 | QString path; ///< Path to host log files. | ||||
53 | |||||
54 | float* fimg[3] = { nullptr }; | ||||
55 | const uint clusterCount = 30; | ||||
56 | const uint size = 512; ///< Size of squared original image. | ||||
57 | }; | ||||
58 | |||||
59 | NREstimate::NREstimate(DImg* const img, QObject* const parent) | ||||
60 | : DImgThreadedAnalyser(parent, QLatin1String("NREstimate")), | ||||
61 | d (new Private) | ||||
62 | { | ||||
63 | // Use the Top/Left corner of 256x256 pixels to analys noise contents from image. | ||||
64 | // This will speed-up computation time with OpenCV | ||||
65 | |||||
66 | int w = (img->width() > d->size) ? d->size : img->width(); | ||||
67 | int h = (img->height() > d->size) ? d->size : img->height(); | ||||
68 | setOriginalImage(img->copy(0, 0, w, h)); | ||||
69 | } | ||||
70 | |||||
71 | NREstimate::~NREstimate() | ||||
72 | { | ||||
73 | delete d; | ||||
74 | } | ||||
75 | |||||
76 | void NREstimate::setLogFilesPath(const QString& path) | ||||
77 | { | ||||
78 | d->path = path; | ||||
79 | } | ||||
80 | |||||
81 | void NREstimate::readImage() const | ||||
82 | { | ||||
83 | DColor col; | ||||
84 | |||||
85 | for (int c = 0 ; runningFlag() && (c < 3) ; ++c) | ||||
86 | { | ||||
87 | d->fimg[c] = new float[m_orgImage.numPixels()]; | ||||
88 | } | ||||
89 | |||||
90 | int j = 0; | ||||
91 | |||||
92 | for (uint y = 0 ; runningFlag() && (y < m_orgImage.height()) ; ++y) | ||||
93 | { | ||||
94 | for (uint x = 0 ; runningFlag() && (x < m_orgImage.width()) ; ++x) | ||||
95 | { | ||||
96 | col = m_orgImage.getPixelColor(x, y); | ||||
97 | d->fimg[0][j] = col.red(); | ||||
98 | d->fimg[1][j] = col.green(); | ||||
99 | d->fimg[2][j] = col.blue(); | ||||
100 | j++; | ||||
101 | } | ||||
102 | } | ||||
103 | } | ||||
104 | |||||
105 | NRContainer NREstimate::settings() const | ||||
106 | { | ||||
107 | return d->prm; | ||||
108 | } | ||||
109 | |||||
110 | void NREstimate::startAnalyse() | ||||
111 | { | ||||
112 | readImage(); | ||||
113 | postProgress(5); | ||||
114 | |||||
115 | //--convert fimg to CvMat*------------------------------------------------------------------------------- | ||||
116 | |||||
117 | // convert the image into YCrCb color model | ||||
118 | |||||
119 | NRFilter::srgb2ycbcr(d->fimg, m_orgImage.numPixels()); | ||||
120 | |||||
121 | // One dimensional CvMat which stores the image | ||||
122 | |||||
123 | CvMat* points = cvCreateMat(m_orgImage.numPixels(), 3, CV_32FC1(((5) & ((1 << 3) - 1)) + (((1)-1) << 3))); | ||||
124 | |||||
125 | // matrix to store the index of the clusters | ||||
126 | |||||
127 | CvMat* clusters = cvCreateMat(m_orgImage.numPixels(), 1, CV_32SC1(((4) & ((1 << 3) - 1)) + (((1)-1) << 3))); | ||||
128 | |||||
129 | // pointer variable to handle the CvMat* points (the image in CvMat format) | ||||
130 | |||||
131 | float* pointsPtr = reinterpret_cast<float*>(points->data.ptr); | ||||
132 | |||||
133 | for (uint x = 0 ; runningFlag() && (x < m_orgImage.numPixels()) ; ++x) | ||||
| |||||
134 | { | ||||
135 | for (int y = 0 ; runningFlag() && (y < 3) ; ++y) | ||||
136 | { | ||||
137 | *pointsPtr++ = (float)d->fimg[y][x]; | ||||
138 | } | ||||
139 | } | ||||
140 | |||||
141 | // Array to store the centers of the clusters | ||||
142 | |||||
143 | CvArr* centers = nullptr; | ||||
144 | |||||
145 | qCDebug(DIGIKAM_DIMG_LOG)for (QLoggingCategoryMacroHolder<QtDebugMsg> qt_category ((DIGIKAM_DIMG_LOG)()); qt_category; qt_category.control = false ) QMessageLogger(static_cast<const char *>("/home/gilles/devel/GIT/8.x/core/libs/dimg/filters/nr/nrestimate.cpp" ), 145, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).debug() << "Everything ready for the cvKmeans2 or as it seems to"; | ||||
146 | postProgress(10); | ||||
147 | |||||
148 | //-- KMEANS --------------------------------------------------------------------------------------------- | ||||
149 | |||||
150 | cvKMeans2(points, d->clusterCount, clusters, | ||||
151 | cvTermCriteria(CV_TERMCRIT_EPS2 + CV_TERMCRIT_ITER1, 10, 1.0), 3, nullptr, 0, centers, nullptr); | ||||
152 | |||||
153 | qCDebug(DIGIKAM_DIMG_LOG)for (QLoggingCategoryMacroHolder<QtDebugMsg> qt_category ((DIGIKAM_DIMG_LOG)()); qt_category; qt_category.control = false ) QMessageLogger(static_cast<const char *>("/home/gilles/devel/GIT/8.x/core/libs/dimg/filters/nr/nrestimate.cpp" ), 153, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).debug() << "cvKmeans2 successfully run"; | ||||
154 | postProgress(15); | ||||
155 | |||||
156 | //-- Divide into cluster->columns, sample->rows, in matrix standard deviation --------------------------- | ||||
157 | |||||
158 | QScopedArrayPointer<int> rowPosition(new int[d->clusterCount]{}); | ||||
159 | |||||
160 | // The row position array would just make the hold the number of elements in each cluster | ||||
161 | |||||
162 | for (uint i = 0 ; runningFlag() && (i
| ||||
163 | { | ||||
164 | // initializing the cluster count array | ||||
165 | |||||
166 | rowPosition[i] = 0; | ||||
167 | } | ||||
168 | |||||
169 | int rowIndex = 0; | ||||
170 | int columnIndex = 0; | ||||
171 | |||||
172 | for (uint i = 0 ; runningFlag() && (i < m_orgImage.numPixels()) ; ++i) | ||||
173 | { | ||||
174 | columnIndex = clusters->data.i[i]; | ||||
175 | rowPosition[columnIndex]++; | ||||
176 | } | ||||
177 | |||||
178 | /* | ||||
179 | qCDebug(DIGIKAM_DIMG_LOG) << "Lets see what the rowPosition array looks like : "; | ||||
180 | |||||
181 | for (uint i = 0 ; runningFlag() && (i < d->clusterCount) ; ++i) | ||||
182 | { | ||||
183 | qCDebug(DIGIKAM_DIMG_LOG) << "Cluster : "<< i << " the count is :" << rowPosition[i]; | ||||
184 | } | ||||
185 | */ | ||||
186 | |||||
187 | qCDebug(DIGIKAM_DIMG_LOG)for (QLoggingCategoryMacroHolder<QtDebugMsg> qt_category ((DIGIKAM_DIMG_LOG)()); qt_category; qt_category.control = false ) QMessageLogger(static_cast<const char *>("/home/gilles/devel/GIT/8.x/core/libs/dimg/filters/nr/nrestimate.cpp" ), 187, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).debug() << "array indexed, and ready to find maximum"; | ||||
188 | postProgress(20); | ||||
189 | |||||
190 | //-- Finding maximum of the rowPosition array ------------------------------------------------------------ | ||||
191 | |||||
192 | int max = rowPosition[0]; | ||||
193 | |||||
194 | for (uint i = 1 ; runningFlag() && (i < d->clusterCount) ; ++i) | ||||
195 | { | ||||
196 | if (rowPosition[i] > max) | ||||
| |||||
197 | { | ||||
198 | max = rowPosition[i]; | ||||
199 | } | ||||
200 | } | ||||
201 | |||||
202 | QString maxString; | ||||
203 | maxString.append(QString::number(max)); | ||||
204 | |||||
205 | qCDebug(DIGIKAM_DIMG_LOG)for (QLoggingCategoryMacroHolder<QtDebugMsg> qt_category ((DIGIKAM_DIMG_LOG)()); qt_category; qt_category.control = false ) QMessageLogger(static_cast<const char *>("/home/gilles/devel/GIT/8.x/core/libs/dimg/filters/nr/nrestimate.cpp" ), 205, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).debug() << QString::fromLatin1("maximum declared = %1").arg(maxString); | ||||
206 | postProgress(25); | ||||
207 | |||||
208 | //-- Divide and conquer --------------------------------------------------------------------------------- | ||||
209 | |||||
210 | CvMat* sd = cvCreateMat(max, (d->clusterCount * points->cols), CV_32FC1(((5) & ((1 << 3) - 1)) + (((1)-1) << 3))); | ||||
211 | |||||
212 | postProgress(30); | ||||
213 | |||||
214 | //-- Initialize the rowPosition array ------------------------------------------------------------------- | ||||
215 | |||||
216 | QScopedArrayPointer<int> rPosition(new int[d->clusterCount]); | ||||
217 | |||||
218 | for (uint i = 0 ; runningFlag() && (i < d->clusterCount) ; ++i) | ||||
219 | { | ||||
220 | rPosition[i] = 0; | ||||
221 | } | ||||
222 | |||||
223 | float* ptr = nullptr; | ||||
224 | |||||
225 | qCDebug(DIGIKAM_DIMG_LOG)for (QLoggingCategoryMacroHolder<QtDebugMsg> qt_category ((DIGIKAM_DIMG_LOG)()); qt_category; qt_category.control = false ) QMessageLogger(static_cast<const char *>("/home/gilles/devel/GIT/8.x/core/libs/dimg/filters/nr/nrestimate.cpp" ), 225, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).debug() << "The rowPosition array is ready!"; | ||||
226 | postProgress(40); | ||||
227 | |||||
228 | for (uint i = 0 ; runningFlag() && (i < m_orgImage.numPixels()) ; ++i) | ||||
229 | { | ||||
230 | columnIndex = clusters->data.i[i]; | ||||
231 | rowIndex = rPosition[columnIndex]; | ||||
232 | |||||
233 | // moving to the right row | ||||
234 | |||||
235 | ptr = reinterpret_cast<float*>(sd->data.ptr + rowIndex*(sd->step)); | ||||
236 | |||||
237 | // moving to the right column | ||||
238 | |||||
239 | for (int j = 0 ; runningFlag() && (j < columnIndex) ; ++j) | ||||
240 | { | ||||
241 | for (int z = 0 ; runningFlag() && (z < (points->cols)) ; ++z) | ||||
242 | { | ||||
243 | ptr++; | ||||
244 | } | ||||
245 | } | ||||
246 | |||||
247 | for (int z = 0 ; runningFlag() && (z < (points->cols)) ; ++z) | ||||
248 | { | ||||
249 | *ptr++ = cvGet2D(points, i, z).val[0]; | ||||
250 | } | ||||
251 | |||||
252 | rPosition[columnIndex] = rPosition[columnIndex] + 1; | ||||
253 | } | ||||
254 | |||||
255 | qCDebug(DIGIKAM_DIMG_LOG)for (QLoggingCategoryMacroHolder<QtDebugMsg> qt_category ((DIGIKAM_DIMG_LOG)()); qt_category; qt_category.control = false ) QMessageLogger(static_cast<const char *>("/home/gilles/devel/GIT/8.x/core/libs/dimg/filters/nr/nrestimate.cpp" ), 255, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).debug() << "sd matrix creation over!"; | ||||
256 | postProgress(50); | ||||
257 | |||||
258 | //-- This part of the code would involve the sd matrix and make the mean and the std of the data ------------------- | ||||
259 | |||||
260 | CvScalar std; | ||||
261 | CvScalar mean; | ||||
262 | int totalcount = 0; // Number of non-empty clusters | ||||
263 | CvMat* meanStore = cvCreateMat(d->clusterCount, points->cols, CV_32FC1(((5) & ((1 << 3) - 1)) + (((1)-1) << 3))); | ||||
264 | CvMat* stdStore = cvCreateMat(d->clusterCount, points->cols, CV_32FC1(((5) & ((1 << 3) - 1)) + (((1)-1) << 3))); | ||||
265 | float* meanStorePtr = reinterpret_cast<float*>(meanStore->data.ptr); | ||||
266 | float* stdStorePtr = reinterpret_cast<float*>(stdStore->data.ptr); | ||||
267 | |||||
268 | for (int i = 0 ; runningFlag() && (i < sd->cols) ; ++i) | ||||
269 | { | ||||
270 | // cppcheck-suppress knownConditionTrueFalse | ||||
271 | if (runningFlag() && (rowPosition[(i/points->cols)] >= 1)) | ||||
272 | { | ||||
273 | CvMat* workingArr = cvCreateMat(rowPosition[(i / points->cols)], 1, CV_32FC1(((5) & ((1 << 3) - 1)) + (((1)-1) << 3))); | ||||
274 | ptr = reinterpret_cast<float*>(workingArr->data.ptr); | ||||
275 | |||||
276 | // cppcheck-suppress knownConditionTrueFalse | ||||
277 | for (int j = 0 ; runningFlag() && (j < rowPosition[(i / (points->cols))]) ; ++j) | ||||
278 | { | ||||
279 | *ptr++ = cvGet2D(sd, j, i).val[0]; | ||||
280 | } | ||||
281 | |||||
282 | cvAvgSdv(workingArr, &mean, &std); | ||||
283 | *meanStorePtr++ = (float)mean.val[0]; | ||||
284 | *stdStorePtr++ = (float)std.val[0]; | ||||
285 | totalcount++; | ||||
286 | cvReleaseMat(&workingArr); | ||||
287 | } | ||||
288 | } | ||||
289 | |||||
290 | qCDebug(DIGIKAM_DIMG_LOG)for (QLoggingCategoryMacroHolder<QtDebugMsg> qt_category ((DIGIKAM_DIMG_LOG)()); qt_category; qt_category.control = false ) QMessageLogger(static_cast<const char *>("/home/gilles/devel/GIT/8.x/core/libs/dimg/filters/nr/nrestimate.cpp" ), 290, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).debug() << "Make the mean and the std of the data"; | ||||
291 | postProgress(60); | ||||
292 | |||||
293 | // ----------------------------------------------------------------------------------------------------------------- | ||||
294 | |||||
295 | meanStorePtr = reinterpret_cast<float*>(meanStore->data.ptr); | ||||
296 | stdStorePtr = reinterpret_cast<float*>(stdStore->data.ptr); | ||||
297 | |||||
298 | if (runningFlag() && !d->path.isEmpty()) | ||||
299 | { | ||||
300 | QString logFile = d->path; | ||||
301 | logFile = logFile.section(QLatin1Char('/'), -1); | ||||
302 | logFile = logFile.left(logFile.indexOf(QLatin1Char('.'))); | ||||
303 | logFile.append(QLatin1String("logMeanStd.txt")); | ||||
304 | |||||
305 | QFile filems(logFile); | ||||
306 | |||||
307 | if (filems.open(QIODevice::WriteOnly | QIODevice::Text)) | ||||
308 | { | ||||
309 | QTextStream oms(&filems); | ||||
310 | oms << "Mean Data\n"; | ||||
311 | |||||
312 | for (int i = 0 ; i < totalcount ; ++i) | ||||
313 | { | ||||
314 | oms << *meanStorePtr++; | ||||
315 | oms << "\t"; | ||||
316 | |||||
317 | if (((i + 1) % 3) == 0) | ||||
318 | { | ||||
319 | oms << "\n"; | ||||
320 | } | ||||
321 | } | ||||
322 | |||||
323 | oms << "\nStd Data\n"; | ||||
324 | |||||
325 | for (int i = 0 ; i < totalcount ; ++i) | ||||
326 | { | ||||
327 | oms << *stdStorePtr++; | ||||
328 | oms << "\t"; | ||||
329 | |||||
330 | if (((i + 1) % 3) == 0) | ||||
331 | { | ||||
332 | oms << "\n"; | ||||
333 | } | ||||
334 | } | ||||
335 | |||||
336 | filems.close(); | ||||
337 | |||||
338 | qCDebug(DIGIKAM_DIMG_LOG)for (QLoggingCategoryMacroHolder<QtDebugMsg> qt_category ((DIGIKAM_DIMG_LOG)()); qt_category; qt_category.control = false ) QMessageLogger(static_cast<const char *>("/home/gilles/devel/GIT/8.x/core/libs/dimg/filters/nr/nrestimate.cpp" ), 338, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).debug() << "Done with the basic work of storing the mean and the std"; | ||||
339 | } | ||||
340 | } | ||||
341 | |||||
342 | postProgress(70); | ||||
343 | |||||
344 | //-- Calculating weighted mean, and weighted std ----------------------------------------------------------- | ||||
345 | |||||
346 | QTextStream owms; | ||||
347 | QFile filewms; | ||||
348 | |||||
349 | if (runningFlag() && !d->path.isEmpty()) | ||||
350 | { | ||||
351 | QString logFile2 = d->path; | ||||
352 | logFile2 = logFile2.section(QLatin1Char('/'), -1); | ||||
353 | logFile2 = logFile2.left(logFile2.indexOf(QLatin1Char('.'))); | ||||
354 | logFile2.append(QLatin1String("logWeightedMeanStd.txt")); | ||||
355 | |||||
356 | filewms.setFileName(logFile2); | ||||
357 | |||||
358 | if (filewms.open(QIODevice::WriteOnly | QIODevice::Text)) | ||||
359 | owms.setDevice(&filewms); | ||||
360 | } | ||||
361 | |||||
362 | QString info; | ||||
363 | float weightedMean = 0.0f; | ||||
364 | float weightedStd = 0.0f; | ||||
365 | float datasd[3] = {0.0f, 0.0f, 0.0f}; | ||||
366 | |||||
367 | for (int j = 0 ; runningFlag() && (j < points->cols) ; ++j) | ||||
368 | { | ||||
369 | meanStorePtr = reinterpret_cast<float*>(meanStore->data.ptr); | ||||
370 | stdStorePtr = reinterpret_cast<float*>(stdStore->data.ptr); | ||||
371 | |||||
372 | for (int moveToChannel = 0 ; moveToChannel <= j ; ++moveToChannel) | ||||
373 | { | ||||
374 | meanStorePtr++; | ||||
375 | stdStorePtr++; | ||||
376 | } | ||||
377 | |||||
378 | for (uint i = 0 ; i < d->clusterCount ; ++i) | ||||
379 | { | ||||
380 | if (rowPosition[i] >= 1) | ||||
381 | { | ||||
382 | weightedMean += (*meanStorePtr) * rowPosition[i]; | ||||
383 | weightedStd += (*stdStorePtr) * rowPosition[i]; | ||||
384 | meanStorePtr += points->cols; | ||||
385 | stdStorePtr += points->cols; | ||||
386 | } | ||||
387 | } | ||||
388 | |||||
389 | weightedMean = weightedMean / (m_orgImage.numPixels()); | ||||
390 | weightedStd = weightedStd / (m_orgImage.numPixels()); | ||||
391 | datasd[j] = weightedStd; | ||||
392 | |||||
393 | if (!d->path.isEmpty()) | ||||
394 | { | ||||
395 | owms << QLatin1String("\nChannel : ") << j << QLatin1Char('\n'); | ||||
396 | owms << QLatin1String("Weighted Mean : ") << weightedMean << QLatin1Char('\n'); | ||||
397 | owms << QLatin1String("Weighted Std : ") << weightedStd << QLatin1Char('\n'); | ||||
398 | } | ||||
399 | |||||
400 | info.append(QLatin1String("\n\nChannel: ")); | ||||
401 | info.append(QString::number(j)); | ||||
402 | info.append(QLatin1String("\nWeighted Mean: ")); | ||||
403 | info.append(QString::number(weightedMean)); | ||||
404 | info.append(QLatin1String("\nWeighted Standard Deviation: ")); | ||||
405 | info.append(QString::number(weightedStd)); | ||||
406 | } | ||||
407 | |||||
408 | if (runningFlag() && !d->path.isEmpty()) | ||||
409 | { | ||||
410 | filewms.close(); | ||||
411 | } | ||||
412 | |||||
413 | qCDebug(DIGIKAM_DIMG_LOG)for (QLoggingCategoryMacroHolder<QtDebugMsg> qt_category ((DIGIKAM_DIMG_LOG)()); qt_category; qt_category.control = false ) QMessageLogger(static_cast<const char *>("/home/gilles/devel/GIT/8.x/core/libs/dimg/filters/nr/nrestimate.cpp" ), 413, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).debug() << "Info : " << info; | ||||
414 | postProgress(80); | ||||
415 | |||||
416 | // -- adaptation --------------------------------------------------------------------------------------- | ||||
417 | |||||
418 | double L = 1.2; | ||||
419 | double LSoft = 0.9; | ||||
420 | double Cr = 1.2; | ||||
421 | double CrSoft = 0.9; | ||||
422 | double Cb = 1.2; | ||||
423 | double CbSoft = 0.9; | ||||
424 | |||||
425 | if (runningFlag()) | ||||
426 | { | ||||
427 | // for 16 bits images only | ||||
428 | |||||
429 | if (m_orgImage.sixteenBit()) | ||||
430 | { | ||||
431 | for (int i = 0 ; i < points->cols ; ++i) | ||||
432 | { | ||||
433 | if (i < 3) | ||||
434 | { | ||||
435 | datasd[i] = datasd[i] / 256; | ||||
436 | } | ||||
437 | } | ||||
438 | } | ||||
439 | |||||
440 | if (datasd[0] < 7) | ||||
441 | { | ||||
442 | L = datasd[0] - 0.98; | ||||
443 | } | ||||
444 | |||||
445 | // cppcheck-suppress knownConditionTrueFalse | ||||
446 | else if ((datasd[0] >= 7) && (datasd[0] < 8)) | ||||
447 | { | ||||
448 | L = datasd[0] - 1.2; | ||||
449 | } | ||||
450 | |||||
451 | else if ((datasd[0] >= 8) && (datasd[0] < 9)) | ||||
452 | { | ||||
453 | L = datasd[0] - 1.5; | ||||
454 | } | ||||
455 | |||||
456 | else | ||||
457 | { | ||||
458 | L = datasd[0] - 1.7; | ||||
459 | } | ||||
460 | |||||
461 | if (L < 0) | ||||
462 | { | ||||
463 | L = 0; | ||||
464 | } | ||||
465 | |||||
466 | if (L > 9) | ||||
467 | { | ||||
468 | L = 9; | ||||
469 | } | ||||
470 | |||||
471 | Cr = datasd[2] * 0.8; | ||||
472 | Cb = datasd[1] * 0.8; | ||||
473 | |||||
474 | if (Cr > 7) | ||||
475 | { | ||||
476 | Cr = 7; | ||||
477 | } | ||||
478 | |||||
479 | if (Cb > 7) | ||||
480 | { | ||||
481 | Cb = 7; | ||||
482 | } | ||||
483 | |||||
484 | L = floorf(L * 100) / 100; | ||||
485 | Cb = floorf(Cb * 100) / 100; | ||||
486 | Cr = floorf(Cr * 100) / 100; | ||||
487 | |||||
488 | if (L > 9) | ||||
489 | { | ||||
490 | LSoft = CrSoft = CbSoft = 0.8; | ||||
491 | } | ||||
492 | else if (L > 3) | ||||
493 | { | ||||
494 | LSoft = CrSoft = CbSoft = 0.7; | ||||
495 | } | ||||
496 | else | ||||
497 | { | ||||
498 | LSoft = CrSoft = CbSoft = 0.6; | ||||
499 | } | ||||
500 | } | ||||
501 | |||||
502 | d->prm.thresholds[0] = L; | ||||
503 | d->prm.thresholds[1] = Cb; | ||||
504 | d->prm.thresholds[2] = Cr; | ||||
505 | d->prm.softness[0] = LSoft; | ||||
506 | d->prm.softness[1] = CbSoft; | ||||
507 | d->prm.softness[2] = CrSoft; | ||||
508 | |||||
509 | qCDebug(DIGIKAM_DIMG_LOG)for (QLoggingCategoryMacroHolder<QtDebugMsg> qt_category ((DIGIKAM_DIMG_LOG)()); qt_category; qt_category.control = false ) QMessageLogger(static_cast<const char *>("/home/gilles/devel/GIT/8.x/core/libs/dimg/filters/nr/nrestimate.cpp" ), 509, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).debug() << "All is completed"; | ||||
510 | postProgress(90); | ||||
511 | |||||
512 | //-- releasing matrices and closing files ---------------------------------------------------------------------- | ||||
513 | |||||
514 | cvReleaseMat(&sd); | ||||
515 | cvReleaseMat(&stdStore); | ||||
516 | cvReleaseMat(&meanStore); | ||||
517 | cvReleaseMat(&points); | ||||
518 | cvReleaseMat(&clusters); | ||||
519 | |||||
520 | for (uint i = 0 ; i < 3 ; ++i) | ||||
521 | { | ||||
522 | delete [] d->fimg[i]; | ||||
523 | } | ||||
524 | |||||
525 | postProgress(100); | ||||
526 | } | ||||
527 | |||||
528 | } // namespace Digikam | ||||
529 | |||||
530 | #include "moc_nrestimate.cpp" |
1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #ifndef QSCOPEDPOINTER_H |
5 | #define QSCOPEDPOINTER_H |
6 | |
7 | #include <QtCore/qglobal.h> |
8 | |
9 | #include <stdlib.h> |
10 | |
11 | QT_BEGIN_NAMESPACE |
12 | |
13 | template <typename T> |
14 | struct QScopedPointerDeleter |
15 | { |
16 | static inline void cleanup(T *pointer) noexcept |
17 | { |
18 | // Enforce a complete type. |
19 | // If you get a compile error here, read the section on forward declared |
20 | // classes in the QScopedPointer documentation. |
21 | typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ]; |
22 | (void) sizeof(IsIncompleteType); |
23 | |
24 | delete pointer; |
25 | } |
26 | void operator()(T *pointer) const noexcept |
27 | { |
28 | cleanup(pointer); |
29 | } |
30 | }; |
31 | |
32 | template <typename T> |
33 | struct QScopedPointerArrayDeleter |
34 | { |
35 | static inline void cleanup(T *pointer) noexcept |
36 | { |
37 | // Enforce a complete type. |
38 | // If you get a compile error here, read the section on forward declared |
39 | // classes in the QScopedPointer documentation. |
40 | typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ]; |
41 | (void) sizeof(IsIncompleteType); |
42 | |
43 | delete[] pointer; |
44 | } |
45 | void operator()(T *pointer) const noexcept |
46 | { |
47 | cleanup(pointer); |
48 | } |
49 | }; |
50 | |
51 | struct QScopedPointerPodDeleter |
52 | { |
53 | static inline void cleanup(void *pointer) noexcept { free(pointer); } |
54 | void operator()(void *pointer) const noexcept { cleanup(pointer); } |
55 | }; |
56 | |
57 | #ifndef QT_NO_QOBJECT |
58 | template <typename T> |
59 | struct QScopedPointerObjectDeleteLater |
60 | { |
61 | static inline void cleanup(T *pointer) { if (pointer) pointer->deleteLater(); } |
62 | void operator()(T *pointer) const { cleanup(pointer); } |
63 | }; |
64 | |
65 | class QObject; |
66 | typedef QScopedPointerObjectDeleteLater<QObject> QScopedPointerDeleteLater; |
67 | #endif |
68 | |
69 | template <typename T, typename Cleanup = QScopedPointerDeleter<T> > |
70 | class QScopedPointer |
71 | { |
72 | public: |
73 | Q_NODISCARD_CTOR[[nodiscard]] |
74 | explicit QScopedPointer(T *p = nullptr) noexcept : d(p) |
75 | { |
76 | } |
77 | |
78 | inline ~QScopedPointer() |
79 | { |
80 | T *oldD = this->d; |
81 | Cleanup::cleanup(oldD); |
82 | } |
83 | |
84 | inline T &operator*() const |
85 | { |
86 | Q_ASSERT(d)((d) ? static_cast<void>(0) : qt_assert("d", "/opt/qt6/include/QtCore/qscopedpointer.h" , 86)); |
87 | return *d; |
88 | } |
89 | |
90 | T *operator->() const noexcept |
91 | { |
92 | return d; |
93 | } |
94 | |
95 | bool operator!() const noexcept |
96 | { |
97 | return !d; |
98 | } |
99 | |
100 | explicit operator bool() const |
101 | { |
102 | return !isNull(); |
103 | } |
104 | |
105 | T *data() const noexcept |
106 | { |
107 | return d; |
108 | } |
109 | |
110 | T *get() const noexcept |
111 | { |
112 | return d; |
113 | } |
114 | |
115 | bool isNull() const noexcept |
116 | { |
117 | return !d; |
118 | } |
119 | |
120 | void reset(T *other = nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval<T *>()))) |
121 | { |
122 | if (d == other) |
123 | return; |
124 | T *oldD = std::exchange(d, other); |
125 | Cleanup::cleanup(oldD); |
126 | } |
127 | |
128 | #if QT_DEPRECATED_SINCE(6, 1)(((6<<16)|(1<<8)|(0)) > 0x050E00) |
129 | QT_DEPRECATED_VERSION_X_6_1("Use std::unique_ptr instead, and call release().") |
130 | T *take() noexcept |
131 | { |
132 | T *oldD = std::exchange(d, nullptr); |
133 | return oldD; |
134 | } |
135 | #endif |
136 | |
137 | #if QT_DEPRECATED_SINCE(6, 2)(((6<<16)|(2<<8)|(0)) > 0x050E00) |
138 | QT_DEPRECATED_VERSION_X_6_2("Use std::unique_ptr instead of QScopedPointer.") |
139 | void swap(QScopedPointer<T, Cleanup> &other) noexcept |
140 | { |
141 | qt_ptr_swap(d, other.d); |
142 | } |
143 | #endif |
144 | |
145 | typedef T *pointer; |
146 | |
147 | friend bool operator==(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) noexcept |
148 | { |
149 | return lhs.data() == rhs.data(); |
150 | } |
151 | |
152 | friend bool operator!=(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) noexcept |
153 | { |
154 | return lhs.data() != rhs.data(); |
155 | } |
156 | |
157 | friend bool operator==(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) noexcept |
158 | { |
159 | return lhs.isNull(); |
160 | } |
161 | |
162 | friend bool operator==(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) noexcept |
163 | { |
164 | return rhs.isNull(); |
165 | } |
166 | |
167 | friend bool operator!=(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) noexcept |
168 | { |
169 | return !lhs.isNull(); |
170 | } |
171 | |
172 | friend bool operator!=(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) noexcept |
173 | { |
174 | return !rhs.isNull(); |
175 | } |
176 | |
177 | #if QT_DEPRECATED_SINCE(6, 2)(((6<<16)|(2<<8)|(0)) > 0x050E00) |
178 | QT_DEPRECATED_VERSION_X_6_2("Use std::unique_ptr instead of QScopedPointer.") |
179 | friend void swap(QScopedPointer<T, Cleanup> &p1, QScopedPointer<T, Cleanup> &p2) noexcept |
180 | { p1.swap(p2); } |
181 | #endif |
182 | |
183 | protected: |
184 | T *d; |
185 | |
186 | private: |
187 | Q_DISABLE_COPY_MOVE(QScopedPointer)QScopedPointer(const QScopedPointer &) = delete; QScopedPointer &operator=(const QScopedPointer &) = delete; QScopedPointer (QScopedPointer &&) = delete; QScopedPointer &operator =(QScopedPointer &&) = delete; |
188 | }; |
189 | |
190 | template <typename T, typename Cleanup = QScopedPointerArrayDeleter<T> > |
191 | class QScopedArrayPointer : public QScopedPointer<T, Cleanup> |
192 | { |
193 | template <typename Ptr> |
194 | using if_same_type = typename std::enable_if<std::is_same<typename std::remove_cv<T>::type, Ptr>::value, bool>::type; |
195 | public: |
196 | Q_NODISCARD_CTOR[[nodiscard]] |
197 | inline QScopedArrayPointer() : QScopedPointer<T, Cleanup>(nullptr) {} |
198 | inline ~QScopedArrayPointer() = default; |
199 | |
200 | template <typename D, if_same_type<D> = true> |
201 | Q_NODISCARD_CTOR[[nodiscard]] |
202 | explicit QScopedArrayPointer(D *p) |
203 | : QScopedPointer<T, Cleanup>(p) |
204 | { |
205 | } |
206 | |
207 | T &operator[](qsizetype i) |
208 | { |
209 | return this->d[i]; |
210 | } |
211 | |
212 | const T &operator[](qsizetype i) const |
213 | { |
214 | return this->d[i]; |
215 | } |
216 | |
217 | #if QT_DEPRECATED_SINCE(6, 2)(((6<<16)|(2<<8)|(0)) > 0x050E00) |
218 | QT_DEPRECATED_VERSION_X_6_2("Use std::unique_ptr instead of QScopedArrayPointer.") |
219 | void swap(QScopedArrayPointer &other) noexcept // prevent QScopedPointer <->QScopedArrayPointer swaps |
220 | { QScopedPointer<T, Cleanup>::swap(other); } |
221 | #endif |
222 | |
223 | private: |
224 | explicit inline QScopedArrayPointer(void *) |
225 | { |
226 | // Enforce the same type. |
227 | |
228 | // If you get a compile error here, make sure you declare |
229 | // QScopedArrayPointer with the same template type as you pass to the |
230 | // constructor. See also the QScopedPointer documentation. |
231 | |
232 | // Storing a scalar array as a pointer to a different type is not |
233 | // allowed and results in undefined behavior. |
234 | } |
235 | |
236 | Q_DISABLE_COPY_MOVE(QScopedArrayPointer)QScopedArrayPointer(const QScopedArrayPointer &) = delete ; QScopedArrayPointer &operator=(const QScopedArrayPointer &) = delete; QScopedArrayPointer(QScopedArrayPointer && ) = delete; QScopedArrayPointer &operator=(QScopedArrayPointer &&) = delete; |
237 | }; |
238 | |
239 | #if QT_DEPRECATED_SINCE(6, 2)(((6<<16)|(2<<8)|(0)) > 0x050E00) |
240 | template <typename T, typename Cleanup> |
241 | QT_DEPRECATED_VERSION_X_6_2("Use std::unique_ptr instead of QScopedArrayPointer.") |
242 | inline void swap(QScopedArrayPointer<T, Cleanup> &lhs, QScopedArrayPointer<T, Cleanup> &rhs) noexcept |
243 | { lhs.swap(rhs); } |
244 | #endif |
245 | |
246 | QT_END_NAMESPACE |
247 | |
248 | #endif // QSCOPEDPOINTER_H |