我如何从DICOM文件中提取信息?

时间:2015-03-20 18:25:03

标签: c++ c file dicom

我想编写一个脚本来使用c或c ++提取DICOM文件的头信息,我不想使用像dicomsdl这样的外部库... 当我用Bloc-notes打开文件时,我看到特殊字符和字符串作为患者姓名.. 如果有人可以帮我读这个文件。

2 个答案:

答案 0 :(得分:2)

是的,我会以二进制文件打开文件,即使它可能包含字符序列。如果考虑得太深,请考虑编写以下内容 记录到文件(我将记录显示为C结构):

    struct rec_tag
    {
         int    id;
         char   name[50];
    };

现在,假设我使用该结构创建文件,如下面的代码所示:

file1.c中:

/* compile as: gcc -ansi -pedantic -Wall file.c -o file_test */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


struct rec_tag
{
    int   id;
    char  name[50];
};

int main(int argc, char** argv)
{
    FILE*          fp = NULL;
    struct rec_tag rec1;
    struct rec_tag rec2;

    rec1.id = 20;
    strcpy(rec1.name, "thurizas");

    rec2.id = 345689;
    strcpy(rec2.name, "Marouane");

    if(NULL != (fp = fopen("./short.dat", "ab")))
    {
         fwrite(&rec1, sizeof(struct rec_tag), 1, fp);
         fwrite(&rec2, sizeof(struct rec_tag), 1, fp);

         fclose(fp);
    }
    return 0;
}

现在,假设我在 emacs 中打开此文件,许多特殊符号(例如^ T和^ @)中的字符串穿插着字符串。在十六进制编辑器(例如 okteta )中打开文件可能很有启发性,我们看到:

    14 00 00 00 74 68 75 72 69 7A 61 73 00 00 00 00 01 00 00 00 00 00
    00 00 ED 06 40 00 00 00 00 00 C2 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 A0 06 40 00 00 00 00 00 59 46 05 00 4D 61 72 6F 75 61 
    6E 65 00 7F 00 00 2E 4E 3D F6 00 00 00 00 67 03 40 00 00 00 00 00 
    FF FF FF FF 00 00 00 00 C0 B5 B3 C5 FF 7F 00 00 38 F1 CA BE 31 7F 
    00 00

现在,十六进制数字74 68 75 72 69 7A 61 73的序列是&#34; thurizas&#34;的ASCII码。 (大多数编辑都会展示)。现在文件中的前四个字节是id号。现在这是另一个(潜在的)问题,我在具有x86_64进程的计算机上创建了该文件,因此整数以小端形式存储在内存中,因此需要读取序列14 00 00 00 ...向后(缺少一个更好的术语)作为00 00 00 14,它是20位的32位十六进制表示。

另外,请注意,因为我对字符数组的处理方式并不特别小心,因为文件中存在无关的垃圾字节。

现在,在不知道文件的格式(如何将数据写入文件)的情况下,我将很难弄清楚如何阅读它。但是,因为我们知道我们可以写一个简单的程序来阅读它的格式:

file1.c中:

/* compile as: gcc -ansi -pedantic -Wall file1.c -o read_test */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct rec_tag
{
    int   id;
    char  name[50];
};

int main(int argc, char** argv)
{
     FILE*          fp = NULL;
     struct rec_tag rec1;
     struct rec_tag rec2;

     if(NULL != (fp = fopen("./short.dat", "rb")))
     {
          fread(&rec1, sizeof(struct rec_tag), 1, fp);
          fread(&rec2, sizeof(struct rec_tag), 1, fp);

          printf("id: %d, name: %s\n", rec1.id, rec1.name);
          printf("id: %d, name: %s\n", rec2.id, rec2.name);

          fclose(fp);
     }

     return 0;
 }

并且在运行时产生以下结果:

    [******@broadsword junk]$ ./read_test
    id: 20, name: thurizas
    id: 345689, name: Marouane

希望这有助于如何解释文件并显示一种阅读方式。所以在你的情况下,我会做以下步骤

  1. 获取并阅读DICOM文件的正式规范。
  2. 尝试&#34;手&#34;读取文件。在十六进制编辑器中打开文件,并使用规范查看是否可以单步调试文件并找出数据的存储方式。
  3. 编写程序以读入数据。
  4. 最后,免责声明:

    1. 所有代码都是使用gcc版本4.8.2编译的,并在Centos 7系统上运行。
    2. 我知道所有符合POSIX标准的系统(包括Linux)都会忽略fopen和fread的b标志,我把它放在那里以防代码在非POSIX系统上运行,并且也是明确表示我正在做二进制I / O
    3. 将错误检查和处理保持在最低限度,以防止此帖子成为文本墙(它确实如此)。
    4. 希望这有帮助, 吨。

答案 1 :(得分:1)

DICOM格式相对复杂。如果您不熟悉它,我建议您使用第三方库打开图像并提取标题。

考虑使用gdcm。它已经有一个示例(gdcmdump)打开文件并将标题转换为文本以供显示。