リスト1 DICOMデータの例 000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 080: 44 49 43 4d 02 00 00 00 55 4c 04 00 56 00 00 00 DICM....UL..V... 090: 02 00 01 00 4f 42 00 00 02 00 00 00 01 00 02 00 ....OB.......... 0a0: 10 00 55 49 12 00 31 2e 32 2e 38 34 30 2e 31 30 ..UI..1.2.840.10 0b0: 30 30 38 2e 31 2e 32 00 02 00 12 00 55 49 12 00 008.1.2.....UI.. 0c0: 31 2e 32 2e 31 32 34 2e 31 31 33 35 33 32 2e 31 1.2.124.113532.1 0d0: 2e 31 02 00 13 00 53 48 0c 00 4d 49 54 52 41 31 .1....SH..MITRA1 0e0: 30 53 45 50 39 36 08 00 00 00 04 00 00 00 b4 00 0SEP96.......... 0f0: 00 00 08 00 16 00 1a 00 00 00 31 2e 32 2e 38 34 ..........1.2.84 リスト1を見てください。DICOMのデータは、最初に128バイトの0x00が続きます。そして、このデータがDICOMデータであることを示す宣言 が、129バイトから132バイトにある"DICM"という文字列です。次のバイトからはメタファイル情報を示すタグ、VR、データ長、データ・フィール ドが続きます。タグ、VR、データ長、データというDICOMデータ要素の関係は次の図で表すことができます。
図1 DICOM画像データファイル構成図 DICOM画像データのファイルは、次の図のような構成になっています。 タグはグループ番号と要素番号の対で構成されます。 short group; /* タグのグループ番号 */ 4: short element; /* タグの要素番号 */
表2 グループ番号の意味 グループ番号 内容 0x0008 検査日等の画像に関する情報 0x0010 患者氏名等の患者に関する情報 0x0028 画像に関する付帯情報 0x7fe0 画像データ メンバーgroupは、グループ番号と呼ばれています。グループ番号は患者に関する情報や画像情報等をまとめた集合を表しています。たとえば、グループ番号が0x0008であれば「画像に対する情報」、0x0010であれば「患者情報」というような意味を持ちます。上記の表に、プログラムを作成する上で、特に重要となるグループ番号を示します。メンバーelementは、集合groupの要素を表しています。たとえば、グループ番号0x0010で要素番号(エレメント番号とも呼ばれています。)が0x0010であるならば患者氏名、0x0030であるならば患者の誕生日というように意味を持たせています(タグの詳細はパート6 「DICOM辞書」にあります。)。 タグというのは、グループ番号と要素番号の対で出来ています。タグは(グループ番号, 要素番号)のように書きます。先の例で言いますと、タグ(0x0010, 0x0010)が患者氏名を表しています。以下の表は、DICOMにおけるタグの一例です。 表3 DICOMタグの例 タグ VR 意味 (0x0008, 0x0020) DA 検査日付 (0x0008, 0x0030) TM 検査時刻 (0x0010, 0x0010) PN 患者の名前 (0x0010, 0x1010) AS 患者の年齢 (0x0018, 0x0015) CS 検査部位 (0x0020, 0x0011) IS シリーズ番号 (0x0028, 0x0004) CS 光度測定解釈 (0x0028, 0x0010) US 横行のPIXEL数 (0x0028, 0x0011) US 縦列のPIXEL数 (0x0028, 0x0100) US 割当てビット (0x0028, 0x0101) US 格納ビット (0x0028, 0x0102) US 高位ビット (0x0028, 0x1050) DS ウィンドウ中心 (0x0028, 0x1051) DS ウィンドウ幅 (0x7fe0, 0x0010) OW, OB 画素データ(画像イメージデータ)
上記の表にはありませんが、グループ番号0x0002と0x0004は、ちょっと特殊なグループでDICOMメタファイル情報、DICOMディレク トリ構造化要素となっています。DICOMメタファイル情報は、DICOMデータの先頭部分に付属したファイル全般に関する情報が含まれています。 DICOMディレクトリ構造化要素は、ファイルの構造に関する情報を含んでいます。 プログラムを作成する上で重要になるのが、表3中のグループ番号0x0028と0x7fe0の要素です。タグ(0x0028, 0x0010)と(0x0028, 0x0011)によって、画像の大きさが分かります。割当てビット(0x0028, 0x0100)は、1つのピクセル(画素)を表すのに何ビット必要なのかを表しています。次に、割当てビットの中で実際に意味があるのは何ビットかを表すのが格納ビット(0x0028, 0x0101)です。そして、意味のあるデータ位置を高位ビット(0x0028, 0x0102)によって示します。 割当てビット、格納ビット、高位ビットは、次のように解釈します。例として、割当てビット=8,格納ビット=5,高位ビット=6としましょう。こ のとき、1つの画素データを2進数で表すと、"0XXXXX00"という形になっています。ここで、0は常に値が0になっていることを示します。そして、 Xが実際に意味のあるデータが入っている場所を示しています。以上より、実際のデータ値は、次の式によって得ることが出来ます。画素データをd、割当て ビット、格納ビット、高位ビットをそれぞれa, s, hとし、実際のデータ値をxとすると、以下の式が成り立ちます。 x = getbits(d, h, s) = ((d >> (h + 1 - s)) & ~(~0 << s)) ここで、getbits(x, p, n)という関数は、カーニハン&リッチーによる「プログラミング言語C 第2版」に掲載されている関数を意味します。getbits(x, p, n)は、pの位置からnビット持ってくるという関数です。以下に、この関数がどのようなものか引用します。 /* getbits: pの位置からnビットを取ってくる */ unsigned getbits(unsigned x, int p, int n) { return (x >> (p + 1 - n)) & ~(~0 << n); } 光度測定解釈(0x0028, 0x0004)は、画素データ(0x7fe0, 0x0010)がどのようなものであるのかを示すのに使われます。画素データが白黒データであるか、カラーデータであるかが定義されるのです。この値 が"MONOCHROME1"であるならば、画素データは単一のモノクロ画像を表し、画素データの最小値が白色を意味します。この 値"MONOCHROME2"である場合には、画素データの最小値が黒色を意味しています。光度測定解釈は、この他に"RGB"、"PALETTE COLOR"や"CMYK"などの値を取ることが出来ます。本書で作成するDICOMビューワでは、"MONOCHROME1" と"MONOCHROME2"のみを取り扱います。
次に、ウィンドウ中心(0x0028, 0x1050)、ウィンドウ幅(0x0028, 0x1051)について述べます。ウィンドウ幅と言うのは、画素データ(0x7fe0, 0x0010)の取りうる値の幅のことです。画素データ(0x7fe0, 0x0010)が0から1024の値をとる場合、ウィンドウ幅は1024となります。そして、ウインドウ中心というのは、画素データの中心値を表したものになります。 タグの後にはVR、データ長、データ・フィールドと続きます。VRはValue Represntations(値表現)の頭文字 を取ったもので、データ・フィールドに含まれる文字列や時刻、数値などのデータ形式を表しています。ただし、DICOMデータには、このVRを省略した形 式もあります。これが、リスト3中の共用体dicom_dataの3番目のメンバーimplicitのことです。さらに、VRを省略しない場合には、VR の後に4バイトのデータ長さを表すデータが続く場合と、2バイトのダミーデータを挿入した後で4バイトのデータ長さを表すデータを続ける場合があります。 VRを省略した形式を、暗黙的VR(Implicit VR)と言います。VRを省略しない場合には、明示的VR(Explicit VR)と言います。明示的VRの場合、VRの値によってデータ長さの前にダミーデータを挿入する場合があります。このために、リスト3中の共用体 dicom_dataは3つのメンバーを持っているのです。図1と、リスト1およびリスト2を見比べて見てください。リスト1はメタファイル情報が付いた DICOMデータであり、リスト2はメタファイル要素のないDICOMデータであると言えます。 VRには、以下のようなものがあります。VRに関する詳細はパート5の22頁ぐらいにあります。VRに関して注意しなければいけないことがありま す。データが明示的VRでOB,OW,SQおよびUNをVRに持つ場合、リスト3中のメンバーexplicit_2のような形式でデータが配置されます。 逆に、それ以外のVRを持つ場合には、メンバーexplicit_4のような形式でデータが配置されています。
表4 主なVRの値と意味 AS 年齢列 固定4バイトの文字列データで日週月年(nnnD,nnnW,nnnM,nnnY)を表します。 DA 日付 固定8バイトの文字列でyyyymmdd(年月日)となっています。 DS 10進数列 最大16バイトまでの固定小数点数または浮動小数点数を表す文字列を表します。 FL 単精度浮動小数点数 4バイトのバイナリーの単精度浮動小数点数を表します。 FD 倍精度浮動小数点数 8バイトのバイナリーの倍精度浮動小数点数を表します。 OB その他バイト列 1バイトのバイナリデータ並びです。 OW その他ワード列 2バイトのバイナリデータ並びで、エンディアンに注意します。 PN 人名 最大64バイトまでの文字列で人名を表します。 TM 時間文字列 最大16バイトの文字列で書式hhmmss.fracを持ちます。 UL 符号無し長整数 符号無しの32ビットバイナリ整数です。 UN 未知のデータ 内容の符号化が未知のデータです。 US 符号無し短整数 符号無しの16ビットバイナリ整数です。