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); }