EasyX绘制透明背景图的方法详解

目录
  • 三元光栅操作
  • 优化方案

三元光栅操作

根据在网上的搜索总结得到两种方案,最常见的绘制带有透明背景的图像的方案都是采用如下的源图像和掩码图像叠加来消去边缘部分:

IMAGE img[2];

loadimage(&img[0], "sun1.png", 100, 100); // 掩码图像
loadimage(&img[1], "sun0.png", 100, 100); // 源图像

putimage(0, 0, &img[0], NOTSRCERASE);   // 掩码图与背景或取反
putimage(0, 0, &img[1], SRCINVERT);     // 源图像与背景异或

直观理解:由于按位运算是依次对某一位做运算,因此只需要考察一位数字的变化

// 不妨假设白色为 1,黑色为 0

// 需要变成透明的部分,需要显示最初的背景色
// 背景色为 a,~a 表示反 a,掩码此部分是黑色 0,源图像此部分是白色 1
~ (a | 0); //-> ~a 或取反
(~a) ^ 1; //-> a 异或
// 结果仍为背景色

// 需要显示源图像的部分
// 背景色为 a,源图像此部分为 b,掩码此部分是白色 1
~ (a | 1); //-> 0 或取反(可以看到第一部分与 a 无关)
0 ^ b; //-> b 异或
// 结果为源图像

然而,上面的方案虽然足够解决问题,但是未免太过繁琐,不仅需要源图像,还需要花时间来制作掩码图。最糟糕的就是技术问题导致掩码图和原图不能完全重合,绘制出的图像有黑边。

于是,经过长期搜索,终于找到一种不需要掩码图,而是直接对图像进行处理的方案。

优化方案

此方案使用了贝叶斯定理来对图像的每个像素进行计算,原版代码的具体来源因为时间比较久,已经找不到了。这里的方案和原版本有所不同,因为实际需求,我根据原版本添加了透明度参数 AA ,并且修改了部分代码使得它与我的需求相契合。

函数声明为:

void drawAlpha(
    IMAGE* image, 			// 图像指针
    int x, int y, 			// 输出坐标
    int width, int height, 	 // 输出尺寸
    int pic_x, int pic_y, 	 // 图像中的位置
    double AA = 1			// 透明度
);

也就是说它会在 x,y 位置输出从图像中 pic_x,pic_y 位置开始,宽高为 width,height 的部分,且透明度为 AA 。

函数定义部分:

// 绘图函数,补充透明度 AA
void drawAlpha(IMAGE* image, int x, int y, int width, int height, int pic_x, int pic_y, double AA = 1)
{
	// 变量初始化
	DWORD* dst = GetImageBuffer();			// GetImageBuffer() 函数,用于获取绘图设备的显存指针, EasyX 自带
	DWORD* draw = GetImageBuffer();
	DWORD* src = GetImageBuffer(image);		// 获取 picture 的显存指针
	int imageWidth = image->getwidth();		// 获取图片宽度
	int imageHeight = image->getheight();	// 获取图片宽度
	int dstX = 0;							// 在 绘图区域 显存里像素的角标
	int srcX = 0;							// 在 image 显存里像素的角标

	// 实现透明贴图 公式: Cp=αp*FP+(1-αp)*BP , 贝叶斯定理来进行点颜色的概率计算
	for (int iy = 0; iy < height; iy++)
	{
		for (int ix = 0; ix < width; ix++)
		{
			// 防止越界
			if (ix + pic_x >= 0 && ix + pic_x < imageWidth && iy + pic_y >= 0 && iy + pic_y < imageHeight &&
				ix + x >= 0 && ix + x < WindowWidth && iy + y >= 0 && iy + y < WindowHeight)
			{
				// 获取像素角标
				int srcX = (ix + pic_x) + (iy + pic_y) * imageWidth;
				dstX = (ix + x) + (iy + y) * WindowWidth;

				int sa = ((src[srcX] & 0xff000000) >> 24) * AA;			// 0xAArrggbb; AA 是透明度
				int sr = ((src[srcX] & 0xff0000) >> 16);				// 获取 RGB 里的 R
				int sg = ((src[srcX] & 0xff00) >> 8);					// G
				int sb = src[srcX] & 0xff;								// B

				// 设置对应的绘图区域像素信息
				int dr = ((dst[dstX] & 0xff0000) >> 16);
				int dg = ((dst[dstX] & 0xff00) >> 8);
				int db = dst[dstX] & 0xff;
				draw[dstX] = ((sr * sa / 255 + dr * (255 - sa) / 255) << 16)  //公式: Cp=αp*FP+(1-αp)*BP  ; αp=sa/255 , FP=sr , BP=dr
					| ((sg * sa / 255 + dg * (255 - sa) / 255) << 8)         //αp=sa/255 , FP=sg , BP=dg
					| (sb * sa / 255 + db * (255 - sa) / 255);              //αp=sa/255 , FP=sb , BP=db
			}
		}
	}
}

注意其中 WindowWidth 和 WindowHeight 都是预先定义的全局变量。实际应用时,先在头文件中定义窗口尺寸,然后就可以直接使用

IMAGE img;
loadimage(&img, "sun.png", 100, 100);

int x = 100, y = 100;
int width = 50, height = 50;
int pic_x = 50, pic_y = 50;

drawAlpha(img, x, y, width, height, pic_x, pic_y, 0.8);

还可以调整透明度为 0.8 ,比方案 1 更为实用。

到此这篇关于EasyX绘制透明背景图的方法详解的文章就介绍到这了,更多相关EasyX绘制透明背景图内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++ EasyX学习之鼠标操作详解

    目录 基础代码 进阶编程 基础代码 功能:移动画点,左键画方块,右键退出. #include <graphics.h> #include <conio.h> int main() { // 初始化图形窗口 initgraph(640, 480); MOUSEMSG m; // 定义鼠标消息 while (true) { ExMessage m;//定义一个消息变量 m = getmessage(EM_MOUSE);//获取鼠标消息 switch (m.message) { case

  • C++使用easyx画实时走动的钟表

    这次的任务是用c++画出实时走动的钟表,并且与当前系统的时间一致. 由于我们使用的是c++语言,我们更需要用这个例子来提高我们对面向对象程序设计的理解. 我们首先需要分析出需求,“画一个能够实时走动的钟表”,根据需求我们可以好处两个对象,钟表对象与画图对象,所以我们大致先建立两个类,Clock类与Paint类. Clock类中的成员变量都有:表的中心坐标x与y.表的时间(时.分.秒).表的大小r(即半径).表盘的颜色color. Clock类中无其他函数,只有用于初始化的构造函数. Paint类

  • Easyx实现扫雷游戏

    本文实例为大家分享了Easyx实现扫雷游戏的具体代码,供大家参考,具体内容如下 代码: #include<stdio.h> #include<stdlib.h> #include<time.h> #include<easyx.h>   #include<mmsystem.h> #pragma comment(lib, "winmm.lib")   #define ROW 10    //定义行列的常量 #define COL 

  • C语言用Easyx绘制围棋和象棋的棋盘

    本文实例为大家分享了C语言绘制围棋和象棋棋盘的具体代码,供大家参考,具体内容如下 一.绘制围棋棋盘 代码如下: #include<graphics.h> #include<conio.h> int main() {     int step=30;     //初始化绘图窗口     initgraph(600,600);     //设置背景色为黄色     setbkcolor(YELLOW);     //用背景色清空屏幕     cleardevice();     set

  • EasyX绘制透明背景图的方法详解

    目录 三元光栅操作 优化方案 三元光栅操作 根据在网上的搜索总结得到两种方案,最常见的绘制带有透明背景的图像的方案都是采用如下的源图像和掩码图像叠加来消去边缘部分: IMAGE img[2]; loadimage(&img[0], "sun1.png", 100, 100); // 掩码图像 loadimage(&img[1], "sun0.png", 100, 100); // 源图像 putimage(0, 0, &img[0], NOT

  • Matlab绘制雨云图的方法详解

    目录 介绍 横向雨云图 纵向雨云图 介绍 写了俩代码模板,用来绘制横向云雨图与纵向云雨图,云雨图其实就是用把小提琴图拆开来的模板,想获取小提琴图绘制函数的可以看这里:基于Matlab绘制小提琴图的示例代码 后面的俩模板用的时候只需要换换数据,颜色及每一类名称即可,雨云图绘制效果如下: 横向雨云图 function rainCloudsTMPL1 % @author: slandarer % 在这里放入你的数据============================================

  • Python实现在Excel中绘制可视化大屏的方法详解

    目录 数据清洗 绘制图表 生成可视化大屏 大家新年好哇,今天小编来给大家分享如何在Excel文档当中来绘制可视化图表,并且制作一个可视化大屏,非常的容易,这里我们会用到openpyxl模块,那么首先第一步便是调用该模块来读取Excel文件,代码如下 # 读取Excel文档并且指定工作表的名称 file_name = 'Bike_Sales_Playground.xlsx' df = pd.read_excel(file_name,sheet_name='bike_buyers') 当然为了保险起

  • 利用Pytorch实现获取特征图的方法详解

    目录 简单加载官方预训练模型 图片预处理 提取单个特征图 提取多个特征图 简单加载官方预训练模型 torchvision.models预定义了很多公开的模型结构 如果pretrained参数设置为False,那么仅仅设定模型结构:如果设置为True,那么会启动一个下载流程,下载预训练参数 如果只想调用模型,不想训练,那么设置model.eval()和model.requires_grad_(False) 想查看模型参数可以使用modules和named_modules,其中named_modul

  • D3.js实现折线图的方法详解

    前言 D3.js是一个帮助开发者操纵基于数据的文档的JavaScript类库,在<D3.js实现柱状图的方法详解>中已经给大家介绍过如何用D3.js来实现一个简单的柱状图了,今天我们来学习用D3.js来实现折线图,感兴趣的朋友们下面来一起看看吧. 折线图由坐标轴.线条和点组成.和实现柱状图一样,我们还是先把大概的画图框架搭起来,代码如下(别忘了添加D3.js): <!DOCTYPE html> <html lang="en"> <head>

  • 209个透明flash背景以及使用方法详解

    我们平时做站的时候偶尔会用到一些比较炫的透明flash去修饰页面,但如果你自己并没有那么高深的flash技术可以随意创造心中所想的效果时,那么这些flash透明和背景或许能帮到你,其中有一些是很漂亮的! 下载地址 透明flash多用户修饰图片,将一个图片作为背景,然后出入flash可以让静态图片具有动态效果,非常好的透明flash素材,一共几百款透明flash下载. 透明flash的使用方法: 透明flash多用户修饰图片,将一个图片作为背景,然后出入flash可以让静态图片具有动态效果. 1

  • Android开发自定义控件之折线图实现方法详解

    本文实例讲述了Android开发自定义控件之折线图实现方法.分享给大家供大家参考,具体如下: 前言 折线图是Android开发中经常会碰到的效果,但由于涉及自定义View的知识,对许多刚入门的小白来说会觉得很高深.其实不然,接下来我就以尽量通俗的语言来说明下图折线图效果的实现过程. 效果图 实现过程 首先,选择自定义控件的方式. 自定义控件的实现有四种方式: 1.继承View,重写onDraw.onMeasure等方法. 2.继承已有的View(比如TextView). 3.继承ViewGrou

  • PHP使用JPGRAPH制作圆柱图的方法详解

    本文实例讲述了PHP使用JPGRAPH制作圆柱图的方法.分享给大家供大家参考,具体如下: 制作圆柱图像的要点 首先,要使用jpgraph库,我们先要去官网进行下载,网址:https://jpgraph.net/. 下载完毕后将他解压到 这个文件夹需要自己手动添加,然后在相同的路径下创建一个文件 命名为jpgraph.php 函数名 作用 new Graph 创建一个新的Graph对象 jpgraph_bar.php 加载画出圆柱的文件 jpgraph.php 加载使用jp库的文件 SetScal

  • jQuery动态移除和添加背景图片的方法详解

    本文实例讲述了jQuery动态移除和添加背景图片的方法.分享给大家供大家参考,具体如下: 利用jQuery移除和添加图片 1.样式 <style type="text/css"> .changeImage{ background:url(images/right.png) no-repeat center; } </style> 2.JS (1)在改变标签的样式,需要移除之前添加的样式 $("#tab tr").find("td&q

  • C#实现绘制面形图表的方法详解

    本例详细讲述了C#实现的面形图绘制例子,这是其中一个核心绘制文件的代码,代码中的里面的注释很多,也比较详细,相信对于初学者学习及理解C#图形绘制方面的技术要点.难点有所帮助. C#绘制面形图的主要功能代码如下: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using S

随机推荐