private static DicomDataset Decode( DicomDataset oldDataset, DicomTransferSyntax outSyntax, IDicomCodec codec, DicomCodecParams parameters) { if (codec == null) { throw new DicomCodecException("Decoding dataset with transfer syntax: {0} is not supported. See here to get help resolving the reason: https://github.com/fo-dicom/fo-dicom/wiki/Native-codecs-on-.NET", oldDataset.InternalTransferSyntax); } var oldPixelData = DicomPixelData.Create(oldDataset); var newDataset = oldDataset.Clone(); newDataset.InternalTransferSyntax = outSyntax; var newPixelData = DicomPixelData.Create(newDataset, true); codec.Decode(oldPixelData, newPixelData, parameters); ProcessOverlays(oldDataset, newDataset); newDataset.RecalculateGroupLengths(false); return(newDataset); }
private static DicomDataset Decode( DicomDataset oldDataset, DicomTransferSyntax outSyntax, IDicomCodec codec, DicomCodecParams parameters) { if (codec == null) { throw new DicomCodecException("Decoding dataset with transfer syntax: {0} is not supported.", oldDataset.InternalTransferSyntax); } var oldPixelData = DicomPixelData.Create(oldDataset); var newDataset = oldDataset.Clone(); newDataset.InternalTransferSyntax = outSyntax; var newPixelData = DicomPixelData.Create(newDataset, true); codec.Decode(oldPixelData, newPixelData, parameters); ProcessOverlays(oldDataset, newDataset); newDataset.RecalculateGroupLengths(false); return(newDataset); }
/// <summary> /// Implementation of method to load codecs from assembly(ies) at the specified <paramref name="path"/> and /// with the specified <paramref name="search"/> pattern. /// </summary> /// <param name="path">Directory path to codec assemblies.</param> /// <param name="search">Search pattern for codec assemblies.</param> protected override void LoadCodecsImpl(string path, string search) { if (IsLoaded) { return; } Codecs.Clear(); var foundAnyCodecs = false; var assembly = Assembly.GetExecutingAssembly(); var types = assembly.GetTypes(); var codecTypes = types.Where(t => typeof(IDicomCodec).IsAssignableFrom(t) && !t.IsAbstract); var log = LogManager.GetLogger("Efferent.Native.Codec"); foreach (var codecType in codecTypes) { foundAnyCodecs = true; IDicomCodec codec = (IDicomCodec)Activator.CreateInstance(codecType); Codecs[codec.TransferSyntax] = codec; } if (!foundAnyCodecs) { log.Warn("No Dicom codecs were found after searching {path}\\{wildcard}", path, search); } else { IsLoaded = true; var codecNames = string.Join("\n", Codecs.Keys.Select(k => "- " + k.ToString())); System.Diagnostics.Debug.WriteLine($"Codecs found:\n{codecNames}"); } }
public DicomCompressCommand(DicomMessageBase file, TransferSyntax syntax, IDicomCodec codec, DicomCodecParameters parms) : base("DICOM Compress Command", true) { _file = file; _syntax = syntax; _codec = codec; _parms = parms; }
/// <summary> /// Gets an array of <see cref="IDicomCodec"/>s (one from each available <see cref="IDicomCodecFactory"/>). /// </summary> public static IDicomCodec[] GetCodecs() { IDicomCodec[] codecs = new IDicomCodec[_dictionary.Count]; int i = 0; foreach (IDicomCodecFactory factory in _dictionary.Values) codecs[i++] = factory.GetDicomCodec(); return codecs; }
public static IDicomCodec GetCodec(DicomTransferSyntax syntax) { IDicomCodec codec = null; if (!_codecs.TryGetValue(syntax, out codec)) { throw new DicomCodecException("No codec registered for tranfer syntax: {0}", syntax); } return(codec); }
/// <summary> /// Gets an array of <see cref="IDicomCodec"/>s (one from each available <see cref="IDicomCodecFactory"/>). /// </summary> public static IDicomCodec[] GetCodecs() { IDicomCodec[] codecs = new IDicomCodec[_dictionary.Count]; int i = 0; foreach (IDicomCodecFactory factory in _dictionary.Values) { codecs[i++] = factory.GetDicomCodec(); } return(codecs); }
static public unsafe void GetAverageValue(this DicomDataset original, IDicomCodec codec, out double average, out double dispersion, out ushort min, out ushort max) { DicomDataset dataset = new DicomDataset(); original.CopyTo(dataset); DicomPixelData pixelData = DicomPixelData.Create(dataset, true); DicomPixelData pixelDataSource = DicomPixelData.Create(original, false); codec.Decode(pixelDataSource, pixelData, new DicomJpegParams { }); GetAverageValue(dataset, out average, out dispersion, out min, out max); }
static public DicomDataset Uncompress(this DicomDataset original, IDicomCodec codec) { DicomDataset dataset = new DicomDataset(); original.CopyTo(dataset); DicomPixelData pixelData = DicomPixelData.Create(dataset, true); DicomPixelData pixelDataSource = DicomPixelData.Create(original, false); codec.Decode(pixelDataSource, pixelData, new DicomJpeg2000Params { }); return(dataset); }
private static DicomDataset Encode( DicomDataset oldDataset, DicomTransferSyntax outSyntax, IDicomCodec codec, DicomCodecParams parameters) { if (codec == null) { throw new DicomCodecException($"Encoding dataset to transfer syntax {outSyntax} is not supported."); } var oldPixelData = DicomPixelData.Create(oldDataset); var newDataset = oldDataset.Clone(); newDataset.InternalTransferSyntax = outSyntax; var newPixelData = DicomPixelData.Create(newDataset, true); codec.Encode(oldPixelData, newPixelData, parameters); if (outSyntax.IsLossy && newPixelData.NumberOfFrames > 0) { newDataset.AddOrUpdate(new DicomCodeString(DicomTag.LossyImageCompression, "01")); var methods = new List <string>(); if (newDataset.Contains(DicomTag.LossyImageCompressionMethod)) { methods.AddRange(newDataset.GetValues <string>(DicomTag.LossyImageCompressionMethod)); } methods.Add(outSyntax.LossyCompressionMethod); newDataset.AddOrUpdate(new DicomCodeString(DicomTag.LossyImageCompressionMethod, methods.ToArray())); double oldSize = oldPixelData.GetFrame(0).Size; double newSize = newPixelData.GetFrame(0).Size; var ratio = string.Format(CultureInfo.InvariantCulture, "{0:0.000}", oldSize / newSize); newDataset.AddOrUpdate(new DicomDecimalString(DicomTag.LossyImageCompressionRatio, ratio)); } ProcessOverlays(oldDataset, newDataset); newDataset.RecalculateGroupLengths(false); return(newDataset); }
public DicomCompressCommand(DicomMessageBase file, XmlDocument parms, bool failOnCodecException) : base("DICOM Compress Command", true) { _file = file; _failOnCodecException = failOnCodecException; XmlElement element = parms.DocumentElement; string syntax = element.Attributes["syntax"].Value; _syntax = TransferSyntax.GetTransferSyntax(syntax); if (_syntax == null) { string failureDescription = String.Format("Invalid transfer syntax in compression command: {0}", element.Attributes["syntax"].Value); Platform.Log(LogLevel.Error, "Error with input syntax: {0}", failureDescription); throw new DicomCodecException(failureDescription); } IDicomCodecFactory[] codecs = DicomCodecRegistry.GetCodecFactories(); IDicomCodecFactory theCodecFactory = null; foreach (IDicomCodecFactory codec in codecs) { if (codec.CodecTransferSyntax.Equals(_syntax)) { theCodecFactory = codec; break; } } if (theCodecFactory == null) { string failureDescription = String.Format("Unable to find codec for compression: {0}", _syntax.Name); Platform.Log(LogLevel.Error, "Error with compression input parameters: {0}", failureDescription); throw new DicomCodecException(failureDescription); } _codec = theCodecFactory.GetDicomCodec(); _parms = theCodecFactory.GetCodecParameters(parms); }
private static DicomDataset Decode( DicomDataset oldDataset, DicomTransferSyntax outSyntax, IDicomCodec codec, DicomCodecParams parameters) { var oldPixelData = DicomPixelData.Create(oldDataset, false); var newDataset = oldDataset.Clone(); newDataset.InternalTransferSyntax = outSyntax; var newPixelData = DicomPixelData.Create(newDataset, true); codec.Decode(oldPixelData, newPixelData, parameters); ProcessOverlays(oldDataset, newDataset); newDataset.RecalculateGroupLengths(false); return(newDataset); }
private static DicomDataset Encode( DicomDataset oldDataset, DicomTransferSyntax inSyntax, IDicomCodec codec, DicomCodecParams parameters) { var oldPixelData = DicomPixelData.Create(oldDataset, false); var newDataset = oldDataset.Clone(); newDataset.InternalTransferSyntax = codec.TransferSyntax; var newPixelData = DicomPixelData.Create(newDataset, true); codec.Encode(oldPixelData, newPixelData, parameters); if (codec.TransferSyntax.IsLossy && newPixelData.NumberOfFrames > 0) { newDataset.AddOrUpdate(new DicomCodeString(DicomTag.LossyImageCompression, "01")); var methods = new List <string>(); if (newDataset.Contains(DicomTag.LossyImageCompressionMethod)) { methods.AddRange(newDataset.Get <string[]>(DicomTag.LossyImageCompressionMethod)); } methods.Add(codec.TransferSyntax.LossyCompressionMethod); newDataset.AddOrUpdate(new DicomCodeString(DicomTag.LossyImageCompressionMethod, methods.ToArray())); double oldSize = oldPixelData.GetFrame(0).Size; double newSize = newPixelData.GetFrame(0).Size; var ratio = String.Format("{0:0.000}", oldSize / newSize); newDataset.AddOrUpdate(new DicomDecimalString(DicomTag.LossyImageCompressionRatio, ratio)); } ProcessOverlays(oldDataset, newDataset); newDataset.RecalculateGroupLengths(false); return(newDataset); }
/// <summary> /// Get a specific frame's data in uncompressed format. /// </summary> /// <remarks> /// <para> /// If a DICOM file is loaded with the <see cref="DicomReadOptions.StorePixelDataReferences"/> /// option set, this method will only load the specific frame's data from the source file to /// do the decompress, thus reducing memory usage to only the frame being decompressed. /// </para> /// </remarks> /// <param name="frame">A zero offset frame to request.</param> /// <param name="photometricInterpretation">The photometric interpretation of the output data</param> /// <returns>A byte array containing the frame.</returns> public override byte[] GetFrame(int frame, out string photometricInterpretation) { DicomUncompressedPixelData pd = new DicomUncompressedPixelData(this); IDicomCodec codec = DicomCodecRegistry.GetCodec(TransferSyntax); if (codec == null) { Platform.Log(LogLevel.Error, "Unable to get registered codec for {0}", TransferSyntax); throw new DicomCodecException("No registered codec for: " + TransferSyntax.Name); } DicomCodecParameters parameters = DicomCodecRegistry.GetCodecParameters(TransferSyntax, null); codec.DecodeFrame(frame, this, pd, parameters); pd.TransferSyntax = TransferSyntax.ExplicitVrLittleEndian; photometricInterpretation = pd.PhotometricInterpretation; return(pd.GetData()); }
public DicomCompressCommand(DicomMessageBase file, XmlDocument parms) : base("DICOM Compress Command", true) { _file = file; XmlElement element = parms.DocumentElement; string syntax = element.Attributes["syntax"].Value; _syntax = TransferSyntax.GetTransferSyntax(syntax); if (_syntax == null) { string failureDescription = String.Format("Invalid transfer syntax in compression command: {0}", element.Attributes["syntax"].Value); Platform.Log(LogLevel.Error, "Error with input syntax: {0}", failureDescription); throw new DicomCodecException(failureDescription); } IDicomCodecFactory[] codecs = DicomCodecRegistry.GetCodecFactories(); IDicomCodecFactory theCodecFactory = null; foreach (IDicomCodecFactory codec in codecs) if (codec.CodecTransferSyntax.Equals(_syntax)) { theCodecFactory = codec; break; } if (theCodecFactory == null) { string failureDescription = String.Format("Unable to find codec for compression: {0}", _syntax.Name); Platform.Log(LogLevel.Error, "Error with compression input parameters: {0}", failureDescription); throw new DicomCodecException(failureDescription); } _codec = theCodecFactory.GetDicomCodec(); _parms = theCodecFactory.GetCodecParameters(parms); }
protected void ProcessFile(Model.WorkQueue item, WorkQueueUid sop, string path, StudyXml studyXml, IDicomCodecFactory theCodecFactory) { DicomFile file = null; _instanceStats = new CompressInstanceStatistics(); _instanceStats.ProcessTime.Start(); // Use the command processor for rollback capabilities. using (ServerCommandProcessor processor = new ServerCommandProcessor("Processing WorkQueue Compress DICOM File")) { string modality = String.Empty; try { file = new DicomFile(path); _instanceStats.FileLoadTime.Start(); file.Load(DicomReadOptions.StorePixelDataReferences | DicomReadOptions.Default); _instanceStats.FileLoadTime.End(); modality = file.DataSet[DicomTags.Modality].GetString(0, String.Empty); FileInfo fileInfo = new FileInfo(path); _instanceStats.FileSize = (ulong)fileInfo.Length; // Get the Patients Name for processing purposes. String patientsName = file.DataSet[DicomTags.PatientsName].GetString(0, ""); if (file.TransferSyntax.Equals(theCodecFactory.CodecTransferSyntax)) { // Delete the WorkQueueUid item processor.AddCommand(new DeleteWorkQueueUidCommand(sop)); // Do the actual processing if (!processor.Execute()) { Platform.Log(LogLevel.Warn, "Failure deleteing WorkQueueUid: {0} for SOP: {1}", processor.Description, file.MediaStorageSopInstanceUid); Platform.Log(LogLevel.Warn, "Compression file that failed: {0}", file.Filename); } else { Platform.Log(LogLevel.Warn, "Skip compressing SOP {0}. Its current transfer syntax is {1}", file.MediaStorageSopInstanceUid, file.TransferSyntax.Name); } } else { IDicomCodec codec = theCodecFactory.GetDicomCodec(); // Create a context for applying actions from the rules engine var context = new ServerActionContext(file, StorageLocation.FilesystemKey, ServerPartition, item.StudyStorageKey); context.CommandProcessor = processor; var parms = theCodecFactory.GetCodecParameters(item.Data); var compressCommand = new DicomCompressCommand(context.Message, theCodecFactory.CodecTransferSyntax, codec, parms); processor.AddCommand(compressCommand); var save = new SaveDicomFileCommand(file.Filename, file, false); processor.AddCommand(save); // Update the StudyStream object, must be done after compression // and after the compressed image has been successfully saved var insertStudyXmlCommand = new UpdateStudyXmlCommand(file, studyXml, StorageLocation); processor.AddCommand(insertStudyXmlCommand); // Delete the WorkQueueUid item processor.AddCommand(new DeleteWorkQueueUidCommand(sop)); // Do the actual processing if (!processor.Execute()) { EventManager.FireEvent(this, new FailedUpdateSopEventArgs { File = file, ServerPartitionEntry = context.ServerPartition, WorkQueueUidEntry = sop, WorkQueueEntry = WorkQueueItem, FileLength = (ulong)insertStudyXmlCommand.FileSize, FailureMessage = processor.FailureReason }); _instanceStats.CompressTime.Add(compressCommand.CompressTime); Platform.Log(LogLevel.Error, "Failure compressing command {0} for SOP: {1}", processor.Description, file.MediaStorageSopInstanceUid); Platform.Log(LogLevel.Error, "Compression file that failed: {0}", file.Filename); throw new ApplicationException("Unexpected failure (" + processor.FailureReason + ") executing command for SOP: " + file.MediaStorageSopInstanceUid, processor.FailureException); } _instanceStats.CompressTime.Add(compressCommand.CompressTime); Platform.Log(ServerPlatform.InstanceLogLevel, "Compress SOP: {0} for Patient {1}", file.MediaStorageSopInstanceUid, patientsName); EventManager.FireEvent(this, new UpdateSopEventArgs { File = file, ServerPartitionEntry = context.ServerPartition, WorkQueueUidEntry = sop, WorkQueueEntry = WorkQueueItem, FileLength = (ulong)insertStudyXmlCommand.FileSize }); } } catch (Exception e) { EventManager.FireEvent(this, new FailedUpdateSopEventArgs { File = file, ServerPartitionEntry = ServerPartition, WorkQueueUidEntry = sop, WorkQueueEntry = WorkQueueItem, FileLength = (ulong)new FileInfo(path).Length, FailureMessage = processor.FailureReason }); Platform.Log(LogLevel.Error, e, "Unexpected exception when {0}. Rolling back operation.", processor.Description); processor.Rollback(); throw; } finally { _instanceStats.ProcessTime.End(); _studyStats.AddSubStats(_instanceStats); _studyStats.StudyInstanceUid = StorageLocation.StudyInstanceUid; if (String.IsNullOrEmpty(modality) == false) { _studyStats.Modality = modality; } // Update the statistics _studyStats.NumInstances++; } } }
/// <summary> /// Scan the files to send, and create presentation contexts for each abstract syntax to send. /// </summary> protected override void SetPresentationContexts() { foreach (StorageInstance sendStruct in _storageInstanceList) { // skip if failed in LoadStorageInstanceInfo, ie file not found if (sendStruct.SendStatus == DicomStatuses.ProcessingFailure) { continue; } if (sendStruct.TransferSyntax.Encapsulated) { // If the image is encapsulated, make sure there's an exact match of the transfer // syntax, if not, just make sure there's an unencapsulated transfer syntax. byte pcid = AssociationParameters.FindAbstractSyntaxWithTransferSyntax(sendStruct.SopClass, sendStruct.TransferSyntax); if (pcid == 0) { pcid = AssociationParameters.AddPresentationContext(sendStruct.SopClass); AssociationParameters.AddTransferSyntax(pcid, sendStruct.TransferSyntax); } // Check for a codec, and if it exists, also register an uncompressed context. IDicomCodec codec = DicomCodecRegistry.GetCodec(sendStruct.TransferSyntax); if (codec != null) { pcid = AssociationParameters.FindAbstractSyntaxWithTransferSyntax(sendStruct.SopClass, TransferSyntax.ExplicitVrLittleEndian); if (pcid == 0) { pcid = AssociationParameters.AddPresentationContext(sendStruct.SopClass); AssociationParameters.AddTransferSyntax(pcid, TransferSyntax.ExplicitVrLittleEndian); AssociationParameters.AddTransferSyntax(pcid, TransferSyntax.ImplicitVrLittleEndian); } } } else { byte pcid = AssociationParameters.FindAbstractSyntaxWithTransferSyntax(sendStruct.SopClass, TransferSyntax.ExplicitVrLittleEndian); if (pcid == 0) { pcid = AssociationParameters.AddPresentationContext(sendStruct.SopClass); AssociationParameters.AddTransferSyntax(pcid, TransferSyntax.ExplicitVrLittleEndian); AssociationParameters.AddTransferSyntax(pcid, TransferSyntax.ImplicitVrLittleEndian); } } // Now add the preferred syntaxes, if its been set. if (_preferredSyntaxes != null) { SupportedSop supportedSop; if (_preferredSyntaxes.TryGetValue(sendStruct.SopClass.Uid, out supportedSop)) { foreach (TransferSyntax syntax in supportedSop.SyntaxList) { byte pcid = AssociationParameters.FindAbstractSyntaxWithTransferSyntax(sendStruct.SopClass, syntax); // If we have more than 1 transfer syntax associated with the preferred, we want to // have a dedicated presentation context for the preferred, so that we ensure it // gets accepted if the SCP supports it. This is only really going to happen if // the preferred is Explicit VR Little Endian or Implicit VR Little Endian. if ((pcid == 0) || (AssociationParameters.GetPresentationContextTransferSyntaxes(pcid).Count > 1)) { pcid = AssociationParameters.AddPresentationContext(sendStruct.SopClass); AssociationParameters.AddTransferSyntax(pcid, syntax); } } } } } }
private DicomDataset Encode(DicomDataset oldDataset, DicomTransferSyntax inSyntax, IDicomCodec codec, DicomCodecParams parameters) { DicomPixelData oldPixelData = DicomPixelData.Create(oldDataset, false); DicomDataset newDataset = oldDataset.Clone(); newDataset.InternalTransferSyntax = codec.TransferSyntax; DicomPixelData newPixelData = DicomPixelData.Create(newDataset, true); codec.Encode(oldPixelData, newPixelData, parameters); if (codec.TransferSyntax.IsLossy && newPixelData.NumberOfFrames > 0) { newDataset.Add(new DicomCodeString(DicomTag.LossyImageCompression, "01")); List <string> methods = new List <string>(); if (newDataset.Exists(DicomTag.LossyImageCompressionMethod)) { methods.AddRange(newDataset.Get <string[]>(DicomTag.LossyImageCompressionMethod)); } methods.Add(codec.TransferSyntax.LossyCompressionMethod); newDataset.Add(new DicomCodeString(DicomTag.LossyImageCompressionMethod, methods.ToArray())); double oldSize = oldPixelData.GetFrame(0).Size; double newSize = newPixelData.GetFrame(0).Size; string ratio = String.Format("{0:0.000}", oldSize / newSize); newDataset.Add(new DicomDecimalString(DicomTag.LossyImageCompressionRatio, ratio)); } return(newDataset); }
public void ChangeTransferSyntax(TransferSyntax newTransferSyntax, IDicomCodec inputCodec, DicomCodecParameters inputParameters) { IDicomCodec codec = inputCodec; DicomCodecParameters parameters = inputParameters; if (newTransferSyntax.Encapsulated && TransferSyntax.Encapsulated) throw new DicomCodecException("Source and destination transfer syntaxes encapsulated"); if (newTransferSyntax.Encapsulated) { if (codec == null) { codec = DicomCodecRegistry.GetCodec(newTransferSyntax); if (codec == null) { Platform.Log(LogLevel.Error, "Unable to get registered codec for {0}", newTransferSyntax); throw new DicomCodecException("No registered codec for: " + newTransferSyntax.Name); } } if (parameters == null) parameters = DicomCodecRegistry.GetCodecParameters(newTransferSyntax, DataSet); DicomAttribute pixelData; if (DataSet.TryGetAttribute(DicomTags.PixelData, out pixelData)) { if (pixelData.IsNull) throw new DicomCodecException("Sop pixel data has no valid value and cannot be compressed."); new OverlayPlaneModuleIod(DataSet).ExtractEmbeddedOverlays(); var pd = new DicomUncompressedPixelData(DataSet); using (var pixelStream = ((DicomAttributeBinary) pixelData).AsStream()) { //Before compression, make the pixel data more "typical", so it's harder to mess up the codecs. //NOTE: Could combine mask and align into one method so we're not iterating twice, but I prefer having the methods separate. if (DicomUncompressedPixelData.RightAlign(pixelStream, pd.BitsAllocated, pd.BitsStored, pd.HighBit)) { var newHighBit = (ushort) (pd.HighBit - pd.LowBit); Platform.Log(LogLevel.Debug, "Right aligned pixel data (High Bit: {0}->{1}).", pd.HighBit, newHighBit); pd.HighBit = newHighBit; //correct high bit after right-aligning. DataSet[DicomTags.HighBit].SetUInt16(0, newHighBit); } if (DicomUncompressedPixelData.ZeroUnusedBits(pixelStream, pd.BitsAllocated, pd.BitsStored, pd.HighBit)) { Platform.Log(LogLevel.Debug, "Zeroed some unused bits before compression."); } } // Set transfer syntax before compression, the codecs need it. var fragments = new DicomCompressedPixelData(pd) { TransferSyntax = newTransferSyntax }; codec.Encode(pd, fragments, parameters); fragments.UpdateMessage(this); //TODO: should we validate the number of frames in the compressed data? if (!DataSet.TryGetAttribute(DicomTags.PixelData, out pixelData) || pixelData.IsNull) throw new DicomCodecException("Sop has no pixel data after compression."); } else { //A bit cheap, but check for basic image attributes - if any exist // and are non-empty, there should probably be pixel data too. DicomAttribute attribute; if (DataSet.TryGetAttribute(DicomTags.Rows, out attribute) && !attribute.IsNull) throw new DicomCodecException("Suspect Sop appears to be an image (Rows is non-empty), but has no pixel data."); if (DataSet.TryGetAttribute(DicomTags.Columns, out attribute) && !attribute.IsNull) throw new DicomCodecException("Suspect Sop appears to be an image (Columns is non-empty), but has no pixel data."); TransferSyntax = newTransferSyntax; } } else { if (codec == null) { codec = DicomCodecRegistry.GetCodec(TransferSyntax); if (codec == null) { Platform.Log(LogLevel.Error, "Unable to get registered codec for {0}", TransferSyntax); throw new DicomCodecException("No registered codec for: " + TransferSyntax.Name); } if (parameters == null) parameters = DicomCodecRegistry.GetCodecParameters(TransferSyntax, DataSet); } DicomAttribute pixelData; if (DataSet.TryGetAttribute(DicomTags.PixelData, out pixelData)) { if (pixelData.IsNull) throw new DicomCodecException("Sop pixel data has no valid value and cannot be decompressed."); var fragments = new DicomCompressedPixelData(DataSet); var pd = new DicomUncompressedPixelData(fragments); codec.Decode(fragments, pd, parameters); pd.TransferSyntax = TransferSyntax.ExplicitVrLittleEndian; TransferSyntax = TransferSyntax.ExplicitVrLittleEndian; pd.UpdateMessage(this); //TODO: should we validate the number of frames in the decompressed data? if (!DataSet.TryGetAttribute(DicomTags.PixelData, out pixelData) || pixelData.IsNull) throw new DicomCodecException("Sop has no pixel data after decompression."); } else { //NOTE: doing this for consistency, really. DicomAttribute attribute; if (DataSet.TryGetAttribute(DicomTags.Rows, out attribute) && !attribute.IsNull) throw new DicomCodecException("Suspect Sop appears to be an image (Rows is non-empty), but has no pixel data."); if (DataSet.TryGetAttribute(DicomTags.Columns, out attribute) && !attribute.IsNull) throw new DicomCodecException("Suspect Sop appears to be an image (Columns is non-empty), but has no pixel data."); TransferSyntax = TransferSyntax.ExplicitVrLittleEndian; } } }
static public DicomDataset Compress(this DicomDataset original, DicomTransferSyntax dicomTransferSyntax, IDicomCodec codec, DicomCodecParams jpegParams) { DicomDataset dataset = new DicomDataset(dicomTransferSyntax); original.CopyTo(dataset); DicomPixelData pixelData = DicomPixelData.Create(dataset, true); DicomPixelData pixelDataSource = DicomPixelData.Create(original, false); codec.Encode(pixelDataSource, pixelData, jpegParams); return(dataset); }
public void ChangeTransferSyntax(TransferSyntax newTransferSyntax, IDicomCodec inputCodec, DicomCodecParameters inputParameters) { IDicomCodec codec = inputCodec; DicomCodecParameters parameters = inputParameters; if (newTransferSyntax.Encapsulated && TransferSyntax.Encapsulated) { throw new DicomCodecException("Source and destination transfer syntaxes encapsulated"); } if (newTransferSyntax.Encapsulated) { if (codec == null) { codec = DicomCodecRegistry.GetCodec(newTransferSyntax); if (codec == null) { Platform.Log(LogLevel.Error, "Unable to get registered codec for {0}", newTransferSyntax); throw new DicomCodecException("No registered codec for: " + newTransferSyntax.Name); } } if (parameters == null) { parameters = DicomCodecRegistry.GetCodecParameters(newTransferSyntax, DataSet); } DicomAttribute pixelData; if (DataSet.TryGetAttribute(DicomTags.PixelData, out pixelData)) { if (pixelData.IsNull) { throw new DicomCodecException("Sop pixel data has no valid value and cannot be compressed."); } DicomUncompressedPixelData pd = new DicomUncompressedPixelData(DataSet); DicomCompressedPixelData fragments = new DicomCompressedPixelData(pd); // Set before compression, the codecs need it. fragments.TransferSyntax = newTransferSyntax; codec.Encode(pd, fragments, parameters); fragments.UpdateMessage(this); //TODO: should we validate the number of frames in the compressed data? if (!DataSet.TryGetAttribute(DicomTags.PixelData, out pixelData) || pixelData.IsNull) { throw new DicomCodecException("Sop has no pixel data after compression."); } } else { //A bit cheap, but check for basic image attributes - if any exist // and are non-empty, there should probably be pixel data too. DicomAttribute attribute; if (DataSet.TryGetAttribute(DicomTags.Rows, out attribute) && !attribute.IsNull) { throw new DicomCodecException("Suspect Sop appears to be an image (Rows is non-empty), but has no pixel data."); } if (DataSet.TryGetAttribute(DicomTags.Columns, out attribute) && !attribute.IsNull) { throw new DicomCodecException("Suspect Sop appears to be an image (Columns is non-empty), but has no pixel data."); } TransferSyntax = newTransferSyntax; } } else { if (codec == null) { codec = DicomCodecRegistry.GetCodec(TransferSyntax); if (codec == null) { Platform.Log(LogLevel.Error, "Unable to get registered codec for {0}", TransferSyntax); throw new DicomCodecException("No registered codec for: " + TransferSyntax.Name); } if (parameters == null) { parameters = DicomCodecRegistry.GetCodecParameters(TransferSyntax, DataSet); } } DicomAttribute pixelData; if (DataSet.TryGetAttribute(DicomTags.PixelData, out pixelData)) { if (pixelData.IsNull) { throw new DicomCodecException("Sop pixel data has no valid value and cannot be decompressed."); } DicomCompressedPixelData fragments = new DicomCompressedPixelData(DataSet); DicomUncompressedPixelData pd = new DicomUncompressedPixelData(fragments); codec.Decode(fragments, pd, parameters); pd.TransferSyntax = TransferSyntax.ExplicitVrLittleEndian; pd.UpdateMessage(this); //TODO: should we validate the number of frames in the decompressed data? if (!DataSet.TryGetAttribute(DicomTags.PixelData, out pixelData) || pixelData.IsNull) { throw new DicomCodecException("Sop has no pixel data after decompression."); } } else { //NOTE: doing this for consistency, really. DicomAttribute attribute; if (DataSet.TryGetAttribute(DicomTags.Rows, out attribute) && !attribute.IsNull) { throw new DicomCodecException("Suspect Sop appears to be an image (Rows is non-empty), but has no pixel data."); } if (DataSet.TryGetAttribute(DicomTags.Columns, out attribute) && !attribute.IsNull) { throw new DicomCodecException("Suspect Sop appears to be an image (Columns is non-empty), but has no pixel data."); } TransferSyntax = TransferSyntax.ExplicitVrLittleEndian; } } }
private DicomDataset Encode(DicomDataset oldDataset, DicomTransferSyntax inSyntax, IDicomCodec codec, DicomCodecParams parameters) { DicomPixelData oldPixelData = DicomPixelData.Create(oldDataset, false); DicomDataset newDataset = oldDataset.Clone(); newDataset.InternalTransferSyntax = codec.TransferSyntax; DicomPixelData newPixelData = DicomPixelData.Create(newDataset, true); codec.Encode(oldPixelData, newPixelData, parameters); if (codec.TransferSyntax.IsLossy && newPixelData.NumberOfFrames > 0) { newDataset.Add(new DicomCodeString(DicomTag.LossyImageCompression, "01")); List<string> methods = new List<string>(); if (newDataset.Contains(DicomTag.LossyImageCompressionMethod)) methods.AddRange(newDataset.Get<string[]>(DicomTag.LossyImageCompressionMethod)); methods.Add(codec.TransferSyntax.LossyCompressionMethod); newDataset.Add(new DicomCodeString(DicomTag.LossyImageCompressionMethod, methods.ToArray())); double oldSize = oldPixelData.GetFrame(0).Size; double newSize = newPixelData.GetFrame(0).Size; string ratio = String.Format("{0:0.000}", oldSize / newSize); newDataset.Add(new DicomDecimalString(DicomTag.LossyImageCompressionRatio, ratio)); } ProcessOverlays(oldDataset, newDataset); newDataset.RecalculateGroupLengths(false); return newDataset; }
private DicomDataset Decode(DicomDataset oldDataset, DicomTransferSyntax outSyntax, IDicomCodec codec, DicomCodecParams parameters) { DicomPixelData oldPixelData = DicomPixelData.Create(oldDataset, false); DicomDataset newDataset = oldDataset.Clone(); newDataset.InternalTransferSyntax = outSyntax; DicomPixelData newPixelData = DicomPixelData.Create(newDataset, true); codec.Decode(oldPixelData, newPixelData, parameters); ProcessOverlays(oldDataset, newDataset); newDataset.RecalculateGroupLengths(false); return newDataset; }
private DicomDataset Decode(DicomDataset oldDataset, DicomTransferSyntax outSyntax, IDicomCodec codec, DicomCodecParams parameters) { DicomPixelData oldPixelData = DicomPixelData.Create(oldDataset, false); DicomDataset newDataset = oldDataset.Clone(); newDataset.InternalTransferSyntax = outSyntax; DicomPixelData newPixelData = DicomPixelData.Create(newDataset, true); codec.Decode(oldPixelData, newPixelData, parameters); newDataset.RecalculateGroupLengths(false); return(newDataset); }
public void ChangeTransferSyntax(TransferSyntax newTransferSyntax, IDicomCodec inputCodec, DicomCodecParameters inputParameters) { IDicomCodec codec = inputCodec; DicomCodecParameters parameters = inputParameters; if (newTransferSyntax.Encapsulated && TransferSyntax.Encapsulated) { throw new DicomCodecException("Source and destination transfer syntaxes encapsulated"); } if (newTransferSyntax.Encapsulated) { if (codec == null) { codec = DicomCodecRegistry.GetCodec(newTransferSyntax); if (codec == null) { Platform.Log(LogLevel.Error, "Unable to get registered codec for {0}", newTransferSyntax); throw new DicomCodecException("No registered codec for: " + newTransferSyntax.Name); } } if (parameters == null) { parameters = DicomCodecRegistry.GetCodecParameters(newTransferSyntax, DataSet); } DicomAttribute pixelData; if (DataSet.TryGetAttribute(DicomTags.PixelData, out pixelData)) { if (pixelData.IsNull) { throw new DicomCodecException("Sop pixel data has no valid value and cannot be compressed."); } new OverlayPlaneModuleIod(DataSet).ExtractEmbeddedOverlays(); var pd = new DicomUncompressedPixelData(DataSet); var rawPixelData = (byte[])pixelData.Values; //Before compression, make the pixel data more "typical", so it's harder to mess up the codecs. //NOTE: Could combine mask and align into one method so we're not iterating twice, but I prefer having the methods separate. if (DicomUncompressedPixelData.RightAlign(rawPixelData, pd.BitsAllocated, pd.BitsStored, pd.HighBit)) { var newHighBit = (ushort)(pd.HighBit - pd.LowBit); Platform.Log(LogLevel.Debug, "Right aligned pixel data (High Bit: {0}->{1}).", pd.HighBit, newHighBit); pd.HighBit = newHighBit; //correct high bit after right-aligning. DataSet[DicomTags.HighBit].SetUInt16(0, newHighBit); } if (DicomUncompressedPixelData.ZeroUnusedBits(rawPixelData, pd.BitsAllocated, pd.BitsStored, pd.HighBit)) { Platform.Log(LogLevel.Debug, "Zeroed some unused bits before compression."); } // Set transfer syntax before compression, the codecs need it. var fragments = new DicomCompressedPixelData(pd) { TransferSyntax = newTransferSyntax }; codec.Encode(pd, fragments, parameters); fragments.UpdateMessage(this); //TODO: should we validate the number of frames in the compressed data? if (!DataSet.TryGetAttribute(DicomTags.PixelData, out pixelData) || pixelData.IsNull) { throw new DicomCodecException("Sop has no pixel data after compression."); } } else { //A bit cheap, but check for basic image attributes - if any exist // and are non-empty, there should probably be pixel data too. DicomAttribute attribute; if (DataSet.TryGetAttribute(DicomTags.Rows, out attribute) && !attribute.IsNull) { throw new DicomCodecException("Suspect Sop appears to be an image (Rows is non-empty), but has no pixel data."); } if (DataSet.TryGetAttribute(DicomTags.Columns, out attribute) && !attribute.IsNull) { throw new DicomCodecException("Suspect Sop appears to be an image (Columns is non-empty), but has no pixel data."); } TransferSyntax = newTransferSyntax; } } else { if (codec == null) { codec = DicomCodecRegistry.GetCodec(TransferSyntax); if (codec == null) { Platform.Log(LogLevel.Error, "Unable to get registered codec for {0}", TransferSyntax); throw new DicomCodecException("No registered codec for: " + TransferSyntax.Name); } if (parameters == null) { parameters = DicomCodecRegistry.GetCodecParameters(TransferSyntax, DataSet); } } DicomAttribute pixelData; if (DataSet.TryGetAttribute(DicomTags.PixelData, out pixelData)) { if (pixelData.IsNull) { throw new DicomCodecException("Sop pixel data has no valid value and cannot be decompressed."); } var fragments = new DicomCompressedPixelData(DataSet); var pd = new DicomUncompressedPixelData(fragments); codec.Decode(fragments, pd, parameters); pd.TransferSyntax = TransferSyntax.ExplicitVrLittleEndian; TransferSyntax = TransferSyntax.ExplicitVrLittleEndian; pd.UpdateMessage(this); //TODO: should we validate the number of frames in the decompressed data? if (!DataSet.TryGetAttribute(DicomTags.PixelData, out pixelData) || pixelData.IsNull) { throw new DicomCodecException("Sop has no pixel data after decompression."); } } else { //NOTE: doing this for consistency, really. DicomAttribute attribute; if (DataSet.TryGetAttribute(DicomTags.Rows, out attribute) && !attribute.IsNull) { throw new DicomCodecException("Suspect Sop appears to be an image (Rows is non-empty), but has no pixel data."); } if (DataSet.TryGetAttribute(DicomTags.Columns, out attribute) && !attribute.IsNull) { throw new DicomCodecException("Suspect Sop appears to be an image (Columns is non-empty), but has no pixel data."); } TransferSyntax = TransferSyntax.ExplicitVrLittleEndian; } } }
public void ChangeTransferSyntax(TransferSyntax newTransferSyntax, IDicomCodec inputCodec, DicomCodecParameters inputParameters) { IDicomCodec codec = inputCodec; DicomCodecParameters parameters = inputParameters; if (newTransferSyntax.Encapsulated && TransferSyntax.Encapsulated) throw new DicomCodecException("Source and destination transfer syntaxes encapsulated"); if (newTransferSyntax.Encapsulated) { if (codec == null) { codec = DicomCodecRegistry.GetCodec(newTransferSyntax); if (codec == null) { Platform.Log(LogLevel.Error, "Unable to get registered codec for {0}", newTransferSyntax); throw new DicomCodecException("No registered codec for: " + newTransferSyntax.Name); } } if (parameters == null) parameters = DicomCodecRegistry.GetCodecParameters(newTransferSyntax, DataSet); DicomAttribute pixelData; if (DataSet.TryGetAttribute(DicomTags.PixelData, out pixelData)) { if (pixelData.IsNull) throw new DicomCodecException("Sop pixel data has no valid value and cannot be compressed."); DicomUncompressedPixelData pd = new DicomUncompressedPixelData(DataSet); DicomCompressedPixelData fragments = new DicomCompressedPixelData(pd); // Set before compression, the codecs need it. fragments.TransferSyntax = newTransferSyntax; codec.Encode(pd, fragments, parameters); fragments.UpdateMessage(this); //TODO: should we validate the number of frames in the compressed data? if (!DataSet.TryGetAttribute(DicomTags.PixelData, out pixelData) || pixelData.IsNull) throw new DicomCodecException("Sop has no pixel data after compression."); } else { //A bit cheap, but check for basic image attributes - if any exist // and are non-empty, there should probably be pixel data too. DicomAttribute attribute; if (DataSet.TryGetAttribute(DicomTags.Rows, out attribute) && !attribute.IsNull) throw new DicomCodecException("Suspect Sop appears to be an image (Rows is non-empty), but has no pixel data."); if (DataSet.TryGetAttribute(DicomTags.Columns, out attribute) && !attribute.IsNull) throw new DicomCodecException("Suspect Sop appears to be an image (Columns is non-empty), but has no pixel data."); TransferSyntax = newTransferSyntax; } } else { if (codec == null) { codec = DicomCodecRegistry.GetCodec(TransferSyntax); if (codec == null) { Platform.Log(LogLevel.Error, "Unable to get registered codec for {0}", TransferSyntax); throw new DicomCodecException("No registered codec for: " + TransferSyntax.Name); } if (parameters == null) parameters = DicomCodecRegistry.GetCodecParameters(TransferSyntax, DataSet); } DicomAttribute pixelData; if (DataSet.TryGetAttribute(DicomTags.PixelData, out pixelData)) { if (pixelData.IsNull) throw new DicomCodecException("Sop pixel data has no valid value and cannot be decompressed."); DicomCompressedPixelData fragments = new DicomCompressedPixelData(DataSet); DicomUncompressedPixelData pd = new DicomUncompressedPixelData(fragments); codec.Decode(fragments, pd, parameters); pd.TransferSyntax = TransferSyntax.ExplicitVrLittleEndian; pd.UpdateMessage(this); //TODO: should we validate the number of frames in the decompressed data? if (!DataSet.TryGetAttribute(DicomTags.PixelData, out pixelData) || pixelData.IsNull) throw new DicomCodecException("Sop has no pixel data after decompression."); } else { //NOTE: doing this for consistency, really. DicomAttribute attribute; if (DataSet.TryGetAttribute(DicomTags.Rows, out attribute) && !attribute.IsNull) throw new DicomCodecException("Suspect Sop appears to be an image (Rows is non-empty), but has no pixel data."); if (DataSet.TryGetAttribute(DicomTags.Columns, out attribute) && !attribute.IsNull) throw new DicomCodecException("Suspect Sop appears to be an image (Columns is non-empty), but has no pixel data."); TransferSyntax = TransferSyntax.ExplicitVrLittleEndian; } } }