File: | /home/gilles/devel/GIT/8.x/core/libs/dimg/filters/nr/nrestimate.cpp |
Warning: | line 192, column 5 Assigned value is garbage or undefined |
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 < d->clusterCount) ; ++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 |