首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >混合2位图

混合2位图
EN

Stack Overflow用户
提问于 2016-01-01 21:08:50
回答 1查看 359关注 0票数 1

我有两个缓冲器指向不同大小的RGB32图像,所以我的想法是缩放一个缓冲区以匹配另一个缓冲区,并将这些图像进行字母混合。

目前,我能够将StretchBlt (用于缩放性能)和GDI+绘图图像函数与用于字母混合的colormatrix混合。这似乎有点慢,而且使用DirectX的其他组件使用缓冲区也有问题。对于缓冲区问题,我试图以相反的顺序复制行,除了在DirectX相关组件中,它可以工作。

代码语言:javascript
复制
Bitmap bmp1(width, height, 4bytesperpixel, RGB32, bufferpointer1);
Bitmap blend(width, height, 4bytesperpixel);
Graphics g(&newbmp)

using GDI function
Bitmap bmp2(scaleWidth, scaleHeight, 4bytesperpixel, RGB32, bufferpointer2)
HDC memdc = g.GetHDC();

////  scaling the bufferpointer2 to actual width & height
StretchDIBits(memdc, x,y, width, height, 0, 0,scaleWidth, scaleHeight, bufferpointer2,..)
g.ReleaseDC(memdc); // so that content is copied to the bitmap

//// Then alphablending bmp1 on top of the scaled imaged bmp2
//// Using lockbits to copy the bitmap bytes and unlocking it.

因此,我需要替换GDI+函数,并为此使用类似于AlphaBlend的Win32函数。我试过这样的方法,它显示了一个黑色的屏幕

代码语言:javascript
复制
    BITMAPINFO bminfo1 = {};
    bminfo1.bmiHeader.biSize = sizeof( BITMAPINFO );
    bminfo1.bmiHeader.biWidth = w;
    bminfo1.bmiHeader.biHeight = h;
    bminfo1.bmiHeader.biBitCount = m_nBytesPerPixel * 8;
    bminfo1.bmiHeader.biCompression = BI_RGB;
    bminfo1.bmiHeader.biPlanes = 1;

    BITMAPINFO bminfo2 = {};
    bminfo2.bmiHeader.biSize = sizeof( BITMAPINFO );
    bminfo2.bmiHeader.biWidth = sW;
    bminfo2.bmiHeader.biHeight = sH;
    bminfo2.bmiHeader.biBitCount = m_nBytesPerPixel * 8;
    bminfo2.bmiHeader.biCompression = BI_RGB;
    bminfo2.bmiHeader.biPlanes = 1;

    char* pBytes1, *pBytes2;

    HDC hmemdc1 = CreateCompatibleDC(GetDC(0));
    HDC hmemdc2 = CreateCompatibleDC(GetDC(0));

    HBITMAP hBitmap1 = CreateDIBSection(hmemdc1, &bminfo1, DIB_RGB_COLORS, (void**) &pBytes1, NULL, 0);
    SetDIBits(hmemdc1, hBitmap1, 0, bminfo1.bmiHeader.bih, pBuffer[0], &bminfo1, DIB_RGB_COLORS);

    HBITMAP hBitmap2 = CreateDIBSection(hmemdc2, &bminfo2, DIB_RGB_COLORS, (void**) &pBytes2, NULL, 0);
    SelectObject(hmemdc2,hBitmap2);
    StretchDIBits(hmemdc2, 0, 0, w, h, 0, 0,
        sW, sH, pBuffer[1], &bminfo2, DIB_RGB_COLORS, SRCCOPY );

    BLENDFUNCTION bStruct; 
    bStruct.BlendOp = AC_SRC_OVER;
    bStruct.BlendFlags = 0;
    bStruct.SourceConstantAlpha = 255;
    bStruct.AlphaFormat = AC_SRC_ALPHA;

    SelectObject(hmemdc1,hBitmap1);
    SelectObject(hmemdc2,hBitmap2);

    //blend bmp2 on bmp1
    BOOL res = AlphaBlend(hmemdc1, 0, 0, w, h, hmemdc2, 0, 0, w, h, bStruct);

    //for testing output
    SelectObject(hmemdc1,hBitmap1);
    BitBlt(GetDC(0),0,0,width,height,hmemdc1,100,100,SRCCOPY);


    //copy the bitmap buffer
    memcpy(out, pBytes1, (w * m_nBytesPerPixel) * h);

我不确定是否可以使用AlphaBlend功能来混合基于2个内存DC的每像素位图。任何帮助都将不胜感激。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-01-02 01:49:19

这部分是错误的:

代码语言:javascript
复制
bminfo1.bmiHeader.biSize = sizeof( BITMAPINFO );

它应该是sizeof(BITMAPINFOHEADER),否则它会破坏一切。此外,您也不能使用GetDC(0)进行任何适当的绘画。改为使用:

代码语言:javascript
复制
HDC hdc = GetDC(hwnd);
...
ReleaseDC(hwnd, hdc);

或者使用来自BeginPaintBeginPaint。由于您使用的是GDI+,所以必须有来自bmp->GetHBITMAP()HBITMAP句柄,因此没有理由将其转换为内存并返回到HBITMAP

对于AlphaBlend集,在没有设置alpha通道的情况下,SourceConstantAlpha = 128;

代码语言:javascript
复制
void blend(HDC hdc, RECT rc, HBITMAP hbitmap1, HBITMAP hbitmap2)
{
    HDC memdc1 = CreateCompatibleDC(hdc);
    HDC memdc2 = CreateCompatibleDC(hdc);

    BITMAP bmp1, bmp2;
    GetObject(hbitmap1, sizeof(BITMAP), &bmp1);
    GetObject(hbitmap2, sizeof(BITMAP), &bmp2);

    SelectObject(memdc1, hbitmap1);
    SelectObject(memdc2, hbitmap2);

    BLENDFUNCTION blend = { 0 };
    blend.SourceConstantAlpha = 128;

    SetStretchBltMode(hdc, COLORONCOLOR);
    AlphaBlend(memdc2, 0, 0, bmp2.bmWidth, bmp2.bmHeight, memdc1, 0, 0, bmp1.bmWidth, bmp1.bmHeight, blend);
    StretchBlt(hdc, 0, 0, rc.right, rc.bottom, memdc2, 0, 0, bmp2.bmWidth, bmp2.bmHeight, SRCCOPY);

    //or create another memdc to get dibs

    DeleteDC(memdc1);
    DeleteDC(memdc2);
}

如果您想获得dib,那么不要使用hdc,而是创建第三个memdc和另一个HBITMAP,然后使用GetDIBits

代码语言:javascript
复制
HDC memdc = CreateCompatibleDC(hdc);
HBITMAP hbmp = CreateCompatibleBitmap(hdc, rc.right, rc.bottom);
SelectObject(memdc, hbmp);
SetStretchBltMode(memdc, COLORONCOLOR);
StretchBlt(memdc, 0, 0, rc.right, rc.bottom, 
    memdc2, 0, 0, bmp2.bmWidth, bmp2.bmHeight, SRCCOPY);

int w = rc.right;
int h = rc.bottom;
BITMAPINFOHEADER bmpInfoHeader = { sizeof(BITMAPINFOHEADER) };
bmpInfoHeader.biWidth = w;
bmpInfoHeader.biHeight = h;
bmpInfoHeader.biBitCount = 32;
bmpInfoHeader.biCompression = BI_RGB;
bmpInfoHeader.biPlanes = 1;

DWORD size = w * 4 * h;
char *dib = new char[size];
GetDIBits(hdc, hbmp, 0, h, dib, (BITMAPINFO*)&bmpInfoHeader, DIB_RGB_COLORS);
...
DeleteDC(memdc);
DeleteObject(hbitmap);
delete[]dib;

编辑

方法2:这个方法应该更快,因为它使用一个StretchBlt和一个AlphaBlend。通过这种方式,您可以使用预先计算的alphas,尽管它不是必要的。

只有当您想要将两个图像与背景混合时,才使用2 AlphaBlend的另一种方法。

代码语言:javascript
复制
void modify_bits(HDC hdc, HBITMAP hbitmap) 
{   //expecting 32-bit bitmap
    BITMAP bm = { 0 };
    GetObject(hbitmap, sizeof(bm), &bm);
    int w = bm.bmWidth;
    int h = bm.bmHeight;
    BITMAPINFOHEADER bmpInfoHeader = { sizeof(BITMAPINFOHEADER),
        w, h, 1, 32, BI_RGB, 0, 0, 0, 0, 0 };
    BYTE* bits = new BYTE[w * h * 4];
    if (GetDIBits(hdc, hbitmap, 0, h, bits, (BITMAPINFO*)&bmpInfoHeader, DIB_RGB_COLORS)) {
        BYTE* p = bits;
        for (int x = 0; x < w; x++) {
            for (int y = 0; y < h; y++) {
                p[3] = 128;
                p[0] = p[0] * p[3] / 255;
                p[1] = p[1] * p[3] / 255;
                p[2] = p[2] * p[3] / 255;
                p += 4;
            }
        }
        SetDIBits(hdc, hbitmap, 0, h, bits, (BITMAPINFO*)&bmpInfoHeader, DIB_RGB_COLORS);
    }
    delete[] bits;
}

void blend2(HDC hdc, RECT rc, HBITMAP hbitmap1, HBITMAP hbitmap2)
{
    int w = rc.right;
    int h = rc.bottom;

    modify_bits(hdc, hbitmap2);

    HDC memdc1 = CreateCompatibleDC(hdc);
    HDC memdc2 = CreateCompatibleDC(hdc);

    BITMAP bmp1, bmp2;
    GetObject(hbitmap1, sizeof(BITMAP), &bmp1);
    GetObject(hbitmap2, sizeof(BITMAP), &bmp2);
    int w1 = bmp1.bmWidth;
    int h1 = bmp1.bmHeight;
    int w2 = bmp2.bmWidth;
    int h2 = bmp2.bmHeight;

    SelectObject(memdc1, hbitmap1);
    SelectObject(memdc2, hbitmap2);

    BLENDFUNCTION blend = { 0 };
    blend.BlendOp = AC_SRC_OVER;
    blend.BlendFlags = 0;
    blend.SourceConstantAlpha = 255;
    blend.AlphaFormat = AC_SRC_ALPHA;

    SetStretchBltMode(hdc, COLORONCOLOR);

    //draw first image normally:
    StretchBlt(hdc, 0, 0, w, h, memdc1, 0, 0, w1, h1, SRCCOPY);

    //AlphaBlend the second image:
    AlphaBlend(hdc, 0, 0, w, h, memdc2, 0, 0, w2, h2, blend);

    DeleteDC(memdc1);
    DeleteDC(memdc2);
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34560068

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档