在16色模式下显示256色及全彩色

在16色模式下显示256色及全彩色,第1张

在16色模式下显示256色及全彩色,第2张

在编写关于图像显示的软件时,有时为了软件的兼容性和通用性,不得不采用VGA标准图形模式,这就涉及到如何在16色图形模式下显示256色和全彩图像。有两种方法可以解决这个问题。一种是颜色近似法,即根据所有需要显示的颜色,通过优化选出16种有代表性的颜色,每种颜色用这16种颜色中最接近的一种来代替。这种方法在《计算机世界月刊》的文章《聚类法选色》中有详细描述。但实际上这种方法只适用于一些理想的情况,对于更一般的情况,无论是运算速度还是处理效果都不尽如人意,不适合实际应用。另一种方法是很多商业软件广泛使用的抖动技术。它的原理是利用各种可见颜色的组合来模拟一种不可见的颜色。目前,关于彩色图像抖动算法的资料并不多。通过对灰度图像处理算法和Windows环境下一些图像处理软件的分析,得出抖动算法的一般原理和实现方法。
一、抖动算法原理
我们知道,在256色和全色图像中,每种颜色都是由R、G、B三个颜色分量组成的,每个分量一般用一个字节表示。这样,每个颜色分量可以有256种亮度变化。
该算法的关键是引入了亮度矩阵的概念,即用一个16×16的矩阵来表示每个颜色分量的亮度值,不同的亮度值对应矩阵的不同排列。矩阵中的全零对应亮度0,全255对应亮度255。
当亮度值为L时,亮度矩阵中会有[L255×256] 255和[(1-L255)×256]个零。此时矩阵的平均亮度值为
L' = {[L/255× 256 ]× 255+。
假设某一颜色C的三个颜色分量R、G、B的亮度矩阵为:
@@01A04600。GIF一个公式@@ @
其中rmn,gmn,bmn(0≤m,n≤15)为0或15。
将以上三个矩阵叠加得到
@@01A04601。GIF公式2 @@
Cmn是由表1中的rmn、gmn和bmn确定的颜色值。表1显示了VGA16色图形模式下的标准调色板(不是设置模式后的默认调色板)。很明显,Cmn只能是0和9 ~ 15中的一个。用这种方法得到的矩阵Mc可以看作是颜色C的模拟矩阵..因为颜色C的三个颜色分量R、G和B具有与亮度矩阵MR、MG和MB相同的亮度值,所以矩阵MC在视觉效果上可以很好地模拟颜色C。但在显示时,不可能用整个矩阵替换一个像素,这会导致整个图像变得是原图像的16倍长和宽。实际的方法是:如果像素距离图像原点的坐标为(X,Y),设:
m = Y mod 16
n = X mod 16(1)
此时像素可以用MC中的颜色Cmn显示。
@@01A04602。GIF表1 16色图形模式标准调色板@@
II。算法
1的实现。亮度矩阵的表示
算法中使用了257个16×16的亮度矩阵。如果每一个都单独表示,会占用大量内存空(64K以上)。因为亮度矩阵的排列和增长有一定的规律性,所以我们只需要使用一个16×16的矩阵。矩阵中256个元素的值分别为0 ~ 255,按照一定的规则排列。顺序是:
@@01A04603。GIF公式3 @@
当亮度为L时,矩阵可以从H开始变化,其中
@@01A04604。GIF公式@@
2。颜色查找表算法中只使用颜色0和9 ~ 15。我们可以忽略其他项目,将有用的部分表示为三维数组形式的颜色查找表,如表2所示。此时R、G、B的值作为数组下标,取值为0或1。
相应的,我们把公式(2)改成
@@01A04605。GIF公式3 @@
3。每个像素的显示步骤
①对于256色图像,通过颜色索引值查颜色映射表,得到R、G、B值;对于全彩图像,直接读取R、G、B值;
②根据像素坐标(X,Y),由公式(1)得到m,n;
③根据R、G、B的值,由式(3)得到rmn、gmn、bmn
④用rmn、gmn、bmn查表2中的色值C;
⑤在(X,Y)显示颜色C的像素。
所附程序用于在16色图形模式下显示256色和全色位图图像。
关于位图图像的格式和读取方法的资料很多,这里就不赘述了。
本程序由Turbo C 2.0和Borland C 3.1编译而成,贯穿。运行方法为:
show filename . BMP
@ @ 01a 04606 . gif;公式3,表2,颜色查找表@@
实践证明,使用本文所述的算法可以获得类似于很多商业软件的处理速度和处理效果。
源程序:
# include
# include
# define no error 0
# define error file open 1
# define error file type 2
# define error image color 3
typedef struct tagbitmapfile header {
unsigned int bfType;
无符号longbfSize
unsigned intbfreserved 1;无符号intbfReserved2
无符号longbfoffBits
} bitmapfile header;
typedef struct tagBITMAPINFOHEADER {
unsigned long bisize;
无符号长双宽度;
无符号longbiHeight
无符号intbiPlanes
unsigned intbiBitCount;
无符号长整型双压缩;
无符号长整型biSizeImage
无符号长整型biXPelsPerMeter
无符号长整型双精度表;
无符号长整型biClrUsed
无符号长双精度浮点数biClrImportant
} BITMAPINFOHEADER;
typedef struct tagRGBQUAD {
unsigned char RGB blue;
unsigned char RGB green;
未签名的charrgbRed
unsigned char rgr served;
} RGBQUAD;
void main(int argc,char * argv[]);
int show BMP(char * FileName);
int GetColor(unsigned char R,unsigned char G,unsigned char B,int X,int Y);
void SetVideoMode(无符号char模式);
void set palReg(unsigned char * palReg);
void SetDacReg(unsigned char * DacReg,int Color,int Count);
void PutPixel(int X,int Y,无符号char Color);
unsigned char PalReg[17]= { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0 };
unsigned char standard pal[48]= {
0,0,0,32,0,32,32,0,0,32,32,32,0,32,0,32,32,32,32,
32,48,48,48,63,0,0,63,63,0,0,0,0,63,63,63
unsigned char lightness matrix[16][16]= {
{ 0,235,59,219,15,231,55,215,2,232,56,217,12,229,52,213},
{128,64,187,123,143,79,183,119,130,66,184
unsigned char color table[2][2][2]= {
{ { 0,12},{10,14}},{{9,13},{11,15 } } };
unsigned char ColorMap[256][3];
void main (int argc,char * argv[])
{
if(argc!=2) {
printf("用法:\ n \显示文件名。BMP \ n ");
退出(1);
}
show BMP(argv[1]);
}
int show BMP(char * FileName)
{
FILE * Fp;
bitmapfile header file head;
BITMAPINFOHEADER info head;
RGBQUAD RGB;
int N,W,Y,X,C,Color
无符号字符缓冲区[4096];
如果(!(Fp=fopen(FileName," Rb "))
return(error fileopen);
fread(&FileHead,siazeof(BITMAPFILEHEADER),1,Fp);
if(FileHead.bfType!= ' BM ')
return(error filetype);
fread(&InfoHead,sizeof(BITMAPFILEHEADER),1,Fp);
if(InfoHead.biBitcount!=8 && InfoHead.biBitCount!= 24){
f close(Fp);
return(error image color);
}
set video mode(0x 12);
set PalReg(pal reg);
SetDacReg(StandardPa1,0,16);
if(infohead . bibitcount = = 8){
for(N = 0;N fread(&RGB,sizeof(RGBQUAD),1,Fp);
ColorMap[N][0]= RGB . rg bred;
ColorMap[N][1]= RGB . RGB green;
ColorMap[N][2]= RGB . RGB blue;
}
W =(info head . bi width+3)/4 * 4;
for(Y = info head . BIH height-1;Y > = 480Y - )
fread(Buffer,sizeof(无符号字符),W,Fp);
for(;y > 0;Y - ) {
fread(Buffer,sizeof(无符号字符),w,FP);
for(X = 0;X C = Buffer[X];
Color = GetColor(ColorMap[C][0],ColorMap[C][1],ColorMap[C][2],X,Y);
PutPixel (X,Y,color);
}
}
}
else {
W =(info head . bi width * 3+3)/4 * 4;
for(Y = info head . BIH height-1;Y > 639Y - )
fread(Buffer,sizeof(无符号字符),W,Fp);
for(;y > = 0;Y - ) {
fread(Buffer,sizeof(无符号字符),W,Fp);
for(X = 0;X C = X * 3;
Color = GetColor(Buffer[C+2],Buffer[C+1],Buffer[C],X,Y);
PutPixel(X,Y,color);
}
}
}
getch();
f close(Fp);
setvideo mode(0x 03);
return(no error);
}
int GetColor(unsigned char R,unsigned char G,unsigned char B,int X,int Y){
unsigned int L = lightness matrix[Y & 0x0F][X & 0x0F];
return(color table[(
unsigned int)R * 256/255 > L][(
unsigned int)G * 256/255 > L][(
unsigned int)B * 256/255 > L]);}
void SetVideoMode(无符号字符模式){
-H = 0x 00;
-AL = Mode;
gen interrupt(0x 10);
}
voidSetPalReg(unsigned char * PalReg){
-ES = FP-SEG((unsigned char far *)PalReg);
-DX = FP-OFF((unsigned char far *)PalReg;
-AX = 0x 1002;
gen interrupt(0x 10);
}
void SetDacReg(unsigned char * DacReg,int Color,int Count){
-ES = FP-SEG((unsigned char far *)DacReg);
-DX = FP-OFF((unsigned char far *)DacReg);
-AX = 0x 1012;
-BX = Color;
-CX = Count;
gen interrupt(0x 10);
}
void PutPixel(int X,int Y,unsigned char color){
-AH = 0x0C;
-AL = Color;
-CX = X;
-DX = Y;
gen interrupt(0x 10);
}
}

位律师回复
DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
白度搜_经验知识百科全书 » 在16色模式下显示256色及全彩色

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情