全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1455
推到 Plurk!
推到 Facebook!

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

 
jackkcg
站務副站長


發表:891
回覆:1050
積分:848
註冊:2002-03-23

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-04-09 16:05:24 IP:61.221.xxx.xxx 未訂閱
此為轉貼資料    http://www.powerba.com/develop/vc/article/20010728010.htm    在16色模式下顯示256色及全彩色    在編寫有關圖像顯示的軟體時,有時?了軟體的相容性和通用性,不得不採用VGA標準的圖形模式,這就涉及到如何在16色圖形模式下顯示256色及全彩色圖像的問題。解決這一問題有兩種方法。一種是採用色彩近似的方法,即根據需要顯示的全部?色,經過尋優來選擇16種最具代表性的?色,每一種?色都用這16種?色中最接近的一種來代替。《電腦世界月刊》1994年第1期的《用集群方法進行?色選擇》一文詳細描述了該方法。但事實上,該方法僅對於某些理想的情況適用,而對於更普遍的情況,該方法無論從運算速度還是從處理效果來講,都不可能令人感到滿意,因而不宜在實際中運用。另一種方法是被?多商品化軟體所廣泛採用的抖動技術,其原理是利用多種可見?色的組合來類比一種不可見的?色。目前,關於彩色圖像抖動演算法的資料不多。筆者通過對灰度圖像處理演算法及Windows環境下一些圖像處理軟體的剖析,得出了抖動演算法的一般原理和實現方法.     一、抖動演算法原理      我們知道,在256色及全彩色圖像中,每一種?色均由R、G、B三個?色分量組成,而每一個分量又一般由一個位元組表示。這樣,每一個?色分量可有256級亮度變化。    本演算法的關鍵在於引入亮度矩陣的概念,即採用一個16×16的矩陣來表示每一個?色分量的亮度值,不同亮度值對應著矩陣的不同排列。矩陣全?0時對應亮度0,全?255時對應亮度255。      當亮度值?L時,亮度矩陣中將有[L255×256]個255及[(1-L255)×256]個0,此時,矩陣的平均亮度值?      L'={[L/255×256]×255+[(1-L/255)×256]×0}/256=L      這就是說,矩陣的平均亮度正好??色分量的實際亮度。      假設某一?色C的R、G、B三個?色分量的亮度矩陣分別?: @@01A04600.GIF;公式一@@      其中rmn、gmn、bmn(0?m, n?15)取值?0或15。      將上述三個矩陣作疊加運算,得@@01A04601.GIF;公式二@@      其中的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色圖形模式標準調色板@@      二、演算法實現      1.亮度矩陣的表示      演算法中要用到257個16×16的亮度矩陣,如果對每一個都分別表示的話,將佔用很大的記憶體空間(大於64K)。由於亮度矩陣的排列及增長均有一定的規律性,我們只需要採用一個16×16的矩陣即可。該矩陣中256個元素的取值分別?0~255,按一定規律排列。令其?:  @@01A04603.GIF;公式三@@      亮度?L時的矩陣可由H變化而來,其中@@01A04604.GIF;公式四@@      2.?色查找表演算法中只用到了?色0及9~15,我們可以忽略其他項並將有用部分表示?一個三維陣列形式的?色查找表,如表2所示。此時,r, g, b值作?陣列下標,取值?0或1。與之相應,我們將(2)式變?@@01A04605.GIF;公式三@@      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;      ?將圖元以?色C顯示於(X,Y)處。      本文所附程式用於在16色圖形模式下顯示256色及全彩色BitMap圖像。      關於BitMap圖像的格式及讀取方法,許多資料均有介紹,這裏不再贅述。      該程式由Turbo C 2.0及Borland C 3.1編譯,在386兼容機上運行通過。運行方法?:   show檔案名.BMP  @@01A04606.GIF;公式三表2 ?色查找表@@      事實證明,採用本文所描述的演算法,可以得到與許多商品化軟體相似的處理速度和處理效果。      根源程式:      #include #include #include #include #define NoError 0 #define ErrorFileOpen1 #define ErrorFileType 2 #define ErrorImageColor 3 typedef struct tagBITMAPFILEHEADER { unsigned int bfType; unsigned longbfSize; unsigned intbfReserved1; unsigned intbfReserved2; unsigned longbfoffBits; } BITMAPFILEHEADER; typedef struct tagBITMAPINFOHEADER { unsigned longbiSize; unsigned long biWidth; unsigned longbiHeight; unsigned intbiPlanes; unsigned intbiBitCount; unsigned long biCompression; unsigned long biSizeImage; unsigned long biXPelsPerMeter; unsigned long biYPelsPerMeter; unsigned long biClrUsed; unsigned long biClrImportant; } BITMAPINFOHEADER; typedef struct tagRGBQUAD { unsigned char rgbBlue; unsigned char rgbGreen; unsigned charrgbRed; unsigned char rgbReserved; } RGBQUAD; void main(int argc,char *argv[]); int ShowBmp(char *FileName); int GetColor(unsigned char R,unsigned char G, unsigned char B,int X,int Y) ; void SetVideoMode(unsigned char Mode); void SetPalReg(unsigned char *palReg); void SetDacReg(unsigned char *DacReg, int Color, int Count); void PutPixel(int X, int Y,unsigned 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 StandardPal[48]= { 0, 0, 0, 32, 0, 0, 0,32, 0, 32,32, 0, 0, 0,32, 32, 0,32, 0,32,32, 32,32, 32, 48,48,48, 63, 0, 0, 0,63, 0, 63,63, 0, 0, 0,63, 63, 0,63, 0,63,63, 63,6 3,63,}; unsigned char LightnessMatrix [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,120,140,76,180,116}, {33,192,16,251,47,207,31,247,34,194,18,248,44,204,28,244}, {161,97,144,80,175,111,159,95,162,98,146,82,172,108,156,92}, {8,225,48,208,5,239,63,223,10,226,50,210,6,236,60,220}, {136,72,176,112,133,69,191,127,138,74,178,114,134,70,188,124}, {41,200,24,240,36,197,20,255,42,202,26,242,38,198,22,252}, {169,105,152,88,164,100,148,84,170,106,154,90,166,102,150,86}, {3,233,57,216,13,228,53,212,1,234,58,218,14,230,54,214}, {131,67,185,121,141,77,181,117,129,65,186,122,142,78,182,118}, {35,195,19,249,45,205,29,245,32,193,17,250,46,206,30,246}, {163,99,147,83,173,109,157,93,160,96,145,81,174,110,158,94}, {11,227,51,211,7,237,61,221,9,224,49,209,4,238,62,222}, {139,75,179,115,135,71,189,125,137,73,177,113,132,68,190,126}, {43,203,27,243,39,199,23,253,40,201,25,241,37,196,21,254}, {171,107,155,91,167,103,151,87,168,104,153,89,165,101,149,85}, }; unsigned char ColorTable[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("Usage:\n\tSHOW Filename.BMP\n"); exit(1); } ShowBmp(argv[1]); } int ShowBmp(char *FileName) { FILE *Fp; BITMAPFILEHEADER FileHead; BITMAPINFOHEADER InfoHead; RGBQUAD RGB; int N, W,Y,X,C,Color; unsigned char Buffer[4096]; if (!(Fp=fopen(FileName,"rb"))) return(ErrorFileOpen); fread(&FileHead,siazeof(BITMAPFILEHEADER),1,Fp); if(FileHead.bfType!='BM') return(ErrorFileType); fread(&InfoHead,sizeof(BITMAPFILEHEADER),1,Fp); if(InfoHead.biBitcount!=8 && InfoHead.biBitCount!=24) { fclose(Fp); return(ErrorImageColor); } SetVideoMode(0x12); SetPalReg(PalReg); SetDacReg(StandardPa1,0,16); if(InfoHead.biBitcount==8) { for (N=0;N<256;N ) { fread(&RGB, sizeof(RGBQUAD),1,Fp); ColorMap[N][0]=RGB.rgbRed; ColorMap[N][1]=RGB.rgbGreen; ColorMap[N][2]=RGB.rgbBlue; } W=(InfoHead.biwidth 3)/4*4; for(Y=InfoHead.biHeight-1;Y>=480;Y--) fread(Buffer,sizeof(unsigned char),W,Fp); for(;Y>0;Y--) { fread(Buffer, sizeof(unsigned char),w,FP); for (X=0;X639;Y--) fread(Buffer,sizeof(unsigned char),W,Fp); for(;Y>=0;Y--) { fread(Buffer,sizeof(unsigned char),W,Fp); for (X=0;XL][( unsigned int)G*256/255>L][( unsigned int)B*256/255>L]);} void SetVideoMode(unsigned char Mode){ -H=0x00; -AL=Mode; geninterrupt(0x10); } voidSetPalReg(unsigned char *PalReg){ -ES=FP-SEG((unsigned char far*)PalReg); -DX=FP-OFF((unsigned char far*)PalReg; -AX=0x1002; geninterrupt(0x10); } void SetDacReg(unsigned char *DacReg,int Color,int Count){ -ES=FP-SEG((unsigned char far*)DacReg); -DX=FP-OFF((unsigned char far*)DacReg); -AX=0x1012; -BX=Color; -CX=Count; geninterrupt(0x10); } void PutPixel(int X, int Y, unsigned charColor){ -AH=0x0C; -AL=Color; -CX=X; -DX=Y; geninterrupt(0x10); } ) ********************************************************* 哈哈&兵燹 最會的2大絕招 這個不會與那個也不會 哈哈哈 粉好 Delphi K.Top的K.Top分兩個字解釋Top代表尖端的意思,希望本討論區能提供Delphi的尖端新知 K.表Knowlege 知識,就是本站的標語:Open our mind to make knowledge together! 希望能大家敞開心胸,將知識寶庫結合一起
------
**********************************************************
哈哈&兵燹
最會的2大絕招 這個不會與那個也不會 哈哈哈 粉好

Delphi K.Top的K.Top分兩個字解釋Top代表尖端的意思,希望本討論區能提供Delphi的尖端新知
K.表Knowlege 知識,就是本站的標語:Open our mind
系統時間:2024-11-23 18:50:49
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!