c++从hbitmap获取原始像素数据
c++ Get raw pixel data from hbitmap
我对使用p/invoke调用相当陌生,不知道是否有人能指导我如何从hbitmap中检索原始像素数据(无符号char*)。
这是我的场景:
我正在加载。NET Bitmap对象,并将其IntPtr发送到我的非托管C++方法。一旦我在C++侧收到hbitmap ptr,我就想访问位图的像素数据。我已经制作了一个接受无符号char*的方法,该方法表示c#中的原始像素数据,但我发现从c#中提取byte[]相当慢。这就是为什么我想发送Bitmap ptr,而不是将Bitmap转换为byte[]并将其发送到我的C++方法。
获取Bitmap IntPtr 的C#代码
Bitmap srcBitmap = new Bitmap(m_testImage);
IntPtr hbitmap = srcBitmap.GetHbitmap();
导入C++方法的C#代码
[SuppressUnmanagedCodeSecurityAttribute()]
[DllImport("MyDll.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
public static extern int ResizeImage(IntPtr srcImg);
将接收Hbitmap处理程序的C++方法
int Resize::ResizeImage(unsigned char* srcImg){
//access srcImgs raw pixel data (preferably in unsigned char* format)
//do work with that
return status;
}
问题:
1) 由于我正在发送IntPrt,我的C++方法参数是否可以是无符号字符*?
2) 如果没有,我如何从c++访问位图的原始数据?
GetHbitmap
方法不检索像素数据。它产生一个类型为HBITMAP
的GDI位图句柄。您的非托管代码会将其作为类型为HBITMAP
的参数接收。您可以使用GDI调用从中获取像素数据。但它本身并不是原始像素。
事实上,我敢肯定你对这个问题的处理方式不对。可能是因为GetPixel
和SetPixel
速度较慢,所以您正朝这个方向前进。这是真的。事实上,它们的GDI等价物也是。您需要做的是使用LockBits
。这将允许您以有效的方式对C#中的整个像素数据进行操作。可以在这里找到对该主题的良好描述:https://web.archive.org/web/20141229164101/http://bobpowell.net/lockingbits.aspx.请注意,为了提高效率,这是一种类型的C#代码,其中不安全的代码和指针通常是最好的解决方案。
无论出于何种原因,如果您仍然希望使用C++代码对像素数据进行操作,那么您仍然可以使用LockBits
作为获取像素数据指针的最简单方法。它肯定比非托管的GDI等价物容易得多。
首先,HBITMAP
不应该是unsigned char*
。如果将HBITMAP
传递给C++,那么参数应该是HBITMAP
:
int Resize::ResizeImage(HBITMAP hBmp)
下一步从HBITMAP
转换为像素:
std::vector<unsigned char> ToPixels(HBITMAP BitmapHandle, int &width, int &height)
{
BITMAP Bmp = {0};
BITMAPINFO Info = {0};
std::vector<unsigned char> Pixels = std::vector<unsigned char>();
HDC DC = CreateCompatibleDC(NULL);
std::memset(&Info, 0, sizeof(BITMAPINFO)); //not necessary really..
HBITMAP OldBitmap = (HBITMAP)SelectObject(DC, BitmapHandle);
GetObject(BitmapHandle, sizeof(Bmp), &Bmp);
Info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
Info.bmiHeader.biWidth = width = Bmp.bmWidth;
Info.bmiHeader.biHeight = height = Bmp.bmHeight;
Info.bmiHeader.biPlanes = 1;
Info.bmiHeader.biBitCount = Bmp.bmBitsPixel;
Info.bmiHeader.biCompression = BI_RGB;
Info.bmiHeader.biSizeImage = ((width * Bmp.bmBitsPixel + 31) / 32) * 4 * height;
Pixels.resize(Info.bmiHeader.biSizeImage);
GetDIBits(DC, BitmapHandle, 0, height, &Pixels[0], &Info, DIB_RGB_COLORS);
SelectObject(DC, OldBitmap);
height = std::abs(height);
DeleteDC(DC);
return Pixels;
}
显然,从Scan0发送指针相当于我所搜索的内容。我能够通过发送从位图数据中检索的IntPtr来按预期操作数据。Scan0方法。
Bitmap srcBitmap = new Bitmap(m_testImage);
Rectangle rect = new Rectangle(0, 0, srcBitmap.Width, srcBitmap.Height);
BitmapData bmpData = srcBitmap.LockBits(rect, ImageLockMode.ReadWrite, srcBitmap.PixelFormat);
//Get ptr to pixel data of image
IntPtr ptr = bmpData.Scan0;
//Call c++ method
int status = myDll.ResizeImage(ptr);
srcBitmap.UnlockBits(bmpData);
为了进一步澄清,我从最初的帖子中更改的唯一代码是第一块代码。其余的都保持不变。(C++方法仍然接受无符号char*作为参数)
- 如何在不产生任何垃圾的情况下获得C中的像素
- 在C++中使用GDAL可以将图像的像素坐标转换为lat,long吗
- 如何在24位SDL_Surface上设置像素的颜色
- 如何从SDL_Surface获取特定像素的颜色
- 如何将CMSampleBufferRef/CIImage/UIImage转换为像素,例如uint8_t[]
- 在C++中查找像素 RGB 数据的最快方法是什么?
- 是否可以从 OpenGL 缓冲区获取原始大小的像素?
- 选择基于另一个垫子的非零像素的cv::Mat的一部分?
- 如何使用 sdl2 快速绘制像素网格?
- 如何在C++中进行像素操作? - Linux
- 他们如何将红外锁定像素转换为镜头前方 1m 的正常平面上的位置
- 访问随机图像像素的快速方法,最多一次
- OpenCV 像素访问点与 at() - 不同的值
- 如何使用 freetype2 访问单色位图中的像素状态
- 尝试渲染像素坐标时,简单线条渲染失败
- 计算另一个图像像素满足条件的像素值的平均值
- 如何返回定义良好的内存部分?例如来自图像数据的像素的颜色值
- 如何从窗口中获取像素数据像素缓冲区并提取RGB
- 覆盖openGL 2d纹理中的每像素像素
- 有没有办法在不复制所有像素的情况下将现有的像素数组转换为位图