DICM和BMP图像的显示及转换
一.與設(shè)備無(wú)關(guān)位圖的顯示(DIB)
與設(shè)備無(wú)關(guān)位圖(DIB)可以在不同的及其或者系統(tǒng)中小時(shí)位圖所固有的顏色。DIB是一種外部的位圖格式,經(jīng)常存儲(chǔ)以BMP為后綴的位圖文件。DIB位圖還支持圖像數(shù)據(jù)的壓縮。
1.BMP文件組成
BMP文件有文件頭、位圖相信頭、顏色信息和圖像數(shù)據(jù)四部分組成。位圖結(jié)構(gòu)如下所示:
| 位圖文件頭結(jié)構(gòu)BITMAPFILEHEADER |
| 位圖信息頭結(jié)構(gòu)BITMAPINFOHEADER |
| 位圖顏色表RGBQUAD |
| 位圖像素?cái)?shù)據(jù) |
a.BMP文件頭
BMP文件頭數(shù)據(jù)結(jié)構(gòu)含有BMP文件的類型、文件大小和位圖其實(shí)位置等信息。其結(jié)構(gòu)定義如下:
typedef struct tagBITMAPFILEHEADER {
? WORD??? bfType; ??????????? //位圖文件的類型,必須為BMP
? DWORD?? bfSize; ??????????? //位圖文件的大小,一字節(jié)為單位
? WORD??? bfReserved1;?????? //位圖文件的保留字,必須為O
? WORD??? bfReserved2; ????? //位圖文件的保留字,必須為O
? DWORD?? bfOffBits; ??????? //位圖數(shù)據(jù)的起始位置,一相對(duì)于位圖文件
//的偏移量表示,以字節(jié)為單位
} BITMAPFILEHEADER, *PBITMAPFILEHEADER;
b.位圖信息頭
BMP位圖信息頭數(shù)據(jù)用于說(shuō)明位圖的尺寸等信息。
typedef struct tagBITMAPINFOHEADER{ DWORD biSize; //本結(jié)構(gòu)所占用的字節(jié)數(shù) LONG biWidth; //位圖的寬度,以像素為單位 LONG biHeight; //位圖的高度,一像素為單位 WORD biPlanes; //目標(biāo)設(shè)備的級(jí)別,必須為1 WORD biBitCount; //每個(gè)像素所需要的位數(shù),必須是1(雙色),//4(16色),8(256色)或24(真彩色)之一 DWORD biCompression; //位圖壓縮類型,必須是0(不壓縮),1 //(BI_RLE8//壓縮類型)或者2(BI_REL4)之一 DWORD biSizeImage; //位圖的大小,以字節(jié)為單位 LONG biXPelsPerMeter; //位圖水平分辨率,每米像素?cái)?shù) LONG biYPelsPerMeter; //位圖垂直分辨率,每米像素?cái)?shù) DWORD biClrUsed; //位圖實(shí)際使用的顏色表中的顏色數(shù) DWORD biClrImportant; // 位圖顯示過(guò)程中重要的顏色數(shù) } BITMAPINFOHEADER, *PBITMAPINFOHEADER; c.顏色表 顏色表用于說(shuō)明位圖中的顏色,它有若干個(gè)表項(xiàng),每一個(gè)表項(xiàng)是一個(gè)RGBQUAD類型的結(jié)構(gòu),定義一種顏色。RGBQUAD結(jié)構(gòu)的定義如下: typedef struct tagRGBQUAD { BYTE rgbBlue; //藍(lán)色的亮度 BYTE rgbGreen; //綠色的亮度 BYTE rgbRed;// 紅色的亮度 BYTE rgbReserved; //保留,必須為0 } RGBQUAD; 顏色表中RGBQUAD結(jié)構(gòu)數(shù)據(jù)的個(gè)數(shù)由biBitCount來(lái)確定: 當(dāng)biBitCount = 1,4,8,時(shí),分別有2,16,256個(gè)表項(xiàng); 當(dāng)biBitCount = 24時(shí),沒有顏色表項(xiàng)。 位圖信息頭和顏色表組成位圖信息,BITMAPINFO結(jié)構(gòu)定義如下: Typedef struct tagBITMAPINFO { BITMAPFILEHEADER bmiHeader;//位圖信息頭 RGBQUAD bimColors[1]; //顏色表 } d.位圖數(shù)據(jù) 位圖數(shù)據(jù)記錄了位圖的沒一個(gè)像素值,記錄順序是在掃描行內(nèi)是從左到右,掃描行之間是從下到上。位圖的一個(gè)像素所占的字節(jié)數(shù): 當(dāng)biBitCount = 1時(shí),8個(gè)像素占一個(gè)字節(jié); 當(dāng)biBitCount = 4時(shí),2個(gè)像素占一個(gè)字節(jié); 當(dāng)biBitCount = 8時(shí),一個(gè)像素占一個(gè)字節(jié); 當(dāng)biBitCount = 24時(shí),一個(gè)像素占3個(gè)字節(jié)。二.BMP圖像的顯示
大多數(shù)圖像處理都是基于與設(shè)備無(wú)關(guān)位圖(DIB)來(lái)進(jìn)行討論的,我們所使用的是方法是windows API來(lái)實(shí)現(xiàn)BMP的顯示,而API中又沒有處理DIB位圖的類,所以需要定義一個(gè)處理DIB位圖的專用Cbmp類,在其中封裝必要而有效的DIB數(shù)據(jù)成員和處理函數(shù),該類具有的功能如下:
class CBmp
{
public:
int GetHeight();//返回位圖的高度
int GetWidth();//返回位圖的寬度
bool SaveToFile(CString & filename); //保存位圖
bool IsCreate();
void ShowBmp(HDC hdc,int x,int y,double k); //顯示BMP位圖
bool SetColor(int x,int y,COLORREF color);
COLORREF GetColor(int x,int y);
bool Create(int width,int heigh);
bool CreateFromFile(CString &FileName); //圖像文件讀取
CBmp();
virtual ~CBmp();
private:
bool is_create;
int BytesPerLine;
int buffer_size;
const int Max_Width;
const int Max_Height;
char * buffer;
int Width;
int Height;
};
Cbmp類設(shè)計(jì)的目標(biāo)
用面向?qū)ο蟮姆椒ㄌ幚砦粓D的核心是設(shè)計(jì)一個(gè)DIB的類,稱之為Cbmp類,我主要從功能、數(shù)據(jù)封裝、和繼承等方面來(lái)分析Cbmp類的設(shè)計(jì)目標(biāo)。
1.功能
a.根據(jù)上面對(duì)DIB操作的分析,Cbmp的基本功能包括:
b.DIB文件的讀、寫;
c.提供位圖寬度、高度、顏色數(shù)目等位圖相關(guān)信息;
d.提供有關(guān)位圖占據(jù)內(nèi)存空間信息,包括:圖像數(shù)據(jù)區(qū)首地址、顏色表首地址、位圖信息結(jié)構(gòu)首地址等信息。
2.數(shù)據(jù)封裝
面向?qū)ο蠓椒ǖ囊粋€(gè)主要的特征就是數(shù)據(jù)封裝,即將類的成員數(shù)據(jù)隱藏在類中,外界只能通過(guò)類的成員函數(shù)來(lái)操作類的成員數(shù)據(jù)。這是面向?qū)ο蠓椒ǖ闹匾獌?yōu)點(diǎn),它可以保護(hù)類中的數(shù)據(jù)不受外界的故意修改。
3.繼承
在這里不多介紹!
三.DICM圖像的讀取與顯示
DICM數(shù)據(jù)的編碼方式和文件結(jié)構(gòu)在莘浩萍本科畢業(yè)論文中有詳細(xì)的論述。
將DCM圖像轉(zhuǎn)化為BMP圖像
要把DICOM圖像轉(zhuǎn)換為BMP圖像,首先要讀取DICOM圖像文件中的參數(shù)。通過(guò)DICOM說(shuō)明文件或DICOM標(biāo)準(zhǔn)中的數(shù)據(jù)字典,查詢到存儲(chǔ)圖像的相關(guān)數(shù)據(jù),主要有:圖像顯示矩陣,即圖像的寬與高;圖像存儲(chǔ)位數(shù),即每一個(gè)像素占用幾個(gè)字節(jié),如果圖像為標(biāo)準(zhǔn)的12位灰度(黑白)圖像,必然占用2個(gè)字節(jié);找到標(biāo)簽號(hào)為(7FE0,0010)的元素,它指明了圖像像素的起始位置。
DICOM中像素的顯示順序是從左到右,從上到下,第一行顯示完再顯示第二行,設(shè)左上角第一個(gè)像素坐標(biāo)為(1,1),在存儲(chǔ)文件中的地址為“A0”,顯示矩陣為寬M、高N,圖像顯示的時(shí)候某一坐標(biāo)為(X,Y)的像素點(diǎn)在文件中存儲(chǔ)的位置為:2×[X+M×(Y-1)-1]+A0。
有了以上數(shù)據(jù),就可以確定BMP圖像的相關(guān)參數(shù),確定每一個(gè)像素在文件中的存儲(chǔ)位置。但與DICOM圖像中像素的顯示順序不同的是,BMP圖像從左下角開始顯示,從左到右,從下到上,因此要將DICOM圖像中最下排的像素填到BMP圖像的最上排。
需要注意的是:BMP圖像中,其存儲(chǔ)像素的藍(lán)、綠、紅3個(gè)字節(jié)的值相等就構(gòu)成了黑白圖像,因此在顯示黑白圖像時(shí),這3個(gè)字節(jié)只包含一個(gè)字節(jié)的信息量,從而BMP圖像只能包含8位256個(gè)灰度等級(jí)。而DICOM的12位灰度圖像可以包含4096個(gè)灰度等級(jí)。將12位的DICOM圖像轉(zhuǎn)換為BMP圖像,必須進(jìn)行變換。
變換利用窗口技術(shù),變換之前,要先讀取DICOM圖像中的顯示窗寬、窗位值(在DICOM設(shè)備或軟件中,將窗寬、窗位調(diào)節(jié)到最佳),根據(jù)窗位確定中間值,低于窗寬的顯示為最
暗,高于窗寬的顯示為最亮,窗寬范圍內(nèi)的值通過(guò)線性或非線性變換轉(zhuǎn)換為小于256的值。由于人眼的分辨率有限,256個(gè)灰度級(jí)已完全能滿足人眼的辨別極限。
對(duì)于8位的黑白圖像或彩超等的彩色圖像的像素,和BMP的單個(gè)像素長(zhǎng)度結(jié)構(gòu)一致,只須按坐標(biāo)位置填入BMP圖像中即可。
四.DICM轉(zhuǎn)換的具體實(shí)現(xiàn):
有DICM的復(fù)雜性,本文只針對(duì)某些DCM圖像做讀取與顯示。
首先在Cbmp類中添加public成員函數(shù):
?? bool CreateFromDicm(DICM & Dicm);//從DICM圖像中讀取數(shù)據(jù)
設(shè)計(jì)一個(gè)新的類DICM,其成員變量和成員函數(shù)如下:
class DICM?
{
public:
?? bool IsCreate();
?? int buffer_size;
?? char * buffer;
?? bool CreateFromFile(CString & filename);//從文件中打開圖像
?? bool Create();
?? DICM();
?? virtual ~DICM();
private:
?? bool is_create;
};
總結(jié)
以上是生活随笔為你收集整理的DICM和BMP图像的显示及转换的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 馈线互调测试仪仿真软件,CYME电力工程
- 下一篇: 通过Cadence学拉扎维的第0天-工艺