protected override IEnumerable <TransferSyntax> GetAllowableTransferSyntaxes() { var list = new List <TransferSyntax>(base.GetAllowableTransferSyntaxes()); list.AddRange(DicomCodecRegistry.GetCodecTransferSyntaxes()); return(list); }
public SamplesForm() { InitializeComponent(); _buttonStorageScuVerify.Text = STR_Verify; if (String.IsNullOrEmpty(Properties.Settings.Default.ScpStorageFolder)) { Properties.Settings.Default.ScpStorageFolder = Path.Combine(Path.GetTempPath(), "DicomImages"); } _destinationSyntaxCombo.Items.Clear(); _destinationSyntaxCombo.Items.Add(TransferSyntax.ExplicitVrLittleEndian); foreach (TransferSyntax syntax in DicomCodecRegistry.GetCodecTransferSyntaxes()) { _destinationSyntaxCombo.Items.Add(syntax); } ComboBoxQueryScuQueryTypeSelectedIndexChanged(null, null); ComboBoxMoveScuQueryTypeSelectedIndexChanged(null, null); // Logging stuff Closing += SamplesFormClosing; BasicConfigurator.Configure(_appender); _timer = new Timer(delegate { try { LoggingEvent[] events = _appender.GetEvents(); if (events != null && events.Length > 0) { // if there are events, we clear them from the logger, // since we're done with them _appender.Clear(); foreach (LoggingEvent ev in events) { // the line we want to log string line = String.Format("({0}) {1} {2} [{3}]: {4}\r\n", ev.ThreadName, ev.TimeStamp.ToShortDateString(), ev.TimeStamp.ToLongTimeString(), ev.Level, ev.RenderedMessage); AppendText(line); if (ev.ExceptionObject != null) { AppendText(string.Format("{0}: {1}\r\n", ev.ExceptionObject, ev.ExceptionObject.Message)); AppendText("Stack Trace:\r\n" + ev.ExceptionObject.StackTrace + "\r\n"); } } } } catch (Exception x) { Platform.Log(LogLevel.Error, x, "Unexpected exception with logging event"); } }, null, 500); _timer.Start(); }
/// <summary> /// Called by the base class to create a new byte buffer containing normalized pixel data /// for this frame (8 or 16-bit grayscale, or 32-bit ARGB). /// </summary> /// <returns>A new byte buffer containing the normalized pixel data.</returns> protected override byte[] CreateNormalizedPixelData() { DicomMessageBase message = this.Parent.SourceMessage; CodeClock clock = new CodeClock(); clock.Start(); PhotometricInterpretation photometricInterpretation; byte[] rawPixelData = null; if (!message.TransferSyntax.Encapsulated) { DicomUncompressedPixelData pixelData = new DicomUncompressedPixelData(message); // DICOM library uses zero-based frame numbers MemoryManager.Execute(delegate { rawPixelData = pixelData.GetFrame(_frameIndex); }); ExtractOverlayFrames(rawPixelData, pixelData.BitsAllocated); photometricInterpretation = PhotometricInterpretation.FromCodeString(message.DataSet[DicomTags.PhotometricInterpretation]); } else if (DicomCodecRegistry.GetCodec(message.TransferSyntax) != null) { DicomCompressedPixelData pixelData = new DicomCompressedPixelData(message); string pi = null; MemoryManager.Execute(delegate { rawPixelData = pixelData.GetFrame(_frameIndex, out pi); }); photometricInterpretation = PhotometricInterpretation.FromCodeString(pi); } else { throw new DicomCodecException("Unsupported transfer syntax"); } if (photometricInterpretation.IsColor) { rawPixelData = ToArgb(message.DataSet, rawPixelData, photometricInterpretation); } else { NormalizeGrayscalePixels(message.DataSet, rawPixelData); } clock.Stop(); PerformanceReportBroker.PublishReport("DicomMessageSopDataSource", "CreateFrameNormalizedPixelData", clock.Seconds); return(rawPixelData); }
private byte SelectPresentationContext(ClientAssociationParameters association, StorageInstance fileToSend, out DicomMessage msg) { byte pcid; if (PresentationContextSelectionDelegate != null) { // Note, this may do a conversion of the file according to codecs, need to catch a codec exception if it occurs var dicomFile = fileToSend.LoadFile(); pcid = PresentationContextSelectionDelegate(association, dicomFile, out msg); } else { msg = null; pcid = association.FindAbstractSyntaxWithTransferSyntax(fileToSend.SopClass, fileToSend.TransferSyntax); if (fileToSend.TransferSyntax.Encapsulated) { if (pcid == 0) { // We can compress/decompress the file. Check if remote device accepts it if (DicomCodecRegistry.GetCodec(fileToSend.TransferSyntax) != null) { var dicomFile = fileToSend.LoadFile(); msg = new DicomMessage(dicomFile); pcid = SelectUncompressedPresentationContext(association, msg); } } } else { if (pcid == 0) { var dicomFile = fileToSend.LoadFile(); msg = new DicomMessage(dicomFile); pcid = SelectUncompressedPresentationContext(association, msg); } } if (pcid != 0 && fileToSend.FileIsLoaded) { msg = new DicomMessage(fileToSend.LoadFile()); } } return(pcid); }
protected static IEnumerable <TransferSyntax> GetTransferSyntaxes(IEnumerable <string> transferSyntaxUids) { foreach (var transferSyntaxUid in transferSyntaxUids) { if (!String.IsNullOrEmpty(transferSyntaxUid)) { TransferSyntax syntax = TransferSyntax.GetTransferSyntax(transferSyntaxUid); if (syntax != null) { //at least for now, restrict to available codecs for compressed syntaxes. if (!syntax.Encapsulated || DicomCodecRegistry.GetCodec(syntax) != null) { yield return(syntax); } } } } }
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); }
public SamplesForm() { InitializeComponent(); _buttonStorageScuVerify.Text = STR_Verify; Logger.RegisterLogHandler(OutputTextBox); if (String.IsNullOrEmpty(Properties.Settings.Default.ScpStorageFolder)) { Properties.Settings.Default.ScpStorageFolder = Path.Combine(Path.GetTempPath(), "DicomImages"); } _destinationSyntaxCombo.Items.Clear(); _destinationSyntaxCombo.Items.Add(TransferSyntax.ExplicitVrLittleEndian); foreach (TransferSyntax syntax in DicomCodecRegistry.GetCodecTransferSyntaxes()) { _destinationSyntaxCombo.Items.Add(syntax); } comboBoxQueryScuQueryType_SelectedIndexChanged(null, null); }
private void LogError(StorageInstance instance, DicomMessage msg, DicomStatus dicomStatus) { if (dicomStatus == DicomStatuses.SOPClassNotSupported) { var log = new StringBuilder(); log.AppendLine(string.Format("Unable to transfer SOP {0} in study {1}. Remote device does not accept {2} in {3} transfer syntax", instance.SopInstanceUid, instance.StudyInstanceUid, msg.SopClass, msg.TransferSyntax)); if (instance.TransferSyntax.Encapsulated) { var codecExists = DicomCodecRegistry.GetCodec(instance.TransferSyntax) != null; log.AppendLine(codecExists ? string.Format("Note: codec is available for {0} but remote device does not support it?", instance.TransferSyntax) : string.Format("Note: codec is NOT available for {0}", instance.TransferSyntax)); } Platform.Log(LogLevel.Error, log.ToString()); } }
/// <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()); }
private ProcessDuplicateResult ProcessDuplicate(DicomFile dupFile, WorkQueueUid uid, StudyXml studyXml) { var result = new ProcessDuplicateResult(); string duplicateSopPath = ServerPlatform.GetDuplicateUidPath(StorageLocation, uid); string basePath = StorageLocation.GetSopInstancePath(uid.SeriesInstanceUid, uid.SopInstanceUid); if (!File.Exists(basePath)) { // NOTE: This is special case. The file which caused dicom service to think this sop is a duplicate // no longer exists in the study folder. Perhaps it has been moved to another folder during auto reconciliation. // We have nothing to compare against so let's just throw it into the SIQ queue. CreateDuplicateSIQEntry(uid, dupFile, null); result.ActionTaken = DuplicateProcessResultAction.Reconcile; } else { // Check if system is configured to override the rule for this study if (DuplicatePolicy.IsParitionDuplicatePolicyOverridden(this.StorageLocation)) { return(OverwriteDuplicate(dupFile, uid, studyXml)); } else { var baseFile = new DicomFile(basePath); baseFile.Load(); if (DuplicateSopProcessorHelper.SopClassIsReport(dupFile.SopClass.Uid) && ServerPartition.AcceptLatestReport) { return(ProcessDuplicateReport(dupFile, baseFile, uid, studyXml)); } if (!dupFile.TransferSyntax.Equals(baseFile.TransferSyntax)) { // If they're compressed, and we have a codec, lets decompress and still do the comparison if (dupFile.TransferSyntax.Encapsulated && !dupFile.TransferSyntax.LossyCompressed && DicomCodecRegistry.GetCodec(dupFile.TransferSyntax) != null) { dupFile.ChangeTransferSyntax(TransferSyntax.ExplicitVrLittleEndian); } if (baseFile.TransferSyntax.Encapsulated && !baseFile.TransferSyntax.LossyCompressed && DicomCodecRegistry.GetCodec(baseFile.TransferSyntax) != null) { baseFile.ChangeTransferSyntax(TransferSyntax.ExplicitVrLittleEndian); } if (dupFile.TransferSyntax.Encapsulated || baseFile.TransferSyntax.Encapsulated) { string failure = String.Format("Base file transfer syntax is '{0}' while duplicate file has '{1}'", baseFile.TransferSyntax, dupFile.TransferSyntax); var list = new List <DicomAttributeComparisonResult>(); var compareResult = new DicomAttributeComparisonResult { ResultType = ComparisonResultType.DifferentValues, TagName = DicomTagDictionary.GetDicomTag(DicomTags.TransferSyntaxUid).Name, Details = failure }; list.Add(compareResult); CreateDuplicateSIQEntry(uid, dupFile, list); result.ActionTaken = DuplicateProcessResultAction.Reconcile; return(result); } } var failureReason = new List <DicomAttributeComparisonResult>(); if (baseFile.DataSet.Equals(dupFile.DataSet, ref failureReason)) { Platform.Log(LogLevel.Info, "Duplicate SOP being processed is identical. Removing SOP: {0}", baseFile.MediaStorageSopInstanceUid); RemoveWorkQueueUid(uid, duplicateSopPath); result.ActionTaken = DuplicateProcessResultAction.Delete; } else { CreateDuplicateSIQEntry(uid, dupFile, failureReason); result.ActionTaken = DuplicateProcessResultAction.Reconcile; } } } return(result); }
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; } } }
protected override void ProcessItem(Model.WorkQueue item) { LoadUids(item); if (WorkQueueUidList.Count == 0) { // No UIDs associated with the WorkQueue item. Set the status back to idle PostProcessing(item, WorkQueueProcessorStatus.Idle, WorkQueueProcessorDatabaseUpdate.ResetQueueState); return; } XmlElement element = item.Data.DocumentElement; string syntax = element.Attributes["syntax"].Value; TransferSyntax compressSyntax = TransferSyntax.GetTransferSyntax(syntax); if (compressSyntax == null) { item.FailureDescription = String.Format("Invalid transfer syntax in compression WorkQueue item: {0}", element.Attributes["syntax"].Value); Platform.Log(LogLevel.Error, "Error with work queue item {0}: {1}", item.GetKey(), item.FailureDescription); base.PostProcessingFailure(item, WorkQueueProcessorFailureType.Fatal); return; } if (Study == null) { item.FailureDescription = String.Format("Compression item does not have a linked Study record"); Platform.Log(LogLevel.Error, "Error with work queue item {0}: {1}", item.GetKey(), item.FailureDescription); base.PostProcessingFailure(item, WorkQueueProcessorFailureType.Fatal); return; } Platform.Log(LogLevel.Info, "Compressing study {0} for Patient {1} (PatientId:{2} A#:{3}) on partition {4} to {5}", Study.StudyInstanceUid, Study.PatientsName, Study.PatientId, Study.AccessionNumber, ServerPartition.Description, compressSyntax.Name); IDicomCodecFactory[] codecs = DicomCodecRegistry.GetCodecFactories(); IDicomCodecFactory theCodecFactory = null; foreach (IDicomCodecFactory codec in codecs) { if (codec.CodecTransferSyntax.Equals(compressSyntax)) { theCodecFactory = codec; break; } } if (theCodecFactory == null) { item.FailureDescription = String.Format("Unable to find codec for compression: {0}", compressSyntax.Name); Platform.Log(LogLevel.Error, "Error with work queue item {0}: {1}", item.GetKey(), item.FailureDescription); base.PostProcessingFailure(item, WorkQueueProcessorFailureType.Fatal); return; } if (!ProcessUidList(item, theCodecFactory)) { PostProcessingFailure(item, WorkQueueProcessorFailureType.NonFatal); } else { Platform.Log(LogLevel.Info, "Completed Compressing study {0} for Patient {1} (PatientId:{2} A#:{3}) on partition {4} to {5}", Study.StudyInstanceUid, Study.PatientsName, Study.PatientId, Study.AccessionNumber, ServerPartition.Description, compressSyntax.Name); if (compressSyntax.LossyCompressed) { UpdateStudyStatus(StorageLocation, StudyStatusEnum.OnlineLossy, compressSyntax); } else { UpdateStudyStatus(StorageLocation, StudyStatusEnum.OnlineLossless, compressSyntax); } PostProcessing(item, WorkQueueProcessorStatus.Pending, WorkQueueProcessorDatabaseUpdate.None); // batch processed, not complete } }
private byte SelectPresentationContext(ClientAssociationParameters association, DicomFile file, out DicomMessage message) { byte pcid = 0; message = new DicomMessage(file); // If Lossy compressed & we have a matching context, send // If we don't have a codec, just return if (message.TransferSyntax.Encapsulated && message.TransferSyntax.LossyCompressed) { pcid = association.FindAbstractSyntaxWithTransferSyntax(message.SopClass, message.TransferSyntax); if (pcid != 0) { return(pcid); } if (DicomCodecRegistry.GetCodec(message.TransferSyntax) == null) { return(0); } } // If the image is lossless compressed & we don't have a codec, send if we // can as is. if (message.TransferSyntax.Encapsulated && message.TransferSyntax.LosslessCompressed) { if (DicomCodecRegistry.GetCodec(message.TransferSyntax) == null) { pcid = association.FindAbstractSyntaxWithTransferSyntax(message.SopClass, message.TransferSyntax); return(pcid); } } // If lossless compressed & requesting lossless syntax, just send as is if (message.TransferSyntax.Encapsulated && message.TransferSyntax.LosslessCompressed && ((_sendRequest.CompressionType == CompressionType.Rle || _sendRequest.CompressionType == CompressionType.JpegLossless || _sendRequest.CompressionType == CompressionType.J2KLossless))) { pcid = association.FindAbstractSyntaxWithTransferSyntax(message.SopClass, message.TransferSyntax); if (pcid != 0) { return(pcid); } } if (_sendRequest.CompressionType == CompressionType.Rle) { pcid = association.FindAbstractSyntaxWithTransferSyntax(message.SopClass, TransferSyntax.RleLossless); if (pcid != 0) { return(pcid); } } else if (_sendRequest.CompressionType == CompressionType.JpegLossless) { pcid = association.FindAbstractSyntaxWithTransferSyntax(message.SopClass, TransferSyntax.JpegLosslessNonHierarchicalFirstOrderPredictionProcess14SelectionValue1); if (pcid != 0) { return(pcid); } } else if (_sendRequest.CompressionType == CompressionType.J2KLossless) { pcid = association.FindAbstractSyntaxWithTransferSyntax(message.SopClass, TransferSyntax.Jpeg2000ImageCompressionLosslessOnly); if (pcid != 0) { return(pcid); } } else if (_sendRequest.CompressionType == CompressionType.J2KLossy) { pcid = association.FindAbstractSyntaxWithTransferSyntax(message.SopClass, TransferSyntax.Jpeg2000ImageCompression); if (pcid != 0) { var doc = new XmlDocument(); XmlElement element = doc.CreateElement("compress"); doc.AppendChild(element); XmlAttribute syntaxAttribute = doc.CreateAttribute("syntax"); syntaxAttribute.Value = TransferSyntax.Jpeg2000ImageCompressionUid; element.Attributes.Append(syntaxAttribute); decimal ratio = 100.0m / _sendRequest.CompressionLevel; XmlAttribute ratioAttribute = doc.CreateAttribute("ratio"); ratioAttribute.Value = ratio.ToString(CultureInfo.InvariantCulture); element.Attributes.Append(ratioAttribute); syntaxAttribute = doc.CreateAttribute("convertFromPalette"); syntaxAttribute.Value = true.ToString(CultureInfo.InvariantCulture); element.Attributes.Append(syntaxAttribute); IDicomCodecFactory[] codecs = DicomCodecRegistry.GetCodecFactories(); foreach (IDicomCodecFactory codec in codecs) { if (codec.CodecTransferSyntax.Equals(TransferSyntax.Jpeg2000ImageCompression)) { try { if (message.TransferSyntax.Encapsulated) { message.ChangeTransferSyntax(TransferSyntax.ExplicitVrLittleEndian); message.TransferSyntax = TransferSyntax.ExplicitVrLittleEndian; } message.ChangeTransferSyntax(TransferSyntax.Jpeg2000ImageCompression, codec.GetDicomCodec(), codec.GetCodecParameters(doc)); message.TransferSyntax = TransferSyntax.Jpeg2000ImageCompression; return(pcid); } catch (Exception e) { Platform.Log(LogLevel.Warn, e, "Unexpected exception changing transfer syntax to {0}.", TransferSyntax.Jpeg2000ImageCompression.Name); } } } } } else if (_sendRequest.CompressionType == CompressionType.JpegLossy) { var iod = new ImagePixelMacroIod(message.DataSet); if (iod.BitsStored == 8) { pcid = association.FindAbstractSyntaxWithTransferSyntax(message.SopClass, TransferSyntax.JpegBaselineProcess1); if (pcid != 0) { var doc = new XmlDocument(); XmlElement element = doc.CreateElement("compress"); doc.AppendChild(element); XmlAttribute syntaxAttribute = doc.CreateAttribute("syntax"); syntaxAttribute.Value = TransferSyntax.JpegBaselineProcess1Uid; element.Attributes.Append(syntaxAttribute); syntaxAttribute = doc.CreateAttribute("quality"); syntaxAttribute.Value = _sendRequest.CompressionLevel.ToString(CultureInfo.InvariantCulture); element.Attributes.Append(syntaxAttribute); syntaxAttribute = doc.CreateAttribute("convertFromPalette"); syntaxAttribute.Value = true.ToString(CultureInfo.InvariantCulture); element.Attributes.Append(syntaxAttribute); IDicomCodecFactory[] codecs = DicomCodecRegistry.GetCodecFactories(); foreach (IDicomCodecFactory codec in codecs) { if (codec.CodecTransferSyntax.Equals(TransferSyntax.JpegBaselineProcess1)) { try { if (message.TransferSyntax.Encapsulated) { message.ChangeTransferSyntax(TransferSyntax.ExplicitVrLittleEndian); message.TransferSyntax = TransferSyntax.ExplicitVrLittleEndian; } message.ChangeTransferSyntax(TransferSyntax.JpegBaselineProcess1, codec.GetDicomCodec(), codec.GetCodecParameters(doc)); message.TransferSyntax = TransferSyntax.JpegBaselineProcess1; return(pcid); } catch (Exception e) { Platform.Log(LogLevel.Warn, e, "Unexpected exception changing transfer syntax to {0}.", TransferSyntax.JpegBaselineProcess1.Name); } } } } } else if (iod.BitsStored == 12) { pcid = association.FindAbstractSyntaxWithTransferSyntax(message.SopClass, TransferSyntax.JpegExtendedProcess24); if (pcid != 0) { var doc = new XmlDocument(); XmlElement element = doc.CreateElement("compress"); doc.AppendChild(element); XmlAttribute syntaxAttribute = doc.CreateAttribute("syntax"); syntaxAttribute.Value = TransferSyntax.JpegExtendedProcess24Uid; element.Attributes.Append(syntaxAttribute); syntaxAttribute = doc.CreateAttribute("quality"); syntaxAttribute.Value = _sendRequest.CompressionLevel.ToString(CultureInfo.InvariantCulture); element.Attributes.Append(syntaxAttribute); syntaxAttribute = doc.CreateAttribute("convertFromPalette"); syntaxAttribute.Value = true.ToString(CultureInfo.InvariantCulture); element.Attributes.Append(syntaxAttribute); IDicomCodecFactory[] codecs = DicomCodecRegistry.GetCodecFactories(); foreach (IDicomCodecFactory codec in codecs) { if (codec.CodecTransferSyntax.Equals(TransferSyntax.JpegExtendedProcess24)) { try { if (message.TransferSyntax.Encapsulated) { message.ChangeTransferSyntax(TransferSyntax.ExplicitVrLittleEndian); message.TransferSyntax = TransferSyntax.ExplicitVrLittleEndian; } message.ChangeTransferSyntax(TransferSyntax.JpegExtendedProcess24, codec.GetDicomCodec(), codec.GetCodecParameters(doc)); message.TransferSyntax = TransferSyntax.JpegExtendedProcess24; return(pcid); } catch (Exception e) { Platform.Log(LogLevel.Warn, e, "Unexpected exception changing transfer syntax to {0}.", TransferSyntax.JpegExtendedProcess24.Name); } } } } } } if (pcid == 0) { pcid = association.FindAbstractSyntaxWithTransferSyntax(message.SopClass, TransferSyntax.ExplicitVrLittleEndian); } if (pcid == 0) { pcid = association.FindAbstractSyntaxWithTransferSyntax(message.SopClass, TransferSyntax.ImplicitVrLittleEndian); } return(pcid); }
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 static void Unregister() { DicomCodecRegistry.SetCodec(TransferSyntax, null); TransferSyntax.UnregisterTransferSyntax(TransferSyntax); }
/// <summary> /// Compares received duplicate with the existing copy in the filesystem and throw it into the SIQ if they differ. /// Otherwise, simply delete the duplicate and keep everything as it. /// </summary> /// <param name="dupFile"></param> /// <param name="baseFile"></param> /// <param name="uid"></param> /// <returns></returns> private ProcessDuplicateResult CompareDuplicates(DicomFile dupFile, DicomFile baseFile, WorkQueueUid uid) { var result = new ProcessDuplicateResult(); string duplicateSopPath = ServerHelper.GetDuplicateUidPath(StorageLocation, uid); if (!dupFile.TransferSyntax.Equals(baseFile.TransferSyntax)) { // If they're compressed, and we have a codec, lets decompress and still do the comparison if (dupFile.TransferSyntax.Encapsulated && !dupFile.TransferSyntax.LossyCompressed && DicomCodecRegistry.GetCodec(dupFile.TransferSyntax) != null) { dupFile.ChangeTransferSyntax(TransferSyntax.ExplicitVrLittleEndian); } if (baseFile.TransferSyntax.Encapsulated && !baseFile.TransferSyntax.LossyCompressed && DicomCodecRegistry.GetCodec(baseFile.TransferSyntax) != null) { baseFile.ChangeTransferSyntax(TransferSyntax.ExplicitVrLittleEndian); } if (dupFile.TransferSyntax.Encapsulated || baseFile.TransferSyntax.Encapsulated) { string failure = String.Format("Base file transfer syntax is '{0}' while duplicate file has '{1}'", baseFile.TransferSyntax, dupFile.TransferSyntax); var list = new List <DicomAttributeComparisonResult>(); var compareResult = new DicomAttributeComparisonResult { ResultType = ComparisonResultType.DifferentValues, TagName = DicomTagDictionary.GetDicomTag(DicomTags.TransferSyntaxUid).Name, Details = failure }; list.Add(compareResult); CreateDuplicateSIQEntry(uid, dupFile, list); result.ActionTaken = DuplicateProcessResultAction.Reconcile; return(result); } } var failureReason = new List <DicomAttributeComparisonResult>(); if (baseFile.DataSet.Equals(dupFile.DataSet, ref failureReason)) { Platform.Log(LogLevel.Info, "Duplicate SOP being processed is identical. Removing SOP: {0}", baseFile.MediaStorageSopInstanceUid); RemoveWorkQueueUid(uid, duplicateSopPath); result.ActionTaken = DuplicateProcessResultAction.Delete; } else { CreateDuplicateSIQEntry(uid, dupFile, failureReason); result.ActionTaken = DuplicateProcessResultAction.Reconcile; } return(result); }
/// <summary> /// Generic routine to send the next C-STORE-RQ message in the <see cref="StorageInstanceList"/>. /// </summary> /// <param name="client">DICOM Client class</param> /// <param name="association">Association Parameters</param> private bool SendCStore(DicomClient client, ClientAssociationParameters association) { StorageInstance fileToSend = _storageInstanceList[_fileListIndex]; OnImageStoreStarted(fileToSend); DicomFile dicomFile; try { // Check to see if image does not exist or is corrupted if (fileToSend.SendStatus == DicomStatuses.ProcessingFailure) { _failureSubOperations++; _remainingSubOperations--; OnImageStoreCompleted(fileToSend); return(false); } dicomFile = fileToSend.LoadFile(); } catch (DicomException e) { Platform.Log(LogLevel.Error, e, "Unexpected exception when loading DICOM file {0}", fileToSend.Filename); fileToSend.ExtendedFailureDescription = e.GetType().Name + " " + e.Message; _failureSubOperations++; _remainingSubOperations--; OnImageStoreCompleted(fileToSend); return(false); } DicomMessage msg = new DicomMessage(dicomFile); byte pcid = 0; if (fileToSend.TransferSyntax.Encapsulated) { pcid = association.FindAbstractSyntaxWithTransferSyntax(fileToSend.SopClass, fileToSend.TransferSyntax); if (DicomCodecRegistry.GetCodec(fileToSend.TransferSyntax) != null) { if (pcid == 0) { pcid = association.FindAbstractSyntaxWithTransferSyntax(fileToSend.SopClass, TransferSyntax.ExplicitVrLittleEndian); } if (pcid == 0) { pcid = association.FindAbstractSyntaxWithTransferSyntax(fileToSend.SopClass, TransferSyntax.ImplicitVrLittleEndian); } } } else { if (pcid == 0) { pcid = association.FindAbstractSyntaxWithTransferSyntax(fileToSend.SopClass, TransferSyntax.ExplicitVrLittleEndian); } if (pcid == 0) { pcid = association.FindAbstractSyntaxWithTransferSyntax(fileToSend.SopClass, TransferSyntax.ImplicitVrLittleEndian); } } if (pcid == 0) { fileToSend.SendStatus = DicomStatuses.SOPClassNotSupported; fileToSend.ExtendedFailureDescription = "No valid presentation contexts for file."; OnImageStoreCompleted(fileToSend); _failureSubOperations++; _remainingSubOperations--; return(false); } try { if (_moveOriginatorAe == null) { client.SendCStoreRequest(pcid, client.NextMessageID(), DicomPriority.Medium, msg); } else { client.SendCStoreRequest(pcid, client.NextMessageID(), DicomPriority.Medium, _moveOriginatorAe, _moveOriginatorMessageId, msg); } } catch (DicomNetworkException) { throw; //This is a DicomException-derived class that we want to throw. } catch (DicomCodecException e) { Platform.Log(LogLevel.Error, e, "Unexpected exception when compressing or decompressing file before send {0}", fileToSend.Filename); fileToSend.SendStatus = DicomStatuses.ProcessingFailure; fileToSend.ExtendedFailureDescription = "Error decompressing or compressing file before send."; OnImageStoreCompleted(fileToSend); _failureSubOperations++; _remainingSubOperations--; return(false); } catch (DicomException e) { Platform.Log(LogLevel.Error, e, "Unexpected exception while sending file {0}", fileToSend.Filename); fileToSend.SendStatus = DicomStatuses.ProcessingFailure; fileToSend.ExtendedFailureDescription = "Unexpected exception while sending file."; OnImageStoreCompleted(fileToSend); _failureSubOperations++; _remainingSubOperations--; return(false); } return(true); }
/// <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); } } } } } }
public static void Register() { TransferSyntax.RegisterTransferSyntax(TransferSyntax); DicomCodecRegistry.SetCodec(TransferSyntax, DicomCodecFactory); }