大家知道CRT图像显示器吗?其实它就是人们常说的光栅扫描的图像显示器,今天yogurt就来跟大家分享一下光栅扫描器显示图案的编程实现方法。哇,听起来是不是好高大上啊!在yogurt的老师在课堂上讲了这个方法之前,yogurt也觉得这是一个十分有技术含量的存在!好像很复杂的样子!不过,当yogurt认真听完课并编程实现之后,觉得其实也就是数学计算而已,也不过如此嘛~~(让yogurt小傲娇一下,嘿嘿嘿)
首先我们来介绍一下光栅扫描吧~~
=================================yogurt的小课堂开课啦=====================================
首先是光栅图像,也就是通过一个一个的像素来显示的图像,因为像素是方方正正的一个单位量,所以当对图像进行放大显示时会存在走样现象,就像我们平时把一幅图像不断地放大到一定程度之后,眼里看到的就是马赛克了一样。因此,无论是用像素来表示直线还是表示圆,它们在光栅中只能用离散的小方块组合来表示,所以都会存在一定的走样!(锯齿状或者阶梯状)
在光栅扫描系统中,电子束依照固定的扫描线和规定的扫描顺序(一般是横向扫描屏幕,一次一行,从上到下的顺序)进行扫描。即电子束先从荧光屏左上角开始,向右扫一条水平线,然后回扫到下一排的左边,再扫第二条水平线,就这样一直扫啊扫,直到扫完最后一排为止。在电子束横向沿每一行移动的过程中,电子束的强度会通过不断变化来建立亮点的图案。(其实还有垂直回扫、逐行扫描和隔行扫描的扫描系统哦,不要以为只可以水平回扫)
==========================嗷,其实百度百科比Yogurt的介绍更好一些,(⊙﹏⊙)==========================
果然直接放代码的部分还是yogurt最喜欢的部分!终于体会到了当yogurt追着别人问十万个为什么时,别人那“只可意会不可言传”的心情了,讲名词解释还是度娘牛13!
接下来的代码,可能需要大家先了解一下中点Bresenham算法(用来画直线和1/8部分的圆弧)以及八分法(对圆弧剩余部分的画法),具体的还是见代码吧!
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 // 光栅化.cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include"stdafx.h" 5 #include"Graph.h" 6 7 typedef struct POINT 8 { 9 int x, y; 10 }point; 11 12 void DrawLine(point p1, point p2); 13 void DrawCircle(int r); 14 15 int _tmain(int argc, _TCHAR* argv[]) 16 { 17 for (int i = -20; i<20; i++) 18 { 19 for (int j = -25; j<25; j++) //把10*10当做一个像素 20 { 21 if ((i + j) % 2 == 0) 22 for (int m = 0; m<10; m++) 23 for (int n = 0; n<10; n++) 24 setPixel(j * 10 + n, i * 10 + m, RED); 25 else 26 for (int m = 0; m<10; m++) 27 for (int n = 0; n<10; n++) 28 setPixel(j * 10 + n, i * 10 + m, WHITE); 29 } 30 } 31 32 point p1, p2; 33 printf("Please enter point one:"); 34 scanf("%d,%d", &(p1.x), &(p1.y)); 35 printf("Please enter point two:"); 36 scanf("%d,%d", &(p2.x), &(p2.y)); 37 38 DrawLine(p1, p2); 39 40 int r; 41 printf("Please enter the radio of a circle:"); 42 scanf("%d", &r); 43 44 DrawCircle(r); 45 46 return 0; 47 } 48 49 void DrawLine(point p1,point p2) 50 { 51 int x, y, dx, dy, d, k; 52 53 int x1 = p1.x, y1 = p1.y; 54 int x2 = p2.x, y2 = p2.y; 55 56 if (x1>x2) //确保从左往右画(点1在左,点2在右) 57 { 58 int t = x1, w = y1; 59 x1 = x2; 60 y1 = y2; 61 x2 = t; 62 y2 = w; 63 } 64 65 dx = x2 - x1; 66 dy = y2 - y1; 67 k = dy / dx; 68 69 //确保0<=k<=1 70 if (k >= 0 && k <= 1) 71 { 72 x = x1; 73 y = y1; 74 dx = x2 - x1; 75 dy = y2 - y1; 76 d = dx - 2 * dy; 77 } 78 else if (k > 1)//做关于Y=X对称:(x,y)-->(y,x) 79 { 80 x = y1; 81 y = x1; 82 dx = y2 - y1; 83 dy = x2 - x1; 84 d = dx - 2 * dy; 85 x2 = y2; //判断终止的条件 86 } 87 else if (k < -1)//关于Y轴对称后还要再关于Y=X对称:(x,y)-->(-x,y)-->(y,-x) 88 { 89 x = y2; 90 y = -x2; 91 dx = y1 - y2; 92 dy = x2 - x1; 93 d = dx - 2 * dy; 94 x2 = y1; //判断终止的条件 95 } 96 else //做关于Y轴的对称:(x,y)-->(-x,y) 97 { 98 x = -x2; 99 y = y2; 100 dx = x2 - x1; 101 dy = y1 - y2; 102 d = dx - 2 * dy; 103 x2 = -x1; //判断终止的条件 104 } 105 106 107 //终点bresenham算法画直线 108 do 109 { //画点(x,y) 110 int i = x * 10, j = y * 10; //坐标点(i,j) 111 for (int p = 0; p < 10; p++) //排 112 { 113 for (int q = 0; q < 10; q++) //列 114 { 115 if (k >= 0 && k <= 1) 116 setPixel(i + q, j + p, GREEN); 117 else if (k>1) 118 setPixel(j + p, i + q, GREEN); 119 else if (k < -1) 120 setPixel(-(j + p), i + q, GREEN); 121 else 122 setPixel(-(i + q), j + p, GREEN); 123 } 124 } 125 if (d < 0) //取右上方的栅格 126 { 127 x += 1; 128 y += 1; 129 d += 2 * dx - 2 * dy; 130 } 131 else //取正右方的栅格 132 { 133 x += 1; 134 d += -2 * dy; 135 } 136 } while (x <= x2); 137 138 } 139 140 void DrawCircle(int r) 141 { 142 int d, x, y; 143 144 x = 0; 145 y = r; 146 d = 1 - r; 147 148 do{ 149 for (int m = 0; m < 10; m++) 150 for (int n = 0; n < 10; n++) 151 { 152 setPixel(x * 10 + m, y * 10 + n, GREEN); 153 setPixel(y * 10 + m, x * 10 + n, GREEN); 154 setPixel(y * 10 + m, -x * 10 + n, GREEN); 155 setPixel(x * 10 + m, -y * 10 + n, GREEN); 156 setPixel(-x * 10 + m, -y * 10 + n, GREEN); 157 setPixel(-y * 10 + m, -x * 10 + n, GREEN); 158 setPixel(-y * 10 + m, x * 10 + n, GREEN); 159 setPixel(-x * 10 + m, y * 10 + n, GREEN); 160 } 161 162 if (d<0) //在圆内,取正右方 163 { 164 d += 2 * x + 3; 165 x += 1; 166 } 167 else 168 { 169 d += 2 * (x - y) + 5; 170 x += 1; 171 y += -1; 172 } 173 } while (x<y); 174 175 setPixel(x, y, GREEN); 176 setPixel(x, -y, GREEN); 177 setPixel(-x, y, GREEN); 178 setPixel(-x, -y, GREEN); 179 }
接下来就是见证奇迹的时刻了!yogurt给大家画了一个小苹果,估计是yogurt自己饿了=.=。yogurt先在像素的基础上为大家画了一个红白相间的网格(一个格子10*10像素哦),可以看到即使超出网格部分还是和网格内每一格一样的大小,相信这样大家能够更加好的了解像素这个概念啦~\(≧▽≦)/~。好了,yogurt要去写作业了~~~~(>_<)~~~~哭!一大堆作业等着yogurt呢,生无可恋脸。。。