File: | /home/gilles/Devel/8.x/core/libs/qtopencvimg/qtopencvimg.cpp |
Warning: | line 233, column 35 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 : 2024-12-23 | |||
7 | * Description : Helper methods to convert OpenCV image to Qt containers and vis-versa. | |||
8 | * | |||
9 | * SPDX-FileCopyrightText: 2024 by Gilles Caulier <caulier dot gilles at gmail dot com> | |||
10 | * SPDX-FileCopyrightText: 2024 by Michael Miller <michael underscore miller at msn dot com> | |||
11 | * SPDX-FileCopyrightText: 2012-2015 by Debao Zhang <hello at debao dot me> | |||
12 | * | |||
13 | * SPDX-License-Identifier: GPL-2.0-or-later | |||
14 | * | |||
15 | * ============================================================ */ | |||
16 | ||||
17 | #include "qtopencvimg.h" | |||
18 | ||||
19 | // Qt includes | |||
20 | ||||
21 | #include <QSysInfo> | |||
22 | #include <QDebug> | |||
23 | ||||
24 | namespace Digikam | |||
25 | { | |||
26 | ||||
27 | namespace | |||
28 | { | |||
29 | ||||
30 | /** | |||
31 | * Convert ARGB to BGRA | |||
32 | */ | |||
33 | cv::Mat argb2bgra(const cv::Mat& mat) | |||
34 | { | |||
35 | Q_ASSERT(mat.channels() == 4)((mat.channels() == 4) ? static_cast<void>(0) : qt_assert ("mat.channels() == 4", "/home/gilles/Devel/8.x/core/libs/qtopencvimg/qtopencvimg.cpp" , 35)); | |||
36 | ||||
37 | cv::Mat newMat(mat.rows, mat.cols, mat.type()); | |||
38 | int from_to[] = { 0, 3, 1, 2, 2, 1, 3, 0 }; | |||
39 | cv::mixChannels(&mat, 1, &newMat, 1, from_to, 4); | |||
40 | ||||
41 | return newMat; | |||
42 | } | |||
43 | ||||
44 | cv::Mat adjustChannelsOrder(const cv::Mat& srcMat, MatColorOrder srcOrder, MatColorOrder targetOrder) | |||
45 | { | |||
46 | Q_ASSERT(srcMat.channels() == 4)((srcMat.channels() == 4) ? static_cast<void>(0) : qt_assert ("srcMat.channels() == 4", "/home/gilles/Devel/8.x/core/libs/qtopencvimg/qtopencvimg.cpp" , 46)); | |||
47 | ||||
48 | if (srcOrder == targetOrder) | |||
49 | { | |||
50 | return srcMat.clone(); | |||
51 | } | |||
52 | ||||
53 | cv::Mat desMat; | |||
54 | ||||
55 | if ( | |||
56 | ((srcOrder == MCO_ARGB) && (targetOrder == MCO_BGRA)) || | |||
57 | ((srcOrder == MCO_BGRA) && (targetOrder == MCO_ARGB)) | |||
58 | ) | |||
59 | { | |||
60 | // ARGB <==> BGRA | |||
61 | ||||
62 | desMat = argb2bgra(srcMat); | |||
63 | } | |||
64 | else if (srcOrder == MCO_ARGB && targetOrder == MCO_RGBA) | |||
65 | { | |||
66 | // ARGB ==> RGBA | |||
67 | ||||
68 | desMat = cv::Mat(srcMat.rows, srcMat.cols, srcMat.type()); | |||
69 | int from_to[] = { 0, 3, 1, 0, 2, 1, 3, 2 }; | |||
70 | cv::mixChannels(&srcMat, 1, &desMat, 1, from_to, 4); | |||
71 | } | |||
72 | else if (srcOrder == MCO_RGBA && targetOrder == MCO_ARGB) | |||
73 | { | |||
74 | // RGBA ==> ARGB | |||
75 | ||||
76 | desMat = cv::Mat(srcMat.rows, srcMat.cols, srcMat.type()); | |||
77 | int from_to[] = { 0, 1, 1, 2, 2, 3, 3, 0 }; | |||
78 | cv::mixChannels(&srcMat, 1, &desMat, 1, from_to, 4); | |||
79 | } | |||
80 | ||||
81 | else | |||
82 | { | |||
83 | // BGRA <==> RBGA | |||
84 | ||||
85 | cv::cvtColor(srcMat, desMat, CV_BGRA2RGBA); | |||
86 | } | |||
87 | ||||
88 | return desMat; | |||
89 | } | |||
90 | ||||
91 | QImage::Format findClosestFormat(QImage::Format formatHint) | |||
92 | { | |||
93 | QImage::Format format = QImage::Format_Invalid; | |||
94 | ||||
95 | switch (formatHint) | |||
96 | { | |||
97 | case QImage::Format_Indexed8: | |||
98 | case QImage::Format_RGB32: | |||
99 | case QImage::Format_ARGB32: | |||
100 | case QImage::Format_ARGB32_Premultiplied: | |||
101 | ||||
102 | #if QT_VERSION((6<<16)|(8<<8)|(0)) >= 0x040400 | |||
103 | ||||
104 | case QImage::Format_RGB888: | |||
105 | ||||
106 | #endif | |||
107 | ||||
108 | #if QT_VERSION((6<<16)|(8<<8)|(0)) >= 0x050200 | |||
109 | ||||
110 | case QImage::Format_RGBX8888: | |||
111 | case QImage::Format_RGBA8888: | |||
112 | case QImage::Format_RGBA8888_Premultiplied: | |||
113 | ||||
114 | #endif | |||
115 | ||||
116 | #if QT_VERSION((6<<16)|(8<<8)|(0)) >= 0x050500 | |||
117 | ||||
118 | case QImage::Format_Alpha8: | |||
119 | case QImage::Format_Grayscale8: | |||
120 | ||||
121 | #endif | |||
122 | ||||
123 | format = formatHint; | |||
124 | ||||
125 | break; | |||
126 | ||||
127 | case QImage::Format_Mono: | |||
128 | case QImage::Format_MonoLSB: | |||
129 | ||||
130 | format = QImage::Format_Indexed8; | |||
131 | ||||
132 | break; | |||
133 | ||||
134 | case QImage::Format_RGB16: | |||
135 | ||||
136 | format = QImage::Format_RGB32; | |||
137 | ||||
138 | break; | |||
139 | ||||
140 | #if QT_VERSION((6<<16)|(8<<8)|(0)) > 0x040400 | |||
141 | ||||
142 | case QImage::Format_RGB444: | |||
143 | case QImage::Format_RGB555: | |||
144 | case QImage::Format_RGB666: | |||
145 | ||||
146 | format = QImage::Format_RGB888; | |||
147 | break; | |||
148 | ||||
149 | case QImage::Format_ARGB4444_Premultiplied: | |||
150 | case QImage::Format_ARGB6666_Premultiplied: | |||
151 | case QImage::Format_ARGB8555_Premultiplied: | |||
152 | case QImage::Format_ARGB8565_Premultiplied: | |||
153 | ||||
154 | format = QImage::Format_ARGB32_Premultiplied; | |||
155 | ||||
156 | break; | |||
157 | ||||
158 | #endif | |||
159 | ||||
160 | default: | |||
161 | ||||
162 | format = QImage::Format_ARGB32; | |||
163 | ||||
164 | break; | |||
165 | } | |||
166 | ||||
167 | return format; | |||
168 | } | |||
169 | ||||
170 | MatColorOrder getColorOrderOfRGB32Format() | |||
171 | { | |||
172 | ||||
173 | #if Q_BYTE_ORDER1234 == Q_LITTLE_ENDIAN1234 | |||
174 | ||||
175 | return MCO_BGRA; | |||
176 | ||||
177 | #else | |||
178 | ||||
179 | return MCO_ARGB; | |||
180 | ||||
181 | #endif | |||
182 | ||||
183 | } | |||
184 | ||||
185 | } // namespace | |||
186 | ||||
187 | /** | |||
188 | * Convert QImage to cv::Mat | |||
189 | */ | |||
190 | cv::Mat image2Mat(const QImage& img, int requiredMatType, MatColorOrder requriedOrder) | |||
191 | { | |||
192 | int targetDepth = CV_MAT_DEPTH(requiredMatType)((requiredMatType) & ((1 << 3) - 1)); | |||
193 | int targetChannels = CV_MAT_CN(requiredMatType)((((requiredMatType) & ((512 - 1) << 3)) >> 3 ) + 1); | |||
194 | ||||
195 | Q_ASSERT((targetChannels == CV_CN_MAX) || (targetChannels == 1) || (targetChannels == 3) || (targetChannels == 4))(((targetChannels == 512) || (targetChannels == 1) || (targetChannels == 3) || (targetChannels == 4)) ? static_cast<void>(0) : qt_assert("(targetChannels == CV_CN_MAX) || (targetChannels == 1) || (targetChannels == 3) || (targetChannels == 4)" , "/home/gilles/Devel/8.x/core/libs/qtopencvimg/qtopencvimg.cpp" , 195)); | |||
| ||||
196 | Q_ASSERT((targetDepth == CV_8U) || (targetDepth == CV_16U) || (targetDepth == CV_32F))(((targetDepth == 0) || (targetDepth == 2) || (targetDepth == 5)) ? static_cast<void>(0) : qt_assert("(targetDepth == CV_8U) || (targetDepth == CV_16U) || (targetDepth == CV_32F)" , "/home/gilles/Devel/8.x/core/libs/qtopencvimg/qtopencvimg.cpp" , 196)); | |||
197 | ||||
198 | if (img.isNull()) | |||
199 | { | |||
200 | return cv::Mat(); | |||
201 | } | |||
202 | ||||
203 | // Find the closest image format that can be used in image2Mat_shared() | |||
204 | ||||
205 | QImage::Format format = findClosestFormat(img.format()); | |||
206 | QImage image = (format == img.format()) ? img : img.convertToFormat(format); | |||
207 | ||||
208 | MatColorOrder srcOrder; | |||
209 | cv::Mat mat0 = image2Mat_shared(image, &srcOrder); | |||
210 | ||||
211 | // Adjust mat channels if needed. | |||
212 | ||||
213 | cv::Mat mat_adjustCn; | |||
214 | const float maxAlpha = (targetDepth
| |||
215 | : ((targetDepth == CV_16U2) ? 65535 | |||
216 | : 1.0); | |||
217 | ||||
218 | if (targetChannels
| |||
219 | { | |||
220 | targetChannels = mat0.channels(); | |||
221 | } | |||
222 | ||||
223 | switch (targetChannels) | |||
224 | { | |||
225 | case 1: | |||
226 | ||||
227 | if (mat0.channels() == 3) | |||
228 | { | |||
229 | cv::cvtColor(mat0, mat_adjustCn, CV_RGB2GRAY); | |||
230 | } | |||
231 | else if (mat0.channels() == 4) | |||
232 | { | |||
233 | if (srcOrder == MCO_BGRA) | |||
| ||||
234 | { | |||
235 | cv::cvtColor(mat0, mat_adjustCn, CV_BGRA2GRAY); | |||
236 | } | |||
237 | else if (srcOrder == MCO_RGBA) | |||
238 | { | |||
239 | cv::cvtColor(mat0, mat_adjustCn, CV_RGBA2GRAY); | |||
240 | } | |||
241 | else // MCO_ARGB | |||
242 | { | |||
243 | cv::cvtColor(argb2bgra(mat0), mat_adjustCn, CV_BGRA2GRAY); | |||
244 | } | |||
245 | } | |||
246 | ||||
247 | break; | |||
248 | ||||
249 | case 3: | |||
250 | ||||
251 | if (mat0.channels() == 1) | |||
252 | { | |||
253 | cv::cvtColor(mat0, mat_adjustCn, (requriedOrder == MCO_BGR) ? CV_GRAY2BGR : CV_GRAY2RGB); | |||
254 | } | |||
255 | else if (mat0.channels() == 3) | |||
256 | { | |||
257 | if (requriedOrder != srcOrder) | |||
258 | { | |||
259 | cv::cvtColor(mat0, mat_adjustCn, CV_RGB2BGR); | |||
260 | } | |||
261 | } | |||
262 | ||||
263 | else if (mat0.channels() == 4) | |||
264 | { | |||
265 | if (srcOrder == MCO_ARGB) | |||
266 | { | |||
267 | mat_adjustCn = cv::Mat(mat0.rows, mat0.cols, CV_MAKE_TYPE(mat0.type(), 3)(((mat0.type()) & ((1 << 3) - 1)) + (((3)-1) << 3))); | |||
268 | int ARGB2RGB[] = { 1, 0, 2, 1, 3, 2 }; | |||
269 | int ARGB2BGR[] = { 1, 2, 2, 1, 3, 0 }; | |||
270 | cv::mixChannels(&mat0, 1, &mat_adjustCn, 1, (requriedOrder == MCO_BGR) ? ARGB2BGR : ARGB2RGB, 3); | |||
271 | } | |||
272 | else if (srcOrder == MCO_BGRA) | |||
273 | { | |||
274 | cv::cvtColor(mat0, mat_adjustCn, (requriedOrder == MCO_BGR) ? CV_BGRA2BGR : CV_BGRA2RGB); | |||
275 | } | |||
276 | else // RGBA | |||
277 | { | |||
278 | cv::cvtColor(mat0, mat_adjustCn, (requriedOrder == MCO_BGR) ? CV_RGBA2BGR : CV_RGBA2RGB); | |||
279 | } | |||
280 | } | |||
281 | ||||
282 | break; | |||
283 | ||||
284 | case 4: | |||
285 | ||||
286 | if (mat0.channels() == 1) | |||
287 | { | |||
288 | if (requriedOrder == MCO_ARGB) | |||
289 | { | |||
290 | cv::Mat alphaMat(mat0.rows, mat0.cols, CV_MAKE_TYPE(mat0.type(), 1)(((mat0.type()) & ((1 << 3) - 1)) + (((1)-1) << 3)), cv::Scalar(maxAlpha)); | |||
291 | mat_adjustCn = cv::Mat(mat0.rows, mat0.cols, CV_MAKE_TYPE(mat0.type(), 4)(((mat0.type()) & ((1 << 3) - 1)) + (((4)-1) << 3))); | |||
292 | cv::Mat in[] = {alphaMat, mat0}; | |||
293 | int from_to[] = {0, 0, 1, 1, 1, 2, 1, 3}; | |||
294 | cv::mixChannels(in, 2, &mat_adjustCn, 1, from_to, 4); | |||
295 | } | |||
296 | else if (requriedOrder == MCO_RGBA) | |||
297 | { | |||
298 | cv::cvtColor(mat0, mat_adjustCn, CV_GRAY2RGBA); | |||
299 | } | |||
300 | else // MCO_BGRA | |||
301 | { | |||
302 | cv::cvtColor(mat0, mat_adjustCn, CV_GRAY2BGRA); | |||
303 | } | |||
304 | } | |||
305 | else if (mat0.channels() == 3) | |||
306 | { | |||
307 | if (requriedOrder == MCO_ARGB) | |||
308 | { | |||
309 | cv::Mat alphaMat(mat0.rows, mat0.cols, CV_MAKE_TYPE(mat0.type(), 1)(((mat0.type()) & ((1 << 3) - 1)) + (((1)-1) << 3)), cv::Scalar(maxAlpha)); | |||
310 | mat_adjustCn = cv::Mat(mat0.rows, mat0.cols, CV_MAKE_TYPE(mat0.type(), 4)(((mat0.type()) & ((1 << 3) - 1)) + (((4)-1) << 3))); | |||
311 | cv::Mat in[] = { alphaMat, mat0 }; | |||
312 | int from_to[] = { 0, 0, 1, 1, 2, 2, 3, 3 }; | |||
313 | cv::mixChannels(in, 2, &mat_adjustCn, 1, from_to, 4); | |||
314 | } | |||
315 | else if (requriedOrder == MCO_RGBA) | |||
316 | { | |||
317 | cv::cvtColor(mat0, mat_adjustCn, CV_RGB2RGBA); | |||
318 | } | |||
319 | else // MCO_BGRA | |||
320 | { | |||
321 | cv::cvtColor(mat0, mat_adjustCn, CV_RGB2BGRA); | |||
322 | } | |||
323 | } | |||
324 | else if (mat0.channels() == 4) | |||
325 | { | |||
326 | if (srcOrder != requriedOrder) | |||
327 | { | |||
328 | mat_adjustCn = adjustChannelsOrder(mat0, srcOrder, requriedOrder); | |||
329 | } | |||
330 | } | |||
331 | ||||
332 | break; | |||
333 | ||||
334 | default: | |||
335 | ||||
336 | break; | |||
337 | } | |||
338 | ||||
339 | // Adjust depth if needed. | |||
340 | ||||
341 | if (targetDepth == CV_8U0) | |||
342 | { | |||
343 | return (mat_adjustCn.empty() ? mat0.clone() : mat_adjustCn); | |||
344 | } | |||
345 | ||||
346 | if (mat_adjustCn.empty()) | |||
347 | { | |||
348 | mat_adjustCn = mat0; | |||
349 | } | |||
350 | ||||
351 | cv::Mat mat_adjustDepth; | |||
352 | mat_adjustCn.convertTo(mat_adjustDepth, | |||
353 | CV_MAKE_TYPE(targetDepth, mat_adjustCn.channels())(((targetDepth) & ((1 << 3) - 1)) + (((mat_adjustCn .channels())-1) << 3)), | |||
354 | (targetDepth == CV_16U2) ? 255.0 : 1 / 255.0); | |||
355 | ||||
356 | return mat_adjustDepth; | |||
357 | } | |||
358 | ||||
359 | /** | |||
360 | * Convert cv::Mat to QImage | |||
361 | */ | |||
362 | QImage mat2Image(const cv::Mat& mat, MatColorOrder order, QImage::Format formatHint) | |||
363 | { | |||
364 | Q_ASSERT((mat.channels() == 1) || (mat.channels() == 3) || (mat.channels() == 4))(((mat.channels() == 1) || (mat.channels() == 3) || (mat.channels () == 4)) ? static_cast<void>(0) : qt_assert("(mat.channels() == 1) || (mat.channels() == 3) || (mat.channels() == 4)" , "/home/gilles/Devel/8.x/core/libs/qtopencvimg/qtopencvimg.cpp" , 364)); | |||
365 | Q_ASSERT((mat.depth() == CV_8U) || (mat.depth() == CV_16U) || (mat.depth() == CV_32F))(((mat.depth() == 0) || (mat.depth() == 2) || (mat.depth() == 5)) ? static_cast<void>(0) : qt_assert("(mat.depth() == CV_8U) || (mat.depth() == CV_16U) || (mat.depth() == CV_32F)" , "/home/gilles/Devel/8.x/core/libs/qtopencvimg/qtopencvimg.cpp" , 365)); | |||
366 | ||||
367 | if (mat.empty()) | |||
368 | { | |||
369 | return QImage(); | |||
370 | } | |||
371 | ||||
372 | // Adjust mat channels if needed, and find proper QImage format. | |||
373 | ||||
374 | QImage::Format format = QImage::Format_Invalid; | |||
375 | cv::Mat mat_adjustCn; | |||
376 | ||||
377 | if (mat.channels() == 1) | |||
378 | { | |||
379 | format = formatHint; | |||
380 | ||||
381 | if ( (formatHint != QImage::Format_Indexed8) | |||
382 | ||||
383 | #if QT_VERSION((6<<16)|(8<<8)|(0)) >= 0x050500 | |||
384 | ||||
385 | && (formatHint != QImage::Format_Alpha8) | |||
386 | && (formatHint != QImage::Format_Grayscale8) | |||
387 | ||||
388 | #endif | |||
389 | ||||
390 | ) | |||
391 | { | |||
392 | format = QImage::Format_Indexed8; | |||
393 | } | |||
394 | } | |||
395 | ||||
396 | else if (mat.channels() == 3) | |||
397 | { | |||
398 | ||||
399 | #if QT_VERSION((6<<16)|(8<<8)|(0)) >= 0x040400 | |||
400 | ||||
401 | format = QImage::Format_RGB888; | |||
402 | ||||
403 | if (order == MCO_BGR) | |||
404 | { | |||
405 | cv::cvtColor(mat, mat_adjustCn, CV_BGR2RGB); | |||
406 | } | |||
407 | ||||
408 | #else | |||
409 | ||||
410 | format = QImage::Format_RGB32; | |||
411 | cv::Mat mat_tmp; | |||
412 | cv::cvtColor(mat, mat_tmp, (order == MCO_BGR) ? CV_BGR2BGRA : CV_RGB2BGRA); | |||
413 | ||||
414 | # if Q_BYTE_ORDER1234 == Q_LITTLE_ENDIAN1234 | |||
415 | ||||
416 | mat_adjustCn = mat_tmp; | |||
417 | ||||
418 | # else | |||
419 | ||||
420 | mat_adjustCn = argb2bgra(mat_tmp); | |||
421 | ||||
422 | # endif | |||
423 | ||||
424 | #endif | |||
425 | ||||
426 | } | |||
427 | ||||
428 | else if (mat.channels() == 4) | |||
429 | { | |||
430 | // Find best format if the formatHint can not be applied. | |||
431 | ||||
432 | format = findClosestFormat(formatHint); | |||
433 | ||||
434 | if ( (format != QImage::Format_RGB32) | |||
435 | && (format != QImage::Format_ARGB32) | |||
436 | && (format != QImage::Format_ARGB32_Premultiplied) | |||
437 | ||||
438 | #if QT_VERSION((6<<16)|(8<<8)|(0)) >= 0x050200 | |||
439 | ||||
440 | && (format != QImage::Format_RGBX8888) | |||
441 | && (format != QImage::Format_RGBA8888) | |||
442 | && (format != QImage::Format_RGBA8888_Premultiplied) | |||
443 | ||||
444 | #endif | |||
445 | ||||
446 | ) | |||
447 | { | |||
448 | ||||
449 | #if QT_VERSION((6<<16)|(8<<8)|(0)) >= 0x050200 | |||
450 | ||||
451 | format = order == MCO_RGBA ? QImage::Format_RGBA8888 : QImage::Format_ARGB32; | |||
452 | ||||
453 | #else | |||
454 | ||||
455 | format = QImage::Format_ARGB32; | |||
456 | ||||
457 | #endif | |||
458 | ||||
459 | } | |||
460 | ||||
461 | // Channel order requried by the target QImage | |||
462 | ||||
463 | MatColorOrder requiredOrder = getColorOrderOfRGB32Format(); | |||
464 | ||||
465 | #if QT_VERSION((6<<16)|(8<<8)|(0)) >= 0x050200 | |||
466 | ||||
467 | if ( (formatHint == QImage::Format_RGBX8888) | |||
468 | || (formatHint == QImage::Format_RGBA8888) | |||
469 | || (formatHint == QImage::Format_RGBA8888_Premultiplied)) | |||
470 | { | |||
471 | requiredOrder = MCO_RGBA; | |||
472 | } | |||
473 | ||||
474 | #endif | |||
475 | ||||
476 | if (order != requiredOrder) | |||
477 | { | |||
478 | mat_adjustCn = adjustChannelsOrder(mat, order, requiredOrder); | |||
479 | } | |||
480 | } | |||
481 | ||||
482 | if (mat_adjustCn.empty()) | |||
483 | { | |||
484 | mat_adjustCn = mat; | |||
485 | } | |||
486 | ||||
487 | // Adjust mat depth if needed. | |||
488 | ||||
489 | cv::Mat mat_adjustDepth = mat_adjustCn; | |||
490 | ||||
491 | if (mat.depth() != CV_8U0) | |||
492 | { | |||
493 | mat_adjustCn.convertTo(mat_adjustDepth, CV_8UC(mat_adjustCn.channels())(((0) & ((1 << 3) - 1)) + ((((mat_adjustCn.channels ()))-1) << 3)), (mat.depth() == CV_16U2) ? 1 / 255.0 : 255.0); | |||
494 | } | |||
495 | ||||
496 | // Should we convert the image to the format specified by formatHint? | |||
497 | ||||
498 | QImage image = mat2Image_shared(mat_adjustDepth, format); | |||
499 | ||||
500 | if ((format == formatHint) || (formatHint == QImage::Format_Invalid)) | |||
501 | { | |||
502 | return image.copy(); | |||
503 | } | |||
504 | else | |||
505 | { | |||
506 | return image.convertToFormat(formatHint); | |||
507 | } | |||
508 | } | |||
509 | ||||
510 | /** | |||
511 | * Convert QImage to cv::Mat without data copy | |||
512 | */ | |||
513 | cv::Mat image2Mat_shared(const QImage& img, MatColorOrder* order) | |||
514 | { | |||
515 | if (img.isNull()) | |||
516 | { | |||
517 | return cv::Mat(); | |||
518 | } | |||
519 | ||||
520 | switch (img.format()) | |||
521 | { | |||
522 | case QImage::Format_Indexed8: | |||
523 | ||||
524 | break; | |||
525 | ||||
526 | #if QT_VERSION((6<<16)|(8<<8)|(0)) >= 0x040400 | |||
527 | ||||
528 | case QImage::Format_RGB888: | |||
529 | ||||
530 | if (order) | |||
531 | { | |||
532 | *order = MCO_RGB; | |||
533 | } | |||
534 | ||||
535 | break; | |||
536 | ||||
537 | #endif | |||
538 | ||||
539 | case QImage::Format_RGB32: | |||
540 | case QImage::Format_ARGB32: | |||
541 | case QImage::Format_ARGB32_Premultiplied: | |||
542 | ||||
543 | if (order) | |||
544 | { | |||
545 | *order = getColorOrderOfRGB32Format(); | |||
546 | } | |||
547 | ||||
548 | break; | |||
549 | ||||
550 | #if QT_VERSION((6<<16)|(8<<8)|(0)) >= 0x050200 | |||
551 | ||||
552 | case QImage::Format_RGBX8888: | |||
553 | case QImage::Format_RGBA8888: | |||
554 | case QImage::Format_RGBA8888_Premultiplied: | |||
555 | ||||
556 | if (order) | |||
557 | { | |||
558 | *order = MCO_RGBA; | |||
559 | } | |||
560 | ||||
561 | break; | |||
562 | ||||
563 | #endif | |||
564 | ||||
565 | #if QT_VERSION((6<<16)|(8<<8)|(0)) >= 0x050500 | |||
566 | ||||
567 | case QImage::Format_Alpha8: | |||
568 | case QImage::Format_Grayscale8: | |||
569 | ||||
570 | break; | |||
571 | ||||
572 | #endif | |||
573 | ||||
574 | default: | |||
575 | ||||
576 | return cv::Mat(); | |||
577 | } | |||
578 | ||||
579 | return cv::Mat(img.height(), img.width(), CV_8UC(img.depth() / 8)(((0) & ((1 << 3) - 1)) + ((((img.depth() / 8))-1) << 3)), (uchar*)img.bits(), img.bytesPerLine()); | |||
580 | } | |||
581 | ||||
582 | /** | |||
583 | * Convert cv::Mat to QImage without data copy | |||
584 | */ | |||
585 | QImage mat2Image_shared(const cv::Mat& mat, QImage::Format formatHint) | |||
586 | { | |||
587 | Q_ASSERT((mat.type() == CV_8UC1) || (mat.type() == CV_8UC3) || (mat.type() == CV_8UC4))(((mat.type() == (((0) & ((1 << 3) - 1)) + (((1)-1) << 3))) || (mat.type() == (((0) & ((1 << 3) - 1)) + (((3)-1) << 3))) || (mat.type() == (((0) & ( (1 << 3) - 1)) + (((4)-1) << 3)))) ? static_cast< void>(0) : qt_assert("(mat.type() == CV_8UC1) || (mat.type() == CV_8UC3) || (mat.type() == CV_8UC4)" , "/home/gilles/Devel/8.x/core/libs/qtopencvimg/qtopencvimg.cpp" , 587)); | |||
588 | ||||
589 | if (mat.empty()) | |||
590 | { | |||
591 | return QImage(); | |||
592 | } | |||
593 | ||||
594 | // Adjust formatHint if needed. | |||
595 | ||||
596 | if (mat.type() == CV_8UC1(((0) & ((1 << 3) - 1)) + (((1)-1) << 3))) | |||
597 | { | |||
598 | // cppcheck-suppress duplicateConditionalAssign | |||
599 | if ( (formatHint != QImage::Format_Indexed8) | |||
600 | ||||
601 | #if QT_VERSION((6<<16)|(8<<8)|(0)) >= 0x050500 | |||
602 | ||||
603 | && (formatHint != QImage::Format_Alpha8) | |||
604 | && (formatHint != QImage::Format_Grayscale8) | |||
605 | ||||
606 | #endif | |||
607 | ||||
608 | ) | |||
609 | { | |||
610 | // cppcheck-suppress duplicateConditionalAssign | |||
611 | formatHint = QImage::Format_Indexed8; | |||
612 | } | |||
613 | ||||
614 | #if QT_VERSION((6<<16)|(8<<8)|(0)) >= 0x040400 | |||
615 | ||||
616 | } | |||
617 | ||||
618 | else if (mat.type() == CV_8UC3(((0) & ((1 << 3) - 1)) + (((3)-1) << 3))) | |||
619 | { | |||
620 | formatHint = QImage::Format_RGB888; | |||
621 | ||||
622 | #endif | |||
623 | ||||
624 | } | |||
625 | ||||
626 | else if (mat.type() == CV_8UC4(((0) & ((1 << 3) - 1)) + (((4)-1) << 3))) | |||
627 | { | |||
628 | if ( (formatHint != QImage::Format_RGB32) | |||
629 | && (formatHint != QImage::Format_ARGB32) | |||
630 | && (formatHint != QImage::Format_ARGB32_Premultiplied) | |||
631 | ||||
632 | #if QT_VERSION((6<<16)|(8<<8)|(0)) >= 0x050200 | |||
633 | ||||
634 | && (formatHint != QImage::Format_RGBX8888) | |||
635 | && (formatHint != QImage::Format_RGBA8888) | |||
636 | && (formatHint != QImage::Format_RGBA8888_Premultiplied) | |||
637 | ||||
638 | #endif | |||
639 | ||||
640 | ) | |||
641 | { | |||
642 | formatHint = QImage::Format_ARGB32; | |||
643 | } | |||
644 | } | |||
645 | ||||
646 | QImage img(mat.data, mat.cols, mat.rows, mat.step, formatHint); | |||
647 | ||||
648 | // Should we add directly support for user-customed-colorTable? | |||
649 | ||||
650 | if (formatHint == QImage::Format_Indexed8) | |||
651 | { | |||
652 | QVector<QRgb> colorTable; | |||
653 | ||||
654 | for (int i = 0 ; i < 256 ; ++i) | |||
655 | { | |||
656 | colorTable.append(qRgb(i, i, i)); | |||
657 | } | |||
658 | ||||
659 | img.setColorTable(colorTable); | |||
660 | } | |||
661 | ||||
662 | return img; | |||
663 | } | |||
664 | ||||
665 | } // namespace Digikam |