首页 > 其他分享 >详解用BitBlt实现透明贴图

详解用BitBlt实现透明贴图

时间:2022-12-04 19:13:15浏览次数:64  
标签:贴图 nHeightDest image nWidthDest 详解 hdc BitBlt 255

效果:

代码:

struct BitmapInDC {
  HDC m_hdc;
  HBITMAP m_hbmp;
  HGDIOBJ m_hbmpOld;
  BitmapInDC(HDC hdc, HBITMAP bmp) {
    m_hdc = CreateCompatibleDC(hdc);
    m_hbmp = bmp;
    m_hbmpOld = SelectObject(m_hdc, m_hbmp);
  }
  ~BitmapInDC() {
    SelectObject(m_hdc, m_hbmpOld);
    DeleteObject(m_hbmp);
    DeleteDC(m_hdc);
  }
  operator HDC () { return m_hdc; }
};

void TransparentBlt2(HDC hdc, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest,
    HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, UINT crTransparent) {

  BitmapInDC  image(hdc, CreateCompatibleBitmap(hdc, nWidthDest, nHeightDest));
  
  // HBITMAP CreateBitmap(nWidth, nHeight, nPlanes, nBitCount, lpBits);
  BitmapInDC  mask(hdc, CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL));

  // 把hdcSrc中的图片复制到到image
  if (nWidthDest == nWidthSrc && nHeightDest == nHeightSrc) {
    BitBlt(image, 0, 0, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, SRCCOPY);
  } else {
    StretchBlt(image, 0, 0, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, SRCCOPY);
  }
  
  // 单色位图每个像素都是0或1。
  // DWORD real_color[2] = { BkColor, TextColor };
  // i = (color == BkColor ? 1 : 0);

  // 把image复制到mask. The transparent region as white (all 1), the non-transparent area Black (all 0).
  SetBkColor(image, crTransparent);
  BitBlt(mask, 0, 0, nWidthDest, nHeightDest, image, 0, 0, SRCCOPY);

  // This way, the background color (black) area of the mask bitmap is reserved in, and the foreground color (white)
  // part becomes black.
  SetBkColor(image, RGB(0,0,0)); SetTextColor(image, RGB(255,255,255));
  BitBlt(image, 0, 0, nWidthDest, nHeightDest, mask, 0, 0, SRCAND);

  // SRCAND后,背景不变,主体成为黑洞
  SetBkColor(hdc, RGB(255,255,255)); SetTextColor(hdc, RGB(0,0,0));
  BitBlt(hdc, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, mask, 0, 0, SRCAND); 

  // SRCPAINT combines the colors of the source and destination rectangles by using the Boolean OR operator.
  BitBlt(hdc, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, image, 0, 0, SRCPAINT);
}
View Code

如果一张图片只有两种颜色,那么每个像素都可以用1个bit表示。这是bitmap这个名字的来历。早期内存非常贵,有图就不错了。这种二值图像,可以把0显示为黑色RGB(0, 0, 0),1显示为白色RGB(255, 255, 255),也可以0显示为RGB(0, 255, 0)等等。即先用0或1查颜色表(或者叫palette)。颜色“丰富”的图片,可以每个像素用4位表示,能显示16种颜色,具体啥颜色还是查表。到了24位,就可以不用查表了,RGB各用8位表示。

灰度图像与二值图像不同。灰度图像可以有各种亮度的灰色,与“五彩斑斓的黑”不同,这个没毛病。

BitBlt是Bit Block Transfer的缩写,就是把一个矩形内的图片数据复制到另外一个矩形。我有破电脑后遗症,倾向于苦思冥想如何优化,其实BitBlt的软件实现可能就是for循环里赋值和if. 高速一点点是memcpy,which用rep movsb (repeat move string byte), 最快还是硬件,这个虽然我不会,但对会者来说很简单。

DC是device context(设备上下文)的缩写。设备就是显卡。VGA是640x480, 每个像素16种颜色,如何把一张8位颜色深度(color depth)的图片显示出来?24位的呢?这个我懒得想,只知道CreateBitmap和CreateCompatibleBitmap()都返回HBITMAP, 后者和DC兼容(格式一样),BitBlt时不用转换,速度快。H代表Handle.

这个洋网站引用的是CSDN,哈哈。

CreateBitmap function (wingdi.h) - Win32 apps | Microsoft Learn说:The CreateBitmap function creates a device-dependent bitmap. After a bitmap is created, it can be selected into a device context by calling the SelectObject function. However, the bitmap can only be selected into a device context if the bitmap and the DC have the same format. [CreateBitmp()根本就没有HDC这个参数,咋个device-dependent?]

CreateCompatibleBitmap function (wingdi.h) - Win32 apps | Microsoft Learn说:The CreateCompatibleBitmap function creates a bitmap compatible with the device that is associated with the specified device context. [这个有HDC参数。]

还有BitBlt的参数,有了SRCAND,再有SRCOR天经地义,结果来了个SRCPAINT不知所云。

如何查看颜色的RGB值?啥软件都没有的话,可以用系统自带的画图。用吸管工具在点上点一下,再点“编辑颜色”。

标签:贴图,nHeightDest,image,nWidthDest,详解,hdc,BitBlt,255
From: https://www.cnblogs.com/funwithwords/p/16950431.html

相关文章

  • 9.【C语言详解】指针
    指针是什么指针是什么?指针理解的2个要点:指针是内存中一个最小单元的编号,也就是地址;平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量;指针就是地址,......
  • 10.【C语言详解】结构体
    结构体的声明什么是结构结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。结构体的声明structtag{ member-list;}variable-list;......
  • Java中的BigDecimal比较大于小于等于,四舍五入保留几位(setScale方法详解),加减乘除取余
    本文主要讲解BigDecimal的比较运算,保留精度和取整和基础运算,BigDecimal与其他数据类型转换。比较运算比较num1是否大于num2publicstaticbooleangt(@NotNullBigD......
  • MySQL进阶实战8,分区表详解
    一、分区表分区表是一个独立的逻辑表,底层是由多个物理子表组成。实现分区的代码实际上是对一组底层表的句柄对象的封装。对分区表的请求,都会通过句柄对象转化成对存储引擎的......
  • CountDownLatch详解以及用法示例
    一、什么是countDownlatchCountDownLatch是一个同步工具类,它通过一个计数器来实现的,初始值为线程的数量。每当一个线程完成了自己的任务,计数器的值就相应得减1。当计数器......
  • 详解cycleGAN(生成对抗网络)代码
    文章目录​​1.cycleGAN简介​​​​2.cycle代码详解​​​​main.py​​​​module.py​​​​model.py​​​​总结​​1.cycleGAN简介关于cGAN我主要参考了知乎量子位的......
  • 详解支持向量机-SVC真实数据案例:预测明天是否会下雨-处理困难特征:地点【菜菜的sklearn
    视频作者:菜菜TsaiTsai链接:【技术干货】菜菜的机器学习sklearn【全85集】Python进阶_哔哩哔哩_bilibili常识上来说,我们认为地点肯定是对明天是否会下雨存在影响的。比如......
  • Day30:ArrayList详解
    ArrayList1.1集合概述当我们要存储多个数据时,固定长度的数组存储格式已经满足不了我们的需要了,且不能满足变化的需求;Java中集合类则可以解决我们的需求特点:提供一种存......
  • Spring MVC请求地址映射详解:HandlerMapping
    1HandlerMapping介绍HandlerMapping是SpringMVC的核心组件之一,用来保存request-handler之间的映射。简单来说,request指的是请求地址(还包括请求方法等),handler指的是Cont......
  • Nginx map 使用详解
    map指令介绍:map指令是由ngx_http_map_module模块提供的,默认情况下安装nginx都会安装该模块。map的主要作用是创建自定义变量,通过使用nginx的内置变量,去匹配某......