📄 medical image format faq - part 4.htm
字号:
136 - int - length of exam header
140 - int - ptr to series header
144 - int - length of series header
148 - int - ptr to image header
152 - int - length of image header
unpack header:
// used when compression is packed, or compressed & packed
// contains perimeter encoding map ... cf. GE 9800
struct {
short pixels_to_left_of_line;
short pixels_in_stored_line;
} table [height_of_image];
compression header:
Not necessary for decompressing entire image ... rather it
contains seeds for various "strips" of the image to allow
jumping into the compressed pixel data ... see the GE docs.
histogram header:
Contains statistical information for determining optimum
windowing ... see the GE docs and GenIncl produced header
exam header:
0 - char[4] - suite ID
8 - u_short - exam number
84 - char[13] - patient ID
97 - char[25] - patient name
122 - short - patient age
126 - short - patient sex
305 - char[3] - exam type - "MR" or "CT"
series header:
10 - short - series number
84 - char[3] - anatomical reference
92 - char[25] - scan protocol name
image header - common to CT and MR:
12 - short - image number
26 - float - slice thickness mm
30 - short - matrix size - X
32 - short - matrix size - Y
34 - float - display field of view - X (mm)
38 - float - display field of view - Y (mm)
42 - float - image dimension - X
46 - float - image dimension - Y
50 - float - pixel size - X
54 - float - pixel size - Y
58 - char[14] - pixel data ID
72 - char[17] - iv contrast agent
89 - char[17] - oral contrast agent
126 - float - image location
130 - float - image centre R mm (ie. X +ve to right)
134 - float - image centre A mm (ie. Y +ve to anterior)
138 - float - image centre S mm (ie. Z +ve to superior)
154 - float - image TLHC R mm (ie. X +ve to right)
158 - float - image TLHC A mm (ie. Y +ve to anterior)
162 - float - image TLHC S mm (ie. Z +ve to superior)
166 - float - image TRHC R mm (ie. X +ve to right)
170 - float - image TRHC A mm (ie. Y +ve to anterior)
174 - float - image TRHC S mm (ie. Z +ve to superior)
178 - float - image BRHC R mm (ie. X +ve to right)
182 - float - image BRHC A mm (ie. Y +ve to anterior)
186 - float - image BRHC S mm (ie. Z +ve to superior)
image header - for MR (1022 bytes long):
194 - int - repetition time(usec)
198 - int - inversion time(usec)
202 - int - echo time(usec)
210 - short - number of echoes
212 - short - echo number
218 - float - NEX
308 - char[33] - pulse sequence name
362 - char[17] - coil name
640 - short - ETL for FSE
</PRE>
<P>So much for the headers. Now how does one deal with the image data ? The
easiest way of course is to save it as "rectangular", that is not compressed and
not packed. If you want to do it the hard way, then if the data is packed, then
unpack it, then if it is compressed, uncompress it. The packing is a perimeter
encoding method like the CT 9800, except that instead of using a map containing
just the width of the stored data, both a left offset and a width are stored for
each row, as described in the "unpack header". The compression scheme is DPCM
again but with a difference ... three alternative encodings are possible ... a 7
bit difference (one byte), a 14 bit difference (two bytes), or a flag byte
followed by a true 16 bit pixel value (three bytes). Presumably this scheme was
devised to handle a greater dynamic range than in the CT 9800 scheme when
necessary, but produce a similar degree of compression otherwise. </P><PRE> 0 +/- <------ 6 bits ------->
_______________ _______________
| | | | | | | | |
|_______________|_______________|
7 4 3 0
or
1 0 +/- <------------------ 13 bits ---------------------->
_______________ _______________ _______________ _______________
| | | | | | | | | | | | | | | | |
|_______________|_______________|_______________|_______________|
15 12 11 8 7 4 3 0
or
1 1 <----- discarded -----> Then two bytes for 16 bit word
_______________ _______________
| | | | | | | | |
|_______________|_______________|
7 4 3 0
</PRE>
<P>The following piece of C++ code pulled out of a Genesis to DICOM translator
will give you the general idea. Note that the perimeter encoding map has already
been read in (map_left and map_wide). Note in particular the need to deal with
sign extension of the difference values. Unlike the CT 9800 example earlier, one
has to use a separate loop for the compressed data stream as all 16 bits are
potentially in use. </P><PRE>static void
copygenesisimage(ifstream& instream,DC3ofstream& outstream,
Uint16 width,Uint16 height,Uint16 depth,Uint16 compress,
Uint16 *map_left,Uint16 *map_wide)
{
unsigned row;
Int16 last_pixel=0;
for (row=0; row<height; ++row) {
unsigned j;
unsigned start;
unsigned end;
if (compress == 2 || compress == 4) { // packed/compacked
start=map_left[row];
end=start+map_wide[row];
}
else {
start=0;
end=width;
}
// Pad the first "empty" part of the line ...
for (j=0; j<start; j++) outstream.write16(0);
if (compress == 3 || compress == 4) { // compressed/compacked
while (start<end) {
unsigned char byte;
instream.read(&byte,1);
if (!instream) return;
if (byte & 0x80) {
unsigned char byte2;
instream.read(&byte2,1);
if (!instream) return;
if (byte & 0x40) { // next word
instream.read(&byte,1);
if (!instream) return;
last_pixel=
(((Uint16)byte2<<8)+byte);
}
else { // 14 bit delta
if (byte & 0x20) byte|=0xe0;
else byte&=0x1f;
last_pixel+=
(((Int16)byte<<8)+byte2);
}
}
else { // 7 bit delta
if (byte & 0x40) byte|=0xc0;
last_pixel+=(signed char)byte;
}
outstream.write16((Uint16)last_pixel);
++start;
}
}
else {
while (start<end) {
Uint16 u=readUint16(instream);
if (!instream) return;
outstream.write16(u);
++start;
}
}
// Pad the last "empty" part of the line ...
for (j=end; j<width; j++) outstream.write16(0);
}
}
</PRE>
<H6>3.3.1.2.2 <A name=Signa5XArchive>GE MR Signa 5.x Archive format</A></H6>
<P>GE supply both DAT tape and 5.25" write once and rewriteable optical disk
drives. </P>
<P>The optical drives are made by Pioneer. This is an unfortunate choice as the
media format is incompatible with any other vendor so you need a Pioneer (DEC
702 ?) drive to read it. The person who made this choice tells me the
fundamental technology seemed more sound on the Pioneer side than from the other
companies, and there were also two sources for the Pioneer and no one was
producing any other interchangeable systems. Interestingly Siemens made the same
choice. </P>
<P>As for the file system, there seem to be two methods in use. One is to use a
monolithic file system on a raw partition. I haven't seen it but there is now
apparently a document from GE available describing this format "direction
46-021863 CT HLA/HSA MR Signa 5.x Optical Disk Raw Partition". See the <A
href="http://www.dclunie.com/medical-image-faq/html/part7.html#GEContactFormats">GEMS
image format information contacts</A> section. This is what is used on the MOD.
</P>
<P>For the WORM, a different choice was made, to use a commericially available
filesystem product that made the disk look like a unix filesystem with the
ability to store and replace and update on a write once medium. It is available
from <A
href="http://www.dclunie.com/medical-image-faq/html/part7.html#DoroTech">DoroTech</A>
of France and called DoroFile. Because it is a commerical product, GE are
restrained from disclosing the file structure. </P>
<P>The formats have been reverse engineered by Jeffrey Siegel of <A
href="http://www.dclunie.com/medical-image-faq/html/part7.html#EvergreenTechnologies">Evergreen
Technologies</A> however, and he can supply you with software to read both GE
and Siemens MOD and WORM formats, on a PC or Mac for $495. He can sell you the
drive as well if necessary for $2800. It can run on a Mac or on a PC with an
Adaptec card and driver. Some driver software for the Pioneer drive is also
available from Corel. </P>
<P>If you have an GE Advantage Windows workstation, there is an optional
MOD/WORM drive and software for that. </P>
<P>As far as the DAT format is concerned, this format is available though I
don't have it (yet). Examining a tape reveals the following however: </P>
<UL>
<LI>One file used as a tape label (single 8192 byte record)
<LI>Tape mark
<LI>Series of image files separated by tape marks </LI></UL>
<P>There does not seem to be a tape directory per se. </P>
<P>Each image file is a modification of the format created by the ximg utility
to extract images from the database. </P>
<P>The ximg format is described as a file header beginning with the magic number
"IMGF" and then a short header that contains byte offsets to the image data, and
various suite, exam, series and image headers. </P>
<P>The DAT images are NOT organized like this, but do use exactly the same
headers and image data layout (and compression schemes). The difference is in
the order of the header. </P>
<P>The first record of the file is 3180 bytes long and contains: </P><PRE> 0-113 suite header (length 114)
114-1137 exam header (length 1024)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -