用 C, C++ 读取DICOM文件
生活随笔
收集整理的這篇文章主要介紹了
用 C, C++ 读取DICOM文件
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
用心閱讀必能正確解析DICOM,外國佬的協議也很隨性. 嫌煩的朋友直接下載代碼就能運行.
此代碼經過許多工業&醫療的CT圖像驗證,確實可行.若有錯誤之處請回貼.
一. 如下圖: Dicom數據集結構? ?理解了VR這個動態可變選項,就全理解了
?DICOM英文文檔下載地址:? ?
https://www.dicomstandard.org/current
https://www.dclunie.com/dicom-status/status.html
?示例使用: (1)開發工具: qt5.14.2; 注意代碼中的日志打印qDebug,(2)代碼本身與QT無關方便移植
DicomFile *pData = new DicomFile;pData->read_dicom("D://1.DICONDE");//1280: dicode文件寬, 1024是行,注意log日志有//QImage image = QImage(pData->m_p_buf_pixel_data,1280,1024,QImage::Format_Grayscale16);QImage image = QImage(pData->get_pixel_data(),pData->get_pixel_column(),pData->get_pixel_rows(),QImage::Format_Grayscale16);二.編碼:常量部份
#ifndef GLOBAL_CONST_H #define GLOBAL_CONST_H///其它↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ #define DIYE_READ_DICOM_DETIAL 0 //1:處理DICOM顯示詳細信息///常量↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ #define DATA_LENGTH_256 256 #define BOOL_FALSE 0 #define BOOL_TRUE 1 #define INT_0 0 #define INT_1 1 #define INT_16 16 #define INT_30 30 #define MAX_KERNEL_LENGTH 31 #define INT_100 100 #define INT_255 255 #define INT_256 256 #define INT_700 700 #define INT_1000 1000 #define INT_1024 1024 #define INT_2048 2048 #define STRING_EMPTY ""///協議文檔:<<DICOM Part 5 Data Structures and Encoding.pdf & DICOM Part 6 Data Dictionary.pdf>>↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ #define DICOM_D_0x44 0x44 //D:DICOM文件格式是以DICM打頭的 #define DICOM_I_0x49 0x49 //I:DICOM文件格式是以DICM打頭的 #define DICOM_C_0x43 0x43 //C:DICOM文件格式是以DICM打頭的 #define DICOM_M_0x4D 0x4D //M:DICOM文件格式是以DICM打頭的#define DICOM_TAG_0028_0010 "dicom_tag_0028_0010" //DICOM文件的像素高度標記 #define DICOM_KEYWORD_0028_0010 "rows" #define DICOM_TAG_0028_0011 "dicom_tag_0028_0011" //DICOM文件的像素寬度標記 #define DICOM_KEYWORD_0028_0011 "columns"#define DICOM_TAG_7FE0_0010 "dicom_tag_7FE0_0010" //DICOM文件的像素數據標記 #define DICOM_KEYWORD_7FE0_0010 "pixel_data" ///協議文檔:<<DICOM Part 5 Data Structures and Encoding.pdf & DICOM Part 6 Data Dictionary.pdf>>↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ #endif // GLOBAL_CONST_H三. 結構體: global_struct.h
#ifndef GLOBAL_STRUCT_H #define GLOBAL_STRUCT_H#include <QObject> class GlobalStruct : public QObject {Q_OBJECT public: //DICOM:typedef struct DICOM_FILE_META_ELEMENTS{uchar group[2]; //TAG:組編號uchar element[2]; //TAG:元素編號uchar keyword[128]; //元素描述uchar vr[2]; //值代表縮寫uchar value_lenght; //用N個字節表示值的長度uchar value_byte_lenght[4]; //實際值的長度:小端模式uchar value_field[256]; //實際值}_DICOM_FILE_META_ELEMENTS;typedef struct DICOM_FILE_META_ELEMENTS_LIST{DICOM_FILE_META_ELEMENTS elements[64];int elements_length;}_DICOM_FILE_META_ELEMENTS_LIST;};#endif // GLOBAL_STRUCT_H?四 編碼:DicomFile.h
#ifndef DICOMFILE_H #define DICOMFILE_H#include <QObject> #include <QFile> #include <map> extern "C"{ #include <stdio.h> #include <io.h> #include <fcntl.h> #include <unistd.h> } #include "../common/global_const.h" #include "../common/global_struct.h"//此處枚舉變量根據實際場景修正一下 enum DICOM_VR_TYPE{VR_TYPE_NULL,VR_TYPE_EXPLICIT_TABLE_7_1_1,VR_TYPE_EXPLICIT_TABLE_7_1_2,VR_TYPE_IMPLICIT_TABLE_7_1_3};using namespace std; typedef bool (*f_group_element)(void*);class DicomFile : public QObject {Q_OBJECT public:explicit DicomFile(QObject *parent = nullptr);~DicomFile();int get_pixel_column(); //像素寬int get_pixel_rows(); //像素高uchar* get_pixel_data();//字符集:組號與元素號static bool dicom_tag_7FE0_0010(void*); //DICOM文件的圖像像素數據標識符static bool dicom_tag_0028_0011(void*);static bool dicom_tag_0028_0010(void*);/*** @brief 讀取DICOM文件*/void read_dicom(QString);/*** @brief 當前文件有效性標記位一定是在文件的index=128,129,130,131處* @param p_file_diconde* @return true; 文件有效*/bool get_is_valid_diconde_file(FILE *p_file_diconde);inline bool dicom_data_element_tag(FILE *p_file_diconde); //組號及元素號inline bool dicom_value_representation(FILE *p_file_diconde); //值代表的意思VRinline bool dicom_value_length(FILE *p_file_diconde); //值占據的長度inline bool dicom_value_field(FILE *p_file_diconde); //具體的值inline bool is_data_structures_and_encoding_vr_table_7_1_1(const uchar*,FILE *p_file_diconde);inline bool is_data_structures_and_encoding_vr_table_7_1_2(const uchar*);bool get_pixel_data(FILE *p_file_diconde); //圖像像素數據inline int hex_to_int_little_endian(uchar* src, int offset); signals:private:int m_diconde_file_byte_count; //DICOM文件字節總數//DICOM的單個數據元數GlobalStruct::DICOM_FILE_META_ELEMENTS_LIST m_dicm_file_meta_elements_list; //DICOM的所有數據元數集GlobalStruct::DICOM_FILE_META_ELEMENTS m_dicom_file_meta_elements; std::map<string,f_group_element> m_f_map; //DICOM的Dataset的TAGbool m_is_tag_e07f_1000;int m_pixel_data_length; //圖像數據標志位bool m_is_tag_rows; int m_rows; //圖像的行像素bool m_is_tag_columns; int m_columns; //圖像的列像素uchar *m_p_buf_pixel_data; //圖像的像素字節//參見<<DICOM Part 5 Data Structures and Encoding.pdf>>Page53//顯示VR在Table 7.1-2中,其值有固定長度表示; 則不在Table 7.1-2中,其值靈活變化EnumParamter::DICOM_VR_TYPE m_dicom_vr_type;};#endif // DICOMFILE_H五.編碼DicomFile.cpp
#include "dicomfile.h"DicomFile::DicomFile(QObject *parent) : QObject(parent),m_diconde_file_byte_count(0),m_is_tag_e07f_1000(false),m_pixel_data_length(0),m_is_tag_rows(false),m_rows(0),m_is_tag_columns(false),m_columns(0),m_p_buf_pixel_data(nullptr),m_dicom_vr_type(EnumParamter::DICOM_VR_TYPE::VR_TYPE_NULL) {m_f_map.clear();//若需要取DICONDE中保存的圖像信息,則可以打開需要的部份m_f_map.insert(std::make_pair(DICOM_TAG_0028_0010,dicom_tag_0028_0010)); //圖像的高度m_f_map.insert(std::make_pair(DICOM_TAG_0028_0011,dicom_tag_0028_0011)); //圖像的寬度m_f_map.insert(std::make_pair(DICOM_TAG_7FE0_0010,dicom_tag_7FE0_0010)); //圖像數據TAG } DicomFile::~DicomFile() {free(m_p_buf_pixel_data); m_p_buf_pixel_data=nullptr; } int DicomFile::get_pixel_column(){return m_columns;} int DicomFile::get_pixel_rows(){return m_rows;} uchar* DicomFile::get_pixel_data(){return m_p_buf_pixel_data;} // //DICOM文件的圖像像素數據標識符 bool DicomFile::dicom_tag_7FE0_0010(void* arg) {char c_keyword[128]; memset(c_keyword,0x00,sizeof(c_keyword));DicomFile* p_dicom_file = (DicomFile*)arg;p_dicom_file->m_is_tag_e07f_1000 = true;snprintf(c_keyword,sizeof(c_keyword),"%s",DICOM_KEYWORD_7FE0_0010);memcpy(p_dicom_file->m_dicom_file_meta_elements.keyword,c_keyword,sizeof(c_keyword));qDebug("step 2:DICOM_KEYWORD_7FE0_0010=%s",p_dicom_file->m_dicom_file_meta_elements.keyword);return true; }//DICOM文件的像素寬度標記 bool DicomFile::dicom_tag_0028_0011(void* arg) {char c_keyword[128]; memset(c_keyword,0x00,sizeof(c_keyword));DicomFile* p_dicom_file = (DicomFile*)arg;p_dicom_file->m_is_tag_columns=true;snprintf(c_keyword,sizeof(c_keyword),"%s",DICOM_KEYWORD_0028_0011);memcpy(p_dicom_file->m_dicom_file_meta_elements.keyword,c_keyword,sizeof(c_keyword));qDebug("step 2:DICOM_KEYWORD_0028_0011=%s",p_dicom_file->m_dicom_file_meta_elements.keyword);return true; }//DICOM文件的像素高度標記 bool DicomFile::dicom_tag_0028_0010(void* arg) {char c_keyword[128]; memset(c_keyword,0x00,sizeof(c_keyword));DicomFile* p_dicom_file = (DicomFile*)arg;p_dicom_file->m_is_tag_rows=true;snprintf(c_keyword,sizeof(c_keyword),"%s",DICOM_KEYWORD_0028_0010);memcpy(p_dicom_file->m_dicom_file_meta_elements.keyword,c_keyword,sizeof(c_keyword));qDebug("step 2:DICOM_KEYWORD_0028_0010=%s",p_dicom_file->m_dicom_file_meta_elements.keyword);return true; } // bool DicomFile::read_dicom(QString e) {bool ret_val=false;m_diconde_file_byte_count = 0;m_is_tag_e07f_1000 =false; m_pixel_data_length=0;m_is_tag_rows=false; m_rows=0;m_is_tag_columns=false; m_columns=0;m_p_buf_pixel_data=nullptr;FILE *p_file_diconde = fopen(e.toLatin1().data(), "rb");if (nullptr == p_file_diconde){qDebug("step 0 :read_diconde nullptr == p_file_diconde error file=%s.",e.toLatin1().data());return ret_val;}if(false == get_is_valid_diconde_file(p_file_diconde)){qDebug("step 1 : dicom file error!"); return ret_val;}memset(&m_dicm_file_meta_elements_list,0x00,sizeof(m_dicm_file_meta_elements_list));bool is_need_save_element = false; int circulation = -1;while (!m_is_tag_e07f_1000){is_need_save_element = false;memset(&m_dicom_file_meta_elements,0x00,sizeof(m_dicom_file_meta_elements));is_need_save_element = dicom_data_element_tag(p_file_diconde);dicom_value_representation(p_file_diconde);dicom_value_length(p_file_diconde);dicom_value_field(p_file_diconde);if(is_need_save_element){++circulation; if(64 <= circulation){ qDebug("Error: Max elements is %d.",circulation); break;}m_dicm_file_meta_elements_list.elements_length = m_dicm_file_meta_elements_list.elements_length+1;m_dicm_file_meta_elements_list.elements[circulation]=m_dicom_file_meta_elements;}if(m_is_tag_e07f_1000 && get_pixel_data(p_file_diconde)){ret_val=true;}}#if DIYE_READ_DICOM_DETIALfor(int i= 0 ; i <m_dicm_file_meta_elements_list.elements_length;i++){qDebug("i=%d, group[%02x%02x], element[%02x%02x], vr[%02x%02x] ,value_lenght=%d"",value_byte_lenght[%02x%02x%02x%02x], value_field=%s",i,m_dicm_file_meta_elements_list.elements[i].group[0],m_dicm_file_meta_elements_list.elements[i].group[1],m_dicm_file_meta_elements_list.elements[i].element[0],m_dicm_file_meta_elements_list.elements[i].element[1],m_dicm_file_meta_elements_list.elements[i].vr[0],m_dicm_file_meta_elements_list.elements[i].vr[1],m_dicm_file_meta_elements_list.elements[i].value_lenght,m_dicm_file_meta_elements_list.elements[i].value_byte_lenght[0],m_dicm_file_meta_elements_list.elements[i].value_byte_lenght[1],m_dicm_file_meta_elements_list.elements[i].value_byte_lenght[2],m_dicm_file_meta_elements_list.elements[i].value_byte_lenght[3],m_dicm_file_meta_elements_list.elements[i].value_field);} #endifclearerr(p_file_diconde);fclose(p_file_diconde);qDebug("p_file_diconde=%s; byte count=%d.",e.toLatin1().data(),m_diconde_file_byte_count);return ret_val; } /*** @brief An ordered pair of 16-bit unsigned integers representing the Group Number followed by Element Number* @param p_file_diconde* @return true:*/ bool DicomFile::dicom_data_element_tag(FILE *p_file_diconde) {bool ret_val = false;size_t count = 0;int fixed_length = 4; uchar buf[fixed_length];char tag[32]; string key;fixed_length = 4; buf[fixed_length]; memset(buf,0x00,sizeof(buf));if(fixed_length == (int)(count = fread(buf, 1, fixed_length, p_file_diconde))) //tag: Registry of DICOM File Meta Elements{m_diconde_file_byte_count = m_diconde_file_byte_count + count;memset(tag,0x00,sizeof(tag));//buf:4個字節串 02 00 00 02-->dicom_tag_0002_0200sprintf(tag, "dicom_tag_%02X%02X_%02X%02X",buf[1],buf[0],buf[3],buf[2]);key = (string)tag;#if DIYE_READ_DICOM_DETIALqDebug("step 2: [%s; raw_data: %02X %02X %02X %02X],m_diconde_file_byte_count=%d",tag,buf[0],buf[1],buf[2],buf[3],m_diconde_file_byte_count);if(m_f_map.find(key) == m_f_map.end()){qDebug("step 2: data_element_tag={%s} isn't exist in this programe.", key.c_str());} #endifif(m_f_map.find(key) != m_f_map.end()){m_f_map[key](this); ret_val = true;}m_dicom_file_meta_elements.group[0]=buf[0];m_dicom_file_meta_elements.group[1]=buf[1];m_dicom_file_meta_elements.element[0]=buf[2];m_dicom_file_meta_elements.element[1]=buf[3];}return ret_val; }bool DicomFile::dicom_value_representation(FILE *p_file_diconde) {bool ret_val = false;m_dicom_vr_type = EnumParamter::DICOM_VR_TYPE::VR_TYPE_NULL;size_t count = 0; int fixed_length = 2;uchar buf[fixed_length];memset(buf,0x00,sizeof(buf));if(fixed_length == (int)(count = fread(buf, 1, fixed_length, p_file_diconde))){ret_val = true;m_diconde_file_byte_count = m_diconde_file_byte_count + count;if(is_data_structures_and_encoding_vr_table_7_1_2(buf)){m_dicom_vr_type = EnumParamter::DICOM_VR_TYPE::VR_TYPE_EXPLICIT_TABLE_7_1_2;}else if(is_data_structures_and_encoding_vr_table_7_1_1(buf,p_file_diconde)){m_dicom_vr_type = EnumParamter::DICOM_VR_TYPE::VR_TYPE_EXPLICIT_TABLE_7_1_1;}else{m_dicom_vr_type = EnumParamter::DICOM_VR_TYPE::VR_TYPE_IMPLICIT_TABLE_7_1_3;m_dicom_file_meta_elements.value_lenght = 4;for(int i = 0 ; i< fixed_length; i++){m_dicom_file_meta_elements.value_byte_lenght[i]=buf[i];}}}return ret_val; }bool DicomFile::dicom_value_length(FILE *p_file_diconde) {bool ret_val = false;size_t count = 0;int fixed_length = m_dicom_file_meta_elements.value_lenght;if(EnumParamter::DICOM_VR_TYPE::VR_TYPE_IMPLICIT_TABLE_7_1_3 == m_dicom_vr_type){fixed_length = 2;}uchar buf[fixed_length];memset(buf,0x00,sizeof(buf));if(fixed_length == (int)(count = fread(buf, 1, fixed_length, p_file_diconde))){m_diconde_file_byte_count = m_diconde_file_byte_count + count;if(EnumParamter::DICOM_VR_TYPE::VR_TYPE_IMPLICIT_TABLE_7_1_3 == m_dicom_vr_type){for(int i = 0 ; i<fixed_length;i++){m_dicom_file_meta_elements.value_byte_lenght[2+i]=buf[i];} #if DIYE_READ_DICOM_DETIALqDebug("step 4: value_byte_lenght =[0]=0x%02x,[1]=0x%02x,[2]=0x%02x,[3]=0x%02x",m_dicom_file_meta_elements.value_byte_lenght[0],m_dicom_file_meta_elements.value_byte_lenght[1],m_dicom_file_meta_elements.value_byte_lenght[2],m_dicom_file_meta_elements.value_byte_lenght[3]); #endif}else{for(int i = 0 ; i<fixed_length;i++){m_dicom_file_meta_elements.value_byte_lenght[i]=buf[i]; #if DIYE_READ_DICOM_DETIALqDebug("step 4:value_byte_lenght=0x%02x; m_diconde_file_byte_count=%d",buf[i],m_diconde_file_byte_count); #endif}}ret_val = true;}return ret_val; }bool DicomFile::dicom_value_field(FILE *p_file_diconde) {bool ret_val = false;size_t count = 0;int fixed_length = 0;if(2 == m_dicom_file_meta_elements.value_lenght){fixed_length = (int)((m_dicom_file_meta_elements.value_byte_lenght[0] & 0xFF)| ((m_dicom_file_meta_elements.value_byte_lenght[1] & 0xFF) << 8));}else if(4 == m_dicom_file_meta_elements.value_lenght){fixed_length = (int)((m_dicom_file_meta_elements.value_byte_lenght[0] & 0xFF)| ((m_dicom_file_meta_elements.value_byte_lenght[1] & 0xFF) << 8)| ((m_dicom_file_meta_elements.value_byte_lenght[2] & 0xFF) << 16)| ((m_dicom_file_meta_elements.value_byte_lenght[3] & 0xFF) << 24));}#if DIYE_READ_DICOM_DETIALqDebug("step 5:dicom_value_field_lenght=%d",fixed_length); #endifif(m_is_tag_e07f_1000){m_pixel_data_length = fixed_length; //DICOM文件像素值數據長度return ret_val = true;}else if(!m_is_tag_e07f_1000 && (INT_256 < fixed_length)) //此字段存貯的字符串長度過大,丟棄處理!若需要可另處理{uchar buf[fixed_length]; memset(buf,0x00,sizeof(buf));count = fread(buf, 1, fixed_length, p_file_diconde);qDebug("DICOM Value field[fixed_length=%d | count=%d] more than 256",fixed_length,(int)count);return ret_val;}if(0 < fixed_length ){uchar buf[fixed_length]; memset(buf,0x00,sizeof(buf));if(fixed_length == (int)(count = fread(buf, 1, fixed_length, p_file_diconde))){ret_val = true;m_diconde_file_byte_count = m_diconde_file_byte_count + count;for(int i = 0 ; i<fixed_length;i++){m_dicom_file_meta_elements.value_field[i]=buf[i]; #if DIYE_READ_DICOM_DETIALqDebug("step 5:0x%02x; m_diconde_file_byte_count=%d",buf[i],m_diconde_file_byte_count); #endif} #if DIYE_READ_DICOM_DETIALqDebug("step 5:value_field=%s", m_dicom_file_meta_elements.value_field); #endifif(m_is_tag_rows){m_is_tag_rows=false; m_rows = hex_to_int_little_endian(buf,0);qDebug("step 5:m_rows=%d", m_rows);}else if(m_is_tag_columns){m_is_tag_columns=false; m_columns = hex_to_int_little_endian(buf,0);qDebug("step 5:m_columns=%d", m_columns);}}}else if(-1 == fixed_length &&EnumParamter::DICOM_VR_TYPE::VR_TYPE_IMPLICIT_TABLE_7_1_3 == m_dicom_vr_type){vector<uchar> vector_buf; //用 vector 來存儲vector_buf.clear();int sum = 0 ;size_t count = 0; int fixed_length = 1;uchar temp[4]; memset(temp,0x00,sizeof(temp));while (true){for(int i = 3; i > 0; i--){ temp[i] = temp[i-1];}if(fixed_length == (int)(count = fread(temp, 1, fixed_length, p_file_diconde))){m_diconde_file_byte_count = m_diconde_file_byte_count + count;sum++;vector_buf.push_back(temp[0]); #if DIYE_READ_DICOM_DETIALqDebug("sum =%d : %02X %02X %02X %02X",sum,temp[0],temp[1],temp[2],temp[3]); #endifif(0xE0 == temp[0] && 0xDD == temp[1] && 0xFF == temp[2] && 0xFE == temp[3]){//參見《DICOM Part 5 Data Structures and Encoding.pdf》//P53 Section:7.1-3. Data Element with Implicit VR 結合才能明白//P56 Section:7.5 Nesting of Data Sets 結合才能明白fread(temp, 1, 4, p_file_diconde);//0x00 00 00 00 跟在 FE FF DD E0之后的固定格式ret_val = true; break;}}else{qDebug("DICOM file formate error.");ret_val = false; break;}}if(ret_val){fixed_length = vector_buf.size();for(int i = 0 ; i < fixed_length; i++){m_dicom_file_meta_elements.value_field[i]=vector_buf[i]; #if DIYE_READ_DICOM_DETIALqDebug("step 5:0x%02x; m_diconde_file_byte_count=%d",vector_buf[i],m_diconde_file_byte_count); #endif}qDebug("step 5:value_field=%s", m_dicom_file_meta_elements.value_field);}}return ret_val; }//DICOM Part 5 Data Structures and Encoding //OB, OD, OF, OL, OV, OW, SQ and UN bool DicomFile::is_data_structures_and_encoding_vr_table_7_1_1(const uchar* p_vr,FILE *p_file_diconde) {bool ret_val = false;if((0x4F == p_vr[0] && 0x42 == p_vr[1]) //VR:OB|| (0x4F == p_vr[0] && 0x44 == p_vr[1]) //VR:OD|| (0x4F == p_vr[0] && 0x46 == p_vr[1]) //VR:OF|| (0x4F == p_vr[0] && 0x4C == p_vr[1]) //VR:OL|| (0x4F == p_vr[0] && 0x56 == p_vr[1]) //VR:OV|| (0x4F == p_vr[0] && 0x57 == p_vr[1]) //VR:OW|| (0x53 == p_vr[0] && 0x51 == p_vr[1]) //VR:SQ|| (0x55 == p_vr[0] && 0x4E == p_vr[1]) //VR:UN|| (0x55 == p_vr[0] && 0x43 == p_vr[1]) //VR:UC|| (0x55 == p_vr[0] && 0x52 == p_vr[1]) //VR:UR|| (0x55 == p_vr[0] && 0x54 == p_vr[1]) //VR:UT){ret_val = true;}if(ret_val){m_dicom_file_meta_elements.vr[0]=p_vr[0];m_dicom_file_meta_elements.vr[1]=p_vr[1];m_dicom_file_meta_elements.value_lenght = 4;//參見<<DICOM Part 5 Data Structures and Encoding.pdf>>Page53//表<Table 7.1-1. Data Element with Explicit VR other than as shown in Table 7.1-2>中字段VR保留int fixed_length = 2; size_t count = 0;uchar buf[fixed_length]; memset(buf,0x00,sizeof(buf));count = fread(buf, 1, fixed_length, p_file_diconde);m_diconde_file_byte_count = m_diconde_file_byte_count + count; #if DIYE_READ_DICOM_DETIALqDebug("step 3 table_7_1_1:Reserved bytes [0x%02X][0x%02X]",buf[0],buf[1]);qDebug("step 3 table_7_1_1:vr is exist in table_7_1_1. vr[0]=0x%02x, vr[1]=0x%02x; m_diconde_file_byte_count=%d",m_dicom_file_meta_elements.vr[0], m_dicom_file_meta_elements.vr[1],m_diconde_file_byte_count); #endif}else{m_dicom_file_meta_elements.value_lenght = 0; #if DIYE_READ_DICOM_DETIALqDebug("step 3 table_7_1_1:vr isn't exist in table_7_1_1. vr[0]=0x%02x, vr[1]=0x%02x; m_diconde_file_byte_count=%d",m_dicom_file_meta_elements.vr[0], m_dicom_file_meta_elements.vr[1],m_diconde_file_byte_count); #endif}return ret_val; }//參見<<DICOM Part 5 Data Structures and Encoding.pdf>>Page53 //AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, PN, SH, SL, SS, ST, TM, UI, UL and US //true:VR在table_7_1_2中存在,其值則有固定的值長底 bool DicomFile::is_data_structures_and_encoding_vr_table_7_1_2(const uchar* p_vr) {bool ret_val = false;if((0x41 == p_vr[0] && 0x45 == p_vr[1]) //VR:AE|| (0x41 == p_vr[0] && 0x53 == p_vr[1]) //VR:AS|| (0x41 == p_vr[0] && 0x54 == p_vr[1]) //VR:AT|| (0x43 == p_vr[0] && 0x53 == p_vr[1]) //VR:CS|| (0x44 == p_vr[0] && 0x41 == p_vr[1]) //VR:DA|| (0x44 == p_vr[0] && 0x53 == p_vr[1]) //VR:DS|| (0x44 == p_vr[0] && 0x54 == p_vr[1]) //VR:DT|| (0x46 == p_vr[0] && 0x4C == p_vr[1]) //VR:FL|| (0x46 == p_vr[0] && 0x44 == p_vr[1]) //VR:FD|| (0x49 == p_vr[0] && 0x53 == p_vr[1]) //VR:IS|| (0x4C == p_vr[0] && 0x4F == p_vr[1]) //VR:LO|| (0x4C == p_vr[0] && 0x54 == p_vr[1]) //VR:LT|| (0x50 == p_vr[0] && 0x4E == p_vr[1]) //VR:PN|| (0x53 == p_vr[0] && 0x48 == p_vr[1]) //VR:SH|| (0x53 == p_vr[0] && 0x4C == p_vr[1]) //VR:SL|| (0x53 == p_vr[0] && 0x53 == p_vr[1]) //VR:SS|| (0x53 == p_vr[0] && 0x54 == p_vr[1]) //VR:ST|| (0x54 == p_vr[0] && 0x4D == p_vr[1]) //VR:TM|| (0x55 == p_vr[0] && 0x49 == p_vr[1]) //VR:UI|| (0x55 == p_vr[0] && 0x4C == p_vr[1]) //VR:UL|| (0x55 == p_vr[0] && 0x53 == p_vr[1]) //VR:US){ ret_val = true; }if(ret_val){m_dicom_file_meta_elements.vr[0]=p_vr[0];m_dicom_file_meta_elements.vr[1]=p_vr[1];m_dicom_file_meta_elements.value_lenght = 2; #if DIYE_READ_DICOM_DETIALqDebug("step 3 table_7_1_2:vr is exist in table_7_1_2. vr[0]=0x%02x, vr[1]=0x%02x; m_diconde_file_byte_count=%d",m_dicom_file_meta_elements.vr[0], m_dicom_file_meta_elements.vr[1],m_diconde_file_byte_count); #endif}else{m_dicom_file_meta_elements.value_lenght = 0; #if DIYE_READ_DICOM_DETIALqDebug("step 3 table_7_1_2:vr isn't exist in table_7_1_2. vr[0]=0x%02x, vr[1]=0x%02x; m_diconde_file_byte_count=%d",m_dicom_file_meta_elements.vr[0], m_dicom_file_meta_elements.vr[1],m_diconde_file_byte_count); #endif}return ret_val; }bool DicomFile::get_pixel_data(FILE *p_file_diconde) {bool ret_val = false;size_t count = 0;if(nullptr != m_p_buf_pixel_data){free(m_p_buf_pixel_data); m_p_buf_pixel_data=nullptr;}m_p_buf_pixel_data = (uchar*)malloc(sizeof(uchar) * m_pixel_data_length);if(m_pixel_data_length == (int)(count = fread(m_p_buf_pixel_data, 1, m_pixel_data_length, p_file_diconde))){ret_val =true; qDebug("step 6:get pixel data successful.");}else{ qDebug("step 6:get pixel data fail."); }return ret_val; }/*** @brief 當前文件有效性標記位一定是在文件的index=128,129,130,131處* @param p_file_diconde* @return*/ bool DicomFile::get_is_valid_diconde_file(FILE *p_file_diconde) {bool ret_val = false;size_t count = 0;int fixed_length = 4;uchar buf[fixed_length]; memset(buf,0x00,sizeof(buf));while((fixed_length == (int)(count = fread(buf, 1, fixed_length, p_file_diconde)))&& 132 >= m_diconde_file_byte_count){m_diconde_file_byte_count = m_diconde_file_byte_count + count;if(buf[0] == DICOM_D_0x44 && buf[1] == DICOM_I_0x49&& buf[2] == DICOM_C_0x43 && buf[3] == DICOM_M_0x4D){qDebug("step 1:dicom file OK!");ret_val = true; break;}memset(buf,0x00,sizeof(buf));}return ret_val; }/*** @brief DicomFile::bytes_to_int_little_endian* @param src* @param offset* @return*/ int DicomFile::hex_to_int_little_endian(uchar* src, int offset) {int value;value = (int) ((src[offset] & 0xFF)| ((src[offset + 1] & 0xFF) << 8));return value; }?
總結
以上是生活随笔為你收集整理的用 C, C++ 读取DICOM文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LDA算法——线性判别
- 下一篇: 馈线互调测试仪仿真软件,CYME电力工程