3 增加更多的颜色(2)(harib22c)
color.hrb很漂亮,不过其实还有一种技巧能够让颜色更加丰富,下面我们就来试试看吧。
实际上,如果我们不用256色模式,而使用VESA的全彩色模式的话,可以轻而易举地显示出更多的颜色,不过在不兼容VESA标准的电脑上(偶尔会有)是完全无法使用全彩色模式和65536色模式的。而且,要在“纸娃娃系统”上实现对全彩色模式的支持,得花上差不多整整一天时间。眼看剩下的日子不多了,笔者也该开始考虑30天到底能做到什么程度了(笑),所以就不在全彩色模式上花费时间了。
可能有人会说“反正我以后是要用全彩色的,这个技巧对我就没什么用了吧”,这个想法也没错。不过笔者认为,即便如此,也还是对这种技巧有点了解比较好,因为有时候需要显示一幅全彩色的图片,但很有可能遇到不支持全彩色模式的电脑,如果了解了这个技巧,在这种情况下也可以让图片看上去相对好看一些。
“谁让他们不能用全彩色的,才不管他们呢”,大家千万不要说这种绝情的话哦。如果大家编写的操作系统能够做到“用全彩色模式的时候很漂亮,不能用的时候也不难看”,笔者也就感到很欣慰了。
怎样才能让颜色看起来更多呢?我们可以用两种颜色交替排列,看上去就像这两种颜色混合在一起一样,这就是要点。颜色的混合方式我们考虑了下面3种(算上完全不混合的情况,一共有5种)。
这样一来,虽然我们只有6级色阶,但却可以显示出21级色阶(在纯色中间可以产生3个中间色,因此是6+5×3=21)。
■■■■■
这次我们只需要修改应用程序即可。
本次的color2.hrb
int api_openwin(char *buf, int xsiz, int ysiz, int col_inv, char *title);
void api_initmalloc(void);
char *api_malloc(int size);
void api_refreshwin(int win, int x0, int y0, int x1, int y1);
void api_linewin(int win, int x0, int y0, int x1, int y1, int col);
int api_getkey(int mode);
void api_end(void);
unsigned char rgb2pal(int r, int g, int b, int x, int y);
void HariMain(void)
{
char *buf;
int win, x, y;
api_initmalloc();
buf = api_malloc(144 * 164);
win = api_openwin(buf, 144, 164, -1, "color2");
for (y = 0; y < 128; y++) {
for (x = 0; x < 128; x++) {
buf[(x + 8) + (y + 28) * 144] = rgb2pal(x * 2, y * 2, 0, x, y);
}
}
api_refreshwin(win, 8, 28, 136, 156);
api_getkey(1); /*等待按下任意键*/
api_end();
}
unsigned char rgb2pal(int r, int g, int b, int x, int y)
{
static int table[4] = { 3, 1, 0, 2 };
int i;
x &= 1; /*判断是偶数还是奇数*/
y &= 1;
i = table[x + y * 2]; /*用来生成中间色的常量*/
r = (r * 21) / 256; /* r为0~20*/
g = (g * 21) / 256;
b = (b * 21) / 256;
r = (r + i) / 4; /* r为0~5*/
g = (g + i) / 4;
b = (b + i) / 4;
return 16 + r + g * 6 + b * 36;
}
rgb2pal是本次增加颜色的核心部分,里面的算法看上去非常神秘,估计很多人都不明白为什么如此简短的代码却能实现我们所需的功能。其实用很多个if语句也可以实现一样的功能,但相比之下显然我们的算法速度更快,因此我们还是采用这个算法吧。
如果对解谜感兴趣的话,可以花点时间仔细思考一下。话说这个算法也不是笔者想出来的,而是一位编程达人传授的(笔者一开始也是写了很多if语句,后来被这位达人给改成这样了)。
好了,我们来“make run”吧。哦哦,看起来平滑多了。
看起来平滑多了