Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
DICOM.java
1 package ij.plugin;
2 import java.io.*;
3 import java.util.*;
4 import java.net.URL;
5 import ij.*;
6 import ij.io.*;
7 import ij.process.*;
8 import ij.util.Tools;
9 import ij.measure.Calibration;
10 
18 /* RAK (Richard Kirk, rak@cre.canon.co.uk) changes 14/7/99
19 
20  InputStream.skip() looped to check the actual number of
21  bytes is read.
22 
23  Big/little-endian options on element length.
24 
25  Explicit check for each known VR to make mistaken identifications
26  of explicit VR's less likely.
27 
28  Variables b1..b4 renamed as b0..b3.
29 
30  Increment of 4 to offset on (7FE0,0010) tag removed.
31 
32  Queries on some other unrecognized tags.
33  Anyone want to claim them?
34 
35  RAK changes 15/7/99
36 
37  Bug fix on magic values for explicit VRs with 32-bit lengths.
38 
39  Various bits of tidying up, including...
40  'location' incremented on read using getByte() or getString().
41  simpler debug mode message generation (values no longer reported).
42 
43  Added z pixel aspect ratio support for multi-slice DICOM volumes.
44  Michael Abramoff, 31-10-2000
45  */
46 
47 public class DICOM extends ImagePlus implements PlugIn {
48  private boolean showErrors = true;
49 
50  public void run(String path) {
51  File pf = new File(path);
52  String directory = pf.getName();
53  String fileName = pf.getParent();
54  IJ.showStatus("Opening: " + directory + fileName);
55  DicomDecoder dd = new DicomDecoder(directory, fileName);
56  FileInfo fi = null;
57  try {fi = dd.getFileInfo();}
58  catch (IOException e) {
59  String msg = e.getMessage();
60  IJ.showStatus("");
61  if (msg.indexOf("EOF")<0&&showErrors) {
62  IJ.showMessage("DicomDecoder", msg);
63  return;
64  } else if (!dd.dicmFound()&&showErrors) {
65  msg = "This does not appear to be a valid\n"
66  + "DICOM file. It does not have the\n"
67  + "characters 'DICM' at offset 128.";
68  IJ.showMessage("DicomDecoder", msg);
69  return;
70  }
71  }
72  if (fi!=null && fi.width>0 && fi.height>0 && fi.offset>0) {
73  FileOpener fo = new FileOpener(fi);
74  ImagePlus imp = fo.open(false);
75  if (fi.fileType==FileInfo.GRAY16_SIGNED)
76  convertToUnsigned(imp, fi);
77  if (dd.windowWidth>0.0) {
78  ImageProcessor ip = imp.getProcessor();
79  double min = dd.windowCenter-dd.windowWidth/2;
80  double max = dd.windowCenter+dd.windowWidth/2;
81  if (fi.fileType==FileInfo.GRAY16_SIGNED) {
82  min += 32768.0;
83  max += 32768.0;
84  }
85  ip.setMinAndMax(min, max);
86  if (IJ.debugMode) IJ.log("window: "+min+"-"+max);
87  }
88  setProcessor(fileName, imp.getProcessor());
90  setProperty("Info", dd.getDicomInfo());
91  setFileInfo(fi); // needed for revert
92  if (path.equals("")) show();
93  } else if (showErrors)
94  IJ.showMessage("DicomDecoder","Unable to decode DICOM header.");
95  IJ.showStatus("");
96  }
97 
110  public void open(String path) {
111  showErrors = false;
112  run(path);
113  }
114 
116  void convertToUnsigned(ImagePlus imp, FileInfo fi) {
117  ImageProcessor ip = imp.getProcessor();
118  short[] pixels = (short[])ip.getPixels();
119  int min = Integer.MAX_VALUE;
120  int value;
121  for (int i=0; i<pixels.length; i++) {
122  value = pixels[i]&0xffff;
123  if (value<min)
124  min = value;
125  }
126  if (IJ.debugMode) IJ.log("min: "+(min-32768));
127  if (min>=32768) {
128  for (int i=0; i<pixels.length; i++)
129  pixels[i] = (short)(pixels[i]-32768);
130  ip.resetMinAndMax();
131  Calibration cal = imp.getCalibration();
132  cal.setFunction(Calibration.NONE, null, "Gray Value");
133  fi.fileType = FileInfo.GRAY16_UNSIGNED;
134  }
135  }
136 
137 }
138 
139 
140 class DicomDecoder {
141 
142  private static final int PIXEL_REPRESENTATION = 0x00280103;
143  private static final int TRANSFER_SYNTAX_UID = 0x00020010;
144  private static final int SLICE_SPACING = 0x00180088;
145  private static final int SAMPLES_PER_PIXEL = 0x00280002;
146  private static final int PHOTOMETRIC_INTERPRETATION = 0x00280004;
147  private static final int PLANAR_CONFIGURATION = 0x00280006;
148  private static final int NUMBER_OF_FRAMES = 0x00280008;
149  private static final int ROWS = 0x00280010;
150  private static final int COLUMNS = 0x00280011;
151  private static final int PIXEL_SPACING = 0x00280030;
152  private static final int BITS_ALLOCATED = 0x00280100;
153  private static final int WINDOW_CENTER = 0x00281050;
154  private static final int WINDOW_WIDTH = 0x00281051;
155  private static final int RED_PALETTE = 0x00281201;
156  private static final int GREEN_PALETTE = 0x00281202;
157  private static final int BLUE_PALETTE = 0x00281203;
158  private static final int PIXEL_DATA = 0x7FE00010;
159 
160  private static final int AE=0x4145, AS=0x4153, AT=0x4154, CS=0x4353, DA=0x4441, DS=0x4453, DT=0x4454,
161  FD=0x4644, FL=0x464C, IS=0x4953, LO=0x4C4F, LT=0x4C54, PN=0x504E, SH=0x5348, SL=0x534C,
162  SS=0x5353, ST=0x5354, TM=0x544D, UI=0x5549, UL=0x554C, US=0x5553, UT=0x5554,
163  OB=0x4F42, OW=0x4F57, SQ=0x5351, UN=0x554E, QQ=0x3F3F;
164 
165  private static Properties dictionary;
166 
167  private String directory, fileName;
168  private static final int ID_OFFSET = 128; //location of "DICM"
169  private static final String DICM = "DICM";
170 
171  private BufferedInputStream f;
172  private int location = 0;
173  private boolean littleEndian = true;
174 
175  private int elementLength;
176  private int vr; // Value Representation
177  private static final int IMPLICIT_VR = 0x2D2D; // '--'
178  private byte[] vrLetters = new byte[2];
179  private int previousGroup;
180  private StringBuffer dicomInfo = new StringBuffer(1000);
181  private boolean dicmFound; // "DICM" found at offset 128
182  private boolean oddLocations; // one or more tags at odd locations
183  private boolean bigEndianTransferSyntax = false;
184  double windowCenter, windowWidth;
185 
186  public DicomDecoder(String directory, String fileName) {
187  this.directory = directory;
188  this.fileName = fileName;
189  if (dictionary==null) {
190  DicomDictionary d = new DicomDictionary();
191  dictionary = d.getDictionary();
192  }
193 
194  IJ.register(DICOM.class);
195  }
196 
197  String getString(int length) throws IOException {
198  byte[] buf = new byte[length];
199  int pos = 0;
200  while (pos<length) {
201  int count = f.read(buf, pos, length-pos);
202  pos += count;
203  }
204  location += length;
205  return new String(buf);
206  }
207 
208  int getByte() throws IOException {
209  int b = f.read();
210  if (b ==-1) throw new IOException("unexpected EOF");
211  ++location;
212  return b;
213  }
214 
215  int getShort() throws IOException {
216  int b0 = getByte();
217  int b1 = getByte();
218  if (littleEndian)
219  return ((b1 << 8) + b0);
220  else
221  return ((b0 << 8) + b1);
222  }
223 
224  final int getInt() throws IOException {
225  int b0 = getByte();
226  int b1 = getByte();
227  int b2 = getByte();
228  int b3 = getByte();
229  if (littleEndian)
230  return ((b3<<24) + (b2<<16) + (b1<<8) + b0);
231  else
232  return ((b0<<24) + (b1<<16) + (b2<<8) + b3);
233  }
234 
235  byte[] getLut(int length) throws IOException {
236  if ((length&1)!=0) { // odd
237  String dummy = getString(length);
238  return null;
239  }
240  length /= 2;
241  byte[] lut = new byte[length];
242  for (int i=0; i<length; i++)
243  lut[i] = (byte)(getShort()>>>8);
244  return lut;
245  }
246 
247  int getLength() throws IOException {
248  int b0 = getByte();
249  int b1 = getByte();
250  int b2 = getByte();
251  int b3 = getByte();
252 
253  // We cannot know whether the VR is implicit or explicit
254  // without the full DICOM Data Dictionary for public and
255  // private groups.
256 
257  // We will assume the VR is explicit if the two bytes
258  // match the known codes. It is possible that these two
259  // bytes are part of a 32-bit length for an implicit VR.
260 
261  vr = (b0<<8) + b1;
262 
263  switch (vr) {
264  case OB: case OW: case SQ: case UN:
265  // Explicit VR with 32-bit length if other two bytes are zero
266  if ( (b2 == 0) || (b3 == 0) ) return getInt();
267  // Implicit VR with 32-bit length
268  vr = IMPLICIT_VR;
269  if (littleEndian)
270  return ((b3<<24) + (b2<<16) + (b1<<8) + b0);
271  else
272  return ((b0<<24) + (b1<<16) + (b2<<8) + b3);
273  case AE: case AS: case AT: case CS: case DA: case DS: case DT: case FD:
274  case FL: case IS: case LO: case LT: case PN: case SH: case SL: case SS:
275  case ST: case TM:case UI: case UL: case US: case UT: case QQ:
276  // Explicit vr with 16-bit length
277  if (littleEndian)
278  return ((b3<<8) + b2);
279  else
280  return ((b2<<8) + b3);
281  default:
282  // Implicit VR with 32-bit length...
283  vr = IMPLICIT_VR;
284  if (littleEndian)
285  return ((b3<<24) + (b2<<16) + (b1<<8) + b0);
286  else
287  return ((b0<<24) + (b1<<16) + (b2<<8) + b3);
288  }
289  }
290 
291  int getNextTag() throws IOException {
292  int groupWord = getShort();
293  if (groupWord==0x0800 && bigEndianTransferSyntax) {
294  littleEndian = false;
295  groupWord = 0x0008;
296  }
297  int elementWord = getShort();
298  int tag = groupWord<<16 | elementWord;
299  elementLength = getLength();
300 
301  // hack needed to read some GE files
302  // The element length must be even!
303  if (elementLength==13 && !oddLocations) elementLength = 10;
304 
305  // "Undefined" element length.
306  // This is a sort of bracket that encloses a sequence of elements.
307  if (elementLength==-1)
308  elementLength = 0;
309  return tag;
310  }
311 
312  FileInfo getFileInfo() throws IOException {
313  long skipCount;
314 
315  boolean isURL = directory.indexOf("://")>0;
316  FileInfo fi = new FileInfo();
317  int bitsAllocated = 16;
318  fi.fileFormat = fi.RAW;
319  fi.fileName = fileName;
320  if (isURL)
321  fi.url = directory;
322  else
323  fi.directory = directory;
324  fi.width = 0;
325  fi.height = 0;
326  fi.offset = 0;
327  fi.intelByteOrder = true;
328  fi.fileType = FileInfo.GRAY16_UNSIGNED;
329  fi.fileFormat = FileInfo.DICOM;
330  int samplesPerPixel = 1;
331  int planarConfiguration = 0;
332  String photoInterpretation = "";
333 
334  if (isURL) {
335  URL u = new URL(fi.url+fi.fileName);
336  f = new BufferedInputStream(u.openStream());
337  } else
338  f = new BufferedInputStream(new FileInputStream(directory + fileName));
339  if (IJ.debugMode) {
340  IJ.log("");
341  IJ.log("DicomDecoder: decoding "+fileName);
342  }
343 
344  skipCount = (long)ID_OFFSET;
345  while (skipCount > 0) skipCount -= f.skip( skipCount );
346  location += ID_OFFSET;
347 
348  if (!getString(4).equals(DICM)) {
349  f.close();
350  if (isURL) {
351  URL u = new URL(fi.url+fi.fileName);
352  f = new BufferedInputStream(u.openStream());
353  } else
354  f = new BufferedInputStream(new FileInputStream(directory + fileName));
355  location = 0;
356  if (IJ.debugMode) IJ.log(DICM + " not found at offset "+ID_OFFSET+"; reseting to offset 0");
357  } else {
358  dicmFound = true;
359  if (IJ.debugMode) IJ.log(DICM + " found at offset " + ID_OFFSET);
360  }
361 
362  boolean inSequence = true;
363  boolean decodingTags = true;
364  boolean signed = false;
365 
366  while (decodingTags) {
367  int tag = getNextTag();
368  if ((location&1)!=0) // DICOM tags must be at even locations
369  oddLocations = true;
370  String s;
371  switch (tag) {
372  case TRANSFER_SYNTAX_UID:
373  s = getString(elementLength);
374  addInfo(tag, s);
375  if (s.indexOf("1.2.4")>-1||s.indexOf("1.2.5")>-1) {
376  f.close();
377  String msg = "ImageJ cannot open compressed DICOM images.\n \n";
378  msg += "Transfer Syntax UID = "+s;
379  throw new IOException(msg);
380  }
381  if (s.indexOf("1.2.840.10008.1.2.2")>=0)
382  bigEndianTransferSyntax = true;
383  break;
384  case NUMBER_OF_FRAMES:
385  s = getString(elementLength);
386  addInfo(tag, s);
387  double frames = s2d(s);
388  if (frames>1.0)
389  fi.nImages = (int)frames;
390  break;
391  case SAMPLES_PER_PIXEL:
392  samplesPerPixel = getShort();
393  addInfo(tag, samplesPerPixel);
394  break;
395  case PHOTOMETRIC_INTERPRETATION:
396  photoInterpretation = getString(elementLength);
397  addInfo(tag, photoInterpretation);
398  break;
399  case PLANAR_CONFIGURATION:
400  planarConfiguration = getShort();
401  addInfo(tag, planarConfiguration);
402  break;
403  case ROWS:
404  fi.height = getShort();
405  addInfo(tag, fi.height);
406  break;
407  case COLUMNS:
408  fi.width = getShort();
409  addInfo(tag, fi.width);
410  break;
411  case PIXEL_SPACING:
412  String scale = getString(elementLength);
413  getSpatialScale(fi, scale);
414  addInfo(tag, scale);
415  break;
416  case SLICE_SPACING:
417  String spacing = getString(elementLength);
418  fi.pixelDepth = s2d(spacing);
419  addInfo(tag, spacing);
420  break;
421  case BITS_ALLOCATED:
422  bitsAllocated = getShort();
423  if (bitsAllocated==8)
424  fi.fileType = FileInfo.GRAY8;
425  else if (bitsAllocated==32)
426  fi.fileType = FileInfo.GRAY32_UNSIGNED;
427  addInfo(tag, bitsAllocated);
428  break;
429  case PIXEL_REPRESENTATION:
430  int pixelRepresentation = getShort();
431  if (pixelRepresentation==1) {
432  fi.fileType = FileInfo.GRAY16_SIGNED;
433  signed = true;
434  }
435  addInfo(tag, pixelRepresentation);
436  break;
437  case WINDOW_CENTER:
438  String center = getString(elementLength);
439  windowCenter = s2d(center);
440  addInfo(tag, center);
441  break;
442  case WINDOW_WIDTH:
443  String width = getString(elementLength);
444  windowWidth = s2d(width);
445  addInfo(tag, width);
446  break;
447  case RED_PALETTE:
448  fi.reds = getLut(elementLength);
449  addInfo(tag, elementLength/2);
450  break;
451  case GREEN_PALETTE:
452  fi.greens = getLut(elementLength);
453  addInfo(tag, elementLength/2);
454  break;
455  case BLUE_PALETTE:
456  fi.blues = getLut(elementLength);
457  addInfo(tag, elementLength/2);
458  break;
459  case PIXEL_DATA:
460  // Start of image data...
461  if (elementLength!=0) {
462  fi.offset = location;
463  addInfo(tag, location);
464  decodingTags = false;
465  } else
466  addInfo(tag, null);
467  break;
468  case 0x7F880010:
469  // What is this? - RAK
470  if (elementLength!=0) {
471  fi.offset = location+4;
472  decodingTags = false;
473  }
474  break;
475  default:
476  // Not used, skip over it...
477  addInfo(tag, null);
478  }
479  } // while(decodingTags)
480 
481  if (fi.fileType==FileInfo.GRAY8) {
482  if (fi.reds!=null && fi.greens!=null && fi.blues!=null
483  && fi.reds.length==fi.greens.length
484  && fi.reds.length==fi.blues.length) {
485  fi.fileType = FileInfo.COLOR8;
486  fi.lutSize = fi.reds.length;
487 
488  }
489  }
490 
491  if (fi.fileType==FileInfo.GRAY32_UNSIGNED && signed)
492  fi.fileType = FileInfo.GRAY32_INT;
493 
494  if (samplesPerPixel==3 && photoInterpretation.startsWith("RGB")) {
495  if (planarConfiguration==0)
496  fi.fileType = FileInfo.RGB;
497  else if (planarConfiguration==1)
498  fi.fileType = FileInfo.RGB_PLANAR;
499  } else if (photoInterpretation.endsWith("1 "))
500  fi.whiteIsZero = true;
501 
502  if (!littleEndian)
503  fi.intelByteOrder = false;
504 
505  if (IJ.debugMode) {
506  IJ.log("width: " + fi.width);
507  IJ.log("height: " + fi.height);
508  IJ.log("images: " + fi.nImages);
509  IJ.log("bits allocated: " + bitsAllocated);
510  IJ.log("offset: " + fi.offset);
511  }
512 
513  f.close();
514  return fi;
515  }
516 
517  String getDicomInfo() {
518  return new String(dicomInfo);
519  }
520 
521  void addInfo(int tag, String value) throws IOException {
522  String info = getHeaderInfo(tag, value);
523  if (info!=null) {
524  int group = tag>>>16;
525  if (group!=previousGroup) dicomInfo.append("\n");
526  previousGroup = group;
527  dicomInfo.append(tag2hex(tag)+info+"\n");
528  }
529  if (IJ.debugMode) {
530  if (info==null) info = "";
531  vrLetters[0] = (byte)(vr >> 8);
532  vrLetters[1] = (byte)(vr & 0xFF);
533  String VR = new String(vrLetters);
534  IJ.log("(" + tag2hex(tag) + VR
535  + " " + elementLength
536  + " bytes from "
537  + (location-elementLength)+") "
538  + info);
539  }
540  }
541 
542  void addInfo(int tag, int value) throws IOException {
543  addInfo(tag, Integer.toString(value));
544  }
545 
546  String getHeaderInfo(int tag, String value) throws IOException {
547  String key = i2hex(tag);
548  //while (key.length()<8)
549  // key = '0' + key;
550  String id = (String)dictionary.get(key);
551  if (id!=null) {
552  if (vr==IMPLICIT_VR && id!=null)
553  vr = (id.charAt(0)<<8) + id.charAt(1);
554  id = id.substring(2);
555  }
556  if (value!=null)
557  return id+": "+value;
558  switch (vr) {
559  case AE: case AS: case AT: case CS: case DA: case DS: case DT: case IS: case LO:
560  case LT: case PN: case SH: case ST: case TM: case UI:
561  value = getString(elementLength);
562  break;
563  case US:
564  if (elementLength==2)
565  value = Integer.toString(getShort());
566  else {
567  value = "";
568  int n = elementLength/2;
569  for (int i=0; i<n; i++)
570  value += Integer.toString(getShort())+" ";
571  }
572  break;
573  default:
574  long skipCount = (long)elementLength;
575  while (skipCount > 0) skipCount -= f.skip(skipCount);
576  location += elementLength;
577  value = "";
578  }
579  if (id==null)
580  return null;
581  else
582  return id+": "+value;
583  }
584 
585  static char[] buf8 = new char[8];
586 
588  String i2hex(int i) {
589  for (int pos=7; pos>=0; pos--) {
590  buf8[pos] = Tools.hexDigits[i&0xf];
591  i >>>= 4;
592  }
593  return new String(buf8);
594  }
595 
596  char[] buf10;
597 
598  String tag2hex(int tag) {
599  if (buf10==null) {
600  buf10 = new char[11];
601  buf10[4] = ',';
602  buf10[9] = ' ';
603  }
604  int pos = 8;
605  while (pos>=0) {
606  buf10[pos] = Tools.hexDigits[tag&0xf];
607  tag >>>= 4;
608  pos--;
609  if (pos==4) pos--; // skip coma
610  }
611  return new String(buf10);
612  }
613 
614  double s2d(String s) {
615  Double d;
616  try {d = new Double(s);}
617  catch (NumberFormatException e) {d = null;}
618  if (d!=null)
619  return(d.doubleValue());
620  else
621  return(0.0);
622  }
623 
624  void getSpatialScale(FileInfo fi, String scale) {
625  double xscale=0, yscale=0;
626  int i = scale.indexOf('\\');
627  if (i>0) {
628  yscale = s2d(scale.substring(0, i));
629  xscale = s2d(scale.substring(i+1));
630  }
631  if (xscale!=0.0 && yscale!=0.0) {
632  fi.pixelWidth = xscale;
633  fi.pixelHeight = yscale;
634  fi.unit = "mm";
635  }
636  }
637 
638  boolean dicmFound() {
639  return dicmFound;
640  }
641 
642 }
643 
644 
645 class DicomDictionary {
646 
647  Properties getDictionary() {
648  Properties p = new Properties();
649  for (int i=0; i<dict.length; i++) {
650  p.put(dict[i].substring(0,8), dict[i].substring(9));
651  }
652  return p;
653  }
654 
655  String[] dict = {
656  //"00020000=ULFile Meta Elements Group Len",
657  //"00020001=OBFile Meta Info Version",
658  "00020002=UIMedia Storage SOP Class UID",
659  "00020003=UIMedia Storage SOP Inst UID",
660  "00020010=UITransfer Syntax UID",
661 
662  "00080005=CSSpecific Character Set",
663  "00080008=CSImage Type",
664  "00080012=DAInstance Creation Date",
665  "00080013=TMInstance Creation Time",
666  "00080014=UIInstance Creator UID",
667  "00080016=UISOP Class UID",
668  "00080018=UISOP Instance UID",
669  "00080020=DAStudy Date",
670  "00080021=DASeries Date",
671  "00080022=DAAcquisition Date",
672  "00080023=DAImage Date",
673  "00080024=DAOverlay Date",
674  "00080025=DACurve Date",
675  "00080030=TMStudy Time",
676  "00080031=TMSeries Time",
677  "00080032=TMAcquisition Time",
678  "00080033=TMImage Time",
679  "00080034=TMOverlay Time",
680  "00080035=TMCurve Time",
681  "00080042=CSNuclear Medicine Series Type",
682  "00080050=SHAccession Number",
683  "00080052=CSQuery/Retrieve Level",
684  "00080054=AERetrieve AE Title",
685  "00080058=AEFailed SOP Instance UID List",
686  "00080060=CSModality",
687  "00080064=CSConversion Type",
688  "00080070=LOManufacturer",
689  "00080080=LOInstitution Name",
690  "00080081=STInstitution Address",
691  "00080082=SQInstitution Code Sequence",
692  "00080090=PNReferring Physician's Name",
693  "00080092=STReferring Physician's Address",
694  "00080094=SHReferring Physician's Telephone Numbers",
695  "00080100=SHCode Value",
696  "00080102=SHCoding Scheme Designator",
697  "00080104=LOCode Meaning",
698  "00081010=SHStation Name",
699  "00081030=LOStudy Description",
700  "00081032=SQProcedure Code Sequence",
701  "0008103E=LOSeries Description",
702  "00081040=LOInstitutional Department Name",
703  "00081050=PNAttending Physician's Name",
704  "00081060=PNName of Physician(s) Reading Study",
705  "00081070=PNOperator's Name",
706  "00081080=LOAdmitting Diagnoses Description",
707  "00081084=SQAdmitting Diagnosis Code Sequence",
708  "00081090=LOManufacturer's Model Name",
709  "00081100=SQReferenced Results Sequence",
710  "00081110=SQReferenced Study Sequence",
711  "00081111=SQReferenced Study Component Sequence",
712  "00081115=SQReferenced Series Sequence",
713  "00081120=SQReferenced Patient Sequence",
714  "00081125=SQReferenced Visit Sequence",
715  "00081130=SQReferenced Overlay Sequence",
716  "00081140=SQReferenced Image Sequence",
717  "00081145=SQReferenced Curve Sequence",
718  "00081150=UIReferenced SOP Class UID",
719  "00081155=UIReferenced SOP Instance UID",
720  "00082111=STDerivation Description",
721  "00082112=SQSource Image Sequence",
722  "00082120=SHStage Name",
723  "00082122=ISStage Number",
724  "00082124=ISNumber of Stages",
725  "00082129=ISNumber of Event Timers",
726  "00082128=ISView Number",
727  "0008212A=ISNumber of Views in Stage",
728  "00082130=DSEvent Elapsed Time(s)",
729  "00082132=LOEvent Timer Name(s)",
730  "00082142=ISStart Trim",
731  "00082143=ISStop Trim",
732  "00082144=ISRecommended Display Frame Rate",
733  "00082200=CSTransducer Position",
734  "00082204=CSTransducer Orientation",
735  "00082208=CSAnatomic Structure",
736 
737  "00100010=PNPatient's Name",
738  "00100020=LOPatient ID",
739  "00100021=LOIssuer of Patient ID",
740  "00100030=DAPatient's Birth Date",
741  "00100032=TMPatient's Birth Time",
742  "00100040=CSPatient's Sex",
743  "00101000=LOOther Patient IDs",
744  "00101001=PNOther Patient Names",
745  "00101005=PNPatient's Maiden Name",
746  "00101010=ASPatient's Age",
747  "00101020=DSPatient's Size",
748  "00101030=DSPatient's Weight",
749  "00101040=LOPatient's Address",
750  "00102150=LOCountry of Residence",
751  "00102152=LORegion of Residence",
752  "00102180=SHOccupation",
753  "001021A0=CSSmoking Status",
754  "001021B0=LTAdditional Patient History",
755  "00104000=LTPatient Comments",
756 
757  "00180010=LOContrast/Bolus Agent",
758  "00180015=CSBody Part Examined",
759  "00180020=CSScanning Sequence",
760  "00180021=CSSequence Variant",
761  "00180022=CSScan Options",
762  "00180023=CSMR Acquisition Type",
763  "00180024=SHSequence Name",
764  "00180025=CSAngio Flag",
765  "00180030=LORadionuclide",
766  "00180031=LORadiopharmaceutical",
767  "00180032=DSEnergy Window Centerline",
768  "00180033=DSEnergy Window Total Width",
769  "00180034=LOIntervention Drug Name",
770  "00180035=TMIntervention Drug Start Time",
771  "00180040=ISCine Rate",
772  "00180050=DSSlice Thickness",
773  "00180060=DSkVp",
774  "00180070=ISCounts Accumulated",
775  "00180071=CSAcquisition Termination Condition",
776  "00180072=DSEffective Series Duration",
777  "00180080=DSRepetition Time",
778  "00180081=DSEcho Time",
779  "00180082=DSInversion Time",
780  "00180083=DSNumber of Averages",
781  "00180084=DSImaging Frequency",
782  "00180085=SHImaged Nucleus",
783  "00180086=ISEcho Numbers(s)",
784  "00180087=DSMagnetic Field Strength",
785  "00180088=DSSpacing Between Slices",
786  "00180089=ISNumber of Phase Encoding Steps",
787  "00180090=DSData Collection Diameter",
788  "00180091=ISEcho Train Length",
789  "00180093=DSPercent Sampling",
790  "00180094=DSPercent Phase Field of View",
791  "00180095=DSPixel Bandwidth",
792  "00181000=LODevice Serial Number",
793  "00181004=LOPlate ID",
794  "00181010=LOSecondary Capture Device ID",
795  "00181012=DADate of Secondary Capture",
796  "00181014=TMTime of Secondary Capture",
797  "00181016=LOSecondary Capture Device Manufacturer",
798  "00181018=LOSecondary Capture Device Manufacturer's Model Name",
799  "00181019=LOSecondary Capture Device Software Version(s)",
800  "00181020=LOSoftware Versions(s)",
801  "00181022=SHVideo Image Format Acquired",
802  "00181023=LODigital Image Format Acquired",
803  "00181030=LOProtocol Name",
804  "00181040=LOContrast/Bolus Route",
805  "00181041=DSContrast/Bolus Volume",
806  "00181042=TMContrast/Bolus Start Time",
807  "00181043=TMContrast/Bolus Stop Time",
808  "00181044=DSContrast/Bolus Total Dose",
809  "00181045=ISSyringe Counts",
810  "00181050=DSSpatial Resolution",
811  "00181060=DSTrigger Time",
812  "00181061=LOTrigger Source or Type",
813  "00181062=ISNominal Interval",
814  "00181063=DSFrame Time",
815  "00181064=LOFraming Type",
816  "00181065=DSFrame Time Vector",
817  "00181066=DSFrame Delay",
818  "00181070=LORadionuclide Route",
819  "00181071=DSRadionuclide Volume",
820  "00181072=TMRadionuclide Start Time",
821  "00181073=TMRadionuclide Stop Time",
822  "00181074=DSRadionuclide Total Dose",
823  "00181080=CSBeat Rejection Flag",
824  "00181081=ISLow R-R Value",
825  "00181082=ISHigh R-R Value",
826  "00181083=ISIntervals Acquired",
827  "00181084=ISIntervals Rejected",
828  "00181085=LOPVC Rejection",
829  "00181086=ISSkip Beats",
830  "00181088=ISHeart Rate",
831  "00181090=ISCardiac Number of Images",
832  "00181094=ISTrigger Window",
833  "00181100=DSReconstruction Diameter",
834  "00181110=DSDistance Source to Detector",
835  "00181111=DSDistance Source to Patient",
836  "00181120=DSGantry/Detector Tilt",
837  "00181130=DSTable Height",
838  "00181131=DSTable Traverse",
839  "00181140=CSRotation Direction",
840  "00181141=DSAngular Position",
841  "00181142=DSRadial Position",
842  "00181143=DSScan Arc",
843  "00181144=DSAngular Step",
844  "00181145=DSCenter of Rotation Offset",
845  "00181146=DSRotation Offset",
846  "00181147=CSField of View Shape",
847  "00181149=ISField of View Dimensions(s)",
848  "00181150=ISExposure Time",
849  "00181151=ISX-ray Tube Current",
850  "00181152=ISExposure",
851  "00181153=ISExposure in uAs",
852  "00181154=DSAverage Pulse Width",
853  "00181155=CSRadiation Setting",
854  "00181156=CSRectification Type",
855  "0018115A=CSRadiation Mode",
856  "0018115E=DSImage Area Dose Product",
857  "00181160=SHFilter Type",
858  "00181161=LOType of Filters",
859  "00181162=DSIntensifier Size",
860  "00181164=DSImager Pixel Spacing",
861  "00181166=CSGrid",
862  "00181170=ISGenerator Power",
863  "00181180=SHCollimator/grid Name",
864  "00181181=CSCollimator Type",
865  "00181182=ISFocal Distance",
866  "00181183=DSX Focus Center",
867  "00181184=DSY Focus Center",
868  "00181190=DSFocal Spot(s)",
869  "00181191=CSAnode Target Material",
870  "001811A0=DSBody Part Thickness",
871  "001811A2=DSCompression Force",
872  "00181200=DADate of Last Calibration",
873  "00181201=TMTime of Last Calibration",
874  "00181210=SHConvolution Kernel",
875  "00181242=ISActual Frame Duration",
876  "00181243=ISCount Rate",
877  "00181250=SHReceiving Coil",
878  "00181251=SHTransmitting Coil",
879  "00181260=SHPlate Type",
880  "00181261=LOPhosphor Type",
881  "00181300=ISScan Velocity",
882  "00181301=CSWhole Body Technique",
883  "00181302=ISScan Length",
884  "00181310=USAcquisition Matrix",
885  "00181312=CSPhase Encoding Direction",
886  "00181314=DSFlip Angle",
887  "00181315=CSVariable Flip Angle Flag",
888  "00181316=DSSAR",
889  "00181318=DSdB/dt",
890  "00181400=LOAcquisition Device Processing Description",
891  "00181401=LOAcquisition Device Processing Code",
892  "00181402=CSCassette Orientation",
893  "00181403=CSCassette Size",
894  "00181404=USExposures on Plate",
895  "00181405=ISRelative X-ray Exposure",
896  "00181450=CSColumn Angulation",
897  "00181500=CSPositioner Motion",
898  "00181508=CSPositioner Type",
899  "00181510=DSPositioner Primary Angle",
900  "00181511=DSPositioner Secondary Angle",
901  "00181520=DSPositioner Primary Angle Increment",
902  "00181521=DSPositioner Secondary Angle Increment",
903  "00181530=DSDetector Primary Angle",
904  "00181531=DSDetector Secondary Angle",
905  "00181600=CSShutter Shape",
906  "00181602=ISShutter Left Vertical Edge",
907  "00181604=ISShutter Right Vertical Edge",
908  "00181606=ISShutter Upper Horizontal Edge",
909  "00181608=ISShutter Lower Horizontal Edge",
910  "00181610=ISCenter of Circular Shutter",
911  "00181612=ISRadius of Circular Shutter",
912  "00181620=ISVertices of the Polygonal Shutter",
913  "00181700=ISCollimator Shape",
914  "00181702=ISCollimator Left Vertical Edge",
915  "00181704=ISCollimator Right Vertical Edge",
916  "00181706=ISCollimator Upper Horizontal Edge",
917  "00181708=ISCollimator Lower Horizontal Edge",
918  "00181710=ISCenter of Circular Collimator",
919  "00181712=ISRadius of Circular Collimator",
920  "00181720=ISVertices of the Polygonal Collimator",
921  "00185000=SHOutput Power",
922  "00185010=LOTransducer Data",
923  "00185012=DSFocus Depth",
924  "00185020=LOPreprocessing Function",
925  "00185021=LOPostprocessing Function",
926  "00185022=DSMechanical Index",
927  "00185024=DSThermal Index",
928  "00185026=DSCranial Thermal Index",
929  "00185027=DSSoft Tissue Thermal Index",
930  "00185028=DSSoft Tissue-focus Thermal Index",
931  "00185029=DSSoft Tissue-surface Thermal Index",
932  "00185050=ISDepth of Scan Field",
933  "00185100=CSPatient Position",
934  "00185101=CSView Position",
935  "00185104=SQProjection Eponymous Name Code Sequence",
936  "00185210=DSImage Transformation Matrix",
937  "00185212=DSImage Translation Vector",
938  "00186000=DSSensitivity",
939  "00186011=SQSequence of Ultrasound Regions",
940  "00186012=USRegion Spatial Format",
941  "00186014=USRegion Data Type",
942  "00186016=ULRegion Flags",
943  "00186018=ULRegion Location Min X0",
944  "0018601A=ULRegion Location Min Y0",
945  "0018601C=ULRegion Location Max X1",
946  "0018601E=ULRegion Location Max Y1",
947  "00186020=SLReference Pixel X0",
948  "00186022=SLReference Pixel Y0",
949  "00186024=USPhysical Units X Direction",
950  "00186026=USPhysical Units Y Direction",
951  "00181628=FDReference Pixel Physical Value X",
952  "0018602A=FDReference Pixel Physical Value Y",
953  "0018602C=FDPhysical Delta X",
954  "0018602E=FDPhysical Delta Y",
955  "00186030=ULTransducer Frequency",
956  "00186031=CSTransducer Type",
957  "00186032=ULPulse Repetition Frequency",
958  "00186034=FDDoppler Correction Angle",
959  "00186036=FDSterring Angle",
960  "00186038=ULDoppler Sample Volume X Position",
961  "0018603A=ULDoppler Sample Volume Y Position",
962  "0018603C=ULTM-Line Position X0",
963  "0018603E=ULTM-Line Position Y0",
964  "00186040=ULTM-Line Position X1",
965  "00186042=ULTM-Line Position Y1",
966  "00186044=USPixel Component Organization",
967  "00186046=ULPixel Component Mask",
968  "00186048=ULPixel Component Range Start",
969  "0018604A=ULPixel Component Range Stop",
970  "0018604C=USPixel Component Physical Units",
971  "0018604E=USPixel Component Data Type",
972  "00186050=ULNumber of Table Break Points",
973  "00186052=ULTable of X Break Points",
974  "00186054=FDTable of Y Break Points",
975  "00186056=ULNumber of Table Entries",
976  "00186058=ULTable of Pixel Values",
977  "0018605A=ULTable of Parameter Values",
978  "00187000=CSDetector Conditions Nominal Flag",
979  "00187001=DSDetector Temperature",
980  "00187004=CSDetector Type",
981  "00187005=CSDetector Configuration",
982  "00187006=LTDetector Description",
983  "00187008=LTDetector Mode",
984  "0018700A=SHDetector ID",
985  "0018700C=DADate of Last Detector Calibration",
986  "0018700E=TMTime of Last Detector Calibration",
987  "00187010=ISExposures on Detector Since Last Calibration",
988  "00187011=ISExposures on Detector Since Manufactured",
989  "00187012=DSDetector Time Since Last Exposure",
990  "00187014=DSDetector Active Time",
991  "00187016=DSDetector Activation Offset From Exposure",
992  "0018701A=DSDetector Binning",
993  "00187020=DSDetector Element Physical Size",
994  "00187022=DSDetector Element Spacing",
995  "00187024=CSDetector Active Shape",
996  "00187026=DSDetector Active Dimension(s)",
997  "00187028=DSDetector Active Origin",
998  "00187030=DSField of View Origin",
999  "00187032=DSField of View Rotation",
1000  "00187034=CSField of View Horizontal Flip",
1001  "00187040=LTGrid Absorbing Material",
1002  "00187041=LTGrid Spacing Material",
1003  "00187042=DSGrid Thickness",
1004  "00187044=DSGrid Pitch",
1005  "00187046=ISGrid Aspect Ratio",
1006  "00187048=DSGrid Period",
1007  "0018704C=DSGrid Focal Distance",
1008  "00187050=LTFilter Material LT",
1009  "00187052=DSFilter Thickness Minimum",
1010  "00187054=DSFilter Thickness Maximum",
1011  "00187060=CSExposure Control Mode",
1012  "00187062=LTExposure Control Mode Description",
1013  "00187064=CSExposure Status",
1014  "00187065=DSPhototimer Setting",
1015 
1016  "0020000D=UIStudy Instance UID",
1017  "0020000E=UISeries Instance UID",
1018  "00200010=SHStudy ID",
1019  "00200011=ISSeries Number",
1020  "00200012=ISAcquisition Number",
1021  "00200013=ISImage Number",
1022  "00200014=ISIsotope Number",
1023  "00200015=ISPhase Number",
1024  "00200016=ISInterval Number",
1025  "00200017=ISTime Slot Number",
1026  "00200018=ISAngle Number",
1027  "00200020=CSPatient Orientation",
1028  "00200022=USOverlay Number",
1029  "00200024=USCurve Number",
1030  "00200032=DSImage Position (Patient)",
1031  "00200037=DSImage Orientation (Patient)",
1032  "00200052=UIFrame of Reference UID",
1033  "00200060=CSLaterality",
1034  "00200080=UIMasking Image UID",
1035  "00200100=ISTemporal Position Identifier",
1036  "00200105=ISNumber of Temporal Positions",
1037  "00200110=DSTemporal Resolution",
1038  "00201000=ISSeries in Study",
1039  "00201002=ISImages in Acquisition",
1040  "00201004=ISAcquisition in Study",
1041  "00201040=LOPosition Reference Indicator",
1042  "00201041=DSSlice Location",
1043  "00201070=ISOther Study Numbers",
1044  "00201200=ISNumber of Patient Related Studies",
1045  "00201202=ISNumber of Patient Related Series",
1046  "00201204=ISNumber of Patient Related Images",
1047  "00201206=ISNumber of Study Related Series",
1048  "00201208=ISNumber of Study Related Images",
1049  "00204000=LTImage Comments",
1050 
1051  "00280002=USSamples per Pixel",
1052  "00280004=CSPhotometric Interpretation",
1053  "00280006=USPlanar Configuration",
1054  "00280008=ISNumber of Frames",
1055  "00280009=ATFrame Increment Pointer",
1056  "00280010=USRows",
1057  "00280011=USColumns",
1058  "00280030=DSPixel Spacing",
1059  "00280031=DSZoom Factor",
1060  "00280032=DSZoom Center",
1061  "00280034=ISPixel Aspect Ratio",
1062  "00280051=CSCorrected Image",
1063  "00280100=USBits Allocated",
1064  "00280101=USBits Stored",
1065  "00280102=USHigh Bit",
1066  "00280103=USPixel Representation",
1067  "00280106=USSmallest Image Pixel Value",
1068  "00280107=USLargest Image Pixel Value",
1069  "00280108=USSmallest Pixel Value in Series",
1070  "00280109=USLargest Pixel Value in Series",
1071  "00280120=USPixel Padding Value",
1072  "00281050=DSWindow Center",
1073  "00281051=DSWindow Width",
1074  "00281052=DSRescale Intercept",
1075  "00281053=DSRescale Slope",
1076  "00281054=LORescale Type",
1077  "00281055=LOWindow Center & Width Explanation",
1078  "00281101=USRed Palette Color Lookup Table Descriptor",
1079  "00281102=USGreen Palette Color Lookup Table Descriptor",
1080  "00281103=USBlue Palette Color Lookup Table Descriptor",
1081  "00281201=USRed Palette Color Lookup Table Data",
1082  "00281202=USGreen Palette Color Lookup Table Data",
1083  "00281203=USBlue Palette Color Lookup Table Data",
1084  "00283000=SQModality LUT Sequence",
1085  "00283002=USLUT Descriptor",
1086  "00283003=LOLUT Explanation",
1087  "00283004=LOMadality LUT Type",
1088  "00283006=USLUT Data",
1089  "00283010=SQVOI LUT Sequence",
1090 
1091  "7FE00010=OXPixel Data",
1092 
1093  "FFFEE000=DLItem",
1094  "FFFEE00D=DLItem Delimitation Item",
1095  "FFFEE0DD=DLSequence Delimitation Item"
1096  };
1097 
1098 }
1099