예제 #1
0
            protected override byte[] CreateNormalizedPixelData()
            {
                string photometricInterpretation;

                byte[] pixelData = _framePixelData.GetUncompressedPixelData(out photometricInterpretation);

                string photometricInterpretationCode = photometricInterpretation ?? Parent[DicomTags.PhotometricInterpretation].ToString();
                PhotometricInterpretation pi         = PhotometricInterpretation.FromCodeString(photometricInterpretationCode);

                if (pi.IsColor)
                {
                    pixelData = ToArgb(this.Parent, pixelData, pi);
                }
                else
                {
                    var overlayPlaneModuleIod = new OverlayPlaneModuleIod(Parent);
                    foreach (var overlayPlane in overlayPlaneModuleIod)
                    {
                        if (!overlayPlane.HasOverlayData && _overlayData[overlayPlane.Index] == null)
                        {
                            // if the overlay is embedded in pixel data and we haven't cached it yet, extract it now before we normalize the frame pixel data
                            var overlayData = OverlayData.UnpackFromPixelData(overlayPlane.OverlayBitPosition, Parent[DicomTags.BitsAllocated].GetInt32(0, 0), false, pixelData);
                            _overlayData[overlayPlane.Index] = overlayData;
                        }
                    }

                    NormalizeGrayscalePixels(this.Parent, pixelData);
                }

                return(pixelData);
            }
예제 #2
0
        public void ChangeSyntax(TransferSyntax syntax)
        {
            try
            {
                if (!_dicomFile.TransferSyntax.Encapsulated)
                {
                    // Check if Overlay is embedded in pixels
                    OverlayPlaneModuleIod overlayIod = new OverlayPlaneModuleIod(_dicomFile.DataSet);
                    for (int i = 0; i < 16; i++)
                    {
                        if (overlayIod.HasOverlayPlane(i))
                        {
                            OverlayPlane overlay = overlayIod[i];
                            if (overlay.OverlayData == null)
                            {
                                DicomUncompressedPixelData pd = new DicomUncompressedPixelData(_dicomFile);
                                overlay.ConvertEmbeddedOverlay(pd);
                            }
                        }
                    }
                }
                else if (syntax.Encapsulated)
                {
                    // Must decompress first.
                    _dicomFile.ChangeTransferSyntax(TransferSyntax.ExplicitVrLittleEndian);
                }

                _dicomFile.ChangeTransferSyntax(syntax);
            }
            catch (Exception e)
            {
                Platform.Log(LogLevel.Error, e, "Unexpected exception compressing/decompressing DICOM file");
            }
        }
예제 #3
0
파일: Compression.cs 프로젝트: nhannd/Xian
		public void ChangeSyntax(TransferSyntax syntax)
		{
			try
			{
				if (!_dicomFile.TransferSyntax.Encapsulated)
				{
					// Check if Overlay is embedded in pixels
					OverlayPlaneModuleIod overlayIod = new OverlayPlaneModuleIod(_dicomFile.DataSet);
					for (int i = 0; i < 16; i++)
					{
						if (overlayIod.HasOverlayPlane(i))
						{
							OverlayPlane overlay = overlayIod[i];
							if (overlay.OverlayData == null)
							{
								DicomUncompressedPixelData pd = new DicomUncompressedPixelData(_dicomFile);
								overlay.ConvertEmbeddedOverlay(pd);	
							}
						}
					}
				}
				else if (syntax.Encapsulated)
				{
					// Must decompress first.
					_dicomFile.ChangeTransferSyntax(TransferSyntax.ExplicitVrLittleEndian);
				}

				_dicomFile.ChangeTransferSyntax(syntax);
			}
			catch (Exception e)
			{
				Platform.Log(LogLevel.Error, e, "Unexpected exception compressing/decompressing DICOM file");
			}
		}
예제 #4
0
		public void TestIsValidMultiFrameOverlay()
		{
			const int size = 3;

			var dataset = new DicomAttributeCollection();
			SetOverlay(dataset, 0, new bool[size*size], OverlayType.R, new Point(0, 0), size, size, null, false, false);
			SetOverlay(dataset, 1, new bool[size*size], OverlayType.R, new Point(0, 0), size, size, 1, false, false);
			SetOverlay(dataset, 2, new bool[size*size*5], OverlayType.R, new Point(0, 0), size, size, 5, false, false);
			SetOverlay(dataset, 3, new bool[size*size], OverlayType.R, new Point(0, 0), size, size, 1, 3, false, false);
			SetOverlay(dataset, 4, new bool[size*size*5], OverlayType.R, new Point(0, 0), size, size, 5, 2, false, false);

			var module = new OverlayPlaneModuleIod(dataset);

			Assert.IsTrue(module[0].IsValidMultiFrameOverlay(1), "Single Frame Overlay / 1 Frame in Image");
			Assert.IsTrue(module[0].IsValidMultiFrameOverlay(2), "Single Frame Overlay / 2 Frames in Image");

			Assert.IsTrue(module[1].IsValidMultiFrameOverlay(1), "1 Frame in Overlay (origin null==1) / 1 Frame in Image");
			Assert.IsTrue(module[1].IsValidMultiFrameOverlay(2), "1 Frame in Overlay (origin null==1) / 2 Frames in Image");

			Assert.IsFalse(module[2].IsValidMultiFrameOverlay(4), "5 Frames in Overlay (origin null==1) / 4 Frames in Image");
			Assert.IsTrue(module[2].IsValidMultiFrameOverlay(5), "5 Frames in Overlay (origin null==1) / 5 Frames in Image");
			Assert.IsTrue(module[2].IsValidMultiFrameOverlay(6), "5 Frames in Overlay (origin null==1) / 6 Frames in Image");

			Assert.IsFalse(module[3].IsValidMultiFrameOverlay(2), "1 Frames in Overlay (origin 3) / 2 Frames in Image");
			Assert.IsTrue(module[3].IsValidMultiFrameOverlay(3), "1 Frames in Overlay (origin 3) / 3 Frames in Image");
			Assert.IsTrue(module[3].IsValidMultiFrameOverlay(4), "1 Frames in Overlay (origin 3) / 4 Frames in Image");

			Assert.IsFalse(module[4].IsValidMultiFrameOverlay(5), "5 Frames in Overlay (origin 2) / 5 Frames in Image");
			Assert.IsTrue(module[4].IsValidMultiFrameOverlay(6), "5 Frames in Overlay (origin 2) / 6 Frames in Image");
			Assert.IsTrue(module[4].IsValidMultiFrameOverlay(7), "5 Frames in Overlay (origin 2) / 7 Frames in Image");
		}
예제 #5
0
            /// <summary>
            /// Called by <see cref="StandardSopFrameData.GetNormalizedOverlayData"/> to create a new byte buffer containing normalized
            /// overlay pixel data for a particular overlay plane.
            /// </summary>
            /// <remarks>
            /// See <see cref="StandardSopFrameData.GetNormalizedOverlayData"/> for details on the expected format of the byte buffer.
            /// </remarks>
            /// <param name="overlayNumber">The 1-based overlay plane number.</param>
            /// <returns>A new byte buffer containing the normalized overlay pixel data.</returns>
            protected override byte[] CreateNormalizedOverlayData(int overlayNumber)
            {
                //TODO (CR December 2010): make this a helper method somewhere, since it's now identical to the one in StreamingSopFrameData?

                var overlayIndex = overlayNumber - 1;

                byte[] overlayData = null;

                var clock = new CodeClock();

                clock.Start();

                // check whether or not the overlay plane exists before attempting to ascertain
                // whether or not the overlay is embedded in the pixel data
                var overlayPlaneModuleIod = new OverlayPlaneModuleIod(Parent);

                if (overlayPlaneModuleIod.HasOverlayPlane(overlayIndex))
                {
                    if (_overlayCache[overlayIndex] == null)
                    {
                        var overlayPlane = overlayPlaneModuleIod[overlayIndex];
                        if (!overlayPlane.HasOverlayData)
                        {
                            // if the overlay is embedded, trigger retrieval of pixel data which will populate the cache for us
                            GetNormalizedPixelData();
                        }
                        else
                        {
                            // try to compute the offset in the OverlayData bit stream where we can find the overlay frame that applies to this image frame
                            int overlayFrame;
                            int bitOffset;
                            if (overlayPlane.TryGetRelevantOverlayFrame(FrameNumber, Parent.NumberOfFrames, out overlayFrame) &&
                                overlayPlane.TryComputeOverlayDataBitOffset(overlayFrame, out bitOffset))
                            {
                                // offset found - unpack only that overlay frame
                                var od = new OverlayData(bitOffset,
                                                         overlayPlane.OverlayRows,
                                                         overlayPlane.OverlayColumns,
                                                         overlayPlane.IsBigEndianOW,
                                                         overlayPlane.OverlayData);
                                _overlayCache[overlayIndex] = od.Unpack();
                            }
                            else
                            {
                                // no relevant overlay frame found - i.e. the overlay for this image frame is blank
                                _overlayCache[overlayIndex] = new byte[0];
                            }
                        }
                    }

                    overlayData = _overlayCache[overlayIndex];
                }

                clock.Stop();
                PerformanceReportBroker.PublishReport("DicomMessageSopDataSource", "CreateNormalizedOverlayData", clock.Seconds);

                return(overlayData);
            }
예제 #6
0
            /// <summary>
            /// Called by <see cref="StandardSopFrameData.GetNormalizedOverlayData"/> to create a new byte buffer containing normalized
            /// overlay pixel data for a particular overlay plane.
            /// </summary>
            /// <remarks>
            /// See <see cref="StandardSopFrameData.GetNormalizedOverlayData"/> for details on the expected format of the byte buffer.
            /// </remarks>
            /// <param name="overlayNumber">The 1-based overlay plane number.</param>
            /// <returns>A new byte buffer containing the normalized overlay pixel data.</returns>
            protected override byte[] CreateNormalizedOverlayData(int overlayNumber)
            {
                var overlayIndex = overlayNumber - 1;

                byte[] overlayData = null;

                // check whether or not the overlay plane exists before attempting to ascertain
                // whether or not the overlay is embedded in the pixel data
                var overlayPlaneModuleIod = new OverlayPlaneModuleIod(Parent);

                if (overlayPlaneModuleIod.HasOverlayPlane(overlayIndex))
                {
                    if (_overlayData[overlayIndex] == null)
                    {
                        var overlayPlane = overlayPlaneModuleIod[overlayIndex];
                        if (!overlayPlane.HasOverlayData)
                        {
                            // if the overlay is embedded, trigger retrieval of pixel data which will populate the cache for us
                            GetNormalizedPixelData();
                        }
                        else
                        {
                            // try to compute the offset in the OverlayData bit stream where we can find the overlay frame that applies to this image frame
                            int overlayFrame;
                            int bitOffset;
                            if (overlayPlane.TryGetRelevantOverlayFrame(FrameNumber, Parent.NumberOfFrames, out overlayFrame) &&
                                overlayPlane.TryComputeOverlayDataBitOffset(overlayFrame, out bitOffset))
                            {
                                // offset found - unpack only that overlay frame
                                var od = new OverlayData(bitOffset,
                                                         overlayPlane.OverlayRows,
                                                         overlayPlane.OverlayColumns,
                                                         overlayPlane.IsBigEndianOW,
                                                         overlayPlane.OverlayData);
                                _overlayData[overlayIndex] = od.Unpack();
                            }
                            else
                            {
                                // no relevant overlay frame found - i.e. the overlay for this image frame is blank
                                _overlayData[overlayIndex] = new byte[0];
                            }
                        }
                    }

                    overlayData = _overlayData[overlayIndex];
                }

                return(overlayData);
            }
예제 #7
0
            private void ExtractOverlayFrames(byte[] rawPixelData, int bitsAllocated)
            {
                // if any overlays have embedded pixel data, extract them now or forever hold your peace
                var overlayPlaneModuleIod = new OverlayPlaneModuleIod(Parent);

                foreach (var overlayPlane in overlayPlaneModuleIod)
                {
                    if (!overlayPlane.HasOverlayData && _overlayCache[overlayPlane.Index] == null)
                    {
                        // if the overlay is embedded in pixel data and we haven't cached it yet, extract it now before we normalize the frame pixel data
                        var overlayData = OverlayData.UnpackFromPixelData(overlayPlane.OverlayBitPosition, bitsAllocated, false, rawPixelData);
                        _overlayCache[overlayPlane.Index] = overlayData;
                    }
                }
            }
        public void SetupMRWithOverlay(DicomAttributeCollection theSet)
        {
            SetupMR(theSet);

            OverlayPlaneModuleIod      overlayIod = new OverlayPlaneModuleIod(theSet);
            DicomUncompressedPixelData pd         = new DicomUncompressedPixelData(theSet);
            OverlayPlane overlay = overlayIod[0];

            // Embedded overlays are retired in dicom, just doing it for testing purposes
            theSet[DicomTags.OverlayBitPosition].SetInt32(0, pd.HighBit + 1);
            overlay.OverlayBitsAllocated = 1;
            overlay.OverlayColumns       = pd.ImageWidth;
            overlay.OverlayRows          = pd.ImageHeight;
            overlay.OverlayOrigin        = new Point(0, 0);
            overlay.OverlayType          = OverlayType.R;
        }
예제 #9
0
        public void SetupMRWithOverlay(DicomAttributeCollection theSet)
        {
            SetupMR(theSet);

            OverlayPlaneModuleIod overlayIod = new OverlayPlaneModuleIod(theSet);
            DicomUncompressedPixelData pd = new DicomUncompressedPixelData(theSet);
            OverlayPlane overlay = overlayIod[0];

            // Embedded overlays are retired in dicom, just doing it for testing purposes
            theSet[DicomTags.OverlayBitPosition].SetInt32(0, pd.HighBit + 1);
            overlay.OverlayBitsAllocated = 1;
            overlay.OverlayColumns = pd.ImageWidth;
            overlay.OverlayRows = pd.ImageHeight;
            overlay.OverlayOrigin = new Point(0, 0);
            overlay.OverlayType = OverlayType.R;
        }
예제 #10
0
        public void RleOverlayTest()
        {
            DicomFile file = new DicomFile("RleCodecOverlayTest.dcm");

            SetupMRWithOverlay(file.DataSet);

            SetupMetaInfo(file);

            // Save a copy
            file.Save();


            // Load the file into new DicomFile object
            DicomFile newFile = new DicomFile(file.Filename);

            newFile.Load();

            OverlayPlaneModuleIod overlayIod = new OverlayPlaneModuleIod(newFile.DataSet);
            OverlayPlane          overlay    = overlayIod[0];

            // SHould be no OverlayData tag
            Assert.IsNull(overlay.OverlayData, "Overlay should be in pixel data");

            // Overlay should be extracted out of pixel data here
            newFile.ChangeTransferSyntax(TransferSyntax.RleLossless);

            Assert.IsNotNull(overlay.OverlayData, "Overlay Data is not null");

            newFile.Save();

            // Load a new copy
            newFile = new DicomFile(file.Filename);

            newFile.Load();

            newFile.ChangeTransferSyntax(TransferSyntax.ExplicitVrLittleEndian);

            newFile.Filename = "Output" + file.Filename;
            newFile.Save();

            List <DicomAttributeComparisonResult> results = new List <DicomAttributeComparisonResult>();
            bool compare = file.DataSet.Equals(newFile.DataSet, ref results);

            // Shouldn't be the same, OverlayData tag should have been added
            Assert.IsFalse(compare, results.Count > 0 ? CollectionUtils.FirstElement(results).Details : string.Empty);
        }
예제 #11
0
            protected override byte[] CreateNormalizedPixelData()
            {
                byte[] pixelData = _framePixelData.GetUncompressedPixelData();

                string photometricInterpretationCode = this.Parent[DicomTags.PhotometricInterpretation].ToString();
                PhotometricInterpretation pi         = PhotometricInterpretation.FromCodeString(photometricInterpretationCode);

                TransferSyntax ts = TransferSyntax.GetTransferSyntax(this.Parent.TransferSyntaxUid);

                if (pi.IsColor)
                {
                    if (ts == TransferSyntax.Jpeg2000ImageCompression ||
                        ts == TransferSyntax.Jpeg2000ImageCompressionLosslessOnly ||
                        ts == TransferSyntax.JpegExtendedProcess24 ||
                        ts == TransferSyntax.JpegBaselineProcess1)
                    {
                        pi = PhotometricInterpretation.Rgb;
                    }

                    pixelData = ToArgb(this.Parent, pixelData, pi);
                }
                else
                {
                    OverlayPlaneModuleIod opmi = new OverlayPlaneModuleIod(this.Parent);
                    foreach (OverlayPlane overlayPlane in opmi)
                    {
                        if (IsOverlayEmbedded(overlayPlane) && _overlayData[overlayPlane.Index] == null)
                        {
                            byte[] overlayData = OverlayData.UnpackFromPixelData(overlayPlane.OverlayBitPosition, this.Parent[DicomTags.BitsAllocated].GetInt32(0, 0), false, pixelData);
                            _overlayData[overlayPlane.Index] = overlayData;
                        }
                        else if (!overlayPlane.HasOverlayData)
                        {
                            Platform.Log(LogLevel.Warn, "The image {0} appears to be missing OverlayData for group 0x{1:X4}.", this.Parent.SopInstanceUid, overlayPlane.Group);
                        }
                    }

                    NormalizeGrayscalePixels(this.Parent, pixelData);
                }

                return(pixelData);
            }
        protected void DeserializeOverlayPlane(OverlayPlaneModuleIod overlayPlaneModule, T image)
        {
            DicomGraphicsPlane dicomGraphicsPlane = DicomGraphicsPlane.GetDicomGraphicsPlane(image, true);

            foreach (OverlayPlaneGraphic overlay in DicomGraphicsFactory.CreateOverlayPlaneGraphics(image.Frame, overlayPlaneModule))
            {
                // the results are a mix of overlays from the image itself and the presentation state
                if (overlay.Source == OverlayPlaneSource.Image)
                {
                    dicomGraphicsPlane.ImageOverlays.Add(overlay);
                }
                else
                {
                    dicomGraphicsPlane.PresentationOverlays.Add(overlay);
                }

                // the above lines will automatically add the overlays to the inactive layer
            }
            _overlayPlanesDeserialized = true;
        }
예제 #13
0
            protected override byte[] CreateNormalizedPixelData()
            {
                byte[] pixelData = _framePixelData.GetUncompressedPixelData();

                string photometricInterpretationCode = this.Parent[DicomTags.PhotometricInterpretation].ToString();
                PhotometricInterpretation pi         = PhotometricInterpretation.FromCodeString(photometricInterpretationCode);

                TransferSyntax ts = TransferSyntax.GetTransferSyntax(this.Parent.TransferSyntaxUid);

                if (pi.IsColor)
                {
                    if (ts == TransferSyntax.Jpeg2000ImageCompression ||
                        ts == TransferSyntax.Jpeg2000ImageCompressionLosslessOnly ||
                        ts == TransferSyntax.JpegExtendedProcess24 ||
                        ts == TransferSyntax.JpegBaselineProcess1)
                    {
                        pi = PhotometricInterpretation.Rgb;
                    }

                    pixelData = ToArgb(this.Parent, pixelData, pi);
                }
                else
                {
                    var overlayPlaneModuleIod = new OverlayPlaneModuleIod(Parent);
                    foreach (var overlayPlane in overlayPlaneModuleIod)
                    {
                        if (!overlayPlane.HasOverlayData && _overlayData[overlayPlane.Index] == null)
                        {
                            // if the overlay is embedded in pixel data and we haven't cached it yet, extract it now before we normalize the frame pixel data
                            var overlayData = OverlayData.UnpackFromPixelData(overlayPlane.OverlayBitPosition, Parent[DicomTags.BitsAllocated].GetInt32(0, 0), false, pixelData);
                            _overlayData[overlayPlane.Index] = overlayData;
                        }
                    }

                    NormalizeGrayscalePixels(this.Parent, pixelData);
                }

                return(pixelData);
            }
예제 #14
0
		/// <summary>
		/// Initializes a new instance of the <see cref="ScImageIod"/> class.
		/// </summary>
		/// <param name="dicomAttributeProvider">The DICOM attribute provider.</param>
		public ScImageIod(IDicomAttributeProvider dicomAttributeProvider)
		{
			_dicomAttributeProvider = dicomAttributeProvider;

			_patientModule = new PatientModuleIod(_dicomAttributeProvider);
			_clinicalTrialSubjectModule = new ClinicalTrialSubjectModuleIod(_dicomAttributeProvider);
			_generalStudyModule = new GeneralStudyModuleIod(_dicomAttributeProvider);
			_patientStudyModule = new PatientStudyModuleIod(_dicomAttributeProvider);
			_clinicalTrialStudyModule = new ClinicalTrialStudyModuleIod(_dicomAttributeProvider);
			_generalSeriesModule = new GeneralSeriesModuleIod(_dicomAttributeProvider);
			_clinicalTrialSeriesModule = new ClinicalTrialSeriesModuleIod(_dicomAttributeProvider);
			_generalEquipmentModule = new GeneralEquipmentModuleIod(_dicomAttributeProvider);
			_scEquipmentModule = new ScEquipmentModuleIod(_dicomAttributeProvider);
			_generalImageModule = new GeneralImageModuleIod(_dicomAttributeProvider);
			_imagePixelModule = new ImagePixelMacroIod(_dicomAttributeProvider);
			_deviceModule = new DeviceModuleIod(_dicomAttributeProvider);
			_scImageModule = new ScImageModuleIod(_dicomAttributeProvider);
			_overlayPlaneModule = new OverlayPlaneModuleIod(_dicomAttributeProvider);
			_modalityLutModule = new ModalityLutModuleIod(_dicomAttributeProvider);
			_voiLutModule = new VoiLutModuleIod(_dicomAttributeProvider);
			_iccProfileModule = new IccProfileModuleIod(_dicomAttributeProvider);
			_sopCommonModule = new SopCommonModuleIod(_dicomAttributeProvider);
		}
예제 #15
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ScImageIod"/> class.
        /// </summary>
        /// <param name="dicomAttributeProvider">The DICOM attribute provider.</param>
        public ScImageIod(IDicomAttributeProvider dicomAttributeProvider)
        {
            _dicomAttributeProvider = dicomAttributeProvider;

            _patientModule = new PatientModuleIod(_dicomAttributeProvider);
            _clinicalTrialSubjectModule = new ClinicalTrialSubjectModuleIod(_dicomAttributeProvider);
            _generalStudyModule         = new GeneralStudyModuleIod(_dicomAttributeProvider);
            _patientStudyModule         = new PatientStudyModuleIod(_dicomAttributeProvider);
            _clinicalTrialStudyModule   = new ClinicalTrialStudyModuleIod(_dicomAttributeProvider);
            _generalSeriesModule        = new GeneralSeriesModuleIod(_dicomAttributeProvider);
            _clinicalTrialSeriesModule  = new ClinicalTrialSeriesModuleIod(_dicomAttributeProvider);
            _generalEquipmentModule     = new GeneralEquipmentModuleIod(_dicomAttributeProvider);
            _scEquipmentModule          = new ScEquipmentModuleIod(_dicomAttributeProvider);
            _generalImageModule         = new GeneralImageModuleIod(_dicomAttributeProvider);
            _imagePixelModule           = new ImagePixelMacroIod(_dicomAttributeProvider);
            _deviceModule       = new DeviceModuleIod(_dicomAttributeProvider);
            _scImageModule      = new ScImageModuleIod(_dicomAttributeProvider);
            _overlayPlaneModule = new OverlayPlaneModuleIod(_dicomAttributeProvider);
            _modalityLutModule  = new ModalityLutModuleIod(_dicomAttributeProvider);
            _voiLutModule       = new VoiLutModuleIod(_dicomAttributeProvider);
            _iccProfileModule   = new IccProfileModuleIod(_dicomAttributeProvider);
            _sopCommonModule    = new SopCommonModuleIod(_dicomAttributeProvider);
        }
예제 #16
0
            protected override byte[] CreateNormalizedOverlayData(int overlayGroupNumber, int overlayFrameNumber)
            {
                int frameIndex   = overlayFrameNumber - 1;
                int overlayIndex = overlayGroupNumber - 1;

                byte[] overlayData = null;

                OverlayPlaneModuleIod opmi = new OverlayPlaneModuleIod(this.Parent);

                if (opmi.HasOverlayPlane(overlayIndex))
                {
                    OverlayPlane overlayPlane = opmi[overlayIndex];

                    if (_overlayData[overlayIndex] == null)
                    {
                        if (IsOverlayEmbedded(overlayPlane))
                        {
                            this.GetNormalizedPixelData();
                        }
                        else
                        {
                            int bitOffset;
                            overlayPlane.TryComputeOverlayDataBitOffset(frameIndex, out bitOffset);

                            OverlayData od = new OverlayData(bitOffset,
                                                             overlayPlane.OverlayRows,
                                                             overlayPlane.OverlayColumns,
                                                             overlayPlane.IsBigEndianOW,
                                                             overlayPlane.OverlayData);
                            _overlayData[overlayIndex] = od.Unpack();
                        }
                    }
                    overlayData = _overlayData[overlayIndex];
                }

                return(overlayData);
            }
예제 #17
0
		public void TestComputeOverlayDataBitOffset_SingleFrameEmbedded()
		{
			const bool bigEndian = false;

			// these parameters should be kept prime numbers so that we can exercise the overlay handling for rows/frames that cross byte boundaries
			const int rows = 97;
			const int columns = 101;

			const int overlayIndex = 0;
			var dataset = new DicomAttributeCollection();
			SetImage(dataset, new byte[rows*columns*2], rows, columns, 1, 16, 12, 14, false);
			SetOverlay(dataset, overlayIndex, new bool[rows*columns], OverlayType.G, new Point(1, 1), 15, bigEndian);

			var module = new OverlayPlaneModuleIod(dataset);
			var overlayPlane = module[overlayIndex];

			int actualBitOffset;

			// bit offset doesn't make any sense for embedded data

			Assert.IsFalse(overlayPlane.TryComputeOverlayDataBitOffset(-1, out actualBitOffset), "Should not be able to compute bit offset for frame number -1");
			Assert.IsFalse(overlayPlane.TryComputeOverlayDataBitOffset(0, out actualBitOffset), "Should not be able to compute bit offset for frame number 0");
			Assert.IsFalse(overlayPlane.TryComputeOverlayDataBitOffset(1, out actualBitOffset), "Should not be able to compute bit offset for frame number 1");
			Assert.IsFalse(overlayPlane.TryComputeOverlayDataBitOffset(2, out actualBitOffset), "Should not be able to compute bit offset for frame number 2");
		}
예제 #18
0
			/// <summary>
			/// Called by <see cref="StandardSopFrameData.GetNormalizedOverlayData"/> to create a new byte buffer containing normalized 
			/// overlay pixel data for a particular overlay plane.
			/// </summary>
			/// <remarks>
			/// See <see cref="StandardSopFrameData.GetNormalizedOverlayData"/> for details on the expected format of the byte buffer.
			/// </remarks>
			/// <param name="overlayNumber">The 1-based overlay plane number.</param>
			/// <returns>A new byte buffer containing the normalized overlay pixel data.</returns>
			protected override byte[] CreateNormalizedOverlayData(int overlayNumber)
			{
				var overlayIndex = overlayNumber - 1;

				byte[] overlayData = null;

				// check whether or not the overlay plane exists before attempting to ascertain
				// whether or not the overlay is embedded in the pixel data
				var overlayPlaneModuleIod = new OverlayPlaneModuleIod(Parent);
				if (overlayPlaneModuleIod.HasOverlayPlane(overlayIndex))
				{
					if (_overlayData[overlayIndex] == null)
					{
						var overlayPlane = overlayPlaneModuleIod[overlayIndex];
						if (!overlayPlane.HasOverlayData)
						{
							// if the overlay is embedded, trigger retrieval of pixel data which will populate the cache for us
							GetNormalizedPixelData();
						}
						else
						{
							// try to compute the offset in the OverlayData bit stream where we can find the overlay frame that applies to this image frame
							int overlayFrame;
							int bitOffset;
							if (overlayPlane.TryGetRelevantOverlayFrame(FrameNumber, Parent.NumberOfFrames, out overlayFrame) &&
							    overlayPlane.TryComputeOverlayDataBitOffset(overlayFrame, out bitOffset))
							{
								// offset found - unpack only that overlay frame
								var od = new OverlayData(bitOffset,
								                         overlayPlane.OverlayRows,
								                         overlayPlane.OverlayColumns,
								                         overlayPlane.IsBigEndianOW,
								                         overlayPlane.OverlayData);
								_overlayData[overlayIndex] = od.Unpack();
							}
							else
							{
								// no relevant overlay frame found - i.e. the overlay for this image frame is blank
								_overlayData[overlayIndex] = new byte[0];
							}
						}
					}

					overlayData = _overlayData[overlayIndex];
				}

				return overlayData;
			}
예제 #19
0
		public void TestComputeOverlayDataBitOffset_MultiframeOverlayDataWithOrigin()
		{
			const bool bigEndian = false;

			// these parameters should be kept prime numbers so that we can exercise the overlay handling for rows/frames that cross byte boundaries
			const int rows = 97;
			const int columns = 101;
			const int frames = 7;

			// just because you're getting overlay frame #2 for image frame #4 doesn't change the offset where overlay frame #2 can be found!!
			const int imageFrameOrigin = 3;

			const int overlayIndex = 0;
			var dataset = new DicomAttributeCollection();
			SetOverlay(dataset, overlayIndex, new bool[rows*columns*frames], OverlayType.G, new Point(1, 1), rows, columns, frames, imageFrameOrigin, bigEndian, false);

			var module = new OverlayPlaneModuleIod(dataset);
			var overlayPlane = module[overlayIndex];

			int actualBitOffset;

			Assert.IsFalse(overlayPlane.TryComputeOverlayDataBitOffset(-1, out actualBitOffset), "Should not be able to compute bit offset for frame number -1");
			Assert.IsFalse(overlayPlane.TryComputeOverlayDataBitOffset(0, out actualBitOffset), "Should not be able to compute bit offset for frame number 0");
			Assert.IsFalse(overlayPlane.TryComputeOverlayDataBitOffset(8, out actualBitOffset), "Should not be able to compute bit offset for frame number 8");

			Assert.IsTrue(overlayPlane.TryComputeOverlayDataBitOffset(1, out actualBitOffset), "Should be able to compute bit offset for frame number 1");
			Assert.AreEqual(0*rows*columns, actualBitOffset, "Wrong offset computed for frame number 1");

			Assert.IsTrue(overlayPlane.TryComputeOverlayDataBitOffset(2, out actualBitOffset), "Should be able to compute bit offset for frame number 2");
			Assert.AreEqual(1*rows*columns, actualBitOffset, "Wrong offset computed for frame number 2");

			Assert.IsTrue(overlayPlane.TryComputeOverlayDataBitOffset(3, out actualBitOffset), "Should be able to compute bit offset for frame number 3");
			Assert.AreEqual(2*rows*columns, actualBitOffset, "Wrong offset computed for frame number 3");

			Assert.IsTrue(overlayPlane.TryComputeOverlayDataBitOffset(4, out actualBitOffset), "Should be able to compute bit offset for frame number 4");
			Assert.AreEqual(3*rows*columns, actualBitOffset, "Wrong offset computed for frame number 4");

			Assert.IsTrue(overlayPlane.TryComputeOverlayDataBitOffset(5, out actualBitOffset), "Should be able to compute bit offset for frame number 5");
			Assert.AreEqual(4*rows*columns, actualBitOffset, "Wrong offset computed for frame number 5");

			Assert.IsTrue(overlayPlane.TryComputeOverlayDataBitOffset(6, out actualBitOffset), "Should be able to compute bit offset for frame number 6");
			Assert.AreEqual(5*rows*columns, actualBitOffset, "Wrong offset computed for frame number 6");

			Assert.IsTrue(overlayPlane.TryComputeOverlayDataBitOffset(7, out actualBitOffset), "Should be able to compute bit offset for frame number 7");
			Assert.AreEqual(6*rows*columns, actualBitOffset, "Wrong offset computed for frame number 7");
		}
예제 #20
0
		public void TestComputeOverlayDataBitOffset_SingleFrameOverlayData()
		{
			const bool bigEndian = false;

			// these parameters should be kept prime numbers so that we can exercise the overlay handling for rows/frames that cross byte boundaries
			const int rows = 97;
			const int columns = 101;

			const int overlayIndex = 0;
			var dataset = new DicomAttributeCollection();
			SetOverlay(dataset, overlayIndex, new bool[rows*columns], OverlayType.G, new Point(1, 1), rows, columns, null, null, bigEndian, false);

			var module = new OverlayPlaneModuleIod(dataset);
			var overlayPlane = module[overlayIndex];

			int actualBitOffset;
			Assert.IsFalse(overlayPlane.TryComputeOverlayDataBitOffset(-1, out actualBitOffset), "Should not be able to compute bit offset for frame number -1");
			Assert.IsFalse(overlayPlane.TryComputeOverlayDataBitOffset(0, out actualBitOffset), "Should not be able to compute bit offset for frame number 0");
			Assert.IsFalse(overlayPlane.TryComputeOverlayDataBitOffset(2, out actualBitOffset), "Should not be able to compute bit offset for frame number 2");

			Assert.IsTrue(overlayPlane.TryComputeOverlayDataBitOffset(1, out actualBitOffset), "Should be able to compute bit offset for frame number 1");
			Assert.AreEqual(0, actualBitOffset, "Wrong offset computed for frame number 1");
		}
예제 #21
0
        public static List <OverlayPlaneGraphic> CreateOverlayPlaneGraphics(Frame frame, OverlayPlaneModuleIod overlaysFromPresentationState)
        {
            ISopDataSource        dataSource  = frame.ParentImageSop.DataSource;
            OverlayPlaneModuleIod overlaysIod = new OverlayPlaneModuleIod(dataSource);

            List <OverlayPlaneGraphic> overlayPlaneGraphics = new List <OverlayPlaneGraphic>();

            bool failedOverlays = false;

            foreach (var overlayPlane in overlaysIod)
            {
                // DICOM 2009 PS 3.3 Section C.9.3.1.1 specifies the rule: NumberOfFramesInOverlay+ImageFrameOrigin-1 must be <= NumberOfFrames
                if (!overlayPlane.IsValidMultiFrameOverlay(frame.ParentImageSop.NumberOfFrames))
                {
                    failedOverlays = true;
                    Platform.Log(LogLevel.Warn, new DicomOverlayDeserializationException(overlayPlane.Group, OverlayPlaneSource.Image), "Encoding error encountered while reading overlay from image headers.");
                    continue;
                }

                try
                {
                    byte[] overlayData = dataSource.GetFrameData(frame.FrameNumber).GetNormalizedOverlayData(overlayPlane.Index + 1);
                    overlayPlaneGraphics.Add(new OverlayPlaneGraphic(overlayPlane, overlayData, OverlayPlaneSource.Image));

                    // if overlay data is null, the data source failed to retrieve the overlay data for some reason, so we also treat it as an encoding error
                    // this is different from if the overlay data is zero-length, which indicates that the retrieval succeeded, but that the overlay data for the frame is empty
                    if (overlayData == null)
                    {
                        throw new NullReferenceException();
                    }
                }
                catch (Exception ex)
                {
                    failedOverlays = true;
                    Platform.Log(LogLevel.Warn, new DicomOverlayDeserializationException(overlayPlane.Group, OverlayPlaneSource.Image, ex), "Failed to load overlay from the image header.");
                }
            }

            if (overlaysFromPresentationState != null)
            {
                foreach (var overlayPlane in overlaysFromPresentationState)
                {
                    // if overlay data is missing, treat as an encoding error
                    if (!overlayPlane.HasOverlayData)
                    {
                        failedOverlays = true;
                        Platform.Log(LogLevel.Warn, new DicomOverlayDeserializationException(overlayPlane.Group, OverlayPlaneSource.PresentationState), "Encoding error encountered while reading overlay from softcopy presentation state.");
                        continue;
                    }

                    try
                    {
                        byte[] overlayData;

                        // try to compute the offset in the OverlayData bit stream where we can find the overlay frame that applies to this image frame
                        int overlayFrame, bitOffset;
                        if (overlayPlane.TryGetRelevantOverlayFrame(frame.FrameNumber, frame.ParentImageSop.NumberOfFrames, out overlayFrame) &&
                            overlayPlane.TryComputeOverlayDataBitOffset(overlayFrame, out bitOffset))
                        {
                            // offset found - unpack only that overlay frame
                            var od = new OverlayData(bitOffset,
                                                     overlayPlane.OverlayRows,
                                                     overlayPlane.OverlayColumns,
                                                     overlayPlane.IsBigEndianOW,
                                                     overlayPlane.OverlayData);

                            overlayData = od.Unpack();
                        }
                        else
                        {
                            // no relevant overlay frame found - i.e. the overlay for this image frame is blank
                            overlayData = new byte[0];
                        }

                        overlayPlaneGraphics.Add(new OverlayPlaneGraphic(overlayPlane, overlayData, OverlayPlaneSource.PresentationState));
                    }
                    catch (Exception ex)
                    {
                        failedOverlays = true;
                        Platform.Log(LogLevel.Warn, new DicomOverlayDeserializationException(overlayPlane.Group, OverlayPlaneSource.PresentationState, ex), "Failed to load overlay from softcopy presentation state.");
                    }
                }
            }

            if (failedOverlays)
            {
                // add an error graphic if any overlays are not being displayed due to deserialization errors.
                overlayPlaneGraphics.Add(new ErrorOverlayPlaneGraphic(SR.MessageErrorDisplayingOverlays));
            }

            return(overlayPlaneGraphics);
        }
예제 #22
0
파일: CodecTest.cs 프로젝트: nhannd/Xian
        public void RleOverlayTest()
        {
            DicomFile file = new DicomFile("RleCodecOverlayTest.dcm");

            SetupMRWithOverlay(file.DataSet);

            SetupMetaInfo(file);

            // Save a copy
            file.Save();


            // Load the file into new DicomFile object
            DicomFile newFile = new DicomFile(file.Filename);

            newFile.Load();

            OverlayPlaneModuleIod overlayIod = new OverlayPlaneModuleIod(newFile.DataSet);
            OverlayPlane overlay = overlayIod[0];
            
            // SHould be no OverlayData tag
            Assert.IsNull(overlay.OverlayData, "Overlay should be in pixel data");

            // Overlay should be extracted out of pixel data here
            newFile.ChangeTransferSyntax(TransferSyntax.RleLossless);

            Assert.IsNotNull(overlay.OverlayData,"Overlay Data is not null");

            newFile.Save();

            // Load a new copy
            newFile = new DicomFile(file.Filename);

            newFile.Load();

            newFile.ChangeTransferSyntax(TransferSyntax.ExplicitVrLittleEndian);

            newFile.Filename = "Output" + file.Filename;
            newFile.Save();

            List<DicomAttributeComparisonResult> results = new List<DicomAttributeComparisonResult>();
            bool compare = file.DataSet.Equals(newFile.DataSet, ref results);

            // Shouldn't be the same, OverlayData tag should have been added
            Assert.IsFalse(compare, results.Count > 0 ? CollectionUtils.FirstElement(results).Details : string.Empty);                      
        }
        protected void SerializeOverlayPlane(OverlayPlaneModuleIod overlayPlaneModule, out IOverlayMapping overlayMapping, DicomPresentationImageCollection <T> images)
        {
            // Doesn't support multiframe or whatever case it is when we get more than one image serialized to one state
            List <OverlayPlaneGraphic> visibleOverlays = new List <OverlayPlaneGraphic>();

            foreach (T image in images)
            {
                DicomGraphicsPlane dicomGraphics = DicomGraphicsPlane.GetDicomGraphicsPlane(image, false);
                if (dicomGraphics != null)
                {
                    // identify visible bitmap shutter if exists
                    OverlayPlaneGraphic bitmapShutter = dicomGraphics.Shutters.ActiveShutter as OverlayPlaneGraphic;
                    if (bitmapShutter != null)
                    {
                        visibleOverlays.Add(bitmapShutter);
                    }

                    // identify any visible overlays
                    visibleOverlays.AddRange(((IEnumerable <ILayer>)dicomGraphics.Layers).Where(l => l.Visible).SelectMany(l => l.Graphics).OfType <OverlayPlaneGraphic>().Where(g => g.Visible));
                }
            }

            OverlayMapping overlayMap = new OverlayMapping();
            Queue <OverlayPlaneGraphic> overlaysToRemap = new Queue <OverlayPlaneGraphic>();

            // user and presentation state overlays are high priority items to remap
            foreach (OverlayPlaneGraphic overlay in CollectionUtils.Select(visibleOverlays, delegate(OverlayPlaneGraphic t) { return(t.Source != OverlayPlaneSource.Image); }))
            {
                overlaysToRemap.Enqueue(overlay);
            }
            foreach (OverlayPlaneGraphic overlay in CollectionUtils.Select(visibleOverlays, delegate(OverlayPlaneGraphic t) { return(t.Source == OverlayPlaneSource.Image); }))
            {
                if (overlayMap[overlay.Index] == null)
                {
                    overlayMap[overlay.Index] = overlay;
                }
                else
                {
                    overlaysToRemap.Enqueue(overlay);                     // image overlays are lower priority items to remap, since they will be included in the header anyway
                }
            }

            // seed the overlays to remap into the remaining available overlay groups
            for (int n = 0; n < 16 && overlaysToRemap.Count > 0; n++)
            {
                if (overlayMap[n] == null)
                {
                    overlayMap[n] = overlaysToRemap.Dequeue();
                }
            }

            // serialize the overlays
            for (int n = 0; n < 16; n++)
            {
                OverlayPlaneGraphic overlay = overlayMap[n];
                if (overlay != null)
                {
                    if (overlay.Source != OverlayPlaneSource.Image || overlay.Index != n)
                    {
                        // only record this overlay in the presentation state if it is being remapped to another group or is not already in the image.
                        OverlayPlane overlayIod = overlayPlaneModule[n];
                        overlayIod.OverlayData          = overlay.CreateOverlayData(overlayIod.IsBigEndianOW).Raw;
                        overlayIod.OverlayBitPosition   = 0;
                        overlayIod.OverlayBitsAllocated = 1;
                        overlayIod.OverlayColumns       = overlay.Columns;
                        overlayIod.OverlayDescription   = overlay.Description;
                        overlayIod.OverlayLabel         = overlay.Label;
                        overlayIod.OverlayOrigin        = Point.Round(overlay.Origin);
                        overlayIod.OverlayRows          = overlay.Rows;
                        overlayIod.OverlaySubtype       = overlay.Subtype;
                        overlayIod.OverlayType          = overlay.Type;
                        overlayIod.RoiArea = null;
                        overlayIod.RoiMean = null;
                        overlayIod.RoiStandardDeviation = null;
                    }
                    else
                    {
                        overlayPlaneModule.Delete(n);
                    }
                }
            }

            if (overlaysToRemap.Count > 0)
            {
                Platform.Log(LogLevel.Warn, "Attempt to serialize presentation state with more than 16 visible overlays - some information may be lost.");
            }

            overlayMapping = overlayMap;
        }
			private void ExtractOverlayFrames(byte[] rawPixelData, int bitsAllocated)
			{
				// if any overlays have embedded pixel data, extract them now or forever hold your peace
				var overlayPlaneModuleIod = new OverlayPlaneModuleIod(Parent);
				foreach (var overlayPlane in overlayPlaneModuleIod)
				{
					if (!overlayPlane.HasOverlayData && _overlayCache[overlayPlane.Index] == null)
					{
						// if the overlay is embedded in pixel data and we haven't cached it yet, extract it now before we normalize the frame pixel data
						var overlayData = OverlayData.UnpackFromPixelData(overlayPlane.OverlayBitPosition, bitsAllocated, false, rawPixelData);
						_overlayCache[overlayPlane.Index] = overlayData;
					}
				}
			}
예제 #25
0
			protected override byte[] CreateNormalizedPixelData()
			{
				byte[] pixelData = _framePixelData.GetUncompressedPixelData();

				string photometricInterpretationCode = this.Parent[DicomTags.PhotometricInterpretation].ToString();
				PhotometricInterpretation pi = PhotometricInterpretation.FromCodeString(photometricInterpretationCode);

				TransferSyntax ts = TransferSyntax.GetTransferSyntax(this.Parent.TransferSyntaxUid);
				if (pi.IsColor)
				{
					if (ts == TransferSyntax.Jpeg2000ImageCompression ||
					    ts == TransferSyntax.Jpeg2000ImageCompressionLosslessOnly ||
					    ts == TransferSyntax.JpegExtendedProcess24 ||
					    ts == TransferSyntax.JpegBaselineProcess1)
						pi = PhotometricInterpretation.Rgb;

					pixelData = ToArgb(this.Parent, pixelData, pi);
				}
				else
				{
					var overlayPlaneModuleIod = new OverlayPlaneModuleIod(Parent);
					foreach (var overlayPlane in overlayPlaneModuleIod)
					{
						if (!overlayPlane.HasOverlayData && _overlayData[overlayPlane.Index] == null)
						{
							// if the overlay is embedded in pixel data and we haven't cached it yet, extract it now before we normalize the frame pixel data
							var overlayData = OverlayData.UnpackFromPixelData(overlayPlane.OverlayBitPosition, Parent[DicomTags.BitsAllocated].GetInt32(0, 0), false, pixelData);
							_overlayData[overlayPlane.Index] = overlayData;
						}
					}

					NormalizeGrayscalePixels(this.Parent, pixelData);
				}

				return pixelData;
			}
			/// <summary>
			/// Called by <see cref="StandardSopFrameData.GetNormalizedOverlayData"/> to create a new byte buffer containing normalized 
			/// overlay pixel data for a particular overlay plane.
			/// </summary>
			/// <remarks>
			/// See <see cref="StandardSopFrameData.GetNormalizedOverlayData"/> for details on the expected format of the byte buffer.
			/// </remarks>
			/// <param name="overlayNumber">The 1-based overlay plane number.</param>
			/// <returns>A new byte buffer containing the normalized overlay pixel data.</returns>
			protected override byte[] CreateNormalizedOverlayData(int overlayNumber)
			{
				//TODO (CR December 2010): make this a helper method somewhere, since it's now identical to the one in StreamingSopFrameData?

				var overlayIndex = overlayNumber - 1;

				byte[] overlayData = null;

				var clock = new CodeClock();
				clock.Start();

				// check whether or not the overlay plane exists before attempting to ascertain
				// whether or not the overlay is embedded in the pixel data
				var overlayPlaneModuleIod = new OverlayPlaneModuleIod(Parent);
				if (overlayPlaneModuleIod.HasOverlayPlane(overlayIndex))
				{
					if (_overlayCache[overlayIndex] == null)
					{
						var overlayPlane = overlayPlaneModuleIod[overlayIndex];
						if (!overlayPlane.HasOverlayData)
						{
							// if the overlay is embedded, trigger retrieval of pixel data which will populate the cache for us
							GetNormalizedPixelData();
						}
						else
						{
							// try to compute the offset in the OverlayData bit stream where we can find the overlay frame that applies to this image frame
							int overlayFrame;
							int bitOffset;
							if (overlayPlane.TryGetRelevantOverlayFrame(FrameNumber, Parent.NumberOfFrames, out overlayFrame) &&
							    overlayPlane.TryComputeOverlayDataBitOffset(overlayFrame, out bitOffset))
							{
								// offset found - unpack only that overlay frame
								var od = new OverlayData(bitOffset,
								                         overlayPlane.OverlayRows,
								                         overlayPlane.OverlayColumns,
								                         overlayPlane.IsBigEndianOW,
								                         overlayPlane.OverlayData);
								_overlayCache[overlayIndex] = od.Unpack();
							}
							else
							{
								// no relevant overlay frame found - i.e. the overlay for this image frame is blank
								_overlayCache[overlayIndex] = new byte[0];
							}
						}
					}

					overlayData = _overlayCache[overlayIndex];
				}

				clock.Stop();
				PerformanceReportBroker.PublishReport("DicomMessageSopDataSource", "CreateNormalizedOverlayData", clock.Seconds);

				return overlayData;
			}
예제 #27
0
		public void TestGetRelevantOverlayFrame_MultiframeEmbedded()
		{
			const bool bigEndian = false;

			// these parameters should be kept prime numbers so that we can exercise the overlay handling for rows/frames that cross byte boundaries
			const int rows = 97;
			const int columns = 101;
			const int frames = 7;

			const int overlayIndex = 0;
			var dataset = new DicomAttributeCollection();
			SetImage(dataset, new byte[rows*columns*2*frames], rows, columns, frames, 16, 12, 11, false);
			SetOverlay(dataset, overlayIndex, new bool[rows*columns*frames], OverlayType.G, new Point(1, 1), 12, bigEndian);

			var module = new OverlayPlaneModuleIod(dataset);
			var overlayPlane = module[overlayIndex];

			int actualOverlayFrame;

			Assert.IsFalse(overlayPlane.TryGetRelevantOverlayFrame(-1, frames, out actualOverlayFrame), "Should not any matching overlay frame for image frame #-1");
			Assert.IsFalse(overlayPlane.TryGetRelevantOverlayFrame(0, frames, out actualOverlayFrame), "Should not any matching overlay frame for image frame #0");
			Assert.IsFalse(overlayPlane.TryGetRelevantOverlayFrame(8, frames, out actualOverlayFrame), "Should not any matching overlay frame for image frame #8");

			// all valid image frame inputs should map 1-to-1 with the same numbered overlay frame

			Assert.IsTrue(overlayPlane.TryGetRelevantOverlayFrame(1, frames, out actualOverlayFrame), "Should be able to match an overlay frame to image frame #1");
			Assert.AreEqual(1, actualOverlayFrame, "Wrong overlay frame matched to image frame #1");

			Assert.IsTrue(overlayPlane.TryGetRelevantOverlayFrame(2, frames, out actualOverlayFrame), "Should be able to match an overlay frame to image frame #2");
			Assert.AreEqual(2, actualOverlayFrame, "Wrong overlay frame matched to image frame #2");

			Assert.IsTrue(overlayPlane.TryGetRelevantOverlayFrame(3, frames, out actualOverlayFrame), "Should be able to match an overlay frame to image frame #3");
			Assert.AreEqual(3, actualOverlayFrame, "Wrong overlay frame matched to image frame #3");

			Assert.IsTrue(overlayPlane.TryGetRelevantOverlayFrame(4, frames, out actualOverlayFrame), "Should be able to match an overlay frame to image frame #4");
			Assert.AreEqual(4, actualOverlayFrame, "Wrong overlay frame matched to image frame #4");

			Assert.IsTrue(overlayPlane.TryGetRelevantOverlayFrame(5, frames, out actualOverlayFrame), "Should be able to match an overlay frame to image frame #5");
			Assert.AreEqual(5, actualOverlayFrame, "Wrong overlay frame matched to image frame #5");

			Assert.IsTrue(overlayPlane.TryGetRelevantOverlayFrame(6, frames, out actualOverlayFrame), "Should be able to match an overlay frame to image frame #6");
			Assert.AreEqual(6, actualOverlayFrame, "Wrong overlay frame matched to image frame #6");

			Assert.IsTrue(overlayPlane.TryGetRelevantOverlayFrame(7, frames, out actualOverlayFrame), "Should be able to match an overlay frame to image frame #7");
			Assert.AreEqual(7, actualOverlayFrame, "Wrong overlay frame matched to image frame #7");
		}
		public static List<OverlayPlaneGraphic> CreateOverlayPlaneGraphics(Frame frame, OverlayPlaneModuleIod overlaysFromPresentationState)
		{
			ISopDataSource dataSource = frame.ParentImageSop.DataSource;
			OverlayPlaneModuleIod overlaysIod = new OverlayPlaneModuleIod(dataSource);

			List<OverlayPlaneGraphic> overlayPlaneGraphics = new List<OverlayPlaneGraphic>();

			bool failedOverlays = false;

			foreach (var overlayPlane in overlaysIod)
			{
				// DICOM 2009 PS 3.3 Section C.9.3.1.1 specifies the rule: NumberOfFramesInOverlay+ImageFrameOrigin-1 must be <= NumberOfFrames
				if (!overlayPlane.IsValidMultiFrameOverlay(frame.ParentImageSop.NumberOfFrames))
				{
					failedOverlays = true;
					Platform.Log(LogLevel.Warn, new DicomOverlayDeserializationException(overlayPlane.Group, OverlayPlaneSource.Image), "Encoding error encountered while reading overlay from image headers.");
					continue;
				}

				try
				{
					byte[] overlayData = dataSource.GetFrameData(frame.FrameNumber).GetNormalizedOverlayData(overlayPlane.Index + 1);
					overlayPlaneGraphics.Add(new OverlayPlaneGraphic(overlayPlane, overlayData, OverlayPlaneSource.Image));

					// if overlay data is null, the data source failed to retrieve the overlay data for some reason, so we also treat it as an encoding error
					// this is different from if the overlay data is zero-length, which indicates that the retrieval succeeded, but that the overlay data for the frame is empty
					if (overlayData == null)
						throw new NullReferenceException();
				}
				catch (Exception ex)
				{
					failedOverlays = true;
					Platform.Log(LogLevel.Warn, new DicomOverlayDeserializationException(overlayPlane.Group, OverlayPlaneSource.Image, ex), "Failed to load overlay from the image header.");
				}
			}

			if (overlaysFromPresentationState != null)
			{
				foreach (var overlayPlane in overlaysFromPresentationState)
				{
					// if overlay data is missing, treat as an encoding error
					if (!overlayPlane.HasOverlayData)
					{
						failedOverlays = true;
						Platform.Log(LogLevel.Warn, new DicomOverlayDeserializationException(overlayPlane.Group, OverlayPlaneSource.PresentationState), "Encoding error encountered while reading overlay from softcopy presentation state.");
						continue;
					}

					try
					{
						byte[] overlayData;

						// try to compute the offset in the OverlayData bit stream where we can find the overlay frame that applies to this image frame
						int overlayFrame, bitOffset;
						if (overlayPlane.TryGetRelevantOverlayFrame(frame.FrameNumber, frame.ParentImageSop.NumberOfFrames, out overlayFrame) &&
						    overlayPlane.TryComputeOverlayDataBitOffset(overlayFrame, out bitOffset))
						{
							// offset found - unpack only that overlay frame
							var od = new OverlayData(bitOffset,
							                         overlayPlane.OverlayRows,
							                         overlayPlane.OverlayColumns,
							                         overlayPlane.IsBigEndianOW,
							                         overlayPlane.OverlayData);

							overlayData = od.Unpack();
						}
						else
						{
							// no relevant overlay frame found - i.e. the overlay for this image frame is blank
							overlayData = new byte[0];
						}

						overlayPlaneGraphics.Add(new OverlayPlaneGraphic(overlayPlane, overlayData, OverlayPlaneSource.PresentationState));
					}
					catch (Exception ex)
					{
						failedOverlays = true;
						Platform.Log(LogLevel.Warn, new DicomOverlayDeserializationException(overlayPlane.Group, OverlayPlaneSource.PresentationState, ex), "Failed to load overlay from softcopy presentation state.");
					}
				}
			}

			if (failedOverlays)
			{
				// add an error graphic if any overlays are not being displayed due to deserialization errors.
				overlayPlaneGraphics.Add(new ErrorOverlayPlaneGraphic(SR.MessageErrorDisplayingOverlays));
			}

			return overlayPlaneGraphics;
		}
예제 #29
0
		public void TestGetRelevantOverlayFrame_SingleFrameEmbedded()
		{
			const bool bigEndian = false;

			// these parameters should be kept prime numbers so that we can exercise the overlay handling for rows/frames that cross byte boundaries
			const int rows = 97;
			const int columns = 101;

			const int overlayIndex = 0;
			var dataset = new DicomAttributeCollection();
			SetImage(dataset, new byte[rows*columns*2], rows, columns, 1, 16, 12, 11, false);
			SetOverlay(dataset, overlayIndex, new bool[rows*columns], OverlayType.G, new Point(1, 1), 12, bigEndian);

			var module = new OverlayPlaneModuleIod(dataset);
			var overlayPlane = module[overlayIndex];

			int actualOverlayFrame;

			Assert.IsFalse(overlayPlane.TryGetRelevantOverlayFrame(-1, 1, out actualOverlayFrame), "Should not any matching overlay frame for image frame #-1");
			Assert.IsFalse(overlayPlane.TryGetRelevantOverlayFrame(0, 1, out actualOverlayFrame), "Should not any matching overlay frame for image frame #0");
			Assert.IsFalse(overlayPlane.TryGetRelevantOverlayFrame(8, 1, out actualOverlayFrame), "Should not any matching overlay frame for image frame #8");

			// in the single frame case, there's only one pairing

			Assert.IsTrue(overlayPlane.TryGetRelevantOverlayFrame(1, 1, out actualOverlayFrame), "Should be able to match an overlay frame to image frame #1");
			Assert.AreEqual(1, actualOverlayFrame, "Wrong overlay frame matched to image frame #1");
		}
예제 #30
0
			protected override byte[] CreateNormalizedPixelData()
			{
				string photometricInterpretation;
				byte[] pixelData = _framePixelData.GetUncompressedPixelData(out photometricInterpretation);

				string photometricInterpretationCode = photometricInterpretation ?? Parent[DicomTags.PhotometricInterpretation].ToString();
				PhotometricInterpretation pi = PhotometricInterpretation.FromCodeString(photometricInterpretationCode);

				if (pi.IsColor)
				{
					pixelData = ToArgb(this.Parent, pixelData, pi);
				}
				else
				{
					var overlayPlaneModuleIod = new OverlayPlaneModuleIod(Parent);
					foreach (var overlayPlane in overlayPlaneModuleIod)
					{
						if (!overlayPlane.HasOverlayData && _overlayData[overlayPlane.Index] == null)
						{
							// if the overlay is embedded in pixel data and we haven't cached it yet, extract it now before we normalize the frame pixel data
							var overlayData = OverlayData.UnpackFromPixelData(overlayPlane.OverlayBitPosition, Parent[DicomTags.BitsAllocated].GetInt32(0, 0), false, pixelData);
							_overlayData[overlayPlane.Index] = overlayData;
						}
					}

					NormalizeGrayscalePixels(this.Parent, pixelData);
				}

				return pixelData;
			}
예제 #31
0
		public void TestGetRelevantOverlayFrame_SingleFrameOverlayData()
		{
			const bool bigEndian = false;

			// these parameters should be kept prime numbers so that we can exercise the overlay handling for rows/frames that cross byte boundaries
			const int rows = 97;
			const int columns = 101;

			const int imageFrames = 7;

			const int overlayIndex = 0;
			var dataset = new DicomAttributeCollection();
			SetOverlay(dataset, overlayIndex, new bool[rows*columns], OverlayType.G, new Point(1, 1), rows, columns, null, null, bigEndian, false);

			var module = new OverlayPlaneModuleIod(dataset);
			var overlayPlane = module[overlayIndex];

			int actualOverlayFrame;

			Assert.IsFalse(overlayPlane.TryGetRelevantOverlayFrame(-1, imageFrames, out actualOverlayFrame), "Should not any matching overlay frame for image frame #-1");
			Assert.IsFalse(overlayPlane.TryGetRelevantOverlayFrame(0, imageFrames, out actualOverlayFrame), "Should not any matching overlay frame for image frame #0");
			Assert.IsFalse(overlayPlane.TryGetRelevantOverlayFrame(8, imageFrames, out actualOverlayFrame), "Should not any matching overlay frame for image frame #8");

			// in the single frame case, all valid image frame inputs should map to overlay frame #1

			Assert.IsTrue(overlayPlane.TryGetRelevantOverlayFrame(1, imageFrames, out actualOverlayFrame), "Should be able to match an overlay frame to image frame #1");
			Assert.AreEqual(1, actualOverlayFrame, "Wrong overlay frame matched to image frame #1");

			Assert.IsTrue(overlayPlane.TryGetRelevantOverlayFrame(2, imageFrames, out actualOverlayFrame), "Should be able to match an overlay frame to image frame #2");
			Assert.AreEqual(1, actualOverlayFrame, "Wrong overlay frame matched to image frame #2");

			Assert.IsTrue(overlayPlane.TryGetRelevantOverlayFrame(3, imageFrames, out actualOverlayFrame), "Should be able to match an overlay frame to image frame #3");
			Assert.AreEqual(1, actualOverlayFrame, "Wrong overlay frame matched to image frame #3");

			Assert.IsTrue(overlayPlane.TryGetRelevantOverlayFrame(4, imageFrames, out actualOverlayFrame), "Should be able to match an overlay frame to image frame #4");
			Assert.AreEqual(1, actualOverlayFrame, "Wrong overlay frame matched to image frame #4");

			Assert.IsTrue(overlayPlane.TryGetRelevantOverlayFrame(5, imageFrames, out actualOverlayFrame), "Should be able to match an overlay frame to image frame #5");
			Assert.AreEqual(1, actualOverlayFrame, "Wrong overlay frame matched to image frame #5");

			Assert.IsTrue(overlayPlane.TryGetRelevantOverlayFrame(6, imageFrames, out actualOverlayFrame), "Should be able to match an overlay frame to image frame #6");
			Assert.AreEqual(1, actualOverlayFrame, "Wrong overlay frame matched to image frame #6");

			Assert.IsTrue(overlayPlane.TryGetRelevantOverlayFrame(7, imageFrames, out actualOverlayFrame), "Should be able to match an overlay frame to image frame #7");
			Assert.AreEqual(1, actualOverlayFrame, "Wrong overlay frame matched to image frame #7");
		}
예제 #32
0
		public void TestOverlayPlaneModuleIod_SingleFrame()
		{
			const bool bigEndian = false;

			// these parameters should be kept prime numbers so that we can exercise the overlay handling for rows/frames that cross byte boundaries
			const int imageRows = 97;
			const int imageColumns = 101;
			const int overlay1Rows = 103;
			const int overlay1Columns = 89;
			const int overlay2Rows = 67;
			const int overlay2Columns = 71;

			var dataset = new DicomAttributeCollection();
			SetImage(dataset, new byte[imageRows*imageColumns*2], imageRows, imageColumns, 1, 16, 13, 12, false);
			SetOverlay(dataset, 0, new bool[overlay1Rows*overlay1Columns], OverlayType.G, new Point(1, 1), overlay1Rows, overlay1Columns, bigEndian, false);
			SetOverlay(dataset, 1, new bool[imageRows*imageColumns], OverlayType.G, new Point(2, 3), 15, bigEndian);
			SetOverlay(dataset, 2, new bool[overlay2Rows*overlay2Columns], OverlayType.R, new Point(4, 5), overlay2Rows, overlay2Columns, bigEndian, true);
			SetOverlay(dataset, 13, new bool[imageRows*imageColumns], OverlayType.R, new Point(6, 7), 14, bigEndian);

			var module = new OverlayPlaneModuleIod(dataset);

			// test overlay group 6000
			{
				const int overlayIndex = 0;
				var overlayPlane = module[overlayIndex];

				// assert overlay plane identification
				Assert.AreEqual(0x6000, overlayPlane.Group, "Wrong overlay group for plane #{0}", overlayIndex);
				Assert.AreEqual(0, overlayPlane.Index, "Wrong overlay index for plane #{0}", overlayIndex);
				Assert.AreEqual(0x000000, overlayPlane.TagOffset, "Wrong tag offset for plane #{0}", overlayIndex);

				// assert overlay plane encoding detection
				Assert.AreEqual(true, overlayPlane.HasOverlayData, "Incorrect OverlayData detection for plane #{0}", overlayIndex);
				Assert.AreEqual(false, overlayPlane.IsBigEndianOW, "Incorrect OW/OB detection for plane #{0}", overlayIndex);
				Assert.AreEqual(false, overlayPlane.IsMultiFrame, "Incorrect multiframe detection for plane #{0}", overlayIndex);
				Assert.AreEqual(103*89, overlayPlane.GetOverlayFrameLength(), "Incorrect frame size computation for plane #{0}", overlayIndex);

				// assert overlay plane basic attribute values
				Assert.AreEqual(103, overlayPlane.OverlayRows, "Wrong overlay rows for plane #{0}", overlayIndex);
				Assert.AreEqual(89, overlayPlane.OverlayColumns, "Wrong overlay columns for plane #{0}", overlayIndex);
				Assert.AreEqual(0, overlayPlane.OverlayBitPosition, "Wrong overlay bit position for plane #{0}", overlayIndex);
				Assert.AreEqual(1, overlayPlane.OverlayBitsAllocated, "Wrong overlay bits allocated for plane #{0}", overlayIndex);
				Assert.AreEqual(OverlayType.G, overlayPlane.OverlayType, "Wrong overlay type for plane #{0}", overlayIndex);
				Assert.AreEqual(new Point(1, 1), overlayPlane.OverlayOrigin, "Wrong overlay origin for plane #{0}", overlayIndex);

				// assert overlay plane multiframe attribute values
				Assert.AreEqual(null, overlayPlane.ImageFrameOrigin, "Wrong image frame origin for plane #{0}", overlayIndex);
				Assert.AreEqual(null, overlayPlane.NumberOfFramesInOverlay, "Wrong number of frames in overlay for plane #{0}", overlayIndex);
			}

			// test overlay group 6002
			{
				const int overlayIndex = 1;
				var overlayPlane = module[overlayIndex];

				// assert overlay plane identification
				Assert.AreEqual(0x6002, overlayPlane.Group, "Wrong overlay group for plane #{0}", overlayIndex);
				Assert.AreEqual(1, overlayPlane.Index, "Wrong overlay index for plane #{0}", overlayIndex);
				Assert.AreEqual(0x020000, overlayPlane.TagOffset, "Wrong tag offset for plane #{0}", overlayIndex);

				// assert overlay plane encoding detection
				Assert.AreEqual(false, overlayPlane.HasOverlayData, "Incorrect OverlayData detection for plane #{0}", overlayIndex);
				Assert.AreEqual(false, overlayPlane.IsBigEndianOW, "Incorrect OW/OB detection for plane #{0}", overlayIndex);
				Assert.AreEqual(false, overlayPlane.IsMultiFrame, "Incorrect multiframe detection for plane #{0}", overlayIndex);
				Assert.AreEqual(97*101, overlayPlane.GetOverlayFrameLength(), "Incorrect frame size computation for plane #{0}", overlayIndex);

				// assert overlay plane basic attribute values
				Assert.AreEqual(97, overlayPlane.OverlayRows, "Wrong overlay rows for plane #{0}", overlayIndex);
				Assert.AreEqual(101, overlayPlane.OverlayColumns, "Wrong overlay columns for plane #{0}", overlayIndex);
				Assert.AreEqual(15, overlayPlane.OverlayBitPosition, "Wrong overlay bit position for plane #{0}", overlayIndex);
				Assert.AreEqual(16, overlayPlane.OverlayBitsAllocated, "Wrong overlay bits allocated for plane #{0}", overlayIndex);
				Assert.AreEqual(OverlayType.G, overlayPlane.OverlayType, "Wrong overlay type for plane #{0}", overlayIndex);
				Assert.AreEqual(new Point(2, 3), overlayPlane.OverlayOrigin, "Wrong overlay origin for plane #{0}", overlayIndex);

				// assert overlay plane multiframe attribute values
				Assert.AreEqual(null, overlayPlane.ImageFrameOrigin, "Wrong image frame origin for plane #{0}", overlayIndex);
				Assert.AreEqual(null, overlayPlane.NumberOfFramesInOverlay, "Wrong number of frames in overlay for plane #{0}", overlayIndex);
			}

			// test overlay group 6004
			{
				const int overlayIndex = 2;
				var overlayPlane = module[overlayIndex];

				// assert overlay plane identification
				Assert.AreEqual(0x6004, overlayPlane.Group, "Wrong overlay group for plane #{0}", overlayIndex);
				Assert.AreEqual(2, overlayPlane.Index, "Wrong overlay index for plane #{0}", overlayIndex);
				Assert.AreEqual(0x040000, overlayPlane.TagOffset, "Wrong tag offset for plane #{0}", overlayIndex);

				// assert overlay plane encoding detection
				Assert.AreEqual(true, overlayPlane.HasOverlayData, "Incorrect OverlayData detection for plane #{0}", overlayIndex);
				Assert.AreEqual(false, overlayPlane.IsBigEndianOW, "Incorrect OW/OB detection for plane #{0}", overlayIndex);
				Assert.AreEqual(false, overlayPlane.IsMultiFrame, "Incorrect multiframe detection for plane #{0}", overlayIndex);
				Assert.AreEqual(67*71, overlayPlane.GetOverlayFrameLength(), "Incorrect frame size computation for plane #{0}", overlayIndex);

				// assert overlay plane basic attribute values
				Assert.AreEqual(67, overlayPlane.OverlayRows, "Wrong overlay rows for plane #{0}", overlayIndex);
				Assert.AreEqual(71, overlayPlane.OverlayColumns, "Wrong overlay columns for plane #{0}", overlayIndex);
				Assert.AreEqual(0, overlayPlane.OverlayBitPosition, "Wrong overlay bit position for plane #{0}", overlayIndex);
				Assert.AreEqual(1, overlayPlane.OverlayBitsAllocated, "Wrong overlay bits allocated for plane #{0}", overlayIndex);
				Assert.AreEqual(OverlayType.R, overlayPlane.OverlayType, "Wrong overlay type for plane #{0}", overlayIndex);
				Assert.AreEqual(new Point(4, 5), overlayPlane.OverlayOrigin, "Wrong overlay origin for plane #{0}", overlayIndex);

				// assert overlay plane multiframe attribute values
				Assert.AreEqual(null, overlayPlane.ImageFrameOrigin, "Wrong image frame origin for plane #{0}", overlayIndex);
				Assert.AreEqual(null, overlayPlane.NumberOfFramesInOverlay, "Wrong number of frames in overlay for plane #{0}", overlayIndex);
			}

			// test overlay group 601A
			{
				const int overlayIndex = 13;
				var overlayPlane = module[overlayIndex];

				// assert overlay plane identification
				Assert.AreEqual(0x601A, overlayPlane.Group, "Wrong overlay group for plane #{0}", overlayIndex);
				Assert.AreEqual(13, overlayPlane.Index, "Wrong overlay index for plane #{0}", overlayIndex);
				Assert.AreEqual(0x1A0000, overlayPlane.TagOffset, "Wrong tag offset for plane #{0}", overlayIndex);

				// assert overlay plane encoding detection
				Assert.AreEqual(false, overlayPlane.HasOverlayData, "Incorrect OverlayData detection for plane #{0}", overlayIndex);
				Assert.AreEqual(false, overlayPlane.IsBigEndianOW, "Incorrect OW/OB detection for plane #{0}", overlayIndex);
				Assert.AreEqual(false, overlayPlane.IsMultiFrame, "Incorrect multiframe detection for plane #{0}", overlayIndex);
				Assert.AreEqual(97*101, overlayPlane.GetOverlayFrameLength(), "Incorrect frame size computation for plane #{0}", overlayIndex);

				// assert overlay plane basic attribute values
				Assert.AreEqual(97, overlayPlane.OverlayRows, "Wrong overlay rows for plane #{0}", overlayIndex);
				Assert.AreEqual(101, overlayPlane.OverlayColumns, "Wrong overlay columns for plane #{0}", overlayIndex);
				Assert.AreEqual(14, overlayPlane.OverlayBitPosition, "Wrong overlay bit position for plane #{0}", overlayIndex);
				Assert.AreEqual(16, overlayPlane.OverlayBitsAllocated, "Wrong overlay bits allocated for plane #{0}", overlayIndex);
				Assert.AreEqual(OverlayType.R, overlayPlane.OverlayType, "Wrong overlay type for plane #{0}", overlayIndex);
				Assert.AreEqual(new Point(6, 7), overlayPlane.OverlayOrigin, "Wrong overlay origin for plane #{0}", overlayIndex);

				// assert overlay plane multiframe attribute values
				Assert.AreEqual(null, overlayPlane.ImageFrameOrigin, "Wrong image frame origin for plane #{0}", overlayIndex);
				Assert.AreEqual(null, overlayPlane.NumberOfFramesInOverlay, "Wrong number of frames in overlay for plane #{0}", overlayIndex);
			}
		}
예제 #33
0
        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);

                    // Check if Overlay is embedded in pixels
                    OverlayPlaneModuleIod overlayIod = new OverlayPlaneModuleIod(DataSet);
                    for (int i = 0; i < 16; i++)
                    {
                        if (overlayIod.HasOverlayPlane(i))
                        {
                            OverlayPlane overlay = overlayIod[i];
                            if (overlay.OverlayData == null)
                            {
                                Platform.Log(LogLevel.Debug,
                                             "SOP Instance has embedded overlay in pixel data, extracting");
                                overlay.ConvertEmbeddedOverlay(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;
                }
            }
        }