VCpp透明图片绘制的三种办法

⌚Time: 2023-10-13 01:28:14

👨‍💻Author: Jack Ge

TransparentBlt

TransparentBlt是一个Windows API函数,可在绘图时进行透明处理。它的函数声明如下:


BOOL TransparentBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc, UINT crTransparent);

参数说明如下:

hdcDest:目标设备的句柄

nXDest:目标图像的左上角的x坐标

nYDest:目标图像的左上角的y坐标

nWidth:目标图像的宽度

nHeight:目标图像的高度

hdcSrc:源设备的句柄

nXSrc:源图像的左上角的x坐标

nYSrc:源图像的左上角的y坐标

crTransparent:指定透明颜色值

透明效果是通过指定crTransparent参数来实现的。在目标设备中,所有像素颜色与crTransparent参数指定的颜色相同的像素都不进行绘制,将变成透明的,这使得在绘制透明图像时非常方便。


HDC hdc = GetDC(hwnd); // 获取窗口设备的句柄

HDC hMemDC = CreateCompatibleDC(hdc); // 创建兼容的内存设备上下文

HBITMAP hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_MYBITMAP)); // 加载位图资源

HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap); // 将位图对象选入内存设备上下文



// 调用TransparentBlt进行绘制,RGB(255, 0, 255)为透明颜色

TransparentBlt(hdc, 0, 0, 200, 200, hMemDC, 0, 0, RGB(255, 0, 255));



SelectObject(hMemDC, hOldBitmap); // 恢复上一个位图对象

DeleteObject(hBitmap); // 删除位图对象

DeleteDC(hMemDC); // 删除设备上下文

ReleaseDC(hwnd, hdc); // 释放设备上下文

根据我的经验,绘制的图形最好是BMP这种无损格式的位图,如果是jpg等有损压缩的图片,透明效果不会很好,因为压缩后的图片边缘变成这种模糊的像素颜色,而TransparentBlt只会保留这些模糊的像素颜色

Gdiplus

jpg、bmp格式的图片没有透明度信息,而png有,可以通过gdiplus实现绘制png图片,实现透明效果

GDI+是Windows平台上的一个高级绘图API,支持多种图像文件格式,包括PNG格式。下面是在GDI+中绘制PNG图像的基本步骤:

1.创建Gdiplus::Image对象,并使用图片文件的路径初始化该对象。

2.创建Gdiplus::Graphics对象,并使用绘图设备的句柄初始化该对象。

3.调用Gdiplus::Graphics对象的DrawImage函数,将Gdiplus::Image对象绘制到绘图设备上。

4.释放Gdiplus::Image和Gdiplus::Graphics对象。


#include <windows.h>

#include <gdiplus.h>

#pragma comment (lib,"Gdiplus.lib")

using namespace Gdiplus;



int main()

{

    GdiplusStartupInput gdiplusStartupInput;

    ULONG_PTR gdiplusToken;

    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);



    HDC hdc = ::GetDC(NULL);

    Graphics graphics(hdc);



    Image image(L"path to your png file");

    graphics.DrawImage(&image, 0, 0);



    ::ReleaseDC(NULL, hdc);



    GdiplusShutdown(gdiplusToken);



    return 0;

}


在上面的示例代码中,首先调用GdiplusStartup函数初始化GDI+库,然后创建一个图形设备上下文(Graphics对象),并调用DrawImage函数将PNG图像绘制在屏幕上。最后调用GdiplusShutdown函数释放GDI+库所占用的资源。

需要注意的是,在使用GDI+库之前,需要在代码中包含头文件<gdiplus.h>,并在链接时将gdiplus.lib库文件添加到工程中。

半透明的公式

可以通过获取图像缓冲区像素,直接对像素进行透明和半透明操作

如果是图片a和屏幕b的像素,alpha是指定的透明度,混合后c的颜色RGB公式:


R(c)=(1-alpha)*R(b)+alpha*R(a)

G(c)=(1-alpha)*G(b)+alpha*G(a)

B(c)=(1-alpha)*B(b)+alpha*B(a)

将图片透明方式绘制到屏幕的伪代码如下


//获取透明度混合后的像素颜色

color get_transparent_color(color a,color b,float alpha){

    color c

    R(c)=(1-alpha)*R(b)+alpha*R(a)

    G(c)=(1-alpha)*G(b)+alpha*G(a)

    B(c)=(1-alpha)*B(b)+alpha*B(a)

    return c

}



...



sbuffer = get_screen_buffer();//获取屏幕像素缓冲区

pbuffer = get_image_buffer();//获取图片像素指针

mbuffer = new color[sbuffer .size()];//混合后的像素空间

for(int i=0; i< sbuffer.sie();i++){//对于每个像素计算透明度混合后的颜色

    mbuffer[i] = get_transparent_color(sbuffer[i],pbuffer[i],0.5);//透明度0.5

}

draw(mbuffer);//画透明混合后的图像

delete mbuffer[];