EGE专栏:EGE专栏
抗锯齿
抗锯齿(英语:anti-aliasing,简称AA),也译为边缘柔化、消除混叠、抗图像折叠有损等。它是一种消除显示器输出的画面中图物边缘出现凹凸锯齿的技术,那些凹凸的锯齿通常因为高分辨率的信号以低分辨率表示或无法准确运算出3D图形坐标定位时所导致的图形混叠 (aliasing) 而产生的,反锯齿技术能有效地解决这些问题。它通常被用在在数字信号处理、数字摄影、电脑绘图与数码音效及电子游戏等方面,柔化被混叠的数字信号。
在EGE中,有些是高级绘图函数,这些函数绘图时是可以带抗锯齿效果 的, 而且可以绘制不同透明度的图形。 这些函数一般是以 ege 作为前缀,如 ege_fillrect, ege_line 等。
左边是普通绘图函数绘制的圆,右边是高级绘图函数绘制的圆,细看可以看到,普通绘图函数绘制的圆边缘带有锯齿, 而用高级绘图函数绘制的圆边缘较为光滑。
下面是直线的比较,上面是用普通函数绘制的直线,下面是用高级函数绘制的带抗锯齿的直线。区别很明显。
下面是高级绘图函数绘制出的两个带有透明度的圆。可以看到,图形是透明的,可以透过图形内部看到其它图形,而不像普通绘图函数绘制出的那样直接将图形遮挡。
设置为ARGB颜色即可使用,抗锯齿效果为可选
ege_enable_aa(true) 调用一次即可设置抗锯齿效果,不需要在每次绘图前都设置。
颜色也是如此,但可以根据当前所要绘制图形的颜色随时进行更改。
以下为设置流程图,因为在实际使用时抗锯齿效果一直都要开启,所以ege_enable_aa(true)
通常在初始时进行调用。颜色设置是在绘图前进行的,每次绘图都可以随时更改颜色。
抗锯齿可设置可不设置,抗锯齿是为了图形绘制有更好的效果,不开抗锯齿也行
ege_enable_aa()
ege_enable_aa(true)
,即设置窗口开启抗锯齿。函数声明:
void ege_enable_aa(bool enable, PIMAGE pimg = NULL);
使用方法如下:
PIMAGE pimg = newimage();
ege_enable_aa(true, pimg);
当pimg默认时(NULL),设置的是窗口。
ege_enable_aa(true);
透明度必须不等于0,否则全透明将看不到图形。
高级函数使用的颜色是 ARGB颜色,通过改变Alpha值,可以改变图形的透明度。
ARGB颜色有几种等价的表示方法:
- 用四个分量表示:EGEARGB(a, r, g, b);
- 用一个alpha分量和一个RGB颜色表示: EGEACOLOR(a, rgbColor);
- 直接用数值表示(一般是十六进制):0xAARRGGBB
ARGB颜色 中的 alpha值范围是0~255, 设置为小于255时有透明效果, 为255时是表示完全不透明,这时就RGB颜色等同,即EGEACOLOR(0xFF, RGBcolor) 等于 RGBcolor
setbkcolor(EGEACOLOR(0xFF, WHITE));
等同于
setbkcolor(EGEACOLOR(0XFF, 0XFCFCFC));
设置画笔颜色为透明度0x80的红色
setcolor(0x80FF0000);
设置填充颜色为 透明度0x80的红色
setfillcolor(EGEARGB(0x80, 0xFF, 0x00, 0x00));
void EGEAPI ege_setalpha(int alpha, PIMAGE pimg = NULL);
#include
int main()
{
//初始化窗口
initgraph(640, 480, 0);
setbkcolor(WHITE);
setlinewidth(3);
//----------高级函数绘图设置-----------------
//对窗口开启抗锯齿
ege_enable_aa(true);
//------------------------------------------
//绘图部分,使用高级函数
//设置ARGB颜色,由于下面几个全是填充图形,只用到填充颜色,所以前景色没有设置
setfillcolor(EGEARGB(0x80, 0, 0x80, 0xFF));
ege_fillellipse(200, 200, 200, 200);
setfillcolor(EGEARGB(0x80, 0xFF, 0x80, 0));
ege_fillellipse(100, 100, 200, 200);
setfillcolor(EGEARGB(0x80, 0x20, 0xFF, 0x20));
ege_fillrect(250, 150, 200, 200);
getch();
return 0;
}
经过上面设置ARGB颜色和开启抗锯齿后,高级函数就可以使用,并且比普通绘图函数有更好看的绘图效果。
说明
高级函数
void EGEAPI ege_line(float x1, float y1, float x2, float y2, PIMAGE pimg = NULL);
void EGEAPI ege_drawpoly(int numpoints, ege_point* polypoints, PIMAGE pimg = NULL);
void EGEAPI ege_fillpoly(int numpoints, ege_point* polypoints, PIMAGE pimg = NULL);
表示区域的参数大多有两种
一种是 left, top right, bottom,说明矩形区域的左上角坐标为(left, top), 右下角坐标为(right, bottom)。
另一种是 x, y, w, h, 分别是指矩形区域的左上角坐标为(x, y), 宽为width, 高为height
void EGEAPI ege_drawcurve(int numpoints, ege_point* polypoints, PIMAGE pimg = NULL);
void EGEAPI ege_rectangle(float x, float y, float w, float h, PIMAGE pimg = NULL);
void EGEAPI ege_fillrect(float x, float y, float w, float h, PIMAGE pimg = NULL);
下面几个和圆有关的函数和普通绘图函数有区别,参数不同, 参数是椭圆所在的矩形区域左上角坐标和宽高
void EGEAPI ege_ellipse(float x, float y, float w, float h, PIMAGE pimg = NULL);
void EGEAPI ege_fillellipse(float x, float y, float w, float h, PIMAGE pimg = NULL);
void EGEAPI ege_pie(float x, float y, float w, float h, float stangle, float sweepAngle, PIMAGE pimg = NULL);
void EGEAPI ege_fillpie(float x, float y, float w, float h, float stangle, float sweepAngle, PIMAGE pimg = NULL);
如左上角的扇形
ege_fillpie(0, 0, 100, 100, 180, 90);
void EGEAPI ege_arc(float x, float y, float w, float h, float stangle, float sweepAngle, PIMAGE pimg = NULL);
void EGEAPI ege_bezier(int numpoints, ege_point* polypoints, PIMAGE pimg = NULL);
只对高级绘图函数有效, 颜色必须使用ARGB颜色
设置了颜色填充模式后,填充图形不再是单调的纯色填充,填充颜色可设置为渐变颜色,甚至是用纹理来填充。这样绘制的图形颜色变化更为丰富
typedef struct ege_point {
float x;
float y;
}ege_point;
表示矩形区域
typedef struct ege_rect {
float x;
float y;
float w;
float h;
}ege_rect;
表示颜色点
typedef struct ege_colpoint {
float x;
float y;
color_t color;
}ege_colpoint;
填充模式的颜色渐变区域需要把绘制的区域包含在其中,所以渐变区域要设置得大一些。
默认填充模式按照 setfillcolor() 所设置的颜色对填充区域进行填充。这便是之前一直使用的填充模式。
void EGEAPI ege_setpattern_none(PIMAGE pimg = NULL);
线性渐变填充模式,对于设置的渐变区域,填充颜色沿对角线方向进行渐变。
void EGEAPI ege_setpattern_lineargradient(float x1, float y1, color_t c1, float x2, float y2, color_t c2, PIMAGE pimg = NULL);
渐变区域是一个宽为直线长度的长条区域, 超出的区域颜色是重复的,所以请画在区域内,。
如下图所示, 线性渐变的有效区域是中间长条部分,超出后填充颜色是重复的,没有得到预期的效果。
如下图所示,图中的直线为渐变区域的对角线,当填充区域在渐变区域内时,就可以得到正确的颜色填充。
#include
int main()
{
initgraph(320, 320, 0);
setbkcolor(EGEACOLOR(0xFF, WHITE));
setcolor(EGEACOLOR(0xF0, RED));
ege_enable_aa(true);
ege_setpattern_lineargradient(0, 0, EGEACOLOR(0XFF, BLUE), 320, 320, EGEACOLOR(0XFF, GREEN));
//填充矩形
ege_fillrect(10, 10, 300, 300);
getch();
closegraph();
return 0;
}
路径渐变模式是对路径围成的多边形区域进行颜色渐变填充, 参数需要指定路径中心点的位置和颜色, 以及路径上的点的位置和颜色。
void EGEAPI ege_setpattern_pathgradient(ege_point center, color_t centercolor,
int count, ege_point* points, int colcount, color_t* pointscolor, PIMAGE pimg = NULL);
参数 :
center :中心点, 类型为ege_point
centercolor :中心点颜色
count, points, colcount, pointscolor : 路径上的点的数目,点数组的首地址及点对应的颜色
颜色渐变的区域是路径点顺序连成的封闭区域,超出这个区域的部分颜色填充很奇怪,所以这些点最好能按顺序连成一个封闭区域,填充区域也需要在这个区域内。
左边连成了一个四边形,而画的填充矩形是整个窗口大小,所以四边形封闭区域外的颜色填充有问题,中间路径是一个Z字,形成的四边形边与边之间有交叉,形成的区域为对顶三角形, 右边的路径连成了窗口一样大的矩形 ,矩形也绘制在这个区域内,所以颜色填充正确。
路径填充示例
#include
int main()
{
initgraph(320, 320, 0);
setbkcolor(EGEACOLOR(0xFF, WHITE));
setcolor(EGEACOLOR(0xF0, RED));
ege_enable_aa(true); //开启抗锯齿
setlinewidth(3.0f); //设置线宽
//渐变填充的参数
ege_point points[4] = { {0, 0}, {320, 0}, {320, 320} , {0, 320} };
color_t pointsColor[4] = { EGEACOLOR(0XFF, BLUE), EGEACOLOR(0XFF, GREEN), EGEACOLOR(0XFF, RED), EGEACOLOR(0XFF, YELLOW) };
ege_point center = {100, 100}; //中心点位置
color_t centerColor = { 0xFFFF00FF }; //中心点颜色为紫色
//设置路径渐变
ege_setpattern_pathgradient(center, centerColor, 4, points, 4, pointsColor);
//填充矩形
ege_fillrect(0, 0, 320, 320);
//绘制路径曲线
ege_drawcurve(4, points);
getch();
closegraph();
return 0;
}
椭圆填充模式 的渐变区域为椭圆,颜色由位于椭圆内的一个点向外圈渐变。需要指定渐变中心点的位置、颜色,以及外圈的颜色。
中心点需要在椭圆内,不然颜色会出错
void EGEAPI ege_setpattern_ellipsegradient(ege_point center, color_t centercolor,
float x, float y, float w, float h, color_t color, PIMAGE pimg = NULL);
来看下面的一个示例, 渐变区域是中间一个椭圆,画了一个填充矩形,可以看到,超出椭圆的部分没被填充。
#include
int main()
{
initgraph(320, 320, 0);
setbkcolor(EGEACOLOR(0xFF, WHITE));
setcolor(EGEACOLOR(0xF0, RED));
ege_enable_aa(true);
ege_setpattern_ellipsegradient(ege_point{ 160, 160}, EGEACOLOR(0XFF, GREEN), 60, 60, 200, 200, EGEACOLOR(0xFF, 0X8080FF));
//填充矩形
ege_fillrect(10, 10, 300, 300);
ege_rectangle(10, 10, 300, 300);
getch();
closegraph();
return 0;
}
设置成纹理填充模式
void EGEAPI ege_setpattern_texture(PIMAGE srcimg, float x, float y, float w, float h, PIMAGE pimg = NULL);
设置成纹理填充模式后, 绘制时图形时, 内部将用纹理图像来填充.
使用步骤
PIMAGE texture = newimage();
...
获取图像
...
ege_gentexture(true, texture);
设置alpha通道: 因为要用ARGB颜色,所以如果图片原来没有alpha通道的话,绘制出来将会是透明的。这样的话可以用 ege_setalpha() 对图片 设置透明度(透明度 0~255),但是如果图片原来有透明度,就可以不用设置。
ege_setalpha(0xFF, texture);
ege_setpattern_texture(texture, 50, 50, 400, 400, pimg);
下面画的填充矩形超出了纹理区域,超出区域将用纹理重复填充。=
#include
int main()
{
initgraph(640, 640, 0);
setbkcolor(EGEACOLOR(0xFF, WHITE));
setcolor(EGEACOLOR(0xF0, RED));
//可设置可不设置
ege_enable_aa(true);
//从文件中加载图片
PIMAGE pimg = newimage(640, 640);
getimage(pimg, "girl.jpg");
//将图片生成纹理
ege_gentexture(true, pimg);
//对图片设置透明度
ege_setalpha(0xFF, pimg);
//设置为纹理填充
ege_setpattern_texture(pimg, 50, 50, 400, 400);
//填充矩形
setlinewidth(4.0f);
ege_fillrect(50, 50, 500, 500);
ege_rectangle(50, 50, 500, 500);
delimage(pimg);
getch();
closegraph();
return 0;
}
生成纹理
将图像生成纹理
void EGEAPI ege_gentexture(bool gen, PIMAGE pimg = NULL);
设置纹理的透明度(因为要用 ARGB 颜色)
如果图像不带透明度(从jpg图片加载的没有), 那么默认透明度为0,那就是看不见. 则需要设置
ege_setalpha(int alpha, PIMAGE pimg = NULL);
绘制纹理
绘制到pimg的目标区域上,单位是像素(pimg 默认参数为绘制到窗口)
void EGEAPI ege_puttexture(PIMAGE srcimg, float x, float y, float w, float h, PIMAGE pimg = NULL);
绘制到pimg的目标区域上(pimg 默认参数为绘制到窗口),srcimg 为纹理
void EGEAPI ege_puttexture(PIMAGE srcimg, ege_rect dest, PIMAGE pimg = NULL);
缩放绘制到 pimg 的目标区域上,矩形区域ege_rect 的属性单位是像素,srcimg为纹理(pimg 默认参数为绘制到窗口)
void EGEAPI ege_puttexture(PIMAGE srcimg, ege_rect dest, ege_rect src, PIMAGE pimg = NULL);
下面是纹理绘制的示例
#include
int main()
{
initgraph(640, 640, 0);
setbkcolor(EGEACOLOR(0xFF, WHITE));
setcolor(EGEACOLOR(0xF0, RED));
//从文件中加载图片
PIMAGE pimg = newimage(640, 640);
getimage(pimg, "girl.jpg");
//对目标图像(这里是窗口)开启透明,这是必须的
ege_enable_aa(true);
//将图片生成纹理
ege_gentexture(true, pimg);
//对图片设置透明度
ege_setalpha(0xFF, pimg);
//缩放绘制纹理图到窗口上
ege_puttexture(pimg, ege_rect{10, 10, 500, 500}, ege_rect{0.0, 0.0, 400.0, 400.0});
delimage(pimg);
getch();
closegraph();
return 0;
}
EGE专栏:EGE专栏