IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 用 C C++ 读取DICOM文件 -> 正文阅读

[C++知识库]用 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);       //值代表的意思VR
    inline 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的TAG
    bool 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_DETIAL
    for(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);
    }
#endif
    clearerr(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_0200
        sprintf(tag, "dicom_tag_%02X%02X_%02X%02X",buf[1],buf[0],buf[3],buf[2]);
        key = (string)tag;
 
#if DIYE_READ_DICOM_DETIAL
        qDebug("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());
        }
#endif
        if(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_DETIAL
            qDebug("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_DETIAL
                qDebug("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_DETIAL
    qDebug("step 5:dicom_value_field_lenght=%d",fixed_length);
#endif
 
    if(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_DETIAL
                qDebug("step 5:0x%02x; m_diconde_file_byte_count=%d",buf[i],m_diconde_file_byte_count);
#endif
            }
#if DIYE_READ_DICOM_DETIAL
            qDebug("step 5:value_field=%s", m_dicom_file_meta_elements.value_field);
#endif
            if(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_DETIAL
                qDebug("sum =%d : %02X %02X %02X %02X",sum,temp[0],temp[1],temp[2],temp[3]);
#endif
                if(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_DETIAL
                qDebug("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_DETIAL
        qDebug("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_DETIAL
        qDebug("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_DETIAL
        qDebug("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_DETIAL
        qDebug("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++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-10-22 20:56:54  更:2022-10-22 20:58:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 2:25:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码