PageRenderTime 57ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/ImageJ/source/ij/plugin/DICOM.java

https://bitbucket.org/Sciumo/imagej
Java | 1613 lines | 1463 code | 57 blank | 93 comment | 150 complexity | 86b0c76c13c8f2dd9c886fa49e1a2b87 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  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. /** This plugin decodes DICOM files. If 'arg' is empty, it
  11. displays a file open dialog and opens and displays the
  12. image selected by the user. If 'arg' is a path, it opens the
  13. specified image and the calling routine can display it using
  14. "((ImagePlus)IJ.runPlugIn("ij.plugin.DICOM", path)).show()".
  15. */
  16. /* RAK (Richard Kirk, rak@cre.canon.co.uk) changes 14/7/99
  17. InputStream.skip() looped to check the actual number of
  18. bytes is read.
  19. Big/little-endian options on element length.
  20. Explicit check for each known VR to make mistaken identifications
  21. of explicit VR's less likely.
  22. Variables b1..b4 renamed as b0..b3.
  23. Increment of 4 to offset on (7FE0,0010) tag removed.
  24. Queries on some other unrecognized tags.
  25. Anyone want to claim them?
  26. RAK changes 15/7/99
  27. Bug fix on magic values for explicit VRs with 32-bit lengths.
  28. Various bits of tidying up, including...
  29. 'location' incremented on read using getByte() or getString().
  30. simpler debug mode message generation (values no longer reported).
  31. Added z pixel aspect ratio support for multi-slice DICOM volumes.
  32. Michael Abramoff, 31-10-2000
  33. Added DICOM tags to the dictionary (now contains about 2700 tags).
  34. implemented getDouble() for VR = FD (Floating Double) and getFloat()
  35. for VR = FL (Floating Single).
  36. Extended case statement in getHeaderInfo to retrieve FD and FL values.
  37. Johannes Hermen, Christian Moll, 25-04-2008
  38. */
  39. public class DICOM extends ImagePlus implements PlugIn {
  40. private boolean showErrors = true;
  41. private boolean gettingInfo;
  42. private BufferedInputStream inputStream;
  43. private String info;
  44. /** Default constructor. */
  45. public DICOM() {
  46. }
  47. /** Constructs a DICOM reader that using an InputStream. Here
  48. is an example that shows how to open and display a DICOM:
  49. <pre>
  50. DICOM dcm = new DICOM(is);
  51. dcm.run("Name");
  52. dcm.show();
  53. <pre>
  54. */
  55. public DICOM(InputStream is) {
  56. this(new BufferedInputStream(is));
  57. }
  58. /** Constructs a DICOM reader that using an BufferredInputStream. */
  59. public DICOM(BufferedInputStream bis) {
  60. inputStream = bis;
  61. }
  62. public void run(String arg) {
  63. OpenDialog od = new OpenDialog("Open Dicom...", arg);
  64. String directory = od.getDirectory();
  65. String fileName = od.getFileName();
  66. if (fileName==null)
  67. return;
  68. //IJ.showStatus("Opening: " + directory + fileName);
  69. DicomDecoder dd = new DicomDecoder(directory, fileName);
  70. dd.inputStream = inputStream;
  71. FileInfo fi = null;
  72. try {
  73. fi = dd.getFileInfo();
  74. } catch (IOException e) {
  75. String msg = e.getMessage();
  76. IJ.showStatus("");
  77. if (msg.indexOf("EOF")<0&&showErrors) {
  78. IJ.error("DicomDecoder", e.getClass().getName()+"\n \n"+msg);
  79. return;
  80. } else if (!dd.dicmFound()&&showErrors) {
  81. msg = "This does not appear to be a valid\n"
  82. + "DICOM file. It does not have the\n"
  83. + "characters 'DICM' at offset 128.";
  84. IJ.error("DicomDecoder", msg);
  85. return;
  86. }
  87. }
  88. if (gettingInfo) {
  89. info = dd.getDicomInfo();
  90. return;
  91. }
  92. if (fi!=null && fi.width>0 && fi.height>0 && fi.offset>0) {
  93. FileOpener fo = new FileOpener(fi);
  94. ImagePlus imp = fo.open(false);
  95. ImageProcessor ip = imp.getProcessor();
  96. if (Prefs.openDicomsAsFloat) {
  97. ip = ip.convertToFloat();
  98. if (dd.rescaleSlope!=1.0)
  99. ip.multiply(dd.rescaleSlope);
  100. if (dd.rescaleIntercept!=0.0)
  101. ip.add(dd.rescaleIntercept);
  102. imp.setProcessor(ip);
  103. } else if (fi.fileType==FileInfo.GRAY16_SIGNED) {
  104. if (dd.rescaleIntercept!=0.0 && dd.rescaleSlope==1.0)
  105. ip.add(dd.rescaleIntercept);
  106. } else if (dd.rescaleIntercept!=0.0 && (dd.rescaleSlope==1.0||fi.fileType==FileInfo.GRAY8)) {
  107. double[] coeff = new double[2];
  108. coeff[0] = dd.rescaleIntercept;
  109. coeff[1] = dd.rescaleSlope;
  110. imp.getCalibration().setFunction(Calibration.STRAIGHT_LINE, coeff, "Gray Value");
  111. }
  112. if (dd.windowWidth>0.0) {
  113. double min = dd.windowCenter-dd.windowWidth/2;
  114. double max = dd.windowCenter+dd.windowWidth/2;
  115. if (Prefs.openDicomsAsFloat) {
  116. min -= dd.rescaleIntercept;
  117. max -= dd.rescaleIntercept;
  118. } else {
  119. Calibration cal = imp.getCalibration();
  120. min = cal.getRawValue(min);
  121. max = cal.getRawValue(max);
  122. }
  123. ip.setMinAndMax(min, max);
  124. if (IJ.debugMode) IJ.log("window: "+min+"-"+max);
  125. }
  126. if (imp.getStackSize()>1)
  127. setStack(fileName, imp.getStack());
  128. else
  129. setProcessor(fileName, imp.getProcessor());
  130. setCalibration(imp.getCalibration());
  131. setProperty("Info", dd.getDicomInfo());
  132. setFileInfo(fi); // needed for revert
  133. if (arg.equals("")) show();
  134. } else if (showErrors)
  135. IJ.error("DicomDecoder","Unable to decode DICOM header.");
  136. IJ.showStatus("");
  137. }
  138. /** Opens the specified file as a DICOM. Does not
  139. display a message if there is an error.
  140. Here is an example:
  141. <pre>
  142. DICOM dcm = new DICOM();
  143. dcm.open(path);
  144. if (dcm.getWidth()==0)
  145. IJ.log("Error opening '"+path+"'");
  146. else
  147. dcm.show();
  148. </pre>
  149. */
  150. public void open(String path) {
  151. showErrors = false;
  152. run(path);
  153. }
  154. /** Returns the DICOM tags of the specified file as a string. */
  155. public String getInfo(String path) {
  156. showErrors = false;
  157. gettingInfo = true;
  158. run(path);
  159. return info;
  160. }
  161. /** Convert 16-bit signed to unsigned if all pixels>=0. */
  162. void convertToUnsigned(ImagePlus imp, FileInfo fi) {
  163. ImageProcessor ip = imp.getProcessor();
  164. short[] pixels = (short[])ip.getPixels();
  165. int min = Integer.MAX_VALUE;
  166. int value;
  167. for (int i=0; i<pixels.length; i++) {
  168. value = pixels[i]&0xffff;
  169. if (value<min)
  170. min = value;
  171. }
  172. if (IJ.debugMode) IJ.log("min: "+(min-32768));
  173. if (min>=32768) {
  174. for (int i=0; i<pixels.length; i++)
  175. pixels[i] = (short)(pixels[i]-32768);
  176. ip.resetMinAndMax();
  177. Calibration cal = imp.getCalibration();
  178. cal.setFunction(Calibration.NONE, null, "Gray Value");
  179. fi.fileType = FileInfo.GRAY16_UNSIGNED;
  180. }
  181. }
  182. }
  183. class DicomDecoder {
  184. private static final int PIXEL_REPRESENTATION = 0x00280103;
  185. private static final int TRANSFER_SYNTAX_UID = 0x00020010;
  186. private static final int MODALITY = 0x00080060;
  187. private static final int SLICE_THICKNESS = 0x00180050;
  188. private static final int SLICE_SPACING = 0x00180088;
  189. private static final int IMAGER_PIXEL_SPACING = 0x00181164;
  190. private static final int SAMPLES_PER_PIXEL = 0x00280002;
  191. private static final int PHOTOMETRIC_INTERPRETATION = 0x00280004;
  192. private static final int PLANAR_CONFIGURATION = 0x00280006;
  193. private static final int NUMBER_OF_FRAMES = 0x00280008;
  194. private static final int ROWS = 0x00280010;
  195. private static final int COLUMNS = 0x00280011;
  196. private static final int PIXEL_SPACING = 0x00280030;
  197. private static final int BITS_ALLOCATED = 0x00280100;
  198. private static final int WINDOW_CENTER = 0x00281050;
  199. private static final int WINDOW_WIDTH = 0x00281051;
  200. private static final int RESCALE_INTERCEPT = 0x00281052;
  201. private static final int RESCALE_SLOPE = 0x00281053;
  202. private static final int RED_PALETTE = 0x00281201;
  203. private static final int GREEN_PALETTE = 0x00281202;
  204. private static final int BLUE_PALETTE = 0x00281203;
  205. private static final int ICON_IMAGE_SEQUENCE = 0x00880200;
  206. private static final int ITEM = 0xFFFEE000;
  207. private static final int ITEM_DELIMINATION = 0xFFFEE00D;
  208. private static final int SEQUENCE_DELIMINATION = 0xFFFEE0DD;
  209. private static final int PIXEL_DATA = 0x7FE00010;
  210. private static final int AE=0x4145, AS=0x4153, AT=0x4154, CS=0x4353, DA=0x4441, DS=0x4453, DT=0x4454,
  211. FD=0x4644, FL=0x464C, IS=0x4953, LO=0x4C4F, LT=0x4C54, PN=0x504E, SH=0x5348, SL=0x534C,
  212. SS=0x5353, ST=0x5354, TM=0x544D, UI=0x5549, UL=0x554C, US=0x5553, UT=0x5554,
  213. OB=0x4F42, OW=0x4F57, SQ=0x5351, UN=0x554E, QQ=0x3F3F;
  214. private static Properties dictionary;
  215. private String directory, fileName;
  216. private static final int ID_OFFSET = 128; //location of "DICM"
  217. private static final String DICM = "DICM";
  218. private BufferedInputStream f;
  219. private int location = 0;
  220. private boolean littleEndian = true;
  221. private int elementLength;
  222. private int vr; // Value Representation
  223. private static final int IMPLICIT_VR = 0x2D2D; // '--'
  224. private byte[] vrLetters = new byte[2];
  225. private int previousGroup;
  226. private String previousInfo;
  227. private StringBuffer dicomInfo = new StringBuffer(1000);
  228. private boolean dicmFound; // "DICM" found at offset 128
  229. private boolean oddLocations; // one or more tags at odd locations
  230. private boolean bigEndianTransferSyntax = false;
  231. double windowCenter, windowWidth;
  232. double rescaleIntercept, rescaleSlope=1.0;
  233. boolean inSequence;
  234. BufferedInputStream inputStream;
  235. String modality;
  236. public DicomDecoder(String directory, String fileName) {
  237. this.directory = directory;
  238. this.fileName = fileName;
  239. String path = null;
  240. if (dictionary==null && IJ.getApplet()==null) {
  241. path = Prefs.getHomeDir()+File.separator+"DICOM_Dictionary.txt";
  242. File f = new File(path);
  243. if (f.exists()) try {
  244. dictionary = new Properties();
  245. InputStream is = new BufferedInputStream(new FileInputStream(f));
  246. dictionary.load(is);
  247. is.close();
  248. if (IJ.debugMode) IJ.log("DicomDecoder: using "+dictionary.size()+" tag dictionary at "+path);
  249. } catch (Exception e) {
  250. dictionary = null;
  251. }
  252. }
  253. if (dictionary==null) {
  254. DicomDictionary d = new DicomDictionary();
  255. dictionary = d.getDictionary();
  256. if (IJ.debugMode) IJ.log("DicomDecoder: "+path+" not found; using "+dictionary.size()+" tag built in dictionary");
  257. }
  258. }
  259. String getString(int length) throws IOException {
  260. byte[] buf = new byte[length];
  261. int pos = 0;
  262. while (pos<length) {
  263. int count = f.read(buf, pos, length-pos);
  264. pos += count;
  265. }
  266. location += length;
  267. return new String(buf);
  268. }
  269. int getByte() throws IOException {
  270. int b = f.read();
  271. if (b ==-1) throw new IOException("unexpected EOF");
  272. ++location;
  273. return b;
  274. }
  275. int getShort() throws IOException {
  276. int b0 = getByte();
  277. int b1 = getByte();
  278. if (littleEndian)
  279. return ((b1 << 8) + b0);
  280. else
  281. return ((b0 << 8) + b1);
  282. }
  283. final int getInt() throws IOException {
  284. int b0 = getByte();
  285. int b1 = getByte();
  286. int b2 = getByte();
  287. int b3 = getByte();
  288. if (littleEndian)
  289. return ((b3<<24) + (b2<<16) + (b1<<8) + b0);
  290. else
  291. return ((b0<<24) + (b1<<16) + (b2<<8) + b3);
  292. }
  293. double getDouble() throws IOException {
  294. int b0 = getByte();
  295. int b1 = getByte();
  296. int b2 = getByte();
  297. int b3 = getByte();
  298. int b4 = getByte();
  299. int b5 = getByte();
  300. int b6 = getByte();
  301. int b7 = getByte();
  302. long res = 0;
  303. if (littleEndian) {
  304. res += b0;
  305. res += ( ((long)b1) << 8);
  306. res += ( ((long)b2) << 16);
  307. res += ( ((long)b3) << 24);
  308. res += ( ((long)b4) << 32);
  309. res += ( ((long)b5) << 40);
  310. res += ( ((long)b6) << 48);
  311. res += ( ((long)b7) << 56);
  312. } else {
  313. res += b7;
  314. res += ( ((long)b6) << 8);
  315. res += ( ((long)b5) << 16);
  316. res += ( ((long)b4) << 24);
  317. res += ( ((long)b3) << 32);
  318. res += ( ((long)b2) << 40);
  319. res += ( ((long)b1) << 48);
  320. res += ( ((long)b0) << 56);
  321. }
  322. return Double.longBitsToDouble(res);
  323. }
  324. float getFloat() throws IOException {
  325. int b0 = getByte();
  326. int b1 = getByte();
  327. int b2 = getByte();
  328. int b3 = getByte();
  329. int res = 0;
  330. if (littleEndian) {
  331. res += b0;
  332. res += ( ((long)b1) << 8);
  333. res += ( ((long)b2) << 16);
  334. res += ( ((long)b3) << 24);
  335. } else {
  336. res += b3;
  337. res += ( ((long)b2) << 8);
  338. res += ( ((long)b1) << 16);
  339. res += ( ((long)b0) << 24);
  340. }
  341. return Float.intBitsToFloat(res);
  342. }
  343. byte[] getLut(int length) throws IOException {
  344. if ((length&1)!=0) { // odd
  345. String dummy = getString(length);
  346. return null;
  347. }
  348. length /= 2;
  349. byte[] lut = new byte[length];
  350. for (int i=0; i<length; i++)
  351. lut[i] = (byte)(getShort()>>>8);
  352. return lut;
  353. }
  354. int getLength() throws IOException {
  355. int b0 = getByte();
  356. int b1 = getByte();
  357. int b2 = getByte();
  358. int b3 = getByte();
  359. // We cannot know whether the VR is implicit or explicit
  360. // without the full DICOM Data Dictionary for public and
  361. // private groups.
  362. // We will assume the VR is explicit if the two bytes
  363. // match the known codes. It is possible that these two
  364. // bytes are part of a 32-bit length for an implicit VR.
  365. vr = (b0<<8) + b1;
  366. switch (vr) {
  367. case OB: case OW: case SQ: case UN: case UT:
  368. // Explicit VR with 32-bit length if other two bytes are zero
  369. if ( (b2 == 0) || (b3 == 0) ) return getInt();
  370. // Implicit VR with 32-bit length
  371. vr = IMPLICIT_VR;
  372. if (littleEndian)
  373. return ((b3<<24) + (b2<<16) + (b1<<8) + b0);
  374. else
  375. return ((b0<<24) + (b1<<16) + (b2<<8) + b3);
  376. case AE: case AS: case AT: case CS: case DA: case DS: case DT: case FD:
  377. case FL: case IS: case LO: case LT: case PN: case SH: case SL: case SS:
  378. case ST: case TM:case UI: case UL: case US: case QQ:
  379. // Explicit vr with 16-bit length
  380. if (littleEndian)
  381. return ((b3<<8) + b2);
  382. else
  383. return ((b2<<8) + b3);
  384. default:
  385. // Implicit VR with 32-bit length...
  386. vr = IMPLICIT_VR;
  387. if (littleEndian)
  388. return ((b3<<24) + (b2<<16) + (b1<<8) + b0);
  389. else
  390. return ((b0<<24) + (b1<<16) + (b2<<8) + b3);
  391. }
  392. }
  393. int getNextTag() throws IOException {
  394. int groupWord = getShort();
  395. if (groupWord==0x0800 && bigEndianTransferSyntax) {
  396. littleEndian = false;
  397. groupWord = 0x0008;
  398. }
  399. int elementWord = getShort();
  400. int tag = groupWord<<16 | elementWord;
  401. elementLength = getLength();
  402. // hack needed to read some GE files
  403. // The element length must be even!
  404. if (elementLength==13 && !oddLocations) elementLength = 10;
  405. // "Undefined" element length.
  406. // This is a sort of bracket that encloses a sequence of elements.
  407. if (elementLength==-1) {
  408. elementLength = 0;
  409. inSequence = true;
  410. }
  411. //IJ.log("getNextTag: "+tag+" "+elementLength);
  412. return tag;
  413. }
  414. FileInfo getFileInfo() throws IOException {
  415. long skipCount;
  416. FileInfo fi = new FileInfo();
  417. int bitsAllocated = 16;
  418. fi.fileFormat = fi.RAW;
  419. fi.fileName = fileName;
  420. if (directory.indexOf("://")>0) { // is URL
  421. URL u = new URL(directory+fileName);
  422. inputStream = new BufferedInputStream(u.openStream());
  423. fi.inputStream = inputStream;
  424. } else if (inputStream!=null)
  425. fi.inputStream = inputStream;
  426. else
  427. fi.directory = directory;
  428. fi.width = 0;
  429. fi.height = 0;
  430. fi.offset = 0;
  431. fi.intelByteOrder = true;
  432. fi.fileType = FileInfo.GRAY16_UNSIGNED;
  433. fi.fileFormat = FileInfo.DICOM;
  434. int samplesPerPixel = 1;
  435. int planarConfiguration = 0;
  436. String photoInterpretation = "";
  437. if (inputStream!=null) {
  438. // Use large buffer to allow URL stream to be reset after reading header
  439. f = inputStream;
  440. f.mark(400000);
  441. } else
  442. f = new BufferedInputStream(new FileInputStream(directory + fileName));
  443. if (IJ.debugMode) {
  444. IJ.log("");
  445. IJ.log("DicomDecoder: decoding "+fileName);
  446. }
  447. skipCount = (long)ID_OFFSET;
  448. while (skipCount > 0) skipCount -= f.skip( skipCount );
  449. location += ID_OFFSET;
  450. if (!getString(4).equals(DICM)) {
  451. if (inputStream==null) f.close();
  452. if (inputStream!=null)
  453. f.reset();
  454. else
  455. f = new BufferedInputStream(new FileInputStream(directory + fileName));
  456. location = 0;
  457. if (IJ.debugMode) IJ.log(DICM + " not found at offset "+ID_OFFSET+"; reseting to offset 0");
  458. } else {
  459. dicmFound = true;
  460. if (IJ.debugMode) IJ.log(DICM + " found at offset " + ID_OFFSET);
  461. }
  462. boolean decodingTags = true;
  463. boolean signed = false;
  464. while (decodingTags) {
  465. int tag = getNextTag();
  466. if ((location&1)!=0) // DICOM tags must be at even locations
  467. oddLocations = true;
  468. if (inSequence) {
  469. addInfo(tag, null);
  470. continue;
  471. }
  472. String s;
  473. switch (tag) {
  474. case TRANSFER_SYNTAX_UID:
  475. s = getString(elementLength);
  476. addInfo(tag, s);
  477. if (s.indexOf("1.2.4")>-1||s.indexOf("1.2.5")>-1) {
  478. f.close();
  479. String msg = "ImageJ cannot open compressed DICOM images.\n \n";
  480. msg += "Transfer Syntax UID = "+s;
  481. throw new IOException(msg);
  482. }
  483. if (s.indexOf("1.2.840.10008.1.2.2")>=0)
  484. bigEndianTransferSyntax = true;
  485. break;
  486. case MODALITY:
  487. modality = getString(elementLength);
  488. addInfo(tag, modality);
  489. break;
  490. case NUMBER_OF_FRAMES:
  491. s = getString(elementLength);
  492. addInfo(tag, s);
  493. double frames = s2d(s);
  494. if (frames>1.0)
  495. fi.nImages = (int)frames;
  496. break;
  497. case SAMPLES_PER_PIXEL:
  498. samplesPerPixel = getShort();
  499. addInfo(tag, samplesPerPixel);
  500. break;
  501. case PHOTOMETRIC_INTERPRETATION:
  502. photoInterpretation = getString(elementLength);
  503. addInfo(tag, photoInterpretation);
  504. break;
  505. case PLANAR_CONFIGURATION:
  506. planarConfiguration = getShort();
  507. addInfo(tag, planarConfiguration);
  508. break;
  509. case ROWS:
  510. fi.height = getShort();
  511. addInfo(tag, fi.height);
  512. break;
  513. case COLUMNS:
  514. fi.width = getShort();
  515. addInfo(tag, fi.width);
  516. break;
  517. case IMAGER_PIXEL_SPACING: case PIXEL_SPACING:
  518. String scale = getString(elementLength);
  519. getSpatialScale(fi, scale);
  520. addInfo(tag, scale);
  521. break;
  522. case SLICE_THICKNESS: case SLICE_SPACING:
  523. String spacing = getString(elementLength);
  524. fi.pixelDepth = s2d(spacing);
  525. addInfo(tag, spacing);
  526. break;
  527. case BITS_ALLOCATED:
  528. bitsAllocated = getShort();
  529. if (bitsAllocated==8)
  530. fi.fileType = FileInfo.GRAY8;
  531. else if (bitsAllocated==32)
  532. fi.fileType = FileInfo.GRAY32_UNSIGNED;
  533. addInfo(tag, bitsAllocated);
  534. break;
  535. case PIXEL_REPRESENTATION:
  536. int pixelRepresentation = getShort();
  537. if (pixelRepresentation==1) {
  538. fi.fileType = FileInfo.GRAY16_SIGNED;
  539. signed = true;
  540. }
  541. addInfo(tag, pixelRepresentation);
  542. break;
  543. case WINDOW_CENTER:
  544. String center = getString(elementLength);
  545. int index = center.indexOf('\\');
  546. if (index!=-1) center = center.substring(index+1);
  547. windowCenter = s2d(center);
  548. addInfo(tag, center);
  549. break;
  550. case WINDOW_WIDTH:
  551. String width = getString(elementLength);
  552. index = width.indexOf('\\');
  553. if (index!=-1) width = width.substring(index+1);
  554. windowWidth = s2d(width);
  555. addInfo(tag, width);
  556. break;
  557. case RESCALE_INTERCEPT:
  558. String intercept = getString(elementLength);
  559. rescaleIntercept = s2d(intercept);
  560. addInfo(tag, intercept);
  561. break;
  562. case RESCALE_SLOPE:
  563. String slop = getString(elementLength);
  564. rescaleSlope = s2d(slop);
  565. addInfo(tag, slop);
  566. break;
  567. case RED_PALETTE:
  568. fi.reds = getLut(elementLength);
  569. addInfo(tag, elementLength/2);
  570. break;
  571. case GREEN_PALETTE:
  572. fi.greens = getLut(elementLength);
  573. addInfo(tag, elementLength/2);
  574. break;
  575. case BLUE_PALETTE:
  576. fi.blues = getLut(elementLength);
  577. addInfo(tag, elementLength/2);
  578. break;
  579. case PIXEL_DATA:
  580. // Start of image data...
  581. if (elementLength!=0) {
  582. fi.offset = location;
  583. addInfo(tag, location);
  584. decodingTags = false;
  585. } else
  586. addInfo(tag, null);
  587. break;
  588. case 0x7F880010:
  589. // What is this? - RAK
  590. if (elementLength!=0) {
  591. fi.offset = location+4;
  592. decodingTags = false;
  593. }
  594. break;
  595. default:
  596. // Not used, skip over it...
  597. addInfo(tag, null);
  598. }
  599. } // while(decodingTags)
  600. if (fi.fileType==FileInfo.GRAY8) {
  601. if (fi.reds!=null && fi.greens!=null && fi.blues!=null
  602. && fi.reds.length==fi.greens.length
  603. && fi.reds.length==fi.blues.length) {
  604. fi.fileType = FileInfo.COLOR8;
  605. fi.lutSize = fi.reds.length;
  606. }
  607. }
  608. if (fi.fileType==FileInfo.GRAY32_UNSIGNED && signed)
  609. fi.fileType = FileInfo.GRAY32_INT;
  610. if (samplesPerPixel==3 && photoInterpretation.startsWith("RGB")) {
  611. if (planarConfiguration==0)
  612. fi.fileType = FileInfo.RGB;
  613. else if (planarConfiguration==1)
  614. fi.fileType = FileInfo.RGB_PLANAR;
  615. } else if (photoInterpretation.endsWith("1 "))
  616. fi.whiteIsZero = true;
  617. if (!littleEndian)
  618. fi.intelByteOrder = false;
  619. if (IJ.debugMode) {
  620. IJ.log("width: " + fi.width);
  621. IJ.log("height: " + fi.height);
  622. IJ.log("images: " + fi.nImages);
  623. IJ.log("bits allocated: " + bitsAllocated);
  624. IJ.log("offset: " + fi.offset);
  625. }
  626. if (inputStream!=null)
  627. f.reset();
  628. else
  629. f.close();
  630. return fi;
  631. }
  632. String getDicomInfo() {
  633. String s = new String(dicomInfo);
  634. char[] chars = new char[s.length()];
  635. s.getChars(0, s.length(), chars, 0);
  636. for (int i=0; i<chars.length; i++) {
  637. if (chars[i]<' ' && chars[i]!='\n') chars[i] = ' ';
  638. }
  639. return new String(chars);
  640. }
  641. void addInfo(int tag, String value) throws IOException {
  642. String info = getHeaderInfo(tag, value);
  643. if (inSequence && info!=null && vr!=SQ) info = ">" + info;
  644. if (info!=null && tag!=ITEM) {
  645. int group = tag>>>16;
  646. //if (group!=previousGroup && (previousInfo!=null&&previousInfo.indexOf("Sequence:")==-1))
  647. // dicomInfo.append("\n");
  648. previousGroup = group;
  649. previousInfo = info;
  650. dicomInfo.append(tag2hex(tag)+info+"\n");
  651. }
  652. if (IJ.debugMode) {
  653. if (info==null) info = "";
  654. vrLetters[0] = (byte)(vr >> 8);
  655. vrLetters[1] = (byte)(vr & 0xFF);
  656. String VR = new String(vrLetters);
  657. IJ.log("(" + tag2hex(tag) + VR
  658. + " " + elementLength
  659. + " bytes from "
  660. + (location-elementLength)+") "
  661. + info);
  662. }
  663. }
  664. void addInfo(int tag, int value) throws IOException {
  665. addInfo(tag, Integer.toString(value));
  666. }
  667. String getHeaderInfo(int tag, String value) throws IOException {
  668. if (tag==ITEM_DELIMINATION || tag==SEQUENCE_DELIMINATION) {
  669. inSequence = false;
  670. if (!IJ.debugMode) return null;
  671. }
  672. String key = i2hex(tag);
  673. //while (key.length()<8)
  674. // key = '0' + key;
  675. String id = (String)dictionary.get(key);
  676. if (id!=null) {
  677. if (vr==IMPLICIT_VR && id!=null)
  678. vr = (id.charAt(0)<<8) + id.charAt(1);
  679. id = id.substring(2);
  680. }
  681. if (tag==ITEM)
  682. return id!=null?id+":":null;
  683. if (value!=null)
  684. return id+": "+value;
  685. switch (vr) {
  686. case FD:
  687. if (elementLength==8)
  688. value = Double.toString(getDouble());
  689. else
  690. for (int i=0; i<elementLength; i++) getByte();
  691. break;
  692. case FL:
  693. if (elementLength==4)
  694. value = Float.toString(getFloat());
  695. else
  696. for (int i=0; i<elementLength; i++) getByte();
  697. break;
  698. //case UT:
  699. //throw new IOException("ImageJ cannot read UT (unlimited text) DICOMs");
  700. case AE: case AS: case AT: case CS: case DA: case DS: case DT: case IS: case LO:
  701. case LT: case PN: case SH: case ST: case TM: case UI:
  702. value = getString(elementLength);
  703. break;
  704. case US:
  705. if (elementLength==2)
  706. value = Integer.toString(getShort());
  707. else {
  708. value = "";
  709. int n = elementLength/2;
  710. for (int i=0; i<n; i++)
  711. value += Integer.toString(getShort())+" ";
  712. }
  713. break;
  714. case IMPLICIT_VR:
  715. value = getString(elementLength);
  716. if (elementLength>44) value=null;
  717. break;
  718. case SQ:
  719. value = "";
  720. boolean privateTag = ((tag>>16)&1)!=0;
  721. if (tag!=ICON_IMAGE_SEQUENCE && !privateTag)
  722. break;
  723. // else fall through and skip icon image sequence or private sequence
  724. default:
  725. long skipCount = (long)elementLength;
  726. while (skipCount > 0) skipCount -= f.skip(skipCount);
  727. location += elementLength;
  728. value = "";
  729. }
  730. if (value!=null && id==null && !value.equals(""))
  731. return "---: "+value;
  732. else if (id==null)
  733. return null;
  734. else
  735. return id+": "+value;
  736. }
  737. static char[] buf8 = new char[8];
  738. /** Converts an int to an 8 byte hex string. */
  739. String i2hex(int i) {
  740. for (int pos=7; pos>=0; pos--) {
  741. buf8[pos] = Tools.hexDigits[i&0xf];
  742. i >>>= 4;
  743. }
  744. return new String(buf8);
  745. }
  746. char[] buf10;
  747. String tag2hex(int tag) {
  748. if (buf10==null) {
  749. buf10 = new char[11];
  750. buf10[4] = ',';
  751. buf10[9] = ' ';
  752. }
  753. int pos = 8;
  754. while (pos>=0) {
  755. buf10[pos] = Tools.hexDigits[tag&0xf];
  756. tag >>>= 4;
  757. pos--;
  758. if (pos==4) pos--; // skip coma
  759. }
  760. return new String(buf10);
  761. }
  762. double s2d(String s) {
  763. if (s==null) return 0.0;
  764. if (s.startsWith("\\"))
  765. s = s.substring(1);
  766. Double d;
  767. try {d = new Double(s);}
  768. catch (NumberFormatException e) {d = null;}
  769. if (d!=null)
  770. return(d.doubleValue());
  771. else
  772. return(0.0);
  773. }
  774. void getSpatialScale(FileInfo fi, String scale) {
  775. double xscale=0, yscale=0;
  776. int i = scale.indexOf('\\');
  777. if (i>0) {
  778. yscale = s2d(scale.substring(0, i));
  779. xscale = s2d(scale.substring(i+1));
  780. }
  781. if (xscale!=0.0 && yscale!=0.0) {
  782. fi.pixelWidth = xscale;
  783. fi.pixelHeight = yscale;
  784. fi.unit = "mm";
  785. }
  786. }
  787. boolean dicmFound() {
  788. return dicmFound;
  789. }
  790. }
  791. class DicomDictionary {
  792. Properties getDictionary() {
  793. Properties p = new Properties();
  794. for (int i=0; i<dict.length; i++) {
  795. p.put(dict[i].substring(0,8), dict[i].substring(9));
  796. }
  797. return p;
  798. }
  799. String[] dict = {
  800. "00020002=UIMedia Storage SOP Class UID",
  801. "00020003=UIMedia Storage SOP Inst UID",
  802. "00020010=UITransfer Syntax UID",
  803. "00020012=UIImplementation Class UID",
  804. "00020013=SHImplementation Version Name",
  805. "00020016=AESource Application Entity Title",
  806. "00080005=CSSpecific Character Set",
  807. "00080008=CSImage Type",
  808. "00080010=CSRecognition Code",
  809. "00080012=DAInstance Creation Date",
  810. "00080013=TMInstance Creation Time",
  811. "00080014=UIInstance Creator UID",
  812. "00080016=UISOP Class UID",
  813. "00080018=UISOP Instance UID",
  814. "00080020=DAStudy Date",
  815. "00080021=DASeries Date",
  816. "00080022=DAAcquisition Date",
  817. "00080023=DAImage Date",
  818. "00080024=DAOverlay Date",
  819. "00080025=DACurve Date",
  820. "00080030=TMStudy Time",
  821. "00080031=TMSeries Time",
  822. "00080032=TMAcquisition Time",
  823. "00080033=TMImage Time",
  824. "00080034=TMOverlay Time",
  825. "00080035=TMCurve Time",
  826. "00080040=USData Set Type",
  827. "00080041=LOData Set Subtype",
  828. "00080042=CSNuclear Medicine Series Type",
  829. "00080050=SHAccession Number",
  830. "00080052=CSQuery/Retrieve Level",
  831. "00080054=AERetrieve AE Title",
  832. "00080058=AEFailed SOP Instance UID List",
  833. "00080060=CSModality",
  834. "00080064=CSConversion Type",
  835. "00080068=CSPresentation Intent Type",
  836. "00080070=LOManufacturer",
  837. "00080080=LOInstitution Name",
  838. "00080081=STInstitution Address",
  839. "00080082=SQInstitution Code Sequence",
  840. "00080090=PNReferring Physician's Name",
  841. "00080092=STReferring Physician's Address",
  842. "00080094=SHReferring Physician's Telephone Numbers",
  843. "00080100=SHCode Value",
  844. "00080102=SHCoding Scheme Designator",
  845. "00080104=LOCode Meaning",
  846. "00080201=SHTimezone Offset From UTC",
  847. "00081010=SHStation Name",
  848. "00081030=LOStudy Description",
  849. "00081032=SQProcedure Code Sequence",
  850. "0008103E=LOSeries Description",
  851. "00081040=LOInstitutional Department Name",
  852. "00081048=PNPhysician(s) of Record",
  853. "00081050=PNAttending Physician's Name",
  854. "00081060=PNName of Physician(s) Reading Study",
  855. "00081070=PNOperator's Name",
  856. "00081080=LOAdmitting Diagnoses Description",
  857. "00081084=SQAdmitting Diagnosis Code Sequence",
  858. "00081090=LOManufacturer's Model Name",
  859. "00081100=SQReferenced Results Sequence",
  860. "00081110=SQReferenced Study Sequence",
  861. "00081111=SQReferenced Study Component Sequence",
  862. "00081115=SQReferenced Series Sequence",
  863. "00081120=SQReferenced Patient Sequence",
  864. "00081125=SQReferenced Visit Sequence",
  865. "00081130=SQReferenced Overlay Sequence",
  866. "00081140=SQReferenced Image Sequence",
  867. "00081145=SQReferenced Curve Sequence",
  868. "00081150=UIReferenced SOP Class UID",
  869. "00081155=UIReferenced SOP Instance UID",
  870. "00082111=STDerivation Description",
  871. "00082112=SQSource Image Sequence",
  872. "00082120=SHStage Name",
  873. "00082122=ISStage Number",
  874. "00082124=ISNumber of Stages",
  875. "00082129=ISNumber of Event Timers",
  876. "00082128=ISView Number",
  877. "0008212A=ISNumber of Views in Stage",
  878. "00082130=DSEvent Elapsed Time(s)",
  879. "00082132=LOEvent Timer Name(s)",
  880. "00082142=ISStart Trim",
  881. "00082143=ISStop Trim",
  882. "00082144=ISRecommended Display Frame Rate",
  883. "00082200=CSTransducer Position",
  884. "00082204=CSTransducer Orientation",
  885. "00082208=CSAnatomic Structure",
  886. "00100010=PNPatient's Name",
  887. "00100020=LOPatient ID",
  888. "00100021=LOIssuer of Patient ID",
  889. "00100030=DAPatient's Birth Date",
  890. "00100032=TMPatient's Birth Time",
  891. "00100040=CSPatient's Sex",
  892. "00101000=LOOther Patient IDs",
  893. "00101001=PNOther Patient Names",
  894. "00101005=PNPatient's Maiden Name",
  895. "00101010=ASPatient's Age",
  896. "00101020=DSPatient's Size",
  897. "00101030=DSPatient's Weight",
  898. "00101040=LOPatient's Address",
  899. "00102150=LOCountry of Residence",
  900. "00102152=LORegion of Residence",
  901. "00102180=SHOccupation",
  902. "001021A0=CSSmoking Status",
  903. "001021B0=LTAdditional Patient History",
  904. "00104000=LTPatient Comments",
  905. "00180010=LOContrast/Bolus Agent",
  906. "00180015=CSBody Part Examined",
  907. "00180020=CSScanning Sequence",
  908. "00180021=CSSequence Variant",
  909. "00180022=CSScan Options",
  910. "00180023=CSMR Acquisition Type",
  911. "00180024=SHSequence Name",
  912. "00180025=CSAngio Flag",
  913. "00180030=LORadionuclide",
  914. "00180031=LORadiopharmaceutical",
  915. "00180032=DSEnergy Window Centerline",
  916. "00180033=DSEnergy Window Total Width",
  917. "00180034=LOIntervention Drug Name",
  918. "00180035=TMIntervention Drug Start Time",
  919. "00180040=ISCine Rate",
  920. "00180050=DSSlice Thickness",
  921. "00180060=DSkVp",
  922. "00180070=ISCounts Accumulated",
  923. "00180071=CSAcquisition Termination Condition",
  924. "00180072=DSEffective Series Duration",
  925. "00180073=CSAcquisition Start Condition",
  926. "00180074=ISAcquisition Start Condition Data",
  927. "00180075=ISAcquisition Termination Condition Data",
  928. "00180080=DSRepetition Time",
  929. "00180081=DSEcho Time",
  930. "00180082=DSInversion Time",
  931. "00180083=DSNumber of Averages",
  932. "00180084=DSImaging Frequency",
  933. "00180085=SHImaged Nucleus",
  934. "00180086=ISEcho Numbers(s)",
  935. "00180087=DSMagnetic Field Strength",
  936. "00180088=DSSpacing Between Slices",
  937. "00180089=ISNumber of Phase Encoding Steps",
  938. "00180090=DSData Collection Diameter",
  939. "00180091=ISEcho Train Length",
  940. "00180093=DSPercent Sampling",
  941. "00180094=DSPercent Phase Field of View",
  942. "00180095=DSPixel Bandwidth",
  943. "00181000=LODevice Serial Number",
  944. "00181004=LOPlate ID",
  945. "00181010=LOSecondary Capture Device ID",
  946. "00181012=DADate of Secondary Capture",
  947. "00181014=TMTime of Secondary Capture",
  948. "00181016=LOSecondary Capture Device Manufacturer",
  949. "00181018=LOSecondary Capture Device Manufacturer's Model Name",
  950. "00181019=LOSecondary Capture Device Software Version(s)",
  951. "00181020=LOSoftware Versions(s)",
  952. "00181022=SHVideo Image Format Acquired",
  953. "00181023=LODigital Image Format Acquired",
  954. "00181030=LOProtocol Name",
  955. "00181040=LOContrast/Bolus Route",
  956. "00181041=DSContrast/Bolus Volume",
  957. "00181042=TMContrast/Bolus Start Time",
  958. "00181043=TMContrast/Bolus Stop Time",
  959. "00181044=DSContrast/Bolus Total Dose",
  960. "00181045=ISSyringe Counts",
  961. "00181050=DSSpatial Resolution",
  962. "00181060=DSTrigger Time",
  963. "00181061=LOTrigger Source or Type",
  964. "00181062=ISNominal Interval",
  965. "00181063=DSFrame Time",
  966. "00181064=LOFraming Type",
  967. "00181065=DSFrame Time Vector",
  968. "00181066=DSFrame Delay",
  969. "00181070=LORadionuclide Route",
  970. "00181071=DSRadionuclide Volume",
  971. "00181072=TMRadionuclide Start Time",
  972. "00181073=TMRadionuclide Stop Time",
  973. "00181074=DSRadionuclide Total Dose",
  974. "00181075=DSRadionuclide Half Life",
  975. "00181076=DSRadionuclide Positron Fraction",
  976. "00181080=CSBeat Rejection Flag",
  977. "00181081=ISLow R-R Value",
  978. "00181082=ISHigh R-R Value",
  979. "00181083=ISIntervals Acquired",
  980. "00181084=ISIntervals Rejected",
  981. "00181085=LOPVC Rejection",
  982. "00181086=ISSkip Beats",
  983. "00181088=ISHeart Rate",
  984. "00181090=ISCardiac Number of Images",
  985. "00181094=ISTrigger Window",
  986. "00181100=DSReconstruction Diameter",
  987. "00181110=DSDistance Source to Detector",
  988. "00181111=DSDistance Source to Patient",
  989. "00181120=DSGantry/Detector Tilt",
  990. "00181130=DSTable Height",
  991. "00181131=DSTable Traverse",
  992. "00181140=CSRotation Direction",
  993. "00181141=DSAngular Position",
  994. "00181142=DSRadial Position",
  995. "00181143=DSScan Arc",
  996. "00181144=DSAngular Step",
  997. "00181145=DSCenter of Rotation Offset",
  998. "00181146=DSRotation Offset",
  999. "00181147=CSField of View Shape",
  1000. "00181149=ISField of View Dimensions(s)",
  1001. "00181150=ISExposure Time",
  1002. "00181151=ISX-ray Tube Current",
  1003. "00181152=ISExposure",
  1004. "00181153=ISExposure in uAs",
  1005. "00181154=DSAverage Pulse Width",
  1006. "00181155=CSRadiation Setting",
  1007. "00181156=CSRectification Type",
  1008. "0018115A=CSRadiation Mode",
  1009. "0018115E=DSImage Area Dose Product",
  1010. "00181160=SHFilter Type",
  1011. "00181161=LOType of Filters",
  1012. "00181162=DSIntensifier Size",
  1013. "00181164=DSImager Pixel Spacing",
  1014. "00181166=CSGrid",
  1015. "00181170=ISGenerator Power",
  1016. "00181180=SHCollimator/grid Name",
  1017. "00181181=CSCollimator Type",
  1018. "00181182=ISFocal Distance",
  1019. "00181183=DSX Focus Center",
  1020. "00181184=DSY Focus Center",
  1021. "00181190=DSFocal Spot(s)",
  1022. "00181191=CSAnode Target Material",
  1023. "001811A0=DSBody Part Thickness",
  1024. "001811A2=DSCompression Force",
  1025. "00181200=DADate of Last Calibration",
  1026. "00181201=TMTime of Last Calibration",
  1027. "00181210=SHConvolution Kernel",
  1028. "00181242=ISActual Frame Duration",
  1029. "00181243=ISCount Rate",
  1030. "00181250=SHReceiving Coil",
  1031. "00181251=SHTransmitting Coil",
  1032. "00181260=SHPlate Type",
  1033. "00181261=LOPhosphor Type",
  1034. "00181300=ISScan Velocity",
  1035. "00181301=CSWhole Body Technique",
  1036. "00181302=ISScan Length",
  1037. "00181310=USAcquisition Matrix",
  1038. "00181312=CSPhase Encoding Direction",
  1039. "00181314=DSFlip Angle",
  1040. "00181315=CSVariable Flip Angle Flag",
  1041. "00181316=DSSAR",
  1042. "00181318=DSdB/dt",
  1043. "00181400=LOAcquisition Device Processing Description",
  1044. "00181401=LOAcquisition Device Processing Code",
  1045. "00181402=CSCassette Orientation",
  1046. "00181403=CSCassette Size",
  1047. "00181404=USExposures on Plate",
  1048. "00181405=ISRelative X-ray Exposure",
  1049. "00181450=CSColumn Angulation",
  1050. "00181500=CSPositioner Motion",
  1051. "00181508=CSPositioner Type",
  1052. "00181510=DSPositioner Primary Angle",
  1053. "00181511=DSPositioner Secondary Angle",
  1054. "00181520=DSPositioner Primary Angle Increment",
  1055. "00181521=DSPositioner Secondary Angle Increment",
  1056. "00181530=DSDetector Primary Angle",
  1057. "00181531=DSDetector Secondary Angle",
  1058. "00181600=CSShutter Shape",
  1059. "00181602=ISShutter Left Vertical Edge",
  1060. "00181604=ISShutter Right Vertical Edge",
  1061. "00181606=ISShutter Upper Horizontal Edge",
  1062. "00181608=ISShutter Lower Horizontal Edge",
  1063. "00181610=ISCenter of Circular Shutter",
  1064. "00181612=ISRadius of Circular Shutter",
  1065. "00181620=ISVertices of the Polygonal Shutter",
  1066. "00181700=ISCollimator Shape",
  1067. "00181702=ISCollimator Left Vertical Edge",
  1068. "00181704=ISCollimator Right Vertical Edge",
  1069. "00181706=ISCollimator Upper Horizontal Edge",
  1070. "00181708=ISCollimator Lower Horizontal Edge",
  1071. "00181710=ISCenter of Circular Collimator",
  1072. "00181712=ISRadius of Circular Collimator",
  1073. "00181720=ISVertices of the Polygonal Collimator",
  1074. "00185000=SHOutput Power",
  1075. "00185010=LOTransducer Data",
  1076. "00185012=DSFocus Depth",
  1077. "00185020=LOPreprocessing Function",
  1078. "00185021=LOPostprocessing Function",
  1079. "00185022=DSMechanical Index",
  1080. "00185024=DSThermal Index",
  1081. "00185026=DSCranial Thermal Index",
  1082. "00185027=DSSoft Tissue Thermal Index",
  1083. "00185028=DSSoft Tissue-focus Thermal Index",
  1084. "00185029=DSSoft Tissue-surface Thermal Index",
  1085. "00185050=ISDepth of Scan Field",
  1086. "00185100=CSPatient Position",
  1087. "00185101=CSView Position",
  1088. "00185104=SQProjection Eponymous Name Code Sequence",
  1089. "00185210=DSImage Transformation Matrix",
  1090. "00185212=DSImage Translation Vector",
  1091. "00186000=DSSensitivity",
  1092. "00186011=SQSequence of Ultrasound Regions",
  1093. "00186012=USRegion Spatial Format",
  1094. "00186014=USRegion Data Type",
  1095. "00186016=ULRegion Flags",
  1096. "00186018=ULRegion Location Min X0",
  1097. "0018601A=ULRegion Location Min Y0",
  1098. "0018601C=ULRegion Location Max X1",
  1099. "0018601E=ULRegion Location Max Y1",
  1100. "00186020=SLReference Pixel X0",
  1101. "00186022=SLReference Pixel Y0",
  1102. "00186024=USPhysical Units X Direction",
  1103. "00186026=USPhysical Units Y Direction",
  1104. "00181628=FDReference Pixel Physical Value X",
  1105. "0018602A=FDReference Pixel Physical Value Y",
  1106. "0018602C=FDPhysical Delta X",
  1107. "0018602E=FDPhysical Delta Y",
  1108. "00186030=ULTransducer Frequency",
  1109. "00186031=CSTransducer Type",
  1110. "00186032=ULPulse Repetition Frequency",
  1111. "00186034=FDDoppler Correction Angle",
  1112. "00186036=FDSterring Angle",
  1113. "00186038=ULDoppler Sample Volume X Position",
  1114. "0018603A=ULDoppler Sample Volume Y Position",
  1115. "0018603C=ULTM-Line Position X0",
  1116. "0018603E=ULTM-Line Position Y0",
  1117. "00186040=ULTM-Line Position X1",
  1118. "00186042=ULTM-Line Position Y1",
  1119. "00186044=USPixel Component Organization",
  1120. "00186046=ULPixel Component Mask",
  1121. "00186048=ULPixel Component Range Start",
  1122. "0018604A=ULPixel Component Range Stop",
  1123. "0018604C=USPixel Component Physical Units",
  1124. "0018604E=USPixel Component Data Type",
  1125. "00186050=ULNumber of Table Break Points",
  1126. "00186052=ULTable of X Break Points",
  1127. "00186054=FDTable of Y Break Points",
  1128. "00186056=ULNumber of Table Entries",
  1129. "00186058=ULTable of Pixel Values",
  1130. "0018605A=ULTable of Parameter Values",
  1131. "00187000=CSDetector Conditions Nominal Flag",
  1132. "00187001=DSDetector Temperature",
  1133. "00187004=CSDetector Type",
  1134. "00187005=CSDetector Configuration",
  1135. "00187006=LTDetector Description",
  1136. "00187008=LTDetector Mode",
  1137. "0018700A=SHDetector ID",
  1138. "0018700C=DADate of Last Detector Calibration",
  1139. "0018700E=TMTime of Last Detector Calibration",
  1140. "00187010=ISExposures on Detector Since Last Calibration",
  1141. "00187011=ISExposures on Detector Since Manufactured",
  1142. "00187012=DSDetector Time Since Last Exposure",
  1143. "00187014=DSDetector Active Time",
  1144. "00187016=DSDetector Activation Offset From Exposure",
  1145. "0018701A=DSDetector Binning",
  1146. "00187020=DSDetector Element Physical Size",
  1147. "00187022=DSDetector Element Spacing",
  1148. "00187024=CSDetector Active Shape",
  1149. "00187026=DSDetector Active Dimension(s)",
  1150. "00187028=DSDetector Active Origin",
  1151. "00187030=DSField of View Origin",
  1152. "00187032=DSField of View Rotation",
  1153. "00187034=CSField of View Horizontal Flip",
  1154. "00187040=LTGrid Absorbing Material",
  1155. "00187041=LTGrid Spacing Material",
  1156. "00187042=DSGrid Thickness",
  1157. "00187044=DSGrid Pitch",
  1158. "00187046=ISGrid Aspect Ratio",
  1159. "00187048=DSGrid Period",
  1160. "0018704C=DSGrid Focal Distance",
  1161. "00187050=LTFilter Material LT",
  1162. "00187052=DSFilter Thickness Minimum",
  1163. "00187054=DSFilter Thickness Maximum",
  1164. "00187060=CSExposure Control Mode",
  1165. "00187062=LTExposure Control Mode Description",
  1166. "00187064=CSExposure Status",
  1167. "00187065=DSPhototimer Setting",
  1168. "0020000D=UIStudy Instance UID",
  1169. "0020000E=UISeries Instance UID",
  1170. "00200010=SHStudy ID",
  1171. "00200011=ISSeries Number",
  1172. "00200012=ISAcquisition Number",
  1173. "00200013=ISImage Number",
  1174. "00200014=ISIsotope Number",
  1175. "00200015=ISPhase Number",
  1176. "00200016=ISInterval Number",
  1177. "00200017=ISTime Slot Number",
  1178. "00200018=ISAngle Number",
  1179. "00200020=CSPatient Orientation",
  1180. "00200022=USOverlay Number",
  1181. "00200024=USCurve Number",
  1182. "00200030=DSImage Position",
  1183. "00200032=DSImage Position (Patient)",
  1184. "00200037=DSImage Orientation (Patient)",
  1185. "00200050=DSLocation",
  1186. "00200052=UIFrame of Reference UID",
  1187. "00200060=CSLaterality",
  1188. "00200070=LOImage Geometry Type",
  1189. "00200080=UIMasking Image UID",
  1190. "00200100=ISTemporal Position Identifier",
  1191. "00200105=ISNumber of Temporal Positions",
  1192. "00200110=DSTemporal Resolution",
  1193. "00201000=ISSeries in Study",
  1194. "00201002=ISImages in Acquisition",
  1195. "00201004=ISAcquisition in Study",
  1196. "00201040=LOPosition Reference Indicator",
  1197. "00201041=DSSlice Location",
  1198. "00201070=ISOther Study Numbers",
  1199. "00201200=ISNumber of Patient Related Studies",
  1200. "00201202=ISNumber of Patient Related Series",
  1201. "00201204=ISNumber of Patient Related Images",
  1202. "00201206=ISNumber of Study Related Series",
  1203. "00201208=ISNumber of Study Related Images",
  1204. "00204000=LTImage Comments",
  1205. "00280002=USSamples per Pixel",
  1206. "00280004=CSPhotometric Interpretation",
  1207. "00280006=USPlanar Configuration",
  1208. "00280008=ISNumber of Frames",
  1209. "00280009=ATFrame Increment Pointer",
  1210. "00280010=USRows",
  1211. "00280011=USColumns",
  1212. "00280030=DSPixel Spacing",
  1213. "00280031=DSZoom Factor",
  1214. "00280032=DSZoom Center",
  1215. "00280034=ISPixel Aspect Ratio",
  1216. "00280051=CSCorrected Image",
  1217. "00280100=USBits Allocated",
  1218. "00280101=USBits Stored",
  1219. "00280102=USHigh Bit",
  1220. "00280103=USPixel Representation",
  1221. "00280106=USSmallest Image Pixel Value",
  1222. "00280107=USLargest Image Pixel Value",
  1223. "00280108=USSmallest Pixel Value in Series",
  1224. "00280109=USLargest Pixel Value in Series",
  1225. "00280120=USPixel Padding Value",
  1226. "00280300=CSQuality Control Image",
  1227. "00280301=CSBurned In Annotation",
  1228. "00281040=CSPixel Intensity Relationship",
  1229. "00281041=SSPixel Intensity Relationship Sign",
  1230. "00281050=DSWindow Center",
  1231. "00281051=DSWindow Width",
  1232. "00281052=DSRescale Intercept",
  1233. "00281053=DSRescale Slope",
  1234. "00281054=LORescale Type",
  1235. "00281055=LOWindow Center & Width Explanation",
  1236. "00281101=USRed Palette Color Lookup Table Descriptor",
  1237. "00281102=USGreen Palette Color Lookup Table Descriptor",
  1238. "00281103=USBlue Palette Color Lookup Table Descriptor",
  1239. "00281201=USRed Palette Color Lookup Table Data",
  1240. "00281202=USGreen Palette Color Lookup Table Data",
  1241. "00281203=USBlue Palette Color Lookup Table Data",
  1242. "00282110=CSLossy Image Compression",
  1243. "00283000=SQModality LUT Sequence",
  1244. "00283002=USLUT Descriptor",
  1245. "00283003=LOLUT Explanation",
  1246. "00283004=LOMadality LUT Type",
  1247. "00283006=USLUT Data",
  1248. "00283010=SQVOI LUT Sequence",
  1249. "30020011=DSImage Plane Pixel Spacing",
  1250. "30020022=DSRadiation Machine SAD",
  1251. "30020026=DSRT IMAGE SID",
  1252. "0032000A=CSStudy Status ID",
  1253. "0032000C=CSStudy Priority ID",
  1254. "00320012=LOStudy ID Issuer",
  1255. "00320032=DAStudy Verified Date",
  1256. "00320033=TMStudy Verified Time",
  1257. "00320034=DAStudy Read Date",
  1258. "00320035=TMStudy Read Time",
  1259. "00321000=DAScheduled Study Start Date",
  1260. "00321001=TMScheduled Study Start Time",
  1261. "00321010=DAScheduled Study Stop Date",
  1262. "00321011=TMScheduled Study Stop Time",
  1263. "00321020=LOScheduled Study Location",
  1264. "00321021=AEScheduled Study Location AE Title(s)",
  1265. "00321030=LOReason for Study",
  1266. "00321032=PNRequesting Physician",
  1267. "00321033=LORequesting Service",
  1268. "00321040=DAStudy Arrival Date",
  1269. "00321041=TMStudy Arrival Time",
  1270. "00321050=DAStudy Completion Date",
  1271. "00321051=TMStudy Completion Time",
  1272. "00321055=CSStudy Component Status ID",
  1273. "00321060=LORequested Procedure Description",
  1274. "00321064=SQRequested Procedure Code Sequence",
  1275. "00321070=LORequested Contrast Agent",
  1276. "00324000=LTStudy Comments",
  1277. "00400001=AEScheduled Station AE Title",
  1278. "00400002=DAScheduled Procedure Step Start Date",
  1279. "00400003=TMScheduled Procedure Step Start Time",
  1280. "00400004=DAScheduled Procedure Step End Date",
  1281. "00400005=TMScheduled Procedure Step End Time",
  1282. "00400006=PNScheduled Performing Physician's Name",
  1283. "00400007=LOScheduled Procedure Step Description",
  1284. "00400008=SQScheduled Action Item Code Sequence",
  1285. "00400009=SHScheduled Procedure Step ID",
  1286. "00400010=SHScheduled Station Name",
  1287. "00400011=SHScheduled Procedure Step Location",
  1288. "00400012=LOPre-Medication",
  1289. "00400020=CSScheduled Procedure Step Status",
  1290. "00400100=SQScheduled Procedure Step Sequence",
  1291. "00400220=SQReferenced Standalone SOP Instance Sequence",
  1292. "00400241=AEPerformed Station AE Title",
  1293. "00400242=SHPerformed Station Name",
  1294. "00400243=SHPerformed Location",
  1295. "00400244=DAPerformed Procedure Step Start Date",
  1296. "00400245=TMPerformed Procedure Step Start Time",
  1297. "00400250=DAPerformed Procedure Step End Date",
  1298. "00400251=TMPerformed Procedure Step End Time",
  1299. "00400252=CSPerformed Procedure Step Status",
  1300. "00400253=SHPerformed Procedure Step ID",
  1301. "00400254=LOPerformed Procedure Step Description",
  1302. "00400255=LOPerformed Procedure Type Description",
  1303. "00400260=SQPerformed Action Item Sequence",
  1304. "00400270=SQScheduled Step Attributes Sequence",
  1305. "00400275=SQRequest Attributes Sequence",
  1306. "00400280=STComments on the Performed Procedure Steps",
  1307. "00400293=SQQuantity Sequence",
  1308. "00400294=DSQuantity",
  1309. "00400295=SQMeasuring Units Sequence",
  1310. "00400296=SQBilling Item Sequence",
  1311. "00400300=USTotal Time of Fluoroscopy",
  1312. "00400301=USTotal Number of Exposures",
  1313. "00400302=USEntrance Dose",
  1314. "00400303=USExposed Area",
  1315. "00400306=DSDistance Source to Entrance",
  1316. "00400307=DSDistance Source to Support",
  1317. "00400310=STComments on Radiation Dose",
  1318. "00400312=DSX-Ray Output",
  1319. "00400314=DSHalf Value Layer",
  1320. "00400316=DSOrgan Dose",
  1321. "00400318=CSOrgan Exposed",
  1322. "00400320=SQBilling Procedure Step Sequence",
  1323. "00400321=SQFilm Consumption Sequence",
  1324. "00400324=SQBilling Supplies and Devices Sequence",
  1325. "00400330=SQReferenced Procedure Step Sequence",
  1326. "00400340=SQPerformed Series Sequence",
  1327. "00400400=LTComments on the Scheduled Procedure Step",
  1328. "0040050A=LOSpecimen Accession Number",
  1329. "00400550=SQSpecimen Sequence",
  1330. "00400551=LOSpecimen Identifier",
  1331. "0040059A=SQSpecimen Type Code Sequence",
  1332. "00400555=SQAcquisition Context Sequence",
  1333. "00400556=STAcquisition Context Description",
  1334. "004006FA=LOSlide Identifier",
  1335. "0040071A=SQImage Center Point Coordinates Sequence",
  1336. "0040072A=DSX offset in Slide Coordinate System",
  1337. "0040073A=DSY offset in Slide Coordinate System",
  1338. "0040074A=DSZ offset in Slide Coordinate System",
  1339. "004008D8=SQPixel Spacing Sequence",
  1340. "004008DA=SQCoordinate System Axis Code Sequence",
  1341. "004008EA=SQMeasurement Units Code Sequence",
  1342. "00401001=SHRequested Procedure ID",
  1343. "00401002=LOReason for the Requested Procedure",
  1344. "00401003=SHRequested Procedure Priority",
  1345. "00401004=LOPatient Transport Arrangements",
  1346. "00401005=LORequested Procedure Location",
  1347. "00401006= 1Placer Order Number / Procedure S",
  1348. "00401007= 1Filler Order Number / Procedure S",
  1349. "00401008=LOConfidentiality Code",
  1350. "00401009=SHReporting Priority",
  1351. "00401010=PNNames of Intended Recipients of Results",
  1352. "00401400=LTRequested Procedure Comments",
  1353. "00402001=LOReason for the Imaging Service Request",
  1354. "00402004=DAIssue Date of Imaging Service Request",
  1355. "00402005=TMIssue Time of Imaging Service Request",
  1356. "00402006= 1Placer Order Number / Imaging Service Request S",
  1357. "00402007= 1Filler Order Number / Imaging Service Request S",
  1358. "00402008=PNOrder Entered By",
  1359. "00402009=SHOrder Enterers Location",
  1360. "00402010=SHOrder Callback Phone Number",
  1361. "00402016=LOPlacer Order Number / Imaging Service Request",
  1362. "00402017=LOFiller Order Number / Imaging Service Request",
  1363. "00402400=LTImaging Service Request Comments",
  1364. "00403001=LOConfidentiality Constraint on Patient Data Description",
  1365. "00408302=DSEntrance Dose in mGy",
  1366. "0040A010=CSRelationship Type",
  1367. "0040A027=LOVerifying Organization",
  1368. "0040A030=DTVerification DateTime",
  1369. "0040A032=DTObservation DateTime",
  1370. "0040A040=CSValue Type",
  1371. "0040A043=SQConcept-name Code Sequence",
  1372. "0040A050=CSContinuity Of Content",
  1373. "0040A073=SQVerifying Observer Sequence",
  1374. "0040A075=PNVerifying Observer Name",
  1375. "0040A088=SQVerifying Observer Identification Code Sequence",
  1376. "0040A0B0=USReferenced Waveform Channels",
  1377. "0040A120=DTDateTime",
  1378. "0040A121=DADate",
  1379. "0040A122=TMTime",
  1380. "0040A123=PNPerson Name",
  1381. "0040A124=UIUID",
  1382. "0040A130=CSTemporal Range Type",
  1383. "0040A132=ULReferenced Sample Positions",
  1384. "0040A136=USReferenced Frame Numbers",
  1385. "0040A138=DSReferenced Time Offsets",
  1386. "0040A13A=DTReferenced Datetime",
  1387. "0040A160=UTText Value",
  1388. "0040A168=SQConcept Code Sequence",
  1389. "0040A180=USAnnotation Group Number",
  1390. "0040A195=SQModifier Code Sequence",
  1391. "0040A300=SQMeasured Value Sequence",
  1392. "0040A30A=DSNumeric Value",
  1393. "0040A360=SQPredecessor Documents Sequence",
  1394. "0040A370=SQReferenced Request Sequence",
  1395. "0040A372=SQPerformed Procedure Code Sequence",
  1396. "0040A375=SQCurrent Requested Procedure Evidence Sequence",
  1397. "0040A385=SQPertinent Other Evidence Sequence",
  1398. "0040A491=CSCompletion Flag",
  1399. "0040A492=LOCompletion Flag Description",
  1400. "0040A493=CSVerification Flag",
  1401. "0040A504=SQContent Template Sequence",
  1402. "0040A525=SQIdentical Documents Sequence",
  1403. "0040A730=SQContent Sequence",
  1404. "0040B020=SQAnnotation Sequence",
  1405. "0040DB00=CSTemplate Identifier",
  1406. "0040DB06=DTTemplate Version",
  1407. "0040DB07=DTTemplate Local Version",
  1408. "0040DB0B=CSTemplate Extension Flag",
  1409. "0040DB0C=UITemplate Extension Organization UID",
  1410. "0040DB0D=UITemplate Extension Creator UID",
  1411. "0040DB73=ULReferenced Content Item Identifier",
  1412. "00540011=USNumber of Energy Windows",
  1413. "00540012=SQEnergy Window Information Sequence",
  1414. "00540013=SQEnergy Window Range Sequence",
  1415. "00540014=DSEnergy Window Lower Limit",
  1416. "00540015=DSEnergy Window Upper Limit",
  1417. "00540016=SQRadiopharmaceutical Information Sequence",
  1418. "00540017=ISResidual Syringe Counts",
  1419. "00540018=SHEnergy Window Name",
  1420. "00540020=USDetector Vector",
  1421. "00540021=USNumber of Detectors",
  1422. "00540022=SQDetector Information Sequence",
  1423. "00540030=USPhase Vector",
  1424. "00540031=USNumber of Phases",
  1425. "00540032=SQPhase Information Sequence",
  1426. "00540033=USNumber of Frames in Phase",
  1427. "00540036=ISPhase Delay",
  1428. "00540038=ISPause Between Frames",
  1429. "00540039=CSPhase Description",
  1430. "00540050=USRotation Vector",
  1431. "00540051=USNumber of Rotations",
  1432. "00540052=SQRotation Information Sequence",
  1433. "00540053=USNumber of Frames in Rotation",
  1434. "00540060=USR-R Interval Vector",
  1435. "00540061=USNumber of R-R Intervals",
  1436. "00540062=SQGated Information Sequence",
  1437. "00540063=SQData Information Sequence",
  1438. "00540070=USTime Slot Vector",
  1439. "00540071=USNumber of Time Slots",
  1440. "00540072=SQTime Slot Information Sequence",
  1441. "00540073=DSTime Slot Time",
  1442. "00540080=USSlice Vector",
  1443. "00540081=USNumber of Slices",
  1444. "00540090=USAngular View Vector",
  1445. "00540100=USTime Sliā€¦

Large files files are truncated, but you can click here to view the full file