我们都在命运湖上荡舟划桨,波浪起伏使我们无法逃离孤行;如果我们迷失方向,波浪将指引我们穿过另一天曙光
靠,你们两个想我破产啊?? 回这么多贴子
色彩寄存器与调色板
我想调色板对各位初学计算机的同学并不陌生。什么?没听说过?顾名思义,我想画家的调色版你总算听说过了吧。画家将颜料调配在颜料盒里,然后将调好的颜色放在一个颜料盘里,那个颜料盘就是画家的调色板。对于计算机系统来说,在256色以下的屏幕模式下,也有这它自己的颜料,那就是RGB三色射线管,而它的颜料盘,就是它的DAC色彩寄存器。画家依据颜料盘绘出多彩的图画在画布上,而计算机则是依据DAC色彩寄存器将显存的数据计算出的颜色点逐个显示在屏幕上。 那么这个DAC色彩寄存器是如何工作的呢?这要涉及到显示器的工作原理,我们知道,显示器是每隔固定的时间进行着刷新的,在屏幕上的图像是一行行的扫描出来的。而在这个扫描过程中,显示卡先读取显存的一个数据,这个数据不一定是8位的,也可能是4位的,要依据所置的屏幕模式而定,在256色模式下是8位而在16色模式下是4位。然后按该数据查找对应的色彩寄存器获得一组RGB分量,然后调整显示器的射线管在屏幕对应位置显示一个点。当显示卡扫描完所需要的所有显存单元后,屏幕上就得到了一幅我们需要的图像。
色彩寄存器与屏幕模式
如果学了在WINDOWS编程,有些人又会产生疑问了。在WINDOWS下,显示256色的图片我没有对色彩寄存器进行操作啊?回答是YES。因为WINDOWS下的编程一般都是在屏幕16位以上的真彩色模式下进行,而所谓的N色位图(N<=256),只是使用了所有真彩色颜色中的256种颜色而已。所以,在真彩色模式下,显示256色位图并没有使用色彩寄存器。而在2色、16色或256色屏幕模式下,都需要使用色彩寄存器。 那么有些人又要想当然了,是不是在2色、16色和256色屏幕模式下DAC色彩寄存器的数量是2个、16个和256个呢?那可就想错了,在显示卡上,无论在任何屏幕模式下,DAC色彩寄存器始终只有256个。在2色屏幕模式下,使用其中两个;在16色屏幕模式下,使用其中16个;在256色模式下,全部的色彩寄存器都要使用。 在对色彩寄存器进行编程之前,色彩寄存器还有一个重要的特性必须要介绍一下,就是它的使用位。对于色彩寄存器,它的RGB分量使用的位数只有6位。也就是说,如果你将一个 unsigned char类型赋值到色彩寄存器的R分量,它只按后面的6位来调整色彩的红色值。如果获取到的RGB值是8位数值,传入色彩寄存器必须进行移位处理。
色彩寄存器的操作
说了这么大堆,理论还要联系实践才能达到实用的目的。接下来就看看色彩寄存器是如何编程进行操作了。
在实际应用中,设置色彩寄存器可以采用两种方法,一是采用直接端口操作的方法,二是使用BIOS中断调用。
方法一:直接端口操作 设置颜色寄存器值的函数: void SetPaletteRegister(int index,RGBColorPtr color) { outportb(0x3c6,0xff); /*通知调色板控制器,该句可省略*/ outportb(0x3c8,index);/*颜色号,如为0则改变显存中对应0值的颜色*/ outportb(0x3c9,r); /*传入红色分量,6bit*/ outportb(0x3c9,g); /*传入蓝色分量,6bit*/ outportb(0x3c9,b); /*传入绿色分量,6bit*/ } 获取颜色寄存器值的函数: void GetPaletteRegister(int index,RGBColorPtr color) { outportb(0x3c6,0xff); /*通知调色板控制器,该句可省略*/ outportb(0x3c7,index);/*颜色号,如为0则获取显存中对应0值的颜色*/ r=inportb(0x3c9); /*获取红色分量,6bit*/ g=inportb(0x3c9); /*获取蓝色分量,6bit*/ b=inportb(0x3c9); /*获取绿色分量,6bit*/ }
方法二:BIOS中断调用 设置颜色寄存器值的函数: 该方法的获取与设置都需要先定义一块足够大的内存来存储或获取系统调色板。 void setpalette(char far *PaletteData)/*PaletteData为要设置到系统调色板的内存位置*/ { struct REGPACK regs; regs.r_ax=0x1012; regs.r_bx=0;/*开始设置的颜色,一般为0,即从0号色开始设置*/ regs.r_cx=256;/*count为要获取的颜色数目,一般为256或16*/ regs.r_es=FP_SEG(PaletteData); regs.r_dx=FP_OFF(PaletteData); intr(0x10,®s); }
获取颜色寄存器值的函数: void getpalette(char far *PaletteData)/*PaletteData为系统调色板获取到的内存位置*/ { struct REGPACK regs; regs.r_ax=0x1017; regs.r_bx=0;/*开始获取的颜色,一般为0,即从0号色开始获取*/ regs.r_cx=256;/*count为要获取的颜色数目,一般为256或16*/ regs.r_es=FP_SEG(PaletteData); regs.r_dx=FP_OFF(PaletteData); intr(0x10,®s); }
调色板动画
由于屏幕颜色的显示是需要查找色彩寄存器来获得,那么如果我要改变所有显存为0的点在屏幕上所显示的颜色,只需要改变颜色号0的色彩寄存器值,让所“翻译”出来的显存颜色改变即可。同理,改变颜色号1的色彩寄存器的值,那么显存内所有为1的单元对应的颜色都要改变。根据这个原理,在某些情况下,将一种颜色改变为另外一种颜色通过改变色彩寄存器比改变显存单元的值来得快得多。依据这个原来制作的动画调色版动画。调色板动画由于只需要改变一个色彩寄存器就可以改变屏幕该色彩寄存器所对应的所有点的颜色,因此具有非常高的硬件速度,一般16色和256色屏幕模式下,均采用调色板动画来制作渐入(Fade In)和渐出(Fade Out)的动画。
TC BGI的调色板
不是说16色模式下只需要部分色彩寄存器吗?对于TC的BGI的EGA/VGA16色模式,所采用的颜色号在其graphics.h中是这样定义的: char ega_colors[16]={0,1,2,3,4,5,20,7,56,57,58,59,60,61,62,63}; 因此,要改变TCBGI 16色调色板只需要对上述16个色号的色彩寄存器进行操作就可以了。
yuki希望上面的资料对你有帮助。还有,既然你同意我的意见,那么,这件事你和georgezf就策划起来,静夜思也同意开个专版了。哈哈,赚我的钱不是太容易的..........
谢谢knocker提供如此好的资料,我回去好好研究。。其实不用特意开个板块的,大家都是爱好者,把自己的成果贴出来就行了。。我这么想的。。