/// <summary>
        /// Creates a <see cref="SegFrameImageGraphic"/> and adds the graphic to the given <see cref="IPresentationImage"/>
        /// </summary>
        /// <param name="presentationImage">The image to add the graphic to</param>
        /// <param name="rows">Number of rows in the new graphic</param>
        /// <param name="columns">Number of columns in the new graphic</param>
        /// <param name="xLocation">X coordinate of the graphic's origin</param>
        /// <param name="yLocation">Y coordinate of the graphic's origin</param>
        /// <param name="color">Color of the new graphic</param>
        /// <param name="frameIndex">Image frame index</param>
        /// <param name="label">Graphic's label</param>
        /// <param name="description">Graphic's description</param>
        /// <param name="segPixelData">8-bit pixel data of the segmentation overlay</param>
        /// <param name="segmentationDocumentReference">Reference to the Segmentation document this graphic is created for</param>
        /// <returns></returns>
        public static SegFrameImageGraphic AddSegFrameImageGraphicToPresentationImage(
            IPresentationImage presentationImage, int rows, int columns, float xLocation, float yLocation,
            Color color, int frameIndex, string label,
            string description, byte[] segPixelData,
            SegmentationDocumentReference segmentationDocumentReference)
        {
            // TODO VK: use IApplicationGraphicsProvider here!!!
            var overlayGraphicsProvider = presentationImage as IOverlayGraphicsProvider;

            if (overlayGraphicsProvider == null)
            {
                return(null);
            }

            var segFrameImageGraphic = new SegFrameImageGraphic(rows, columns, xLocation, yLocation, color,
                                                                frameIndex, -1, label,
                                                                description, segPixelData, segmentationDocumentReference);

            segFrameImageGraphic.Alpha = Seg.DefaultOpacity;

            var sopProvider = presentationImage as IImageSopProvider;

            if (sopProvider != null)
            {
                segFrameImageGraphic.ImageSopInstanceUid = sopProvider.Sop.SopInstanceUid;
                segFrameImageGraphic.ImageFrameNumber    = sopProvider.Frame.FrameNumber;
                segFrameImageGraphic.ImageNumber         = sopProvider.ImageSop.InstanceNumber;
            }

            overlayGraphicsProvider.OverlayGraphics.Add(segFrameImageGraphic);

            return(segFrameImageGraphic);
        }
        public static SegFrameImageGraphic AddSegFrameImageGraphicToPresentationImage(
            IPresentationImage presentationImage,
            Color color,
            IEnumerable <PointF> vertices)
        {
            var image = presentationImage as IImageGraphicProvider;

            if (image == null)
            {
                return(null);
            }

            // Get the base image
            ImageGraphic baseImage = image.ImageGraphic;

            var segFrameImageGraphic = new SegFrameImageGraphic(baseImage.Rows, baseImage.Columns, color);

            segFrameImageGraphic.Alpha = Seg.DefaultOpacity;
            RectangleF boundingBox = RectangleUtilities.ComputeBoundingRectangle(vertices.ToArray());

            // Convert vector polygon to raster on a per pixel basis
            baseImage.PixelData.ForEachPixel(
                delegate(int i, int x, int y, int pixelIndex)
            {
                var point = new PointF(x, y);
                if (boundingBox.Contains(point))
                {
                    if (IsInPolygon(vertices.ToArray(), point))
                    {
                        segFrameImageGraphic[x, y] = true;
                    }
                }
            }
                );

            var overlayGraphicsProvider = presentationImage as IOverlayGraphicsProvider;

            if (overlayGraphicsProvider != null)
            {
                overlayGraphicsProvider.OverlayGraphics.Add(segFrameImageGraphic);
            }

            return(segFrameImageGraphic);
        }
        public static SegFrameImageGraphic AddSegFrameImageGraphicToPresentationImage(
            IPresentationImage presentationImage,
            Color color,
            IEnumerable<PointF> vertices)
        {
            var image = presentationImage as IImageGraphicProvider;

            if (image == null)
                return null;

            // Get the base image
            ImageGraphic baseImage = image.ImageGraphic;

            var segFrameImageGraphic = new SegFrameImageGraphic(baseImage.Rows, baseImage.Columns, color);
            segFrameImageGraphic.Alpha = Seg.DefaultOpacity;
            RectangleF boundingBox = RectangleUtilities.ComputeBoundingRectangle(vertices.ToArray());

            // Convert vector polygon to raster on a per pixel basis
            baseImage.PixelData.ForEachPixel(
                delegate(int i, int x, int y, int pixelIndex)
                    {
                        var point = new PointF(x, y);
                        if (boundingBox.Contains(point))
                            if (IsInPolygon(vertices.ToArray(), point))
                            {
                                segFrameImageGraphic[x, y] = true;
                            }
                    }
                );

            var overlayGraphicsProvider = presentationImage as IOverlayGraphicsProvider;
            if (overlayGraphicsProvider != null)
            {
                overlayGraphicsProvider.OverlayGraphics.Add(segFrameImageGraphic);
            }

            return segFrameImageGraphic;
        }
        internal static double CalculateStandardDeviationForStack(double mean,
                                                                  List <ImageCalculationInfo> imageCalculationInfoStack)
        {
            double sum        = 0;
            int    pixelCount = 0;

            for (int imageCount = 0; imageCount < imageCalculationInfoStack.Count; imageCount++)
            {
                PixelData            pixelData            = imageCalculationInfoStack[imageCount].PixelData;
                SegFrameImageGraphic segFrameImageGraphic = imageCalculationInfoStack[imageCount].SegFrameImageGraphic;
                RectangleF           roiBoundingBox       = imageCalculationInfoStack[imageCount].RoiBoundingBox;
                IModalityLut         modalityLut          = imageCalculationInfoStack[imageCount].ModalityLut;

                Rectangle boundingBox =
                    RectangleUtilities.RoundInflate(RectangleUtilities.ConvertToPositiveRectangle(roiBoundingBox));

                int left = boundingBox.Left;
                if (left < 0)
                {
                    left = 0;
                }
                if (left >= segFrameImageGraphic.Columns)
                {
                    left = segFrameImageGraphic.Columns - 1;
                }
                int right = boundingBox.Right;
                if (right < 0)
                {
                    right = 0;
                }
                if (right >= segFrameImageGraphic.Columns)
                {
                    right = segFrameImageGraphic.Columns - 1;
                }
                int top = boundingBox.Top;
                if (top < 0)
                {
                    top = 0;
                }
                if (top >= segFrameImageGraphic.Rows)
                {
                    top = segFrameImageGraphic.Rows - 1;
                }
                int bottom = boundingBox.Bottom;
                if (bottom < 0)
                {
                    bottom = 0;
                }
                if (bottom >= segFrameImageGraphic.Rows)
                {
                    bottom = segFrameImageGraphic.Rows - 1;
                }

                pixelData.ForEachPixel(
                    left,
                    top,
                    right,
                    bottom,
                    delegate(int i, int x, int y, int pixelIndex)
                {
                    if (segFrameImageGraphic[x, y])
                    {
                        ++pixelCount;
                        int storedValue  = pixelData.GetPixel(pixelIndex);
                        double realValue = modalityLut != null ? modalityLut[storedValue] : storedValue;

                        double deviation = realValue - mean;
                        sum += deviation * deviation;
                    }
                });
            }

            if (pixelCount == 0)
            {
                return(0);
            }

            return(Math.Sqrt(sum / pixelCount));
        }
        internal static double CalculateMeanForStack(List <ImageCalculationInfo> imageCalculationInfoStack)
        {
            double sum        = 0;
            int    pixelCount = 0;

            for (int imageCount = 0; imageCount < imageCalculationInfoStack.Count; imageCount++)
            {
                PixelData            pixelData            = imageCalculationInfoStack[imageCount].PixelData;
                SegFrameImageGraphic segFrameImageGraphic = imageCalculationInfoStack[imageCount].SegFrameImageGraphic;
                RectangleF           roiBoundingBox       = imageCalculationInfoStack[imageCount].RoiBoundingBox;
                IModalityLut         modalityLut          = imageCalculationInfoStack[imageCount].ModalityLut;

                Rectangle boundingBox =
                    RectangleUtilities.RoundInflate(RectangleUtilities.ConvertToPositiveRectangle(roiBoundingBox));

                int left = boundingBox.Left;
                if (left < 0)
                {
                    left = 0;
                }
                if (left >= segFrameImageGraphic.Columns)
                {
                    left = segFrameImageGraphic.Columns - 1;
                }
                int right = boundingBox.Right;
                if (right < 0)
                {
                    right = 0;
                }
                if (right >= segFrameImageGraphic.Columns)
                {
                    right = segFrameImageGraphic.Columns - 1;
                }
                int top = boundingBox.Top;
                if (top < 0)
                {
                    top = 0;
                }
                if (top >= segFrameImageGraphic.Rows)
                {
                    top = segFrameImageGraphic.Rows - 1;
                }
                int bottom = boundingBox.Bottom;
                if (bottom < 0)
                {
                    bottom = 0;
                }
                if (bottom >= segFrameImageGraphic.Rows)
                {
                    bottom = segFrameImageGraphic.Rows - 1;
                }

                pixelData.ForEachPixel(
                    left,
                    top,
                    right,
                    bottom,
                    delegate(int i, int x, int y, int pixelIndex)
                {
                    //if (x >= 0 && x < segFrameImageGraphic.Columns && y >= 0 && y < segFrameImageGraphic.Rows)
                    if (segFrameImageGraphic[x, y])
                    {
                        ++pixelCount;
                        // Make sure we run the raw pixel through the modality LUT
                        // when doing the calculation. Note that the modality LUT
                        // can be something other than a rescale intercept, so we can't
                        // just run the mean through the LUT.
                        int storedValue  = pixelData.GetPixel(pixelIndex);
                        double realValue = modalityLut != null ? modalityLut[storedValue] : storedValue;
                        sum += realValue;
                    }
                });
            }

            if (pixelCount == 0)
            {
                return(0);
            }

            return(sum / pixelCount);
        }
        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");
                }
            }
        }
        /// <summary>
        /// Creates a <see cref="SegFrameImageGraphic"/> and adds the graphic to the given <see cref="IPresentationImage"/>
        /// </summary>
        /// <param name="presentationImage">The image to add the graphic to</param>
        /// <param name="rows">Number of rows in the new graphic</param>
        /// <param name="columns">Number of columns in the new graphic</param>
        /// <param name="xLocation">X coordinate of the graphic's origin</param>
        /// <param name="yLocation">Y coordinate of the graphic's origin</param>
        /// <param name="color">Color of the new graphic</param>
        /// <param name="frameIndex">Image frame index</param>
        /// <param name="label">Graphic's label</param>
        /// <param name="description">Graphic's description</param>
        /// <param name="segPixelData">8-bit pixel data of the segmentation overlay</param>
        /// <param name="segmentationDocumentReference">Reference to the Segmentation document this graphic is created for</param>
        /// <returns></returns>
        public static SegFrameImageGraphic AddSegFrameImageGraphicToPresentationImage(
            IPresentationImage presentationImage, int rows, int columns, float xLocation, float yLocation,
            Color color, int frameIndex, string label,
            string description, byte[] segPixelData,
            SegmentationDocumentReference segmentationDocumentReference)
        {
            // TODO VK: use IApplicationGraphicsProvider here!!!
            var overlayGraphicsProvider = presentationImage as IOverlayGraphicsProvider;
            if (overlayGraphicsProvider == null)
                return null;

            var segFrameImageGraphic = new SegFrameImageGraphic(rows, columns, xLocation, yLocation, color,
                                                                frameIndex, -1, label,
                                                                description, segPixelData, segmentationDocumentReference);

            segFrameImageGraphic.Alpha = Seg.DefaultOpacity;

            var sopProvider = presentationImage as IImageSopProvider;

            if (sopProvider != null)
            {
                segFrameImageGraphic.ImageSopInstanceUid = sopProvider.Sop.SopInstanceUid;
                segFrameImageGraphic.ImageFrameNumber = sopProvider.Frame.FrameNumber;
                segFrameImageGraphic.ImageNumber = sopProvider.ImageSop.InstanceNumber;
            }

            overlayGraphicsProvider.OverlayGraphics.Add(segFrameImageGraphic);

            return segFrameImageGraphic;
        }