我目前正在使用here找到的以下代码的修改版本来尝试将项目中的.png资源转换为HBITMAP,然后转换为cv::Map。
cv::Mat Resource2mat(const HMODULE hModule, const LPCSTR lpPNGName) {
cv::Mat src;
HRSRC found = FindResource(hModule, lpPNGName, "PNG");
unsigned int size = SizeofResource(hModule, found);
HGLOBAL loaded = LoadResource(hModule, found);
void* resource_data = LockResource(loaded);
/* Now we decode the PNG */
vector<unsigned char> raw;
unsigned long width, height;
int err = decodePNG(raw, width, height, (const unsigned char*)resource_data, size);
if (err != 0)
{
cout<<"\nError while decoding png splash: "<< err <<endl;
return src;
}
// copy from the window device context to the bitmap device context
BITMAPV5HEADER bmpheader = { 0 };
bmpheader.bV5Size = sizeof(BITMAPV5HEADER);
bmpheader.bV5Width = width;
bmpheader.bV5Height = height;
bmpheader.bV5Planes = 1;
bmpheader.bV5BitCount = 32;
bmpheader.bV5Compression = BI_BITFIELDS;
bmpheader.bV5SizeImage = width * height * 4;
bmpheader.bV5RedMask = 0x00FF0000;
bmpheader.bV5GreenMask = 0x0000FF00;
bmpheader.bV5BlueMask = 0x000000FF;
bmpheader.bV5AlphaMask = 0xFF000000;
bmpheader.bV5CSType = LCS_WINDOWS_COLOR_SPACE;
bmpheader.bV5Intent = LCS_GM_BUSINESS;
void* converted = NULL;
HDC screen = GetDC(NULL);
HBITMAP result = CreateDIBSection(screen, reinterpret_cast<BITMAPINFO*>(&bmpheader), DIB_RGB_COLORS, &converted, NULL, 0);
cout << "Error Final: " << GetLastError() << endl;
/* Copy the decoded image into the bitmap in the correct order */
for (unsigned int y1 = height - 1, y2 = 0; y2 < height; y1--, y2++)
for (unsigned int x = 0; x < width; x++)
{
*((char*)converted + 0 + 4 * x + 4 * width*y2) = raw[2 + 4 * x + 4 * width*y1]; // Blue
*((char*)converted + 1 + 4 * x + 4 * width*y2) = raw[1 + 4 * x + 4 * width*y1]; // Green
*((char*)converted + 2 + 4 * x + 4 * width*y2) = raw[0 + 4 * x + 4 * width*y1]; // Red
*((char*)converted + 3 + 4 * x + 4 * width*y2) = raw[3 + 4 * x + 4 * width*y1]; // Alpha
}
GetDIBits(screen, result, 0, height, src.data, (BITMAPINFO *)&bmpheader, DIB_RGB_COLORS);
cv::Mat Actual = src.clone();
ReleaseDC(NULL, screen);
/* Done! */
return Actual;
}
我的 .rc 文件如下所示:
resources.h 条目如下所示
当运行代码并点击这一行时,我最终遇到了 2012 ( ERROR_TAG_NOT_FOUND ) 错误
HBITMAP result = CreateDIBSection(screen, reinterpret_cast<BITMAPINFO*>(&bmpheader), DIB_RGB_COLORS, &converted, NULL, 0);
通过在这行代码前后调用GetLastError()找到了它
这就是我在 int main() 中调用这个函数的方式:
HINSTANCE BotModuleHandle = GetModuleHandle(NULL);
cout << "Attempting to load a resource: " << endl;
cv::Mat S = Resource2mat(BotModuleHandle, MAKEINTRESOURCE(103));
提前致谢。
此外,任何有关将 PNG 资源转换为 cv::Mat 的更好方法的建议都非常感谢
如果您真正希望实现的是将资源图像加载到
cv::Mat
中,那么您可以使用更短的函数来完成:
cv::Mat Resource2mat(const HMODULE hModule, const LPCSTR lpPNGName)
{
HRSRC found = FindResource(hModule, lpPNGName, "PNG");
unsigned int size = SizeofResource(hModule, found);
HGLOBAL loaded = LoadResource(hModule, found);
void* resource_data = LockResource(loaded);
return cv::imdecode(cv::_InputArray(static_cast<uchar*>(resource_data), size)
, cv::IMREAD_UNCHANGED);
}
LockResource
为您提供一个指向包含 PNG 编码图像的缓冲区(字节数组)的指针(就好像您刚刚将 PNG 文件的内容读入数组一样)。 SizeofResource
给出该数组的大小(以字节为单位)。
cv::imdecode
,它可以从内存缓冲区中解码 PNG(和其他格式)图像。这里有一个小问题——我们需要在一个参数中传递指针和大小。为此,我们可以显式构造一个临时的 cv::_InputArray
。
整个测试程序:
#include <windows.h>
#include "resource.h"
#include <opencv2/opencv.hpp>
cv::Mat Resource2mat(const HMODULE hModule, const LPCSTR lpPNGName)
{
HRSRC found = FindResource(hModule, lpPNGName, "PNG");
CV_Assert(found);
unsigned int size = SizeofResource(hModule, found);
CV_Assert(size);
HGLOBAL loaded = LoadResource(hModule, found);
CV_Assert(size);
void* resource_data = LockResource(loaded);
CV_Assert(resource_data);
return cv::imdecode(cv::_InputArray(static_cast<uchar*>(resource_data), size)
, cv::IMREAD_UNCHANGED);
}
int main()
{
HINSTANCE hModule = GetModuleHandle(NULL);
cv::Mat image(Resource2mat(hModule, MAKEINTRESOURCE(IDB_PNG1)));
cv::imshow("Resource image", image);
cv::waitKey();
return 0;
}
资源标题
resource.h
:
#define IDB_PNG1 101
资源文件
pngres.rc
:
#include "resource.h"
#include "winres.h"
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
IDB_PNG1 PNG "resource.png"
运行此命令会给我一个正确显示图像的窗口:
这在 Opencv c++ 应用程序中为我工作,我对代码进行了一些更改,因为它给出了错误:参数 const char* 与 LPCWSTR 不兼容。
#include <windows.h>
#include "resource.h"
#include <opencv2/opencv.hpp>
cv::Mat Resource2mat(const HMODULE hModule, const LPCWSTR lpPNGName)
{
HRSRC found = FindResource(hModule, lpPNGName, L"PNG");
CV_Assert(found);
unsigned int size = SizeofResource(hModule, found);
CV_Assert(size);
HGLOBAL loaded = LoadResource(hModule, found);
CV_Assert(size);
void* resource_data = LockResource(loaded);
CV_Assert(resource_data);
return cv::imdecode(cv::_InputArray(static_cast<uchar*>(resource_data), size)
, cv::IMREAD_COLOR);
}
int main()
{
HINSTANCE hModule = GetModuleHandle(NULL);
cv::Mat image(Resource2mat(hModule, MAKEINTRESOURCE(IDB_PNG1)));
cv::imshow("Resource image", image);
cv::waitKey();
return 0;
}