将是“BlendDIBitsToDevice”:用透明度进行blitting [英] Would be "BlendDIBitsToDevice": blitting with transparency

查看:82
本文介绍了将是“BlendDIBitsToDevice”:用透明度进行blitting的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用来通过 SetDIBitsToDevice (真实大小)或 StretchDIBits (带缩放)。



这些函数将像素数据从内存缓冲区直接移动到屏幕。 [此操作与从一个DC(设备上下文)复制到另一个DC或从DDB(设备相关位图)复制到另一个DC不同。]



到目前为止超好的。适用于我正在使用的图像深度( biBitCount = 8,24或32)。



现在我想要进行局部绘图,就好像图像的某些部分是透明的一样。换句话说,将alpha值附加到每个像素。我可以用二进制值(完全不透明或完全透明)来满足自己,但是普通的alpha也很好。



我可以选择从屏幕读取背景像素自己做混合,但这个解决方案看起来并不吸引我,因为它涉及昂贵的读取,加上需要转换为24位,因为窗口的背景是彩色的。



所以我正在寻找有效的方法来实现这种效果。我希望找到 BlendDIBitsToDevice StretchBlendDIBits 条目或者类似的东西,但似乎我需要卷起袖子。 />


有什么建议吗?

I use to draw device-independent bitmaps (DIBs) to the screen by means of either SetDIBitsToDevice (true size) or StretchDIBits (with zoom).

These functions move pixel data from a memory buffer directly to screen. [This operation is not the same as copying from one DC (Device Context) to another DC nor from a DDB (Device Dependent Bitmap) to another.]

So far so good. Works well with the image depths I am using (biBitCount = 8, 24 or 32).

Now I want to do partial drawing, as if parts of the image were transparent. In other words, attach an alpha value to every pixel. I can satisfy myself with binary values (fully opaque or fully transparent), but plain alpha is good too.

I have the option of reading the background pixels from screen and doing the blend myself, but this solution doesn't look attractive to me, because it involves costly reads, plus the need to convert to 24 bits because the background of a Window is in color.

So I am looking for efficient ways to achieve this effect. I expected to find BlendDIBitsToDevice or StretchBlendDIBits entries or similar, but it seems I need to roll up my sleeves.

Any suggestion ?

推荐答案

解决方法是使用 AlphaBlend 功能。后者需要两件事:一方面是源设备上下文,另一方面是源位图,必须选择它(不要问我原因)。



设备上下文创建为与显示DC兼容的内存DC。它是通过 CreateCompatibleDC 获得的。



位图生成为所谓的DIB部分,通过 CreateDIBSection



最后但并非最不重要的是,你必须知道需要预乘Alpha,这意味着所有三个红色在blitting之前,绿色,蓝色组件必须乘以Alpha(和缩放)。这是一个片段。

The solution is to use the AlphaBlend function. The latter requires two things: on one hand a source device context, and on the other hand a source bitmap, which must be selected into it (don't ask me why).

The device context is created as a memory DC which is compatible with the display DC. It is obtained by means of CreateCompatibleDC.

The bitmap is generated as a so called DIB Section, via CreateDIBSection.

Last but not least, you have to know that premultiplied Alpha is required, meaning that all three Red, Green, Blue components must be multiplied by Alpha (and scaled) before blitting. Here is a snippet.
// Initialize the bitmap info structure
struct tagBITMAPINFO
{
    BITMAPV4HEADER bmiHeader;
    RGBQUAD bmiColors[256];
} BufferInfo;

BufferInfo.bmiHeader.bV4Size= sizeof(BITMAPV4HEADER);
BufferInfo.bmiHeader.bV4Width= Width;
BufferInfo.bmiHeader.bV4Height= Height;
BufferInfo.bmiHeader.bV4Planes= 1;
BufferInfo.bmiHeader.bV4BitCount= 32;
BufferInfo.bmiHeader.bV4V4Compression= BI_BITFIELDS;
BufferInfo.bmiHeader.bV4SizeImage= 0;
BufferInfo.bmiHeader.bV4ClrUsed= 0;
BufferInfo.bmiHeader.bV4ClrImportant= 0;
BufferInfo.bmiHeader.bV4AlphaMask= 0xff000000;
BufferInfo.bmiHeader.bV4RedMask=   0x00ff0000;
BufferInfo.bmiHeader.bV4GreenMask= 0x0000ff00;
BufferInfo.bmiHeader.bV4BlueMask=  0x000000ff;
BufferInfo.bmiHeader.bV4CSType= 0;

// Create a compatible device context
HDC hMemoryDC= CreateCompatibleDC(hDC);

// Create a DIB section and select it
byte* Section;
HBITMAP hBitMap = CreateDIBSection(MemoryDC, (BITMAPINFO*)&BufferInfo, DIB_RGB_COLORS, (void**)&Section, NULL, 0x0);
HGDIOBJ Save= SelectObject(hMemoryDC, hBitMap);

// Premultiply by alpha
for (int y= 0; y < Height; y++)
{
    for (int x= 0; x < Width; x++)
    {
        RgbaPixel P= *(RgbaPixel*)&SrcBuffer[y * SrcPitch + 4 * x];
        int Q= P.Alpha * 33025; // 2^31 / 255^2
        P.Red=   (P.Red   * Q) >> 23;
        P.Green= (P.Green * Q) >> 23;
        P.Blue=  (P.Blue  * Q) >> 23;
        *(RgbaPixel*)&Section[y * SrcPitch + 4 * x]= P;
    }
}

// Blending function (required by AlphaBlend)
BLENDFUNCTION Blend;
Blend.BlendOp = AC_SRC_OVER;
Blend.BlendFlags = 0;
Blend.AlphaFormat = AC_SRC_ALPHA;
Blend.SourceConstantAlpha = 0xff;

// Blit with blending
AlphaBlend(
    hDC, 0, 0, (int)(Width * Zoom), (int)(Height * Zoom),
    hMemoryDC, 0, 0, Width, Height,
    Blend);

SelectObject(hMemoryDC, Save);
DeleteObject(hBitMap);
DeleteObject(hMemoryDC);


这篇关于将是“BlendDIBitsToDevice”:用透明度进行blitting的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆