protected void SerializeDisplayedArea(DisplayedAreaModuleIod displayedAreaModule, DicomPresentationImageCollection <T> images)
        {
            displayedAreaModule.InitializeAttributes();
            List <DisplayedAreaModuleIod.DisplayedAreaSelectionSequenceItem> displayedAreas = new List <DisplayedAreaModuleIod.DisplayedAreaSelectionSequenceItem>();

            foreach (T image in images)
            {
                DisplayedAreaModuleIod.DisplayedAreaSelectionSequenceItem displayedArea = new DisplayedAreaModuleIod.DisplayedAreaSelectionSequenceItem();
                displayedArea.InitializeAttributes();
                displayedArea.ReferencedImageSequence = new[] { CreateImageSopInstanceReference(image.Frame) };

                ImageGraphic imageGraphic = ((IImageGraphicProvider)image).ImageGraphic;
                Size         imageSize    = new Size(imageGraphic.Columns, imageGraphic.Rows);

                // compute the visible area of the image as a rectangle oriented positively in screen space
                RectangleF visibleImageArea = imageGraphic.SpatialTransform.ConvertToSource(image.ClientRectangle);
                visibleImageArea = RectangleUtilities.ConvertToPositiveRectangle(visibleImageArea);
                visibleImageArea = RectangleUtilities.RoundInflate(visibleImageArea);
                visibleImageArea = RectangleUtilities.Intersect(visibleImageArea, new Rectangle(new Point(0, 0), imageSize));

                // compute the pixel addresses of the visible area by intersecting area with actual pixel addresses available
                Rectangle visiblePixels = ConvertToPixelAddressRectangle(Rectangle.Truncate(visibleImageArea));
                displayedArea.DisplayedAreaTopLeftHandCorner     = visiblePixels.Location;
                displayedArea.DisplayedAreaBottomRightHandCorner = visiblePixels.Location + visiblePixels.Size;

                ISpatialTransform spatialTransform = image.SpatialTransform;
                switch (_displayAreaSerializationOption)
                {
                case DisplayAreaSerializationOption.SerializeAsMagnification:
                    displayedArea.PresentationSizeMode = DisplayedAreaModuleIod.PresentationSizeMode.Magnify;
                    displayedArea.PresentationPixelMagnificationRatio = spatialTransform.Scale;
                    break;

                case DisplayAreaSerializationOption.SerializeAsTrueSize:
                    displayedArea.PresentationSizeMode     = DisplayedAreaModuleIod.PresentationSizeMode.TrueSize;
                    displayedArea.PresentationPixelSpacing = image.Frame.NormalizedPixelSpacing;
                    break;

                case DisplayAreaSerializationOption.SerializeAsDisplayedArea:
                default:
                    displayedArea.PresentationSizeMode = DisplayedAreaModuleIod.PresentationSizeMode.ScaleToFit;
                    break;
                }

                displayedArea.PresentationPixelAspectRatio = PixelAspectRatio.FromString(image.Frame.NormalizedPixelSpacing.GetPixelAspectRatioString());

                displayedAreas.Add(displayedArea);
            }
            displayedAreaModule.DisplayedAreaSelectionSequence = displayedAreas.ToArray();
        }
        protected void DeserializeDisplayedArea(DisplayedAreaModuleIod dispAreaMod, out RectangleF displayedArea, T image)
        {
            ISpatialTransform spatialTransform = image.SpatialTransform;

            foreach (DisplayedAreaModuleIod.DisplayedAreaSelectionSequenceItem item in dispAreaMod.DisplayedAreaSelectionSequence)
            {
                var dictionary = !DeserializeIgnoreImageRelationship ? new ImageSopInstanceReferenceDictionary(item.ReferencedImageSequence, true) : null;
                if (dictionary == null || dictionary.ReferencesFrame(image.Frame.SopInstanceUid, image.Frame.FrameNumber))
                {
                    // get the displayed area of the image in source coordinates (stored values do not have sub-pixel accuracy)
                    var displayRect = RectangleF.FromLTRB(item.DisplayedAreaTopLeftHandCorner.X,
                                                          item.DisplayedAreaTopLeftHandCorner.Y,
                                                          item.DisplayedAreaBottomRightHandCorner.X,
                                                          item.DisplayedAreaBottomRightHandCorner.Y);
                    displayRect          = RectangleUtilities.ConvertToPositiveRectangle(displayRect);
                    displayRect.Location = displayRect.Location - new SizeF(1, 1);
                    displayRect.Size     = displayRect.Size + new SizeF(1, 1);

                    var centerDisplay = true;

                    switch (item.PresentationSizeMode)
                    {
                    case DisplayedAreaModuleIod.PresentationSizeMode.Magnify:
                        // displays selected area at specified magnification factor
                        spatialTransform.Scale = (float)item.PresentationPixelMagnificationRatio.GetValueOrDefault(1);
                        break;

                    case DisplayedAreaModuleIod.PresentationSizeMode.TrueSize:
                    // currently no support for determining true size, so default to scale area to fit
                    case DisplayedAreaModuleIod.PresentationSizeMode.ScaleToFit:
                    case DisplayedAreaModuleIod.PresentationSizeMode.None:
                    default:
                        if (spatialTransform is IImageSpatialTransform && displayRect.Location == new PointF(0, 0) && displayRect.Size == new SizeF(image.ImageGraphic.Columns, image.ImageGraphic.Rows))
                        {
                            // if the display rect is the whole image, then take advantage of the built-in scale image to fit functionality
                            IImageSpatialTransform iist = (IImageSpatialTransform)spatialTransform;
                            iist.ScaleToFit = true;
                            centerDisplay   = false;                                   // when ScaleToFit is true, the image will automatically be positioned correctly in the client area
                        }
                        else
                        {
                            var clientArea  = image.ClientRectangle.Size;
                            var displaySize = displayRect.Size;

                            // if image is rotated 90 or 270, transpose width/height
                            if (Math.Abs(Math.Round(Math.Sin(spatialTransform.RotationXY * Math.PI / 180))) > 0)
                            {
                                displaySize = new SizeF(displaySize.Height, displaySize.Width);
                            }

                            // compute the maximum magnification that allows the entire displayRect to be visible
                            spatialTransform.Scale = Math.Min(clientArea.Width / displaySize.Width, clientArea.Height / displaySize.Height);
                        }

                        break;
                    }

                    if (centerDisplay)
                    {
                        // compute translation so that the displayRect is centered in the clientRect
                        var displayCentre = GetRectangleCenter(displayRect);
                        var clientCentre  = spatialTransform.ConvertToSource(GetRectangleCenter(image.ClientRectangle));
                        spatialTransform.TranslationX = clientCentre.X - displayCentre.X;
                        spatialTransform.TranslationY = clientCentre.Y - displayCentre.Y;
                    }

                    displayedArea = displayRect;
                    return;
                }
            }
            displayedArea = new RectangleF(0, 0, image.ImageGraphic.Columns, image.ImageGraphic.Rows);
        }