微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用Direct2D从BITMAPINFOHEADER和BYTE渲染位图

如何解决如何使用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 举报,一经查实,本站将立刻删除。