/// <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);
            }
            /// <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);
            }
Example #3
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);
            }
        public static void CreateSeriesGraphicsForSeg(IPresentationImage presentationImage, Seg seg,
                                                      SegmentationDocument segmentationDocument,
                                                      IDicomMessageSopDataSource dicomMessageSopDataSourceSop)
        {
            Platform.CheckForNullReference(presentationImage, "presentationImage");
            Platform.CheckForNullReference(seg, "seg");
            Platform.CheckForNullReference(segmentationDocument, "segmentationDocument");

            SegmentImageData segImageData = seg.SegmentImageData;

            if (segImageData == null)
            {
                Platform.Log(LogLevel.Error,
                             "Cannot create segmentation graphics when no segmentation imaging data is provided");
                return;
            }

            var imageSopProvider = presentationImage as IImageSopProvider;

            if (imageSopProvider == null)
            {
                Platform.Log(LogLevel.Error,
                             "Failed to populate SegFrameGraphics collection. Image is not an ImageSopProvider");
                return;
            }

            DicomPixelData segmentationPixelData = DicomPixelData.CreateFrom(dicomMessageSopDataSourceSop.SourceMessage);
            var            rawPixelData          =
                (byte[])dicomMessageSopDataSourceSop.SourceMessage.DataSet.GetAttribute(DicomTags.PixelData).Values;
            var pixelDataGetter = new Func <int, byte[]>(frameIndex =>
            {
                if (segImageData.BitsStored == 1)
                {
                    // Do unpacking
                    int frameLength = segImageData.Rows *
                                      segImageData.Columns;
                    var overlayData =
                        new OverlayData(frameIndex * frameLength,
                                        segImageData.Rows,
                                        segImageData.Columns, false,
                                        rawPixelData);
                    return(overlayData.Unpack());
                }
                if (segImageData.BitsStored == 8)
                {
                    return(segmentationPixelData.GetFrame(frameIndex));
                }
                throw new InvalidDataException(
                    "Segmentation objects need to have BitsStored as either 1 or 8");
            });

            // NOTE: SegmentFrameData was already sorted
            foreach (SegmentFrameData segmentFrameData in segImageData.SegmentFrameData)
            {
                IPresentationImage segPresentationImage = null;

                // Get the presentation image if we have an image reference
                string referencedSopInstanceUid   = segmentFrameData.ReferencedSopInstanceUid;
                int    referencedImageFrameNumber = segmentFrameData.ReferencedFrameNumber ?? 1;
                if (!string.IsNullOrEmpty(referencedSopInstanceUid))
                {
                    segPresentationImage =
                        presentationImage.ParentDisplaySet.PresentationImages.OfType <IImageSopProvider>()
                        .FirstOrDefault(curImageSopProvider => curImageSopProvider != null &&
                                        curImageSopProvider.ImageSop.SopInstanceUid ==
                                        referencedSopInstanceUid &&
                                        curImageSopProvider.Frame.FrameNumber ==
                                        referencedImageFrameNumber) as IPresentationImage;
                }

                // Location defaults to 0, 0 unless determined otherwise from image position and image orientation
                var segLocation = new PointF();

                // Get the presentation image from the image position and orientation
                if (segmentFrameData.ImagePositionPatient != null &&
                    segmentFrameData.ImagePositionPatient.Count() > 2 &&
                    segmentFrameData.ImageOrientationPatient != null &&
                    segmentFrameData.ImageOrientationPatient.Count() > 5)
                {
                    var imagePositionPatient = new ImagePositionPatient(
                        segmentFrameData.ImagePositionPatient[0],
                        segmentFrameData.ImagePositionPatient[1],
                        segmentFrameData.ImagePositionPatient[2]);
                    var imageOrientationPatient = new ImageOrientationPatient(
                        segmentFrameData.ImageOrientationPatient[0],
                        segmentFrameData.ImageOrientationPatient[1],
                        segmentFrameData.ImageOrientationPatient[2],
                        segmentFrameData.ImageOrientationPatient[3],
                        segmentFrameData.ImageOrientationPatient[4],
                        segmentFrameData.ImageOrientationPatient[5]);
                    IDisplaySet displaySet = presentationImage.ParentDisplaySet;

                    if (segPresentationImage == null)
                    {
                        segPresentationImage = PresentationImageFromPositionOrientation(
                            imagePositionPatient,
                            imageOrientationPatient,
                            displaySet,
                            segImageData.FrameOfReferenceUid);
                    }

                    var imageSop = segPresentationImage as IImageSopProvider;
                    if (imageSop != null)
                    {
                        Vector3D segImageLocation =
                            imageSop.Frame.ImagePlaneHelper.ConvertToImagePlane(new Vector3D(
                                                                                    (float)imagePositionPatient.X,
                                                                                    (float)imagePositionPatient.Y,
                                                                                    (float)imagePositionPatient.Z));
                        PointF?segPixelLocation =
                            imageSop.Frame.ImagePlaneHelper.ConvertToImage(
                                new PointF(segImageLocation.X, segImageLocation.Y));
                        if (segPixelLocation.HasValue)
                        {
                            segLocation = segPixelLocation.Value;
                        }
                    }
                }

                if (segPresentationImage != null)
                {
                    SegFrameImageGraphic newGraphic = AddSegFrameImageGraphicToPresentationImage(
                        segPresentationImage,
                        segImageData.Rows,
                        segImageData.Columns,
                        segLocation.X,
                        segLocation.Y,
                        seg.Color,
                        referencedImageFrameNumber,
                        seg.Label,
                        seg.Description,
                        pixelDataGetter.Invoke(segmentFrameData.FrameNumber - 1),
                        new SegmentationDocumentReference(segmentationDocument, seg.SegmentationNumber));
                    if (newGraphic != null &&
                        segPresentationImage == segPresentationImage.ParentDisplaySet.ImageBox.TopLeftPresentationImage)
                    {
                        newGraphic.Draw();
                    }
                }
                else
                {
                    Platform.Log(LogLevel.Error, "Failed to find Presentation Image to display a segment on");
                }
            }
        }
Example #5
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);
        }