-
Notifications
You must be signed in to change notification settings - Fork 4
/
convertmattowxbmp.cpp
111 lines (91 loc) · 3.54 KB
/
convertmattowxbmp.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
///////////////////////////////////////////////////////////////////////////////
// Name: convertmattowxbmp.cpp
// Purpose: Converts OpenCV bitmap (Mat) stored as BGR CVU8 to wxBitmap
// Author: PB
// Created: 2020-09-16
// Copyright: (c) 2020 PB
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#include <wx/wx.h>
#include <wx/rawbmp.h>
#include <opencv2/core/mat.hpp>
#include "convertmattowxbmp.h"
#ifdef __WXMSW__
namespace
{
// Version optimized for Microsoft Windows.
// matBitmap must be continous and matBitmap.cols % 4 must equal 0
// as SetDIBits() requires the DIB rows to be DWORD-aligned.
// Should not be called directly but only from ConvertMatBitmapTowxBitmap()
// which does all the necessary debug checks.
bool ConvertMatBitmapTowxBitmapMSW(const cv::Mat& matBitmap, wxBitmap& bitmap)
{
const HDC hScreenDC = ::GetDC(nullptr);
BITMAPINFO bitmapInfo{0};
bool success;
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFO) - sizeof(RGBQUAD);
bitmapInfo.bmiHeader.biWidth = bitmap.GetWidth();
bitmapInfo.bmiHeader.biHeight = 0 - bitmap.GetHeight();
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biBitCount = 24;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
success = ::SetDIBits(hScreenDC, bitmap.GetHBITMAP(), 0, bitmap.GetHeight(),
matBitmap.data, &bitmapInfo, DIB_RGB_COLORS) != 0;
::ReleaseDC(nullptr, hScreenDC);
return success;
}
} // unnamed namespace
#endif // #ifndef __WXMSW__
// See the function description in the header file.
bool ConvertMatBitmapTowxBitmap(const cv::Mat& matBitmap, wxBitmap& bitmap)
{
wxCHECK(!matBitmap.empty(), false);
wxCHECK(matBitmap.type() == CV_8UC3, false);
wxCHECK(matBitmap.dims == 2, false);
wxCHECK(bitmap.IsOk(), false);
wxCHECK(bitmap.GetWidth() == matBitmap.cols && bitmap.GetHeight() == matBitmap.rows, false);
wxCHECK(bitmap.GetDepth() == 24, false);
#ifdef __WXMSW__
if ( bitmap.IsDIB()
&& matBitmap.isContinuous()
&& matBitmap.cols % 4 == 0 )
{
return ConvertMatBitmapTowxBitmapMSW(matBitmap, bitmap);
}
#endif
wxNativePixelData pixelData(bitmap);
wxNativePixelData::Iterator pixelDataIt(pixelData);
if ( matBitmap.isContinuous() )
{
const uchar* bgr = matBitmap.data;
for ( int row = 0; row < pixelData.GetHeight(); ++row )
{
pixelDataIt.MoveTo(pixelData, 0, row);
for ( int col = 0;
col < pixelData.GetWidth();
++col, ++pixelDataIt )
{
pixelDataIt.Blue() = *bgr++;
pixelDataIt.Green() = *bgr++;
pixelDataIt.Red() = *bgr++;
}
}
}
else // Is it even possible for Mat with image to be not continous?
{
auto matBitmapIt = matBitmap.begin<cv::Vec3b>();
for ( int row = 0; row < pixelData.GetHeight(); ++row )
{
pixelDataIt.MoveTo(pixelData, 0, row);
for ( int col = 0;
col < pixelData.GetWidth();
++col, ++pixelDataIt, ++matBitmapIt )
{
pixelDataIt.Blue() = (*matBitmapIt)[0];
pixelDataIt.Green() = (*matBitmapIt)[1];
pixelDataIt.Red() = (*matBitmapIt)[2];
}
}
}
return bitmap.IsOk();
}