我正在使用Bitmap.GetHbitmap将图像从 C# 传递到 C++ dll,如下所示。
Bitmap img = Bitmap.FromFile(PATH); // this is 24bppRGB bitmap.
IntPtr hBit = img.GetHbitmap(); // Make hbitmap for c++ dll.
Run Code Online (Sandbox Code Playgroud)
这是问题:
Bitmap temp = Bitmap.FromHbitmap(hBit); // It changes to 32bppRGB.
Run Code Online (Sandbox Code Playgroud)
我需要 C++ dll 方法的 24bpp 位图,但GetHbitmap()更改了位计数。
我怎样才能制作24bpp HBITMAP?
使用Bitmap.LockBits和CreateDIBSection手动创建您想要的HBITMAP.
Bitmap.GetHBITMAP将始终返回 32bppHBITMAP;无论您实际加载的图像是什么格式。这是因为它是图像内部存储的格式。您需要HBITMAP自己手动创建一个。
您可以使用CreateDIBSection创建您自己的 24bpp 位图。该函数返回一个指针,您可以在其中放置原始像素数据。
幸运的是,GDI+ 允许您通过调用LockBits并指定您想要的像素格式(即PixelFormat24bppRGB)来获取任何您想要的格式的像素数据。然后你只需复制像素数据即可。-Stride、 自上而下或自下而上位图可能存在问题。
BITMAPINFO为我们要创建的位图定义 a :
BITMAPINFO bm;
bm.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bm.bmiHeader.biWidth = img.Width;
bm.bmiHeader.biHeight = -img.Height; // oriented top-down
bm.bmiHeader.biPlanes = 1;
bm.bmiHeader.biBitCount = 24; // 24bpp
bm.bmiHeader.biCompression = BI_RGB; // no compression
bm.bmiHeader.biSizeImage = 0; // let Windows determine size
bm.bmiHeader.biXPelsPerMeter = 0; // Not used by CreateDIBSection
bm.bmiHeader.biYPelsPerMeter = 0; // Not used by CreateDIBSection
Run Code Online (Sandbox Code Playgroud)
根据位图信息创建 DIBSection,并获取放置像素数据的缓冲区
Pointer dibPixels; //will receive a point where we can stuff our pixel data
HBITMAP bmp = CreateDIBSection(0, bmInfo, DIB_RGB_COLORS, out dibPixels, 0, 0);
Run Code Online (Sandbox Code Playgroud)
使用Bitmap.LockBits获取指向所需格式的像素数据的指针:
BitmapData bitmapData = img.LockBits(
img.Bounds, //get entire image
ImageLockModeRead,
PixelFormat24bppRGB //we want the pixel data in 24bpp format
);
Run Code Online (Sandbox Code Playgroud)
将像素数据从源图像复制到CreateDIBSectinbitmapData返回的像素缓冲区中:
int stride = bitmapData.Stride;
int bufferSize = stride * bmData.Height;
CopyMemory(bitmapData.Scan0, dibPixels, bufferSize);
Run Code Online (Sandbox Code Playgroud)
解锁位:
img.UnlockBits(bitmapData);
Run Code Online (Sandbox Code Playgroud)
现在您已HBITMAP准备好位图,可以在七年后传递给您的 dll。