C++创建图像Bitmap返回null,如何正确构造实现像素扫描
C++ GDI+ Bitmap对象创建失败及逐像素扫描解决方案
问题核心原因排查
- 未初始化GDI+运行环境:GDI+ 接口使用前必须完成初始化操作,这是最常见的创建返回null的原因
- 字符串编码转换错误:直接通过迭代器转换
std::string到std::wstring仅支持纯ASCII路径,包含中文、特殊符号的路径会出现乱码,导致找不到文件 - 路径本身无效:文件不存在、无读取权限、格式不被GDI+支持也会返回空对象
正确实现代码
第一步:GDI+ 初始化(程序启动时执行一次即可)
#include <gdiplus.h> #pragma comment(lib, "gdiplus.lib") // 全局变量,用于GDI+关闭时使用 ULONG_PTR gdiplusToken; // 初始化代码放在main函数最开始或者窗口初始化逻辑中 Gdiplus::GdiplusStartupInput startupInput; Gdiplus::GdiplusStartup(&gdiplusToken, &startupInput, NULL); // 程序退出前执行关闭逻辑 Gdiplus::GdiplusShutdown(gdiplusToken);
第二步:正确的string转wstring编码转换(适配中文路径)
#include <windows.h> #include <string> std::wstring StringToWString(const std::string& str) { int len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0); wchar_t* wstr = new wchar_t[len]; MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, wstr, len); std::wstring result(wstr); delete[] wstr; return result; }
第三步:创建Bitmap对象并校验状态
std::string path = currImg.path; std::wstring pathWstr = StringToWString(path); Gdiplus::Bitmap* img = new Gdiplus::Bitmap(pathWstr.c_str()); // 校验创建结果 if (img->GetLastStatus() != Gdiplus::Ok) { // 创建失败,可根据状态码排查问题:FileNotFound代表文件不存在,InvalidParameter代表参数错误 delete img; img = nullptr; // 自行补充错误处理逻辑 }
第四步:高效逐像素扫描获取颜色(优先用LockBits,比逐次调用GetPixel效率高10倍以上)
if (img != nullptr) { int width = img->GetWidth(); int height = img->GetHeight(); Gdiplus::Rect rect(0, 0, width, height); Gdiplus::BitmapData bmpData; // 锁定像素区域,可读可写 img->LockBits(&rect, Gdiplus::ImageLockModeRead, PixelFormat32bppARGB, &bmpData); // 获取像素数据首地址 BYTE* ptr = (BYTE*)bmpData.Scan0; int stride = bmpData.Stride; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { // 每个像素占4字节,存储顺序为B、G、R、A BYTE b = ptr[y * stride + x * 4 + 0]; BYTE g = ptr[y * stride + x * 4 + 1]; BYTE r = ptr[y * stride + x * 4 + 2]; BYTE a = ptr[y * stride + x * 4 + 3]; // 此处可对r/g/b/a值进行颜色判断逻辑 } } // 解锁像素区域,必须调用否则会内存泄漏 img->UnlockBits(&bmpData); // 用完释放Bitmap对象 delete img; }
内容的提问来源于stack exchange,提问作者vytaute
相关产品推荐
相关产品推荐

