如何解决如何使用Direct2D从BITMAPINFOHEADER和BYTE渲染位图
我正在尝试创建一个C ++应用程序,该应用程序实际上是从放大镜捕获位图并使用Direct 2d渲染的。
我目前正在使用代码将放大镜中的位图保存到文件中。但是我要做的是使用直接2d将该位图绘制到我的窗口中,而不是将其保存到文件中。
放大镜以MAGIMAGEHEADER的形式返回图像作为结构,我能够从中获得BITMAPINFOHEADER和字节。我需要使用直接2D渲染到窗口。
这里是用于从放大镜API获取BITMAPINFOHEADER和字节的代码
BOOL MagImageScaling(HWND hwnd,void *srcdata,MAGIMAGEHEADER srcheader,void *destdata,MAGIMAGEHEADER destheader,RECT unclipped,RECT clipped,HRGN dirty)
{
// Setup the bitmap info header
bmif.biSize = sizeof(BITMAPINFOHEADER);
bmif.biHeight = srcheader.height;
bmif.biWidth = srcheader.width;
bmif.biSizeImage = srcheader.cbSize;
bmif.biPlanes = 1;
bmif.biBitCount = (WORD)(bmif.biSizeImage / bmif.biHeight / bmif.biWidth * 8);
bmif.biCompression = BI_RGB;
// Prepare the buffer
if (pData != NULL)
{
delete pData;
pData = NULL;
}
pData = (BYTE*)malloc(bmif.biSizeImage);
memcpy(pData,srcdata,bmif.biSizeImage);
// The data bit is in top->bottom order,so we convert it to bottom->top order
LONG linesize = bmif.biWidth * bmif.biBitCount / 8;
BYTE* pLineData = new BYTE[linesize];
BYTE* pStart;
BYTE* pEnd;
LONG linestart = 0;
LONG lineEnd = bmif.biHeight - 1;
while (linestart < lineEnd)
{
// Get the address of the swap line
pStart = pData + (linestart * linesize);
pEnd = pData + (lineEnd * linesize);
// Swap the top with the bottom
memcpy(pLineData,pStart,linesize);
memcpy(pStart,pEnd,linesize);
memcpy(pEnd,pLineData,linesize);
// Adjust the line index
linestart++;
lineEnd--;
}
delete pLineData;
// Set the flag to say that the callback function is finished
bCallbacked = TRUE;
return TRUE;
}
此处变量 bmif是BITMAPINFOHEADER ,而 pData是字节 有什么办法可以做到这一点?
解决方法
如果您拥有HBITMAP
句柄,则可以执行以下操作:
图片的尺寸使用:::GetObject(hBmp,sizeof(BITMAP),&bmpSizeInfo);
像这样填充BITMAPINFO
:
memset(&bmpData,sizeof(BITMAPINFO));
bmpData.bmiHeader.biSize = sizeof(bmpData.bmiHeader);
bmpData.bmiHeader.biHeight = -bmpSizeInfo.bmHeight;
bmpData.bmiHeader.biWidth = bmpSizeInfo.bmWidth;
bmpData.bmiHeader.biPlanes = bmpSizeInfo.bmPlanes;
bmpData.bmiHeader.biBitCount = bmpSizeInfo.bmBitsPixel;
创建足够的堆内存来保存位图的数据:
pBuff = new char[bmpSizeInfo.bmWidth * bmpSizeInfo.bmHeight * 4];
获取像这样的位图数据:
::GetDIBits(hDc,hBmp,bmpSizeInfo.bmHeight,(void*)pBuff,&bmpData,DIB_RGB_COLORS);
创建一个D2D1_BITMAP_PROPERTIES
并像这样填充它:
bmpPorp.dpiX = 0.0f;
bmpPorp.dpiY = 0.0f;
bmpPorp.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
bmpPorp.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
使用渲染目标将数据转换为ID2D1Bitmap
pRT->CreateBitmap(bmpSize,pBuff,4 * bmpSizeInfo.bmWidth,bmpPorp,&pBmpFromH);
,
这是如何在Direct2D中使用mag的位图。您不需要BITMAPINFOHEADER,因为mag格式与DXGI_FORMAT_B8G8R8A8_UNORM相同:
BOOL MagImageScaling(HWND hwnd,void* srcdata,MAGIMAGEHEADER srcheader,void* destdata,MAGIMAGEHEADER destheader,RECT unclipped,RECT clipped,HRGN dirty)
{
// note: all this (dc,surface,targte) can be created only once as long as the D3D device isn't reset
ComPtr<ID2D1DeviceContext> dc;
HR(d2Device->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE,dc.GetAddressOf()));
ComPtr<IDXGISurface2> surface;
HR(swapChain->GetBuffer(0,IID_PPV_ARGS(&surface)));
ComPtr<ID2D1Bitmap1> target;
HR(dc->CreateBitmapFromDxgiSurface(surface.Get(),NULL,target.GetAddressOf()));
dc->SetTarget(target.Get());
D2D1_BITMAP_PROPERTIES properties = {};
properties.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
// note: this is ok as srcheader.format (GUID_WICPixelFormat32bppRGBA) is compatible
properties.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
D2D1_SIZE_U size = {};
size.width = srcheader.width;
size.height = srcheader.height;
ComPtr<ID2D1Bitmap> bitmap;
HR(dc->CreateBitmap(size,properties,bitmap.GetAddressOf()));
HR(bitmap->CopyFromMemory(NULL,srcdata,srcheader.stride));
dc->BeginDraw();
// note: we don't call this because we draw on the whole render target
//dc->Clear();
dc->DrawBitmap(bitmap.Get());
HR(dc->EndDraw());
HR(swapChain->Present(1,0));
return TRUE;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。