/// <summary> /// Loads a dicom file, stopping at a certain tag /// </summary> /// <param name="file">Filename</param> /// <param name="stopTag">Tag to stop parsing at</param> /// <param name="options">DICOM read options</param> public DicomReadStatus Load(String file, DicomTag stopTag, DicomReadOptions options) { using (FileStream fs = File.OpenRead(file)) { fs.Seek(128, SeekOrigin.Begin); CheckFileHeader(fs); DicomStreamReader dsr = new DicomStreamReader(fs); _metainfo = new DcmFileMetaInfo(); dsr.Dataset = _metainfo; dsr.Read(DcmFileMetaInfo.StopTag, options | DicomReadOptions.FileMetaInfoOnly); if (_metainfo.TransferSyntax.IsDeflate) { MemoryStream ms = StreamUtility.Deflate(fs, false); dsr = new DicomStreamReader(ms); } _dataset = new DcmDataset(_metainfo.TransferSyntax); dsr.Dataset = _dataset; DicomReadStatus status = dsr.Read(stopTag, options); fs.Close(); return(status); } }
private void ReadWriteOptionsTest(DicomFile sourceFile, DicomReadOptions readOptions, DicomWriteOptions options) { var sourceIconImageSq = (DicomAttributeSQ)sourceFile.DataSet[DicomTags.IconImageSequence]; Assert.IsTrue(!sourceIconImageSq.IsEmpty && !sourceIconImageSq.IsNull && sourceIconImageSq.Count == 1, "File doesn't have icon image sequence"); Assert.IsTrue(sourceFile.Save(options), "Failed to write file"); var newFile = new DicomFile(sourceFile.Filename); newFile.Load(readOptions); var resultList = new List <DicomAttributeComparisonResult>(); var result = sourceFile.DataSet.Equals(newFile.DataSet, ref resultList); string resultMessage = resultList.Count > 0 ? resultList.First().ToString() : string.Empty; Assert.IsTrue(result, resultMessage); var newIconImageSq = (DicomAttributeSQ)newFile.DataSet[DicomTags.IconImageSequence]; Assert.IsTrue(!newIconImageSq.IsEmpty && !newIconImageSq.IsNull && newIconImageSq.Count == 1, "New file doesn't have icon image sequence"); // update a tag, and make sure it shows they're different newFile.DataSet[DicomTags.PatientsName].Values = "NewPatient^First"; Assert.IsFalse(sourceFile.DataSet.Equals(newFile.DataSet, ref resultList)); // Now update the original file with the name, and they should be the same again sourceFile.DataSet[DicomTags.PatientsName].Values = "NewPatient^First"; Assert.IsTrue(sourceFile.DataSet.Equals(newFile.DataSet)); // Return the original string value. sourceFile.DataSet[DicomTags.PatientsName].SetStringValue("Patient^Test"); }
public void WriteOptionsTest(DicomFile sourceFile, DicomWriteOptions options) { bool result = sourceFile.Save(options); Assert.AreEqual(result, true); DicomFile newFile = new DicomFile(sourceFile.Filename); DicomReadOptions readOptions = DicomReadOptions.Default; newFile.Load(readOptions); Assert.AreEqual(sourceFile.DataSet.Equals(newFile.DataSet), true); // update a tag, and make sure it shows they're different newFile.DataSet[DicomTags.PatientsName].Values = "NewPatient^First"; Assert.AreEqual(sourceFile.DataSet.Equals(newFile.DataSet), false); // Now update the original file with the name, and they should be the same again sourceFile.DataSet[DicomTags.PatientsName].Values = "NewPatient^First"; Assert.AreEqual(sourceFile.DataSet.Equals(newFile.DataSet), true); // Return the original string value. sourceFile.DataSet[DicomTags.PatientsName].SetStringValue("Patient^Test"); }
/// <summary> /// Load a DICOM file (as set by the <see cref="Filename"/> property). /// </summary> /// <remarks> /// Note: If the file does not contain DICM encoded in it, the routine will assume /// the file is not a Part 10 format file, and is instead encoded as just a DataSet /// with the transfer syntax set to Implicit VR Little Endian. /// </remarks> /// <param name="stopTag">A tag to stop at when reading the file. See the constants in <see cref="DicomTags"/>.</param> /// <param name="options">The options to use when reading the file.</param> public void Load(uint stopTag, DicomReadOptions options) { DicomTag stopDicomTag = DicomTagDictionary.GetDicomTag(stopTag) ?? new DicomTag(stopTag, "Bogus Tag", "BogusTag", DicomVr.NONE, false, 1, 1, false); Load(stopDicomTag, options); }
/// <summary> /// Load a DICOM file from an input stream. /// </summary> /// <remarks> /// Note: If the file does not contain DICM encoded in it, and /// <see cref="Stream.CanSeek"/> is true for <paramref name="stream"/>, /// the routine will assume the file is not a Part 10 format file, and is /// instead encoded as just a DataSet with the transfer syntax set to /// Implicit VR Little Endian. /// </remarks> /// <param name="stream">The input stream to read from.</param> public void Load(Stream stream) { const DicomReadOptions options = DicomReadOptions.Default; Platform.CheckForNullReference(stream, "stream"); LoadCore(stream, null, null, options); }
public void SimpleFileTest() { DicomFile file = new DicomFile("LittleEndianReadFileTest.dcm"); DicomAttributeCollection dataSet = file.DataSet; SetupMR(dataSet); SetupMetaInfo(file); dataSet[DicomTags.StudyDescription].SetNullValue(); // Little Endian Tests file.TransferSyntax = TransferSyntax.ExplicitVrLittleEndian; DicomReadOptions readOptions = DicomReadOptions.Default; bool result = file.Save(DicomWriteOptions.Default); Assert.AreEqual(result, true); DicomFile newFile = new DicomFile(file.Filename); newFile.Load(readOptions); Assert.IsTrue(newFile.DataSet[DicomTags.StudyDescription].IsNull); Assert.AreEqual(file.DataSet.Equals(newFile.DataSet), true); DicomAttributeCollection dicomAttributeCollection = new DicomAttributeCollection(); dicomAttributeCollection[DicomTags.PatientId].SetNullValue(); Assert.IsFalse(dicomAttributeCollection[DicomTags.PatientId].IsEmpty, "Dicom Tag is empty, won't be written in DicomStreamWriter.Write()"); }
/// <summary> /// Creates an instance of <see cref="DicomPixelData"/> from specified image path /// </summary> /// <param name="path"></param> /// <param name="readOptions"></param> /// <returns> /// </returns> public static DicomPixelData CreateFrom(string path, DicomReadOptions readOptions) { var file = new DicomFile(path); file.Load(readOptions); return(CreateFrom(file)); }
/// <summary> /// Creates an instance of <see cref="DicomPixelData"/> from specified stream /// </summary> /// <param name="filename"></param> /// <param name="stream"></param> /// <param name="readOptions"></param> /// <returns> /// </returns> public static DicomPixelData CreateFrom(string filename, Stream stream, DicomReadOptions readOptions) { var file = new DicomFile(filename); file.Load(stream, null, readOptions); return(CreateFrom(file)); }
private DicomReadStatus InsertFragmentItem(DicomReadOptions options) { if (_tag == DicomTags.Item) { if (_len > _remain) { return(NeedMoreData(_len)); } ByteBuffer data = CurrentBuffer(options); _remain -= _len; _read += _len; if (!_fragment.HasOffsetTable) { _fragment.SetOffsetTable(data); } else { _fragment.AddFragment(data); } } else if (_tag == DicomTags.SequenceDelimitationItem) { _fragment = null; } else { // unexpected tag return(DicomReadStatus.UnknownError); } return(DicomReadStatus.Success); }
/// <summary> /// Load a DICOM file from an input stream, given a delegate to open the stream. /// </summary> /// <remarks> /// Note: If the file does not contain DICM encoded in it, and /// <see cref="Stream.CanSeek"/> is true for the stream returned by <paramref name="streamOpener"/>, /// the routine will assume the file is not a Part 10 format file, and is /// instead encoded as just a DataSet with the transfer syntax set to /// Implicit VR Little Endian. /// /// Also, if you are using the <see cref="DicomReadOptions.StorePixelDataReferences"/> option with /// a <see cref="Stream"/> as opposed to simply a file name, you must use this method so that the /// stream can be reopenened internally whenever pixel data is accessed. /// </remarks> /// <param name="streamOpener">A delegate that opens the stream to read from.</param> /// <param name="stopTag">The dicom tag to stop the reading at.</param> /// <param name="options">The dicom read options to consider.</param> public void Load(DicomStreamOpener streamOpener, DicomTag stopTag, DicomReadOptions options) { Platform.CheckForNullReference(streamOpener, "streamOpener"); StreamOpener = streamOpener; using (var stream = streamOpener.Open()) LoadCore(stream, streamOpener, stopTag, options); }
private void InsertDatasetItem(DcmItem item, DicomReadOptions options) { if (_sds.Count > 0 && _sds.Count == _sqs.Count) { DcmDataset ds = _sds.Peek(); if (_tag.Element == 0x0000) { if (Flags.IsSet(options, DicomReadOptions.KeepGroupLengths)) { ds.AddItem(item); } } else { ds.AddItem(item); } if (ds.StreamLength != UndefinedLength) { long end = ds.StreamPosition + ds.StreamLength; if ((_stream.Position - _offset) >= end) { _sds.Pop(); } } } else { if (_tag.Element == 0x0000) { if (Flags.IsSet(options, DicomReadOptions.KeepGroupLengths)) { _dataset.AddItem(item); } } else { _dataset.AddItem(item); } } if (_tag == DicomTags.SpecificCharacterSet && item is DcmCodeString) { DcmCodeString cs = (DcmCodeString)item; if (cs.Length > 0) { string[] values = cs.GetValues(); for (int i = 0; i < values.Length; i++) { if (String.IsNullOrEmpty(values[i])) { continue; } _encoding = DcmEncoding.GetEncodingForSpecificCharacterSet(values[i]); break; } } } }
/// <summary> /// Load a DICOM file (as set by the <see cref="Filename"/> property). /// </summary> /// <remarks> /// Note: If the file does not contain DICM encoded in it, the routine will assume /// the file is not a Part 10 format file, and is instead encoded as just a DataSet /// with the transfer syntax set to Implicit VR Little Endian. /// </remarks> /// <param name="stopTag"></param> /// <param name="options">The options to use when reading the file.</param> public void Load(DicomTag stopTag, DicomReadOptions options) { using (FileStream fs = File.OpenRead(Filename)) { Load(fs, stopTag, options); fs.Close(); } }
/// <summary> /// Load a DICOM file (as set by the <see cref="Filename"/> property). /// </summary> /// <remarks> /// Note: If the file does not contain DICM encoded in it, the routine will assume /// the file is not a Part 10 format file, and is instead encoded as just a DataSet /// with the transfer syntax set to Implicit VR Little Endian. /// </remarks> /// <param name="stopTag"></param> /// <param name="options">The options to use when reading the file.</param> public void Load(DicomTag stopTag, DicomReadOptions options) { var streamOpener = StreamOpener; Platform.CheckForNullReference(streamOpener, "filename"); // the only reason why stream opener is null here is because filename is empty using (var stream = streamOpener.Open()) LoadCore(stream, streamOpener, stopTag, options); }
/// <summary> /// Load a DICOM file (as set by the <see cref="Filename"/> property). /// </summary> /// <remarks> /// Note: If the file does not contain DICM encoded in it, the routine will assume /// the file is not a Part 10 format file, and is instead encoded as just a DataSet /// with the transfer syntax set to Implicit VR Little Endian. /// </remarks> /// <param name="stopTag"></param> /// <param name="options">The options to use when reading the file.</param> /// <param name="file">The path of the file to load.</param> public void Load(DicomTag stopTag, DicomReadOptions options, string file) { if (file == null) { throw new ArgumentNullException("file"); } Filename = file; Load(stopTag, options); }
public void FixedSequenceLengthTest() { var file = new DicomFile("FixedSequenceLengthTest.dcm"); DicomAttributeCollection dataSet = file.DataSet; SetupMR(dataSet); SetupMetaInfo(file); dataSet[DicomTags.StudyDescription].SetNullValue(); // Force another empty tag var s = dataSet[DicomTags.ServiceEpisodeId]; var item = new DicomSequenceItem(); item[DicomTags.PhotometricInterpretation].AppendString("MONOCHROME1"); item[DicomTags.Rows].AppendUInt16(256); item[DicomTags.Columns].AppendUInt16(256); item[DicomTags.BitsAllocated].AppendUInt16(8); item[DicomTags.BitsStored].AppendUInt16(8); item[DicomTags.HighBit].AppendUInt16(7); item[DicomTags.PixelData].Values = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; // Force an empty tag var m = item[DicomTags.LossyImageCompression]; var privateTagSQ = new DicomTag(0x00091038, "PrivateSQ", "PrivateSQ", DicomVr.SQvr, true, 1, 10, false); dataSet[privateTagSQ].AddSequenceItem(item); // Little Endian Tests file.TransferSyntax = TransferSyntax.ExplicitVrLittleEndian; const DicomReadOptions readOptions = DicomReadOptions.Default; const DicomWriteOptions writeOptions = DicomWriteOptions.ExplicitLengthSequence | DicomWriteOptions.ExplicitLengthSequenceItem; bool result = file.Save(writeOptions); Assert.AreEqual(result, true); var newFile = new DicomFile(file.Filename); newFile.Load(readOptions); Assert.IsTrue(newFile.DataSet[DicomTags.StudyDescription].IsNull); Assert.AreEqual(file.DataSet.Equals(newFile.DataSet), true); var dicomAttributeCollection = new DicomAttributeCollection(); dicomAttributeCollection[DicomTags.PatientId].SetNullValue(); Assert.IsFalse(dicomAttributeCollection[DicomTags.PatientId].IsEmpty, "Dicom Tag is empty, won't be written in DicomStreamWriter.Write()"); }
private ByteBuffer CurrentBuffer(DicomReadOptions options) { #if SILVERLIGHT ByteBuffer bb = new ByteBuffer(_endian); bb.CopyFrom(_stream, (int)_len); #else ByteBuffer bb = null; if (_isFile) { bool delayLoad = false; if (_len >= _largeElementSize && _vr != DicomVR.SQ) { if (Flags.IsSet(options, DicomReadOptions.DeferLoadingLargeElements)) { delayLoad = true; } else if (Flags.IsSet(options, DicomReadOptions.DeferLoadingPixelData) && _tag == DicomTags.PixelData) { delayLoad = true; } else if (Flags.IsSet(options, DicomReadOptions.DeferLoadingPixelData) && _fragment != null && _fragment.Tag == DicomTags.PixelData) { delayLoad = true; } } if (delayLoad) { FileStream fs = (FileStream)_stream; FileSegment segment = new FileSegment(fs.Name, fs.Position, _len); _stream.Seek(_len, SeekOrigin.Current); bb = new ByteBuffer(segment, _endian); } } if (bb == null) { bb = new ByteBuffer(_endian); bb.CopyFrom(_stream, (int)_len); } #endif if (_vr.IsEncodedString) { bb.Encoding = _encoding; } return(bb); }
private void ButtonLoadFile_Click(object sender, EventArgs e) { openFileDialog.DefaultExt = "dcm"; openFileDialog.ShowDialog(); DicomFile dicomFile = new DicomFile(openFileDialog.FileName); DicomReadOptions options = new DicomReadOptions(); dicomFile.Load(options); _theStream.AddFile(dicomFile); }
public void PrivateAttributeTest() { DicomFile file = new DicomFile("LittleEndianPrivateReadFileTest.dcm"); DicomAttributeCollection dataSet = file.DataSet; SetupMR(dataSet); dataSet[DicomTags.StudyDescription].SetNullValue(); List <DicomTag> tagList = new List <DicomTag>(); SetupPrivateGroups(tagList, dataSet); SetupMetaInfo(file); // Little Endian Tests file.TransferSyntax = TransferSyntax.ImplicitVrLittleEndian; DicomReadOptions readOptions = DicomReadOptions.Default; // Use ExplicitLengthSequence to force SQ attributes to UN VR when they're read back in Assert.IsTrue(file.Save(DicomWriteOptions.ExplicitLengthSequence)); DicomFile newFile = new DicomFile(file.Filename); newFile.Load(readOptions); Assert.IsTrue(newFile.DataSet[DicomTags.StudyDescription].IsNull); Assert.AreNotEqual(file.DataSet.Equals(newFile.DataSet), true); foreach (DicomTag tag in tagList) { DicomAttributeUN unAttrib = newFile.DataSet[tag] as DicomAttributeUN; Assert.IsNotNull(unAttrib, String.Format("UN VR Attribute is not null for tag {0}", tag)); ByteBuffer bb = unAttrib.GetByteBuffer(TransferSyntax.ImplicitVrLittleEndian, newFile.DataSet[DicomTags.SpecificCharacterSet].ToString()); Assert.IsNotNull(bb, String.Format("ByteBuffer not null for tag: {0}", tag)); DicomAttribute validAttrib = tag.VR.CreateDicomAttribute(tag, bb); Assert.IsNotNull(validAttrib); Assert.IsTrue(validAttrib.Equals(file.DataSet[tag]), String.Format("Attributes equal for tag {0}", tag)); } }
public void ReadPixelDataReferencesTest() { DicomFile file = new DicomFile("LittleEndianReadFileTest2.dcm"); DicomAttributeCollection dataSet = file.DataSet; SetupMR(dataSet); SetupMetaInfo(file); // Little Endian Tests file.TransferSyntax = TransferSyntax.ExplicitVrLittleEndian; DicomReadOptions readOptions = DicomReadOptions.StorePixelDataReferences; bool result = file.Save(DicomWriteOptions.Default); Assert.AreEqual(result, true); DicomFile newFile = new DicomFile(file.Filename); newFile.Load(readOptions); DicomAttribute attrib = newFile.DataSet[DicomTags.PixelData]; Assert.IsFalse(attrib.IsEmpty); Assert.IsFalse(attrib.IsNull); Assert.AreEqual(attrib.StreamLength, dataSet[DicomTags.PixelData].StreamLength); // Set the pixel data to null and re-read dataSet[DicomTags.PixelData].SetNullValue(); result = file.Save(DicomWriteOptions.Default); Assert.AreEqual(result, true); newFile = new DicomFile(file.Filename); newFile.Load(readOptions); attrib = newFile.DataSet[DicomTags.PixelData]; Assert.IsFalse(attrib.IsEmpty); Assert.IsTrue(attrib.IsNull); Assert.AreEqual(attrib.StreamLength, dataSet[DicomTags.PixelData].StreamLength); }
public void ReadOptionsTest(DicomFile sourceFile, DicomReadOptions options, bool areEqual) { bool result = sourceFile.Save(DicomWriteOptions.Default); Assert.AreEqual(result, true); DicomFile newFile = new DicomFile(sourceFile.Filename); newFile.Load(options); if (areEqual) { Assert.AreEqual(sourceFile.DataSet.Equals(newFile.DataSet), true); } else { Assert.AreNotEqual(sourceFile.DataSet.Equals(newFile.DataSet), true); } }
private void ImportFile(string file, ImportStudyContext context) { // Note, we're not doing impersonation of the user's identity, so we may have failures here // which would be new in Marmot. try { EnsureMaxUsedSpaceNotExceeded(); var dicomFile = new DicomFile(file); DicomReadOptions readOptions = Request.FileImportBehaviour == FileImportBehaviourEnum.Save ? DicomReadOptions.Default : DicomReadOptions.Default | DicomReadOptions.StorePixelDataReferences; dicomFile.Load(readOptions); var importer = new ImportFilesUtility(context); DicomProcessingResult result = importer.Import(dicomFile, Request.BadFileBehaviour, Request.FileImportBehaviour); if (result.DicomStatus == DicomStatuses.Success) { Progress.NumberOfFilesImported++; } else { Progress.NumberOfImportFailures++; Progress.StatusDetails = result.ErrorMessage; } } catch (NotEnoughStorageException) { Progress.NumberOfImportFailures++; Progress.StatusDetails = SR.ExceptionNotEnoughStorage; context.FatalError = true; } catch (Exception e) { Platform.Log(LogLevel.Warn, "Unable to import DICOM File ({0}): {1}", file, e.Message); Progress.NumberOfImportFailures++; Progress.StatusDetails = string.Format("{0}: {1}", file, e.Message); } }
public void MultiframeReadTest() { DicomFile file = new DicomFile("LittleEndianMultiframeTest.dcm"); DicomAttributeCollection dataSet = file.DataSet; SetupMultiframeXA(dataSet, 511, 511, 5); SetupMetaInfo(file); // Little Endian Tests file.TransferSyntax = TransferSyntax.ExplicitVrLittleEndian; DicomReadOptions readOptions = DicomReadOptions.Default; ReadOptionsTest(file, readOptions, true); readOptions = DicomReadOptions.StorePixelDataReferences; ReadOptionsTest(file, readOptions, true); readOptions = DicomReadOptions.DoNotStorePixelDataInDataSet; ReadOptionsTest(file, readOptions, false); readOptions = DicomReadOptions.None; ReadOptionsTest(file, readOptions, true); // Big Endian Tests file.Filename = "BigEndianMultiframeTest.dcm"; file.TransferSyntax = TransferSyntax.ExplicitVrBigEndian; readOptions = DicomReadOptions.Default; ReadOptionsTest(file, readOptions, true); readOptions = DicomReadOptions.StorePixelDataReferences; ReadOptionsTest(file, readOptions, true); readOptions = DicomReadOptions.DoNotStorePixelDataInDataSet; ReadOptionsTest(file, readOptions, false); readOptions = DicomReadOptions.None; ReadOptionsTest(file, readOptions, true); }
/// <summary> /// Loads a dicom file, stopping at a certain tag /// </summary> /// <param name="file">Filename</param> /// <param name="stopTag">Tag to stop parsing at</param> /// <param name="options">DICOM read options</param> /// <param name="useIsoStore">Load file from isolated storage</param> public DicomReadStatus Load(String file, DicomTag stopTag, DicomReadOptions options, bool useIsoStore = false) { if (useIsoStore) { using (var store = IsolatedStorageFile.GetUserStoreForApplication()) { using (var fs = store.OpenFile(file, FileMode.Open, FileAccess.Read)) { return(Load(fs, stopTag, options)); } } } else { using (var fs = File.OpenRead(file)) { return(Load(fs, stopTag, options)); } } }
private void LoadFiles(DirectoryInfo dir) { FileInfo[] files = dir.GetFiles(); foreach (FileInfo file in files) { DicomFile dicomFile = new DicomFile(file.FullName); try { DicomReadOptions options = new DicomReadOptions(); dicomFile.Load(options); _theStream.AddFile(dicomFile); /* if (true == dicomFile.Load()) { _theStream.AddFile(dicomFile); } * */ } catch (DicomException) { // TODO: Add some logging for failed files } } String[] subdirectories = Directory.GetDirectories(dir.FullName); foreach (String subPath in subdirectories) { DirectoryInfo subDir = new DirectoryInfo(subPath); LoadFiles(subDir); continue; } }
public void TestRoundtripEncapsulatedImageEncapsulatedIconFileReferences() { var file = new DicomFile("TestRoundtripEncapsulatedImageEncapsulatedIconFileReferences.dcm"); SetupEncapsulatedImageWithIconSequence(file, true); const DicomReadOptions readOptions = DicomReadOptions.Default | DicomReadOptions.StorePixelDataReferences; var writeOptions = DicomWriteOptions.WriteFragmentOffsetTable; ReadWriteOptionsTest(file, readOptions, writeOptions); writeOptions = DicomWriteOptions.WriteFragmentOffsetTable | DicomWriteOptions.ExplicitLengthSequence; ReadWriteOptionsTest(file, readOptions, writeOptions); writeOptions = DicomWriteOptions.WriteFragmentOffsetTable | DicomWriteOptions.ExplicitLengthSequenceItem; ReadWriteOptionsTest(file, readOptions, writeOptions); writeOptions = DicomWriteOptions.WriteFragmentOffsetTable | DicomWriteOptions.ExplicitLengthSequenceItem | DicomWriteOptions.ExplicitLengthSequence; ReadWriteOptionsTest(file, readOptions, writeOptions); }
public void TestRoundtripEncapsulatedImageNativeIcon() { var file = new DicomFile("TestRoundtripEncapsulatedImageNativeIcon.dcm"); SetupEncapsulatedImageWithIconSequence(file, false); const DicomReadOptions readOptions = DicomReadOptions.Default; var writeOptions = DicomWriteOptions.WriteFragmentOffsetTable; ReadWriteOptionsTest(file, readOptions, writeOptions); writeOptions = DicomWriteOptions.WriteFragmentOffsetTable | DicomWriteOptions.ExplicitLengthSequence; ReadWriteOptionsTest(file, readOptions, writeOptions); writeOptions = DicomWriteOptions.WriteFragmentOffsetTable | DicomWriteOptions.ExplicitLengthSequenceItem; ReadWriteOptionsTest(file, readOptions, writeOptions); writeOptions = DicomWriteOptions.WriteFragmentOffsetTable | DicomWriteOptions.ExplicitLengthSequenceItem | DicomWriteOptions.ExplicitLengthSequence; ReadWriteOptionsTest(file, readOptions, writeOptions); }
static void Main(string[] args) { if (args.Length == 0) { PrintCommandLine(); return; } if (false == ParseArgs(args)) { return; } foreach (String filename in args) { if (filename.StartsWith("-")) { continue; } DicomFile file = new DicomFile(filename); DicomReadOptions readOptions = DicomReadOptions.Default; try { file.Load(readOptions); } catch (Exception e) { Console.WriteLine("Unexpected exception when loading file: {0}", e.Message); } StringBuilder sb = new StringBuilder(); file.Dump(sb, "", _options); Console.WriteLine(sb.ToString()); } }
private void CheckPixels(string filename) { DicomReadOptions readOptions = DicomReadOptions.StorePixelDataReferences; DicomFile newFile = new DicomFile(filename); newFile.Load(readOptions); DicomUncompressedPixelData pd = new DicomUncompressedPixelData(newFile.DataSet); for (int frame = 0; frame < pd.NumberOfFrames; frame++) { byte[] data = pd.GetFrame(frame); uint pdVal = (uint)frame + 1; for (int i = 0; i < pd.UncompressedFrameSize; i++, pdVal++) { if (data[i] != pdVal % 255) { string val = String.Format("Value bad: frame: {0}, pixel: {1}, val1: {2}, val2: {3}", frame, i, data[i], pdVal % 255); Console.Write(val); } Assert.AreEqual(data[i], pdVal % 255); } } }
private void LoadFiles(DirectoryInfo dir) { FileInfo[] files = dir.GetFiles(); foreach (FileInfo file in files) { DicomFile dicomFile = new DicomFile(file.FullName); try { DicomReadOptions options = new DicomReadOptions(); dicomFile.Load(options); _theStream.AddFile(dicomFile); /* * if (true == dicomFile.Load()) * { * _theStream.AddFile(dicomFile); * } * */ } catch (DicomException) { // TODO: Add some logging for failed files } } String[] subdirectories = Directory.GetDirectories(dir.FullName); foreach (String subPath in subdirectories) { DirectoryInfo subDir = new DirectoryInfo(subPath); LoadFiles(subDir); continue; } }
public static bool IsSet(DicomReadOptions options, DicomReadOptions flag) { return((options & flag) == flag); }
/// <summary> /// Load a DICOM file from an input stream. /// </summary> /// <remarks> /// Note: If the file does not contain DICM encoded in it, and /// <see cref="Stream.CanSeek"/> is true for <paramref name="iStream"/>, /// the routine will assume the file is not a Part 10 format file, and is /// instead encoded as just a DataSet with the transfer syntax set to /// Implicit VR Little Endian. /// </remarks> /// <param name="iStream">The input stream to read from.</param> /// <param name="stopTag">The dicom tag to stop the reading at.</param> /// <param name="options">The dicom read options to consider.</param> public void Load(Stream iStream, DicomTag stopTag, DicomReadOptions options) { if (iStream == null) throw new ArgumentNullException("iStream"); if (stopTag == null) stopTag = new DicomTag(0xFFFFFFFF, "Bogus Tag", "BogusTag", DicomVr.NONE, false, 1, 1, false); DicomStreamReader dsr; if (iStream.CanSeek) { iStream.Seek(128, SeekOrigin.Begin); if (!FileHasPart10Header(iStream)) { if (!Flags.IsSet(options, DicomReadOptions.ReadNonPart10Files)) throw new DicomException(String.Format("File is not part 10 format file: {0}", Filename)); iStream.Seek(0, SeekOrigin.Begin); dsr = new DicomStreamReader(iStream) { Filename = Filename, TransferSyntax = TransferSyntax.ImplicitVrLittleEndian, Dataset = DataSet }; DicomReadStatus stat = dsr.Read(stopTag, options); if (stat != DicomReadStatus.Success) { Platform.Log(LogLevel.Error, "Unexpected error when reading file: {0}", Filename); throw new DicomException("Unexpected read error with file: " + Filename); } TransferSyntax = TransferSyntax.ImplicitVrLittleEndian; if (DataSet.Contains(DicomTags.SopClassUid)) MediaStorageSopClassUid = DataSet[DicomTags.SopClassUid].ToString(); if (DataSet.Contains(DicomTags.SopInstanceUid)) MediaStorageSopInstanceUid = DataSet[DicomTags.SopInstanceUid].ToString(); return; } } else { // Read the 128 byte header first, then check for DICM iStream.Read(new byte[128], 0, 128); if (!FileHasPart10Header(iStream)) { Platform.Log(LogLevel.Error, "Reading DICOM file from stream, file does not have part 10 format header."); throw new DicomException("File being read from stream is not a part 10 format file"); } } dsr = new DicomStreamReader(iStream) { TransferSyntax = TransferSyntax.ExplicitVrLittleEndian, Filename = Filename, Dataset = MetaInfo }; DicomReadStatus readStat = dsr.Read(new DicomTag(0x0002FFFF, "Bogus Tag", "BogusTag", DicomVr.UNvr, false, 1, 1, false), options); if (readStat != DicomReadStatus.Success) { Platform.Log(LogLevel.Error, "Unexpected error when reading file Meta info for file: {0}", Filename); throw new DicomException("Unexpected failure reading file Meta info for file: " + Filename); } MetaInfoFileLength = dsr.EndGroupTwo + 128 + 4; dsr.Dataset = DataSet; dsr.TransferSyntax = TransferSyntax; readStat = dsr.Read(stopTag, options); if (readStat != DicomReadStatus.Success) { Platform.Log(LogLevel.Error, "Unexpected error ({0}) when reading file at offset {2}: {1}", readStat, Filename,dsr.BytesRead); throw new DicomException("Unexpected failure (" + readStat + ") reading file at offset " + dsr.BytesRead + ": " + Filename); } Loaded = true; }
/// <summary> /// Load a DICOM file (as set by the <see cref="Filename"/> property). /// </summary> /// <remarks> /// Note: If the file does not contain DICM encoded in it, the routine will assume /// the file is not a Part 10 format file, and is instead encoded as just a DataSet /// with the transfer syntax set to Implicit VR Little Endian. /// </remarks> /// <param name="stopTag"></param> /// <param name="options">The options to use when reading the file.</param> /// <param name="file">The path of the file to load.</param> public void Load(DicomTag stopTag, DicomReadOptions options, string file) { if (file == null) throw new ArgumentNullException("file"); Filename = file; Load(stopTag, options); }
/// <summary> /// Load a DICOM file (as set by the <see cref="Filename"/> property). /// </summary> /// <remarks> /// Note: If the file does not contain DICM encoded in it, the routine will assume /// the file is not a Part 10 format file, and is instead encoded as just a DataSet /// with the transfer syntax set to Implicit VR Little Endian. /// </remarks> /// <param name="options">The options to use when reading the file.</param> public void Load(DicomReadOptions options) { Load(null, options); }
/// <summary> /// Load a DICOM file from an input stream. /// </summary> /// <remarks> /// Note: If the file does not contain DICM encoded in it, and /// <see cref="Stream.CanSeek"/> is true for <paramref name="stream"/>, /// the routine will assume the file is not a Part 10 format file, and is /// instead encoded as just a DataSet with the transfer syntax set to /// Implicit VR Little Endian. /// /// Also, this overload cannot be used directly with <see cref="DicomReadOptions.StorePixelDataReferences"/>, /// as there must be a way to re-open the same stream at a later time. If the option is required, /// use the <see cref="Load(Func{Stream}, DicomTag, DicomReadOptions)">overload</see> that accepts a delegate for opening the stream. /// </remarks> /// <param name="stream">The input stream to read from.</param> /// <param name="stopTag">The dicom tag to stop the reading at.</param> /// <param name="options">The dicom read options to consider.</param> public void Load(Stream stream, DicomTag stopTag, DicomReadOptions options) { Platform.CheckForNullReference(stream, "stream"); LoadCore(stream, null, stopTag, options); }
/// <summary> /// Load a DICOM file (as set by the <see cref="Filename"/> property). /// </summary> /// <remarks> /// Note: If the file does not contain DICM encoded in it, the routine will assume /// the file is not a Part 10 format file, and is instead encoded as just a DataSet /// with the transfer syntax set to Implicit VR Little Endian. /// </remarks> /// <param name="stopTag"></param> /// <param name="options">The options to use when reading the file.</param> public void Load(DicomTag stopTag, DicomReadOptions options) { var streamOpener = StreamOpener; Platform.CheckForNullReference(streamOpener, "filename"); // the only reason why stream opener is null here is because filename is empty using (var stream = streamOpener.Open()) { LoadCore(stream, streamOpener, stopTag, options); stream.Close(); } }
/// <summary> /// Creates an instance of <see cref="DicomPixelData"/> from specified image path /// </summary> /// <param name="path"></param> /// <param name="readOptions"></param> /// <returns> /// </returns> public static DicomPixelData CreateFrom(string path, DicomReadOptions readOptions) { var file = new DicomFile(path); file.Load(readOptions); return CreateFrom(file); }
private void InsertDatasetItem(DcmItem item, DicomReadOptions options) { if (_sds.Count > 0 && _sds.Count == _sqs.Count) { DcmDataset ds = _sds.Peek(); if (_tag.Element == 0x0000) { if (Flags.IsSet(options, DicomReadOptions.KeepGroupLengths)) ds.AddItem(item); } else ds.AddItem(item); if (ds.StreamLength != UndefinedLength) { long end = ds.StreamPosition + ds.StreamLength; if ((_stream.Position - _offset) >= end) _sds.Pop(); } } else { if (_tag.Element == 0x0000) { if (Flags.IsSet(options, DicomReadOptions.KeepGroupLengths)) _dataset.AddItem(item); } else _dataset.AddItem(item); } if (_tag == DicomTags.SpecificCharacterSet && item is DcmCodeString) { DcmCodeString cs = (DcmCodeString)item; if (cs.Length > 0) { string[] values = cs.GetValues(); for (int i = 0; i < values.Length; i++) { if (String.IsNullOrEmpty(values[i])) continue; _encoding = DcmEncoding.GetEncodingForSpecificCharacterSet(values[i]); break; } } } }
private ByteBuffer CurrentBuffer(DicomReadOptions options) { ByteBuffer bb = null; if (_isFile) { bool delayLoad = false; if (_len >= _largeElementSize && _vr != DicomVR.SQ) { if (Flags.IsSet(options, DicomReadOptions.DeferLoadingLargeElements)) delayLoad = true; else if (Flags.IsSet(options, DicomReadOptions.DeferLoadingPixelData) && _tag == DicomTags.PixelData) delayLoad = true; else if (Flags.IsSet(options, DicomReadOptions.DeferLoadingPixelData) && _fragment != null && _fragment.Tag == DicomTags.PixelData) delayLoad = true; } if (delayLoad) { FileStream fs = (FileStream)_stream; FileSegment segment = new FileSegment(fs.Name, fs.Position, _len); _stream.Seek(_len, SeekOrigin.Current); bb = new ByteBuffer(segment, _endian); } } if (bb == null) { bb = new ByteBuffer(_endian); bb.CopyFrom(_stream, (int)_len); } if (_vr.IsEncodedString) bb.Encoding = _encoding; return bb; }
/// <summary> /// Read dataset from stream /// </summary> /// <param name="stopAtTag">End parsing at this tag</param> /// <param name="options">DICOM read options</param> /// <returns>Status code</returns> public DicomReadStatus Read(DicomTag stopAtTag, DicomReadOptions options) { // Counters: // _remain - bytes remaining in stream // _bytes - estimates bytes to end of dataset // _read - number of bytes read from stream try { _need = 0; _remain = _stream.Length - _stream.Position; while (_remain > 0) { DicomReadStatus status = ParseTag(stopAtTag, options); if (status == DicomReadStatus.SuccessEndRead) return DicomReadStatus.Success; if (status != DicomReadStatus.Success) return status; status = ParseVR(options); if (status != DicomReadStatus.Success) return status; status = ParseLength(options); if (status != DicomReadStatus.Success) return status; if (_tag.IsPrivate) { if (_tag.Element != 0x0000 && _tag.Element <= 0x00ff) { // handle UN private creator id if (_vr != DicomVR.LO && Flags.IsSet(options, DicomReadOptions.ForcePrivateCreatorToLO)) { Dicom.Debug.Log.Warn("Converting Private Creator VR from '{0}' to 'LO'", _vr.VR); _vr = DicomVR.LO; } } } if (_vr == DicomVR.UN && _syntax.IsExplicitVR && Flags.IsSet(options, DicomReadOptions.UseDictionaryForExplicitUN)) { _vr = _tag.Entry.DefaultVR; } if (_fragment != null) { status = InsertFragmentItem(options); if (status != DicomReadStatus.Success) return status; } else if (_sqs.Count > 0 && (_tag == DicomTags.Item || _tag == DicomTags.ItemDelimitationItem || _tag == DicomTags.SequenceDelimitationItem)) { status = InsertSequenceItem(options); if (status != DicomReadStatus.Success) return status; } else { if (_sqs.Count > 0) { DcmItemSequence sq = _sqs.Peek(); if (sq.StreamLength != UndefinedLength) { long end = sq.StreamPosition + 8 + sq.StreamLength; if (_syntax.IsExplicitVR) end += 2 + 2; if ((_stream.Position - _offset) >= end) { if (_sds.Count == _sqs.Count) _sds.Pop(); _sqs.Pop(); } } } if (_len == UndefinedLength) { if (_vr == DicomVR.SQ) { DcmItemSequence sq = new DcmItemSequence(_tag, _pos, _len, _endian); InsertDatasetItem(sq, options); _sqs.Push(sq); } else { _fragment = new DcmFragmentSequence(_tag, _vr, _pos, _endian); InsertDatasetItem(_fragment, options); } } else { if (_vr == DicomVR.SQ) { DcmItemSequence sq = new DcmItemSequence(_tag, _pos, _len, _endian); InsertDatasetItem(sq, options); _sqs.Push(sq); } else { if (_len > _remain) return NeedMoreData(_len); DcmElement elem = DcmElement.Create(_tag, _vr, _pos, _endian, CurrentBuffer(options)); _remain -= _len; _read += _len; InsertDatasetItem(elem, options); } } } _tag = null; _vr = null; _len = UndefinedLength; } return DicomReadStatus.Success; } catch (EndOfStreamException) { // should never happen return DicomReadStatus.UnknownError; } }
public static bool IsSet(DicomReadOptions options, DicomReadOptions flag) { return (options & flag) == flag; }
/// <summary> /// Loads a dicom file, stopping at a certain tag /// </summary> /// <param name="file">Filename</param> /// <param name="stopTag">Tag to stop parsing at</param> /// <param name="options">DICOM read options</param> /// <param name="useIsoStore">Load file from isolated storage</param> public DicomReadStatus Load(String file, DicomTag stopTag, DicomReadOptions options, bool useIsoStore = false) { if (useIsoStore) { using (var store = IsolatedStorageFile.GetUserStoreForApplication()) { using (var fs = store.OpenFile(file, FileMode.Open, FileAccess.Read)) { return Load(fs, stopTag, options); } } } else { using (var fs = File.OpenRead(file)) { return Load(fs, stopTag, options); } } }
public DicomReadStatus Read(DicomTag stopAtTag, DicomReadOptions options) { if (stopAtTag == null) stopAtTag = new DicomTag(0xFFFFFFFF, "Bogus Tag", "BogusTag", DicomVr.UNvr, false, 1, 1, false); // Counters: // _remain - bytes remaining in stream // _bytes - estimates bytes to end of dataset // _read - number of bytes read from stream try { BytesNeeded = 0; _remain = _stream.Length - _stream.Position; while (_remain > 0) { if (_inGroup2 && BytesRead >= _endGroup2) { _inGroup2 = false; // Only change if we're still reading the meta info if (Dataset.StartTagValue < DicomTags.TransferSyntaxUid) { TransferSyntax group2Syntax = TransferSyntax.GetTransferSyntax( Dataset[DicomTags.TransferSyntaxUid].GetString(0, String.Empty)); if (group2Syntax == null) throw new DicomException("Unsupported transfer syntax in group 2 elements"); TransferSyntax = group2Syntax; } } uint tagValue; if (LastTagRead == null) { if (_remain < 4) return NeedMoreData(4); _pos = _stream.Position; ushort g = _reader.ReadUInt16(); ushort e = _reader.ReadUInt16(); tagValue = DicomTag.GetTagValue(g, e); if (DicomTag.IsPrivateGroup(g) && e > 0x00ff) { SaveTagRead = LastTagRead = DicomTagDictionary.GetDicomTag(g, e) ?? new DicomTag((uint) g << 16 | e, "Private Tag", "PrivateTag", DicomVr.UNvr, false, 1, uint.MaxValue, false); } else { if (e == 0x0000) SaveTagRead = LastTagRead = new DicomTag((uint)g << 16 | e, "Group Length", "GroupLength", DicomVr.ULvr, false, 1, 1, false); else { SaveTagRead = LastTagRead = DicomTagDictionary.GetDicomTag(g, e) ?? new DicomTag((uint) g << 16 | e, "Private Tag", "PrivateTag", DicomVr.UNvr, false, 1, uint.MaxValue, false); } } _remain -= 4; BytesEstimated += 4; BytesRead += 4; } else tagValue = LastTagRead.TagValue; if ((tagValue >= stopAtTag.TagValue) && (_sqrs.Count == 0)) // only exit in root message when after stop tag return DicomReadStatus.Success; bool twoByteLength; if (_vr == null) { if (_syntax.ExplicitVr) { if (LastTagRead == DicomTag.Item || LastTagRead == DicomTag.ItemDelimitationItem || LastTagRead == DicomTag.SequenceDelimitationItem) { _vr = DicomVr.NONE; twoByteLength = _vr.Is16BitLengthField; } else { if (_remain < 2) return NeedMoreData(2); string vr = new string(_reader.ReadChars(2)); _vr = DicomVr.GetVR(vr); twoByteLength = _vr.Is16BitLengthField; _remain -= 2; BytesEstimated += 2; BytesRead += 2; if (LastTagRead.VR.Equals(DicomVr.UNvr)) { LastTagRead = new DicomTag(LastTagRead.TagValue, "Private Tag", "PrivateTag", _vr, false, 1, uint.MaxValue, false); if (vr.Equals("??")) twoByteLength = true; } else if (!LastTagRead.VR.Equals(_vr)) { if (!vr.Equals(" ")) { DicomTag tag = new DicomTag(LastTagRead.TagValue, LastTagRead.Name, LastTagRead.VariableName, _vr, LastTagRead.MultiVR, LastTagRead.VMLow, LastTagRead.VMHigh, LastTagRead.Retired); LastTagRead = tag; ; // TODO, log something } } } } else { _vr = LastTagRead.VR; twoByteLength = _vr.Is16BitLengthField; } if (_vr == DicomVr.UNvr) { if (LastTagRead.IsPrivate) { if (LastTagRead.Element <= 0x00ff && LastTagRead.Element >= 0x0010) { // Reset the tag with the right VR and a more descriptive name. LastTagRead = new DicomTag(LastTagRead.TagValue, "Private Creator Code", "PrivateCreatorCode", DicomVr.LOvr, false, 1, uint.MaxValue, false); // private creator id // Only set the VR to LO for Implicit VR, if we do it for // Explicit VR syntaxes, we would incorrectly read the tag // length below. if (!_syntax.ExplicitVr) _vr = DicomVr.LOvr; } else if (_stream.CanSeek && Flags.IsSet(options, DicomReadOptions.AllowSeekingForContext)) { // attempt to identify private sequence by checking if the tag has // an undefined length long pos = _stream.Position; int bytesToCheck = _syntax.ExplicitVr ? 6 : 4; if (_remain >= bytesToCheck) { if (_syntax.ExplicitVr) _reader.ReadUInt16(); uint l = _reader.ReadUInt32(); if (l == UndefinedLength) _vr = DicomVr.SQvr; } _stream.Position = pos; } } } } else twoByteLength = _vr.Is16BitLengthField; // Read the value length if (_len == UndefinedLength) { if (_syntax.ExplicitVr) { if (LastTagRead == DicomTag.Item || LastTagRead == DicomTag.ItemDelimitationItem || LastTagRead == DicomTag.SequenceDelimitationItem) { if (_remain < 4) return NeedMoreData(4); _len = _reader.ReadUInt32(); _remain -= 4; BytesEstimated += 4; BytesRead += 4; } else { if (twoByteLength) { if (_remain < 2) return NeedMoreData(2); _len = _reader.ReadUInt16(); _remain -= 2; BytesEstimated += 2; BytesRead += 2; } else { if (_remain < 6) return NeedMoreData(6); _reader.ReadByte(); _reader.ReadByte(); _len = _reader.ReadUInt32(); _remain -= 6; BytesEstimated += 6; BytesRead += 6; } } } else { if (_remain < 4) return NeedMoreData(4); _len = _reader.ReadUInt32(); _remain -= 4; BytesEstimated += 4; BytesRead += 4; } if ((_len != UndefinedLength) && !_vr.Equals(DicomVr.SQvr) && !(LastTagRead.Equals(DicomTag.Item) && _fragment == null)) BytesEstimated += _len; } // If we have a private creator code, set the VR to LO, because // that is what it is. We must do this after we read the length // so that the 32 bit length is read properly. if ((LastTagRead.IsPrivate) && (_vr.Equals(DicomVr.UNvr)) && (LastTagRead.Element <= 0x00ff)) _vr = DicomVr.LOvr; if (_fragment != null) { // In the middle of parsing pixels if (LastTagRead == DicomTag.Item) { if (_remain < _len) return NeedMoreData(_remain - _len); if (Flags.IsSet(options, DicomReadOptions.StorePixelDataReferences) && _fragment.HasOffsetTable) { FileReference reference = new FileReference(Filename, _stream.Position, _len, _endian, DicomVr.OBvr); DicomFragment fragment = new DicomFragment(reference); _fragment.AddFragment(fragment); _stream.Seek(_len, SeekOrigin.Current); } else { ByteBuffer data = new ByteBuffer(_endian, _len); data.CopyFrom(_stream, (int) _len); if (!_fragment.HasOffsetTable) _fragment.SetOffsetTable(data); else { DicomFragment fragment = new DicomFragment(data); _fragment.AddFragment(fragment); } } _remain -= _len; BytesRead += _len; } else if (LastTagRead == DicomTag.SequenceDelimitationItem) { Dataset[_fragment.Tag] = _fragment; _fragment = null; } else { Platform.Log(LogLevel.Error, "Encountered unexpected tag in stream: {0}", LastTagRead.ToString()); // unexpected tag return DicomReadStatus.UnknownError; } } else if (_sqrs.Count > 0 && (LastTagRead == DicomTag.Item || LastTagRead == DicomTag.ItemDelimitationItem || LastTagRead == DicomTag.SequenceDelimitationItem)) { SequenceRecord rec = _sqrs.Peek(); if (LastTagRead.Equals(DicomTag.Item)) { if (_len != UndefinedLength) { if (_len > _remain) return NeedMoreData(_remain - _len); } DicomSequenceItem ds; if (rec.Tag.TagValue.Equals(DicomTags.DirectoryRecordSequence)) { DirectoryRecordSequenceItem dr = new DirectoryRecordSequenceItem { Offset = (uint) _pos }; ds = dr; } else ds = new DicomSequenceItem(); rec.Current = ds; if (rec.Tag.VR.Equals(DicomVr.UNvr)) { DicomTag tag = new DicomTag(rec.Tag.TagValue, rec.Tag.Name, rec.Tag.VariableName, DicomVr.SQvr, rec.Tag.MultiVR, rec.Tag.VMLow, rec.Tag.VMHigh, rec.Tag.Retired); rec.Parent[tag].AddSequenceItem(ds); } else rec.Parent[rec.Tag].AddSequenceItem(ds); // Specific character set is inherited, save it. It will be overwritten // if a new value of the tag is encountered in the sequence. rec.Current.SpecificCharacterSet = rec.Parent.SpecificCharacterSet; // save the sequence length rec.Curpos = _pos + 8; rec.Curlen = _len; _sqrs.Pop(); _sqrs.Push(rec); if (_len != UndefinedLength) { ByteBuffer data = new ByteBuffer(_endian, _len); data.CopyFrom(_stream, (int)_len); data.Stream.Position = 0; _remain -= _len; BytesRead += _len; DicomStreamReader idsr = new DicomStreamReader(data.Stream) { Dataset = ds, TransferSyntax = rec.Tag.VR.Equals(DicomVr.UNvr) ? TransferSyntax.ImplicitVrLittleEndian : _syntax, Filename = Filename }; DicomReadStatus stat = idsr.Read(null, options); if (stat != DicomReadStatus.Success) { Platform.Log(LogLevel.Error, "Unexpected parsing error ({0}) when reading sequence attribute: {1}.", stat, rec.Tag.ToString()); return stat; } } } else if (LastTagRead == DicomTag.ItemDelimitationItem) { } else if (LastTagRead == DicomTag.SequenceDelimitationItem) { SequenceRecord rec2 = _sqrs.Pop(); if (rec2.Current==null) rec2.Parent[rec.Tag].SetNullValue(); } if (rec.Len != UndefinedLength) { long end = rec.Pos + 8 + rec.Len; if (_syntax.ExplicitVr) end += 2 + 2; if (_stream.Position >= end) { _sqrs.Pop(); } } } else { if (_len == UndefinedLength) { if (_vr.Equals(DicomVr.UNvr)) { if (!_syntax.ExplicitVr) { _vr = DicomVr.SQvr; LastTagRead = LastTagRead.IsPrivate ? new DicomTag(LastTagRead.TagValue, "Private Tag", "PrivateTag", DicomVr.SQvr, false, 1, uint.MaxValue, false) : new DicomTag(LastTagRead.TagValue, "Unknown Tag", "UnknownTag", DicomVr.SQvr, false, 1, uint.MaxValue, false); } else { // To handle this case, we'd have to add a new mechanism to transition the parser to implicit VR parsing, // and then return back to implicit once the parsing of the SQ is complete. Platform.Log(LogLevel.Error, "Encountered unknown tag {0}, encoded as undefined length in an Explicit VR transfer syntax at offset {1}. Unable to parse.", LastTagRead, _stream.Position); return DicomReadStatus.UnknownError; } } if (_vr.Equals(DicomVr.SQvr)) { SequenceRecord rec = new SequenceRecord { Parent = _sqrs.Count > 0 ? _sqrs.Peek().Current : Dataset, Current = null, Tag = LastTagRead, Len = UndefinedLength }; _sqrs.Push(rec); } else { _fragment = new DicomFragmentSequence(LastTagRead); Dataset.LoadDicomFields(_fragment); } } else { if (_vr.Equals(DicomVr.SQvr)) { if (_len == 0) { DicomAttributeCollection ds; if (_sqrs.Count > 0) { SequenceRecord rec = _sqrs.Peek(); ds = rec.Current; } else ds = Dataset; ds[LastTagRead].SetNullValue(); } else { SequenceRecord rec = new SequenceRecord { Len = _len, Pos = _pos, Tag = LastTagRead, Parent = _sqrs.Count > 0 ? _sqrs.Peek().Current : Dataset }; _sqrs.Push(rec); } } else { if (_remain < _len) return NeedMoreData(_len - _remain); if ((LastTagRead.TagValue == DicomTags.PixelData) && Flags.IsSet(options, DicomReadOptions.DoNotStorePixelDataInDataSet)) { // Skip PixelData !! _stream.Seek((int) _len, SeekOrigin.Current); _remain -= _len; BytesRead += _len; } else if ((LastTagRead.TagValue == DicomTags.PixelData) && Flags.IsSet(options, DicomReadOptions.StorePixelDataReferences)) { FileReference reference = new FileReference(Filename, _stream.Position, _len, _endian, LastTagRead.VR); _stream.Seek((int) _len, SeekOrigin.Current); if (LastTagRead.VR.Equals(DicomVr.OWvr)) { DicomAttributeOW elem = new DicomAttributeOW(LastTagRead, reference); Dataset[LastTagRead] = elem; } else if (LastTagRead.VR.Equals(DicomVr.OBvr)) { DicomAttributeOB elem = new DicomAttributeOB(LastTagRead, reference); Dataset[LastTagRead] = elem; } else { DicomAttributeOF elem = new DicomAttributeOF(LastTagRead, reference); Dataset[LastTagRead] = elem; } _remain -= _len; BytesRead += _len; } else { ByteBuffer bb = new ByteBuffer(_len); // If the tag is impacted by specific character set, // set the encoding properly. if (LastTagRead.VR.SpecificCharacterSet) { if (_sqrs.Count > 0) { SequenceRecord rec = _sqrs.Peek(); bb.SpecificCharacterSet = rec.Current.SpecificCharacterSet; } else { bb.SpecificCharacterSet = Dataset.SpecificCharacterSet; } } if (LastTagRead.VR.Equals(DicomVr.UNvr) && !SaveTagRead.VR.Equals(DicomVr.UNvr) && !SaveTagRead.VR.Equals(DicomVr.SQvr) && Flags.IsSet(options, DicomReadOptions.UseDictionaryForExplicitUN)) { LastTagRead = SaveTagRead; bb.Endian = Endian.Little; } else { bb.Endian = _endian; } bb.CopyFrom(_stream, (int) _len); DicomAttribute elem = LastTagRead.CreateDicomAttribute(bb); _remain -= _len; BytesRead += _len; if (_sqrs.Count > 0) { SequenceRecord rec = _sqrs.Peek(); DicomAttributeCollection ds = rec.Current; if (elem.Tag.TagValue == DicomTags.SpecificCharacterSet) { ds.SpecificCharacterSet = elem.ToString(); } if (LastTagRead.Element == 0x0000) { if (Flags.IsSet(options, DicomReadOptions.KeepGroupLengths)) ds[LastTagRead] = elem; } else ds[LastTagRead] = elem; if (rec.Curlen != UndefinedLength) { long end = rec.Curpos + rec.Curlen; if (_stream.Position >= end) { rec.Current = null; } } } else { if (LastTagRead.TagValue == DicomTags.FileMetaInformationGroupLength) { // Save the end of the group 2 elements, so that we can automatically // check and change our transfer syntax when needed. _inGroup2 = true; uint group2Len; elem.TryGetUInt32(0, out group2Len); _endGroup2 = BytesRead + group2Len; } else if (LastTagRead.TagValue == DicomTags.SpecificCharacterSet) { Dataset.SpecificCharacterSet = elem.ToString(); } if (LastTagRead.Element == 0x0000) { if (Flags.IsSet(options, DicomReadOptions.KeepGroupLengths)) Dataset[LastTagRead] = elem; } else Dataset[LastTagRead] = elem; } } } } } LastTagRead = null; _vr = null; _len = UndefinedLength; } return DicomReadStatus.Success; } catch (EndOfStreamException e) { // should never happen Platform.Log(LogLevel.Error, "Unexpected exception when reading file: {0}", e.ToString()); return DicomReadStatus.UnknownError; } }
private DicomReadStatus InsertFragmentItem(DicomReadOptions options) { if (_tag == DicomTags.Item) { if (_len > _remain) return NeedMoreData(_len); ByteBuffer data = CurrentBuffer(options); _remain -= _len; _read += _len; if (!_fragment.HasOffsetTable) _fragment.SetOffsetTable(data); else _fragment.AddFragment(data); } else if (_tag == DicomTags.SequenceDelimitationItem) { _fragment = null; } else { // unexpected tag return DicomReadStatus.UnknownError; } return DicomReadStatus.Success; }
/// <summary> /// Creates an instance of <see cref="DicomPixelData"/> from specified stream /// </summary> /// <param name="filename"></param> /// <param name="stream"></param> /// <param name="readOptions"></param> /// <returns> /// </returns> public static DicomPixelData CreateFrom(string filename, Stream stream, DicomReadOptions readOptions) { var file = new DicomFile(filename); file.Load(stream, null, readOptions); return CreateFrom(file); }
private DicomReadStatus InsertSequenceItem(DicomReadOptions options) { if (_tag.Equals(DicomTags.Item)) { if (_len != UndefinedLength && _len > _remain) return NeedMoreData(_len); if (_sds.Count > _sqs.Count) _sds.Pop(); DcmItemSequenceItem si = new DcmItemSequenceItem(_pos, _len); if (_len != UndefinedLength || (_stream.CanSeek && Flags.IsSet(options, DicomReadOptions.AllowSeekingForContext))) { if (_len == UndefinedLength) options |= DicomReadOptions.SequenceItemOnly; DcmDataset ds = null; DicomReadStatus status = ParseSequenceItemDataset(TransferSyntax, _len, out ds, options); if (status != DicomReadStatus.Success) { Dicom.Debug.Log.Warn("Unknown error while attempting to read sequence item. Trying again with alternate encodings."); DicomTransferSyntax[] syntaxes = null; if (TransferSyntax == DicomTransferSyntax.ExplicitVRBigEndian) syntaxes = new DicomTransferSyntax[] { DicomTransferSyntax.ImplicitVRLittleEndian, DicomTransferSyntax.ExplicitVRLittleEndian }; else if (TransferSyntax.IsExplicitVR) syntaxes = new DicomTransferSyntax[] { DicomTransferSyntax.ImplicitVRLittleEndian, DicomTransferSyntax.ExplicitVRBigEndian }; else syntaxes = new DicomTransferSyntax[] { DicomTransferSyntax.ExplicitVRLittleEndian, DicomTransferSyntax.ExplicitVRBigEndian }; foreach (DicomTransferSyntax tx in syntaxes) { status = ParseSequenceItemDataset(tx, _len, out ds, options); if (status == DicomReadStatus.Success) break; } } if (status != DicomReadStatus.Success) return DicomReadStatus.UnknownError; si.Dataset = ds; if (_len == UndefinedLength) { if (8 > _remain) { // need more data? _sds.Push(ds); } else { // skip delimitation item _stream.Seek(8, SeekOrigin.Current); _remain -= 8; _bytes += 8; _read += 8; } } } else { DcmDataset ds = new DcmDataset(_pos + 8, _len, TransferSyntax); _sds.Push(ds); } _sqs.Peek().AddSequenceItem(si); } else if (_tag == DicomTags.ItemDelimitationItem) { if (_sds.Count == _sqs.Count) _sds.Pop(); } else if (_tag == DicomTags.SequenceDelimitationItem) { if (_sds.Count == _sqs.Count) _sds.Pop(); _sqs.Pop(); } return DicomReadStatus.Success; }
/// <summary> /// Load a DICOM file (as set by the <see cref="Filename"/> property). /// </summary> /// <remarks> /// Note: If the file does not contain DICM encoded in it, the routine will assume /// the file is not a Part 10 format file, and is instead encoded as just a DataSet /// with the transfer syntax set to Implicit VR Little Endian. /// </remarks> /// <param name="stopTag"></param> /// <param name="options">The options to use when reading the file.</param> /// <param name="filename">The path of the file to load.</param> public void Load(DicomTag stopTag, DicomReadOptions options, string filename) { Platform.CheckForEmptyString(filename, "filename"); Filename = filename; Load(stopTag, options); }
private DicomReadStatus ParseLength(DicomReadOptions options) { if (_len == UndefinedLength) { if (_syntax.IsExplicitVR) { if (_tag == DicomTags.Item || _tag == DicomTags.ItemDelimitationItem || _tag == DicomTags.SequenceDelimitationItem) { if (_remain >= 4) { _len = _reader.ReadUInt32(); _remain -= 4; _bytes += 4; _read += 4; } else { return NeedMoreData(4); } } else { if (_vr.Is16BitLengthField) { if (_remain >= 2) { _len = (uint)_reader.ReadUInt16(); _remain -= 2; _bytes += 2; _read += 2; } else { return NeedMoreData(2); } } else { if (_remain >= 6) { _reader.ReadByte(); _reader.ReadByte(); _len = _reader.ReadUInt32(); _remain -= 6; _bytes += 6; _read += 6; } else { return NeedMoreData(6); } } } } else { if (_remain >= 4) { _len = _reader.ReadUInt32(); _remain -= 4; _bytes += 4; _read += 4; } else { return NeedMoreData(4); } } if (_len != UndefinedLength) { if (_vr != DicomVR.SQ && !(_tag.Equals(DicomTags.Item) && _fragment == null)) _bytes += _len; } } return DicomReadStatus.Success; }
/// <summary> /// Load a DICOM file from an input stream, given a delegate to open the stream. /// </summary> /// <remarks> /// Note: If the file does not contain DICM encoded in it, and /// <see cref="Stream.CanSeek"/> is true for the stream returned by <paramref name="streamOpener"/>, /// the routine will assume the file is not a Part 10 format file, and is /// instead encoded as just a DataSet with the transfer syntax set to /// Implicit VR Little Endian. /// /// Also, if you are using the <see cref="DicomReadOptions.StorePixelDataReferences"/> option with /// a <see cref="Stream"/> as opposed to simply a file name, you must use this method so that the /// stream can be reopenened internally whenever pixel data is accessed. /// </remarks> /// <param name="streamOpener">A delegate that opens the stream to read from.</param> /// <param name="stopTag">The dicom tag to stop the reading at.</param> /// <param name="options">The dicom read options to consider.</param> public void Load(DicomStreamOpener streamOpener, DicomTag stopTag, DicomReadOptions options) { Platform.CheckForNullReference(streamOpener, "streamOpener"); StreamOpener = streamOpener; using (var stream = streamOpener.Open()) { LoadCore(stream, streamOpener, stopTag, options); stream.Close(); } }
private DicomReadStatus ParseSequenceItemDataset(DicomTransferSyntax syntax, long len, out DcmDataset dataset, DicomReadOptions options) { long pos = _stream.Position; dataset = new DcmDataset(pos, (uint)len, syntax); Stream stream = (len != UndefinedLength) ? new SegmentStream(_stream, _stream.Position, _len) : _stream; DicomStreamReader idsr = new DicomStreamReader(stream); idsr.Dataset = dataset; idsr.Encoding = _encoding; if (len != UndefinedLength) idsr.PositionOffset = dataset.StreamPosition; DicomReadStatus status = idsr.Read(null, options); if (status != DicomReadStatus.Success) { _stream.Seek(pos, SeekOrigin.Begin); dataset = null; } else { if (len == UndefinedLength) { // rewind delimitation item tag _stream.Seek(-4, SeekOrigin.Current); len = _stream.Position - pos; } _remain -= len; _bytes += len; _read += len; } return status; }
private void LoadCore(Stream stream, DicomStreamOpener streamOpener, DicomTag stopTag, DicomReadOptions options) { // TODO CR (24 Jan 2014): DICOM stream read only uses tag value, so the real implementation should be the uint overload! if (stopTag == null) stopTag = new DicomTag(0xFFFFFFFF, "Bogus Tag", "BogusTag", DicomVr.NONE, false, 1, 1, false); DicomStreamReader dsr; var iStream = stream ?? streamOpener.Open(); if (iStream.CanSeek) { iStream.Seek(128, SeekOrigin.Begin); if (!FileHasPart10Header(iStream)) { if (!Flags.IsSet(options, DicomReadOptions.ReadNonPart10Files)) throw new DicomException(String.Format("File is not part 10 format file: {0}", Filename)); iStream.Seek(0, SeekOrigin.Begin); dsr = new DicomStreamReader(iStream) { StreamOpener = streamOpener, TransferSyntax = TransferSyntax.ImplicitVrLittleEndian, Dataset = DataSet }; DicomReadStatus stat = dsr.Read(stopTag, options); if (stat != DicomReadStatus.Success) { Platform.Log(LogLevel.Error, "Unexpected error when reading file: {0}", Filename); throw new DicomException("Unexpected read error with file: " + Filename); } TransferSyntax = TransferSyntax.ImplicitVrLittleEndian; if (DataSet.Contains(DicomTags.SopClassUid)) MediaStorageSopClassUid = DataSet[DicomTags.SopClassUid].ToString(); if (DataSet.Contains(DicomTags.SopInstanceUid)) MediaStorageSopInstanceUid = DataSet[DicomTags.SopInstanceUid].ToString(); Loaded = true; return; } } else { // TODO CR (04 Apr 2014): this code here is almost identical to the seekable stream above, except that we use the 4CC wrapper // we can combine these two when we trust that the wrapper works in all cases iStream = FourCcReadStream.Create(iStream); // Read the 128 byte header first, then check for DICM iStream.SeekEx(128, SeekOrigin.Begin); if (!FileHasPart10Header(iStream)) { if (!Flags.IsSet(options, DicomReadOptions.ReadNonPart10Files)) throw new DicomException(String.Format("File is not part 10 format file: {0}", Filename)); iStream.Seek(0, SeekOrigin.Begin); dsr = new DicomStreamReader(iStream) { StreamOpener = streamOpener, TransferSyntax = TransferSyntax.ImplicitVrLittleEndian, Dataset = DataSet }; DicomReadStatus stat = dsr.Read(stopTag, options); if (stat != DicomReadStatus.Success) { Platform.Log(LogLevel.Error, "Unexpected error when reading file: {0}", Filename); throw new DicomException("Unexpected read error with file: " + Filename); } TransferSyntax = TransferSyntax.ImplicitVrLittleEndian; if (DataSet.Contains(DicomTags.SopClassUid)) MediaStorageSopClassUid = DataSet[DicomTags.SopClassUid].ToString(); if (DataSet.Contains(DicomTags.SopInstanceUid)) MediaStorageSopInstanceUid = DataSet[DicomTags.SopInstanceUid].ToString(); Loaded = true; return; } } dsr = new DicomStreamReader(iStream) { TransferSyntax = TransferSyntax.ExplicitVrLittleEndian, StreamOpener = streamOpener, Dataset = MetaInfo }; DicomReadStatus readStat = dsr.Read(new DicomTag(0x0002FFFF, "Bogus Tag", "BogusTag", DicomVr.UNvr, false, 1, 1, false), options); if (readStat != DicomReadStatus.Success) { Platform.Log(LogLevel.Error, "Unexpected error when reading file Meta info for file: {0}", Filename); throw new DicomException("Unexpected failure reading file Meta info for file: " + Filename); } MetaInfoFileLength = dsr.EndGroupTwo + 128 + 4; dsr.Dataset = DataSet; dsr.TransferSyntax = TransferSyntax; readStat = dsr.Read(stopTag, options); if (readStat != DicomReadStatus.Success) { Platform.Log(LogLevel.Error, "Unexpected error ({0}) when reading file at offset {2}: {1}", readStat, Filename, dsr.BytesRead); throw new DicomException("Unexpected failure (" + readStat + ") reading file at offset " + dsr.BytesRead + ": " + Filename); } Loaded = true; }
private DicomReadStatus ParseTag(DicomTag stopAtTag, DicomReadOptions options) { if (_tag == null) { if (_remain >= 4) { _pos = _stream.Position + _offset; ushort g = _reader.ReadUInt16(); if (Flags.IsSet(options, DicomReadOptions.FileMetaInfoOnly) && g != 0x0002) { _stream.Seek(-2, SeekOrigin.Current); return DicomReadStatus.SuccessEndRead; } ushort e = _reader.ReadUInt16(); if (DicomTag.IsPrivateGroup(g) && e > 0x00ff) { uint card = DicomTag.GetCard(g, e); if ((card & 0xffffff00) != _privateCreatorCard) { _privateCreatorCard = card & 0xffffff00; DicomTag pct = DicomTag.GetPrivateCreatorTag(g, e); DcmDataset ds = _dataset; if (_sds.Count > 0 && _sds.Count == _sqs.Count) { ds = _sds.Peek(); if (!ds.Contains(pct)) ds = _dataset; } _privateCreatorId = ds.GetString(pct, String.Empty); } _tag = new DicomTag(g, e, _privateCreatorId); } else { _tag = new DicomTag(g, e); if (g == 0xfffe) { if (_tag == DicomTags.Item || _tag == DicomTags.ItemDelimitationItem || _tag == DicomTags.SequenceDelimitationItem) _vr = DicomVR.NONE; } } _remain -= 4; _bytes += 4; _read += 4; } else { return NeedMoreData(4); } } if (_tag == DicomTags.ItemDelimitationItem && Flags.IsSet(options, DicomReadOptions.SequenceItemOnly)) return DicomReadStatus.SuccessEndRead; if (_tag >= stopAtTag) return DicomReadStatus.SuccessEndRead; return DicomReadStatus.Success; }
private DicomReadStatus ParseVR(DicomReadOptions options) { if (_vr == null) { if (_syntax.IsExplicitVR) { if (_remain >= 2) { _vr = DicomVR.Lookup(_reader.ReadChars(2)); _remain -= 2; _bytes += 2; _read += 2; } else { return NeedMoreData(2); } } else { if (_tag.Element == 0x0000) _vr = DicomVR.UL; else if (Flags.IsSet(options, DicomReadOptions.ForcePrivateCreatorToLO) && _tag.IsPrivate && _tag.Element > 0x0000 && _tag.Element <= 0x00ff) _vr = DicomVR.UN; else _vr = _tag.Entry.DefaultVR; } if (_vr == DicomVR.UN) { if (_tag.Element == 0x0000) _vr = DicomVR.UL; // is this needed? else if (_tag.IsPrivate) { if (_tag.Element <= 0x00ff) { // private creator id } else if (_stream.CanSeek && Flags.IsSet(options, DicomReadOptions.AllowSeekingForContext)) { // attempt to identify private sequence long pos = _stream.Position; if (_syntax.IsExplicitVR) { if (_remain >= 2) _reader.ReadUInt16(); else { _vr = null; _stream.Position = pos; return NeedMoreData(2); } } uint l = 0; if (_remain >= 4) { l = _reader.ReadUInt32(); if (l == UndefinedLength) _vr = DicomVR.SQ; } else { _vr = null; _stream.Position = pos; return NeedMoreData(4); } //if (l != 0 && _vr == DicomVR.UN) { // if (_remain >= 4) { // ushort g = _reader.ReadUInt16(); // ushort e = _reader.ReadUInt16(); // DicomTag tag = new DicomTag(g, e); // if (tag == DicomTags.Item || tag == DicomTags.SequenceDelimitationItem) // _vr = DicomVR.SQ; // } else { // _vr = null; // _stream.Position = pos; // return NeedMoreData(4); // } //} _stream.Position = pos; } } } } return DicomReadStatus.Success; }
public void ReadOptionsTest(DicomFile sourceFile, DicomReadOptions options, bool areEqual) { bool result = sourceFile.Save(DicomWriteOptions.Default); Assert.AreEqual(result, true); DicomFile newFile = new DicomFile(sourceFile.Filename); newFile.Load(options); if (areEqual) Assert.AreEqual(sourceFile.DataSet.Equals(newFile.DataSet), true); else Assert.AreNotEqual(sourceFile.DataSet.Equals(newFile.DataSet), true); }
/// <summary> /// Loads a dicom file /// </summary> /// <param name="file">Filename</param> /// <param name="options">DICOM read options</param> public DicomReadStatus Load(String file, DicomReadOptions options) { return Load(file, null, options); }
/// <summary> /// Loads a dicom file /// </summary> /// <param name="fs">File stream to read</param> /// <param name="options">DICOM read options</param> public DicomReadStatus Load(Stream fs, DicomReadOptions options) { return Load(fs, null, options); }
public DicomReadStatus Read(DicomTag stopAtTag, DicomReadOptions options) { if (stopAtTag == null) { stopAtTag = new DicomTag(0xFFFFFFFF, "Bogus Tag", "BogusTag", DicomVr.UNvr, false, 1, 1, false); } // Counters: // _remain - bytes remaining in stream // _bytes - estimates bytes to end of dataset // _read - number of bytes read from stream try { BytesNeeded = 0; _remain = _stream.Length - _stream.Position; while (_remain > 0) { if (_inGroup2 && BytesRead >= _endGroup2) { _inGroup2 = false; // Only change if we're still reading the meta info if (Dataset.StartTagValue < DicomTags.TransferSyntaxUid) { TransferSyntax group2Syntax = TransferSyntax.GetTransferSyntax( Dataset[DicomTags.TransferSyntaxUid].GetString(0, String.Empty)); if (group2Syntax == null) { throw new DicomException("Unsupported transfer syntax in group 2 elements"); } TransferSyntax = group2Syntax; } } uint tagValue; if (LastTagRead == null) { if (_remain < 4) { return(NeedMoreData(4)); } _pos = _stream.Position; ushort g = _reader.ReadUInt16(); ushort e = _reader.ReadUInt16(); tagValue = DicomTag.GetTagValue(g, e); if (DicomTag.IsPrivateGroup(g) && e > 0x00ff) { SaveTagRead = LastTagRead = DicomTagDictionary.GetDicomTag(g, e) ?? new DicomTag((uint)g << 16 | e, "Private Tag", "PrivateTag", DicomVr.UNvr, false, 1, uint.MaxValue, false); } else { if (e == 0x0000) { SaveTagRead = LastTagRead = new DicomTag((uint)g << 16 | e, "Group Length", "GroupLength", DicomVr.ULvr, false, 1, 1, false); } else { SaveTagRead = LastTagRead = DicomTagDictionary.GetDicomTag(g, e) ?? new DicomTag((uint)g << 16 | e, "Private Tag", "PrivateTag", DicomVr.UNvr, false, 1, uint.MaxValue, false); } } _remain -= 4; BytesEstimated += 4; BytesRead += 4; } else { tagValue = LastTagRead.TagValue; } if ((tagValue >= stopAtTag.TagValue) && (_sqrs.Count == 0)) // only exit in root message when after stop tag { if (_inGroup2 && tagValue > 0x0002FFFF) { if (_endGroup2 != BytesRead - 4) { Platform.Log(LogLevel.Debug, "File Meta Info Length, {0}, not equal to actual bytes read in file, {1}, overwriting length.", EndGroupTwo, BytesRead - 4); _endGroup2 = BytesRead - 4; } _inGroup2 = false; } EncounteredStopTag = true; return(DicomReadStatus.Success); } bool twoByteLength; if (_vr == null) { if (_syntax.ExplicitVr) { if (LastTagRead == DicomTag.Item || LastTagRead == DicomTag.ItemDelimitationItem || LastTagRead == DicomTag.SequenceDelimitationItem) { _vr = DicomVr.NONE; twoByteLength = _vr.Is16BitLengthField; } else { if (_remain < 2) { return(NeedMoreData(2)); } string vr = new string(_reader.ReadChars(2)); _vr = DicomVr.GetVR(vr); twoByteLength = _vr.Is16BitLengthField; _remain -= 2; BytesEstimated += 2; BytesRead += 2; if (LastTagRead.VR.Equals(DicomVr.UNvr)) { LastTagRead = new DicomTag(LastTagRead.TagValue, "Private Tag", "PrivateTag", _vr, false, 1, uint.MaxValue, false); if (vr.Equals("??")) { twoByteLength = true; } } else if (!LastTagRead.VR.Equals(_vr)) { if (!vr.Equals(" ")) { DicomTag tag = new DicomTag(LastTagRead.TagValue, LastTagRead.Name, LastTagRead.VariableName, _vr, LastTagRead.MultiVR, LastTagRead.VMLow, LastTagRead.VMHigh, LastTagRead.Retired); LastTagRead = tag; ; // TODO, log something } } } } else { _vr = LastTagRead.VR; twoByteLength = _vr.Is16BitLengthField; } if (_vr == DicomVr.UNvr) { if (LastTagRead.IsPrivate) { if (LastTagRead.Element <= 0x00ff && LastTagRead.Element >= 0x0010) { // Reset the tag with the right VR and a more descriptive name. LastTagRead = new DicomTag(LastTagRead.TagValue, "Private Creator Code", "PrivateCreatorCode", DicomVr.LOvr, false, 1, uint.MaxValue, false); // private creator id // Only set the VR to LO for Implicit VR, if we do it for // Explicit VR syntaxes, we would incorrectly read the tag // length below. if (!_syntax.ExplicitVr) { _vr = DicomVr.LOvr; } } else if (_stream.CanSeek && Flags.IsSet(options, DicomReadOptions.AllowSeekingForContext)) { // attempt to identify private sequence by checking if the tag has // an undefined length long pos = _stream.Position; int bytesToCheck = _syntax.ExplicitVr ? 6 : 4; if (_remain >= bytesToCheck) { if (_syntax.ExplicitVr) { _reader.ReadUInt16(); } uint l = _reader.ReadUInt32(); if (l == _undefinedLength) { _vr = DicomVr.SQvr; } } _stream.Position = pos; } } } } else { twoByteLength = _vr.Is16BitLengthField; } // Read the value length if (_len == _undefinedLength) { if (_syntax.ExplicitVr) { if (LastTagRead == DicomTag.Item || LastTagRead == DicomTag.ItemDelimitationItem || LastTagRead == DicomTag.SequenceDelimitationItem) { if (_remain < 4) { return(NeedMoreData(4)); } _len = _reader.ReadUInt32(); _remain -= 4; BytesEstimated += 4; BytesRead += 4; } else { if (twoByteLength) { if (_remain < 2) { return(NeedMoreData(2)); } _len = _reader.ReadUInt16(); _remain -= 2; BytesEstimated += 2; BytesRead += 2; } else { if (_remain < 6) { return(NeedMoreData(6)); } _reader.ReadByte(); _reader.ReadByte(); _len = _reader.ReadUInt32(); _remain -= 6; BytesEstimated += 6; BytesRead += 6; } } } else { if (_remain < 4) { return(NeedMoreData(4)); } _len = _reader.ReadUInt32(); _remain -= 4; BytesEstimated += 4; BytesRead += 4; } if ((_len != _undefinedLength) && !_vr.Equals(DicomVr.SQvr) && !(LastTagRead.Equals(DicomTag.Item) && _fragment == null)) { BytesEstimated += _len; } } // If we have a private creator code, set the VR to LO, because // that is what it is. We must do this after we read the length // so that the 32 bit length is read properly. if ((LastTagRead.IsPrivate) && (_vr.Equals(DicomVr.UNvr)) && (LastTagRead.Element <= 0x00ff)) { _vr = DicomVr.LOvr; } if (_fragment != null) { // In the middle of parsing pixels if (LastTagRead == DicomTag.Item) { if (_remain < _len) { return(NeedMoreData(_remain - _len)); } if (Flags.IsSet(options, DicomReadOptions.StorePixelDataReferences) && _fragment.HasOffsetTable) { FileReference reference = new FileReference(StreamOpener, _stream.Position, _len, _endian, DicomVr.OBvr); DicomFragment fragment = new DicomFragment(reference); _fragment.AddFragment(fragment); if (_stream.CanSeek) { _stream.Seek(_len, SeekOrigin.Current); } else { ConsumeStreamBytes(_stream, _len); } } else { ByteBuffer data = new ByteBuffer(_endian, _len); data.CopyFrom(_stream, (int)_len); if (!_fragment.HasOffsetTable) { _fragment.SetOffsetTable(data); } else { DicomFragment fragment = new DicomFragment(data); _fragment.AddFragment(fragment); } } _remain -= _len; BytesRead += _len; } else if (LastTagRead == DicomTag.SequenceDelimitationItem) { if (_sqrs.Count > 0) { SequenceRecord rec = _sqrs.Peek(); DicomAttributeCollection ds = rec.Current; ds[_fragment.Tag] = _fragment; if (rec.Curlen != _undefinedLength) { long end = rec.Curpos + rec.Curlen; if (_stream.Position >= end) { rec.Current = null; } } } else { Dataset[_fragment.Tag] = _fragment; } _fragment = null; } else { Platform.Log(LogLevel.Error, "Encountered unexpected tag in stream: {0}", LastTagRead.ToString()); // unexpected tag return(DicomReadStatus.UnknownError); } } else if (_sqrs.Count > 0 && (LastTagRead == DicomTag.Item || LastTagRead == DicomTag.ItemDelimitationItem || LastTagRead == DicomTag.SequenceDelimitationItem)) { SequenceRecord rec = _sqrs.Peek(); if (LastTagRead.Equals(DicomTag.Item)) { if (_len != _undefinedLength) { if (_len > _remain) { return(NeedMoreData(_remain - _len)); } } DicomSequenceItem ds; if (rec.Tag.TagValue.Equals(DicomTags.DirectoryRecordSequence)) { DirectoryRecordSequenceItem dr = new DirectoryRecordSequenceItem { Offset = (uint)_pos }; ds = dr; } else { ds = new DicomSequenceItem(); } rec.Current = ds; if (rec.Tag.VR.Equals(DicomVr.UNvr)) { DicomTag tag = new DicomTag(rec.Tag.TagValue, rec.Tag.Name, rec.Tag.VariableName, DicomVr.SQvr, rec.Tag.MultiVR, rec.Tag.VMLow, rec.Tag.VMHigh, rec.Tag.Retired); rec.Parent[tag].AddSequenceItem(ds); } else { rec.Parent[rec.Tag].AddSequenceItem(ds); } // Specific character set is inherited, save it. It will be overwritten // if a new value of the tag is encountered in the sequence. rec.Current.SpecificCharacterSet = rec.Parent.SpecificCharacterSet; // save the sequence length rec.Curpos = _pos + 8; rec.Curlen = _len; _sqrs.Pop(); _sqrs.Push(rec); if (_len != _undefinedLength) { ByteBuffer data = new ByteBuffer(_endian, _len); data.CopyFrom(_stream, (int)_len); data.Stream.Position = 0; _remain -= _len; BytesRead += _len; DicomStreamReader idsr = new DicomStreamReader(data.Stream) { Dataset = ds, TransferSyntax = rec.Tag.VR.Equals(DicomVr.UNvr) ? TransferSyntax.ImplicitVrLittleEndian : _syntax, StreamOpener = StreamOpener }; DicomReadStatus stat = idsr.Read(null, options & ~DicomReadOptions.StorePixelDataReferences); if (stat != DicomReadStatus.Success) { Platform.Log(LogLevel.Error, "Unexpected parsing error ({0}) when reading sequence attribute: {1}.", stat, rec.Tag.ToString()); return(stat); } } } else if (LastTagRead == DicomTag.ItemDelimitationItem) { } else if (LastTagRead == DicomTag.SequenceDelimitationItem) { SequenceRecord rec2 = _sqrs.Pop(); if (rec2.Current == null) { rec2.Parent[rec.Tag].SetNullValue(); } } if (rec.Len != _undefinedLength) { long end = rec.Pos + 8 + rec.Len; if (_syntax.ExplicitVr) { end += 2 + 2; } if (_stream.Position >= end) { _sqrs.Pop(); } } } else { if (_len == _undefinedLength) { if (_vr.Equals(DicomVr.UNvr)) { if (!_syntax.ExplicitVr) { _vr = DicomVr.SQvr; LastTagRead = LastTagRead.IsPrivate ? new DicomTag(LastTagRead.TagValue, "Private Tag", "PrivateTag", DicomVr.SQvr, false, 1, uint.MaxValue, false) : new DicomTag(LastTagRead.TagValue, "Unknown Tag", "UnknownTag", DicomVr.SQvr, false, 1, uint.MaxValue, false); } else { // To handle this case, we'd have to add a new mechanism to transition the parser to implicit VR parsing, // and then return back to implicit once the parsing of the SQ is complete. Platform.Log(LogLevel.Error, "Encountered unknown tag {0}, encoded as undefined length in an Explicit VR transfer syntax at offset {1}. Unable to parse.", LastTagRead, _stream.Position); return(DicomReadStatus.UnknownError); } } if (_vr.Equals(DicomVr.SQvr)) { SequenceRecord rec = new SequenceRecord { Parent = _sqrs.Count > 0 ? _sqrs.Peek().Current : Dataset, Current = null, Tag = LastTagRead, Len = _undefinedLength }; _sqrs.Push(rec); } else { _fragment = new DicomFragmentSequence(LastTagRead); } } else { if (_vr.Equals(DicomVr.SQvr)) { if (_len == 0) { DicomAttributeCollection ds; if (_sqrs.Count > 0) { SequenceRecord rec = _sqrs.Peek(); ds = rec.Current; } else { ds = Dataset; } ds[LastTagRead].SetNullValue(); } else { SequenceRecord rec = new SequenceRecord { Len = _len, Pos = _pos, Tag = LastTagRead, Parent = _sqrs.Count > 0 ? _sqrs.Peek().Current : Dataset }; _sqrs.Push(rec); } } else { if (_remain < _len) { return(NeedMoreData(_len - _remain)); } if ((LastTagRead.TagValue == DicomTags.PixelData) && Flags.IsSet(options, DicomReadOptions.DoNotStorePixelDataInDataSet)) { // Skip PixelData !! if (_stream.CanSeek) { _stream.Seek((int)_len, SeekOrigin.Current); } else { ConsumeStreamBytes(_stream, _len); } _remain -= _len; BytesRead += _len; } else if ((LastTagRead.TagValue == DicomTags.PixelData) && Flags.IsSet(options, DicomReadOptions.StorePixelDataReferences)) { var reference = new FileReference(StreamOpener, _stream.Position, _len, _endian, LastTagRead.VR); if (_stream.CanSeek) { _stream.Seek((int)_len, SeekOrigin.Current); } else { ConsumeStreamBytes(_stream, _len); } DicomAttribute elem; if (LastTagRead.VR.Equals(DicomVr.OWvr)) { elem = new DicomAttributeOW(LastTagRead, reference); } else if (LastTagRead.VR.Equals(DicomVr.OBvr)) { elem = new DicomAttributeOB(LastTagRead, reference); } else if (LastTagRead.VR.Equals(DicomVr.ODvr)) { elem = new DicomAttributeOD(LastTagRead, reference); } else { elem = new DicomAttributeOF(LastTagRead, reference); } if (_sqrs.Count > 0) { SequenceRecord rec = _sqrs.Peek(); DicomAttributeCollection ds = rec.Current; ds[LastTagRead] = elem; if (rec.Curlen != _undefinedLength) { long end = rec.Curpos + rec.Curlen; if (_stream.Position >= end) { rec.Current = null; } } } else { Dataset[LastTagRead] = elem; } _remain -= _len; BytesRead += _len; } else { ByteBuffer bb = new ByteBuffer(_len); // If the tag is impacted by specific character set, // set the encoding properly. if (LastTagRead.VR.SpecificCharacterSet) { if (_sqrs.Count > 0) { SequenceRecord rec = _sqrs.Peek(); bb.SpecificCharacterSet = rec.Current.SpecificCharacterSet; } else { bb.SpecificCharacterSet = Dataset.SpecificCharacterSet; } } if (LastTagRead.VR.Equals(DicomVr.UNvr) && !SaveTagRead.VR.Equals(DicomVr.UNvr) && !SaveTagRead.VR.Equals(DicomVr.SQvr) && Flags.IsSet(options, DicomReadOptions.UseDictionaryForExplicitUN)) { LastTagRead = SaveTagRead; bb.Endian = Endian.Little; } else { bb.Endian = _endian; } bb.CopyFrom(_stream, (int)_len); DicomAttribute elem = LastTagRead.CreateDicomAttribute(bb); _remain -= _len; BytesRead += _len; if (_sqrs.Count > 0) { SequenceRecord rec = _sqrs.Peek(); DicomAttributeCollection ds = rec.Current; if (elem.Tag.TagValue == DicomTags.SpecificCharacterSet) { ds.SpecificCharacterSet = elem.ToString(); } if (LastTagRead.Element == 0x0000) { if (Flags.IsSet(options, DicomReadOptions.KeepGroupLengths)) { ds[LastTagRead] = elem; } } else { ds[LastTagRead] = elem; } if (rec.Curlen != _undefinedLength) { long end = rec.Curpos + rec.Curlen; if (_stream.Position >= end) { rec.Current = null; } } } else { if (LastTagRead.TagValue == DicomTags.FileMetaInformationGroupLength) { // Save the end of the group 2 elements, so that we can automatically // check and change our transfer syntax when needed. _inGroup2 = true; uint group2Len; elem.TryGetUInt32(0, out group2Len); _endGroup2 = BytesRead + group2Len; } else if (LastTagRead.TagValue == DicomTags.SpecificCharacterSet) { Dataset.SpecificCharacterSet = elem.ToString(); } if (LastTagRead.Element == 0x0000) { if (Flags.IsSet(options, DicomReadOptions.KeepGroupLengths)) { Dataset[LastTagRead] = elem; } } else { Dataset[LastTagRead] = elem; } } } } } } LastTagRead = null; _vr = null; _len = _undefinedLength; } return(DicomReadStatus.Success); } catch (EndOfStreamException e) { // should never happen Platform.Log(LogLevel.Error, "Unexpected exception when reading file: {0}", e.ToString()); return(DicomReadStatus.UnknownError); } }
/// <summary> /// Loads a dicom file, stopping at a certain tag /// </summary> /// <param name="file">Filename</param> /// <param name="stopTag">Tag to stop parsing at</param> /// <param name="options">DICOM read options</param> public DicomReadStatus Load(String file, DicomTag stopTag, DicomReadOptions options) { using (FileStream fs = File.OpenRead(file)) { fs.Seek(128, SeekOrigin.Begin); CheckFileHeader(fs); DicomStreamReader dsr = new DicomStreamReader(fs); _metainfo = new DcmFileMetaInfo(); dsr.Dataset = _metainfo; dsr.Read(DcmFileMetaInfo.StopTag, options | DicomReadOptions.FileMetaInfoOnly); if (_metainfo.TransferSyntax.IsDeflate) { MemoryStream ms = StreamUtility.Deflate(fs, false); dsr = new DicomStreamReader(ms); } _dataset = new DcmDataset(_metainfo.TransferSyntax); dsr.Dataset = _dataset; DicomReadStatus status = dsr.Read(stopTag, options); fs.Close(); return status; } }