internal static void Launch(IDesktopWindow desktopWindow, List <IClipboardItem> clipboardItems) { Platform.CheckForNullReference(desktopWindow, "desktopWindow"); Platform.CheckForNullReference(clipboardItems, "clipboardItems"); if (_multipleImageExporter != null) { desktopWindow.ShowMessageBox(SR.MessageImageExportStillRunning, MessageBoxActions.Ok); return; } int numberOfImagesToExport = GetNumberOfImagesToExport(clipboardItems); Platform.CheckPositive(numberOfImagesToExport, "numberOfImagesToExport"); string title = SR.TitleExportImages; if (numberOfImagesToExport == 1) { title = SR.TitleExportSingleImage; } //initialize the component. ImageExportComponent component = new ImageExportComponent(); component.ItemsToExport = clipboardItems; component.NumberOfImagesToExport = numberOfImagesToExport; // give the width and height values from the first image to be exported if (clipboardItems.Count > 0) { object item = clipboardItems[0].Item; if (item is IImageGraphicProvider) { IImageGraphicProvider imageGraphicProvider = (IImageGraphicProvider)item; component.Height = imageGraphicProvider.ImageGraphic.Rows; component.Width = imageGraphicProvider.ImageGraphic.Columns; } else if (item is IDisplaySet) { foreach (IPresentationImage image in ((IDisplaySet)item).PresentationImages) { if (image is IImageGraphicProvider) { IImageGraphicProvider imageGraphicProvider = (IImageGraphicProvider)image; component.Height = imageGraphicProvider.ImageGraphic.Rows; component.Width = imageGraphicProvider.ImageGraphic.Columns; break; } } } } if (ApplicationComponentExitCode.Accepted != LaunchAsDialog(desktopWindow, component, title)) { return; } component.Export(); }
private void AnalyzeInternal() { IPresentationImage presImage = this.ImageViewer.SelectedPresentationImage; IImageGraphicProvider imageGraphicProvider = presImage as IImageGraphicProvider; GrayscaleImageGraphic imageGraphic = imageGraphicProvider.ImageGraphic as GrayscaleImageGraphic; IOverlayGraphicsProvider overlayProvider = presImage as IOverlayGraphicsProvider; CadOverlayGraphic cadOverlay = GetCadOverlayGraphic(overlayProvider); if (cadOverlay == null) { cadOverlay = new CadOverlayGraphic(imageGraphic); overlayProvider.OverlayGraphics.Add(cadOverlay); } MemorableUndoableCommand command = new MemorableUndoableCommand(cadOverlay); command.BeginState = cadOverlay.CreateMemento(); cadOverlay.Threshold = (int)this.Threshold; cadOverlay.Opacity = (int)this.Opacity; cadOverlay.Analyze(); command.EndState = cadOverlay.CreateMemento(); this.ImageViewer.CommandHistory.AddCommand(command); }
/// <summary> /// Constructs a new region of interest, specifying an <see cref="IPresentationImage"/> as the source of the pixel data. /// </summary> /// <param name="presentationImage">The image containing the source pixel data.</param> protected Roi(IPresentationImage presentationImage) { IImageGraphicProvider provider = presentationImage as IImageGraphicProvider; if (provider == null) return; _imageRows = provider.ImageGraphic.Rows; _imageColumns = provider.ImageGraphic.Columns; _presentationImage = presentationImage; _pixelData = provider.ImageGraphic.PixelData; if (presentationImage is IModalityLutProvider) _modalityLut = ((IModalityLutProvider) presentationImage).ModalityLut; if (presentationImage is IImageSopProvider) { Frame frame = ((IImageSopProvider) presentationImage).Frame; _normalizedPixelSpacing = frame.NormalizedPixelSpacing; _pixelAspectRatio = frame.PixelAspectRatio; _modality = frame.ParentImageSop.Modality; _modalityLutUnits = frame.RescaleUnits; _subnormalModalityLut = frame.IsSubnormalRescale; } else { _normalizedPixelSpacing = new PixelSpacing(0, 0); _pixelAspectRatio = new PixelAspectRatio(0, 0); _modalityLutUnits = RescaleUnits.None; _subnormalModalityLut = false; } }
private static void TestVolume(bool signed, VolumeFunction f, IEnumerable <IVolumeSlicerParams> slicerParams, string testName, ImageKernelFunction imageKernel, VolumeKernelFunction volumeKernel) { const int FULL_SCALE = 65535; VolumeFunction normalizedFunction = f.Normalize(100); using (Volume volume = normalizedFunction.CreateVolume(100, signed)) { float offset = signed ? -32768 : 0; foreach (IVolumeSlicerParams slicing in slicerParams) { List <double> list = new List <double>(); using (VolumeSlicer slicer = new VolumeSlicer(volume, slicing, DicomUid.GenerateUid().UID)) { foreach (ISopDataSource slice in slicer.CreateSlices()) { using (ImageSop imageSop = new ImageSop(slice)) { foreach (IPresentationImage image in PresentationImageFactory.Create(imageSop)) { IImageSopProvider imageSopProvider = (IImageSopProvider)image; IImageGraphicProvider imageGraphicProvider = (IImageGraphicProvider)image; DicomImagePlane dip = DicomImagePlane.FromImage(image); for (int y = 1; y < imageSopProvider.Frame.Rows - 1; y++) { for (int x = 1; x < imageSopProvider.Frame.Columns - 1; x++) { // pixels on the extreme sides of the volume tend to have more interpolation error due to MPR padding values Vector3D vector = dip.ConvertToPatient(new PointF(x, y)); // +new Vector3D(-0.5f, -0.5f, 0); if (Between(vector.X, 1, 98) && Between(vector.Y, 1, 98) && Between(vector.Z, 1, 98)) { float expected = volumeKernel.Invoke(normalizedFunction, vector.X, vector.Y, vector.Z) + offset; float actual = imageKernel.Invoke(imageGraphicProvider.ImageGraphic.PixelData, x, y); list.Add(Math.Abs(expected - actual)); } } } image.Dispose(); } } slice.Dispose(); } } Statistics stats = new Statistics(list); Trace.WriteLine(string.Format("Testing {0}", testName)); Trace.WriteLine(string.Format("\tFunction/Slicing: {0} / {1}", normalizedFunction.Name, slicing.Description)); Trace.WriteLine(string.Format("\t Pixel Rep: {0}", signed ? "signed" : "unsigned")); Trace.WriteLine(string.Format("\t Voxels Compared: {0}", list.Count)); Trace.WriteLine(string.Format("\t Mean Delta: {0:f2} ({1:p2} of full scale)", stats.Mean, stats.Mean / FULL_SCALE)); Trace.WriteLine(string.Format("\t StdDev Delta: {0:f2} ({1:p2} of full scale)", stats.StandardDeviation, stats.StandardDeviation / FULL_SCALE)); Assert.Less(stats.Mean, FULL_SCALE * 0.05, "Mean delta exceeds 5% of full scale ({0})", FULL_SCALE); Assert.Less(stats.StandardDeviation, FULL_SCALE * 0.05, "StdDev delta exceeds 5% of full scale ({0})", FULL_SCALE); } } }
protected static void ValidateVolumeSlicePoints(Volumes.Volume volume, IVolumeSlicerParams slicerParams, IList <KnownSample> expectedPoints, double xAxialGantryTilt, double yAxialGantryTilt, bool gantryTiltInDegrees) { if (gantryTiltInDegrees) { xAxialGantryTilt *= Math.PI / 180; yAxialGantryTilt *= Math.PI / 180; } Trace.WriteLine(string.Format("Using slice plane: {0}", slicerParams.Description)); using (VolumeSlicer slicer = new VolumeSlicer(volume, slicerParams)) { foreach (ISopDataSource slice in slicer.CreateSliceSops()) { using (ImageSop imageSop = new ImageSop(slice)) { foreach (IPresentationImage image in PresentationImageFactory.Create(imageSop)) { IImageGraphicProvider imageGraphicProvider = (IImageGraphicProvider)image; DicomImagePlane dip = DicomImagePlane.FromImage(image); foreach (KnownSample sample in expectedPoints) { Vector3D patientPoint = sample.Point; if (xAxialGantryTilt != 0 && yAxialGantryTilt == 0) { float cos = (float)Math.Cos(xAxialGantryTilt); float sin = (float)Math.Sin(xAxialGantryTilt); patientPoint = new Vector3D(patientPoint.X, patientPoint.Y * cos + (xAxialGantryTilt > 0 ? 100 * sin : 0), patientPoint.Z / cos - patientPoint.Y * sin - (xAxialGantryTilt > 0 ? 100 * sin * sin / cos : 0)); } else if (yAxialGantryTilt != 0) { Assert.Fail("Unit test not designed to work with gantry tilts about Y (i.e. slew)"); } Vector3D slicedPoint = dip.ConvertToImagePlane(patientPoint); if (slicedPoint.Z > -0.5 && slicedPoint.Z < 0.5) { int actual = imageGraphicProvider.ImageGraphic.PixelData.GetPixel((int)slicedPoint.X, (int)slicedPoint.Y); Trace.WriteLine(string.Format("Sample {0} @{1} (SLICE: {2}; PATIENT: {3})", actual, FormatVector(sample.Point), FormatVector(slicedPoint), FormatVector(patientPoint))); Assert.AreEqual(sample.Value, actual, "Wrong colour sample @{0}", sample.Point); } } image.Dispose(); } } slice.Dispose(); } } }
internal static void Launch(IDesktopWindow desktopWindow, ClipboardItem clipboardItem) { Platform.CheckForNullReference(clipboardItem, "clipboardItem"); IDisplaySet displaySet = clipboardItem.Item as IDisplaySet; if (displaySet == null) { throw new ArgumentException("The item being exported must be a display set."); } if (_progressComponentShelf != null) { desktopWindow.ShowMessageBox(SR.MessageVideoExportStillRunning, MessageBoxActions.Ok); return; } if (displaySet.PresentationImages.Count <= 1) { desktopWindow.ShowMessageBox(SR.MessageDisplaySetTooFewImagesForVideo, MessageBoxActions.Ok); return; } AviExportComponent component = new AviExportComponent(clipboardItem); component.LoadSettings(); if (component.SelectedCodec == null) { desktopWindow.ShowMessageBox(SR.MessageNoAcceptableCodecsInstalled, MessageBoxActions.Ok); return; } // give the width and height values from the item to be exported foreach (IPresentationImage image in (displaySet.PresentationImages)) { if (image is IImageGraphicProvider) { IImageGraphicProvider imageGraphicProvider = (IImageGraphicProvider)image; component.Height = imageGraphicProvider.ImageGraphic.Rows; component.Width = imageGraphicProvider.ImageGraphic.Columns; break; } } if (ApplicationComponentExitCode.Accepted != LaunchAsDialog(desktopWindow, component, SR.TitleExportToVideo)) { return; } component.Export(); }
private void AddUnsignedSliceToVolume(ushort[] volumeData, IImageGraphicProvider slice, int imageIndex) { byte[] sliceData = slice.ImageGraphic.PixelData.Raw; int start = imageIndex * sliceData.Length / 2; int end = start + sliceData.Length / 2; int j = 0; for (int i = start; i < end; i++) { ushort lowbyte = sliceData[j]; ushort highbyte = sliceData[j + 1]; volumeData[i] = (ushort)((highbyte << 8) | lowbyte); j += 2; } }
private void AddPinwheelGraphic() { IPresentationImage selectedImage = base.SelectedPresentationImage; if (selectedImage == null) { return; } if (!base.IsMprImage(selectedImage)) { return; } MprDisplaySet displaySet = (MprDisplaySet)selectedImage.ParentDisplaySet; if (displaySet.Identifier == MprDisplaySetIdentifier.Oblique) { return; } IOverlayGraphicsProvider overlayProvider = selectedImage as IOverlayGraphicsProvider; IImageGraphicProvider imageGraphicProvider = selectedImage as IImageGraphicProvider; if (overlayProvider != null && imageGraphicProvider != null) { _currentPinwheelGraphic = new PinwheelGraphic(); int width = imageGraphicProvider.ImageGraphic.Columns; int height = imageGraphicProvider.ImageGraphic.Rows; overlayProvider.OverlayGraphics.Add(_currentPinwheelGraphic); _currentPinwheelGraphic.CoordinateSystem = CoordinateSystem.Source; _currentPinwheelGraphic.Rotation = GetRotationAngle(); _currentPinwheelGraphic.Draw(); } }
public static Bitmap DrawToBitmap(IPresentationImage image, ExportImageParams exportParams) { Platform.CheckForNullReference(image, "image"); Platform.CheckForNullReference(exportParams, "exportParams"); if (!(image is ISpatialTransformProvider) || !(image is IImageGraphicProvider)) { throw new ArgumentException("The image must implement IImageGraphicProvider and have a valid ImageSpatialTransform in order to be exported."); } if (exportParams.ExportOption == ExportOption.TrueSize) { var imageSopProvider = image as IImageSopProvider; var pixelSpacing = imageSopProvider == null ? null : imageSopProvider.Frame.NormalizedPixelSpacing; if (pixelSpacing == null || pixelSpacing.IsNull) { throw new ArgumentException("The image does not contain pixel spacing information. TrueSize export is not possible."); } } ImageSpatialTransform transform = ((ISpatialTransformProvider)image).SpatialTransform as ImageSpatialTransform; if (transform == null) { throw new ArgumentException("The image must have a valid ImageSpatialTransform in order to be exported."); } if (exportParams.ExportOption == ExportOption.TrueSize) { return(DrawTrueSizeImageToBitmap(image, exportParams.OutputSize, exportParams.Dpi)); } if (exportParams.SizeMode == SizeMode.Scale) { // TODO: Refactor ImageExporter, so there only the displayRectangle and OutputRectangle are provided // Scale can be automatically figured out. // A "Padded" option can be provided to distinguish between the current Fixed and ScaleToFit options // TODO: Refactor ImageExporter, so there are separate exporters for each ExportOption. // The ExportImageParams is getting too many options and not all of them are applicable to each exporter // Instead, each exporter should have its own parameters. if (exportParams.ExportOption == ExportOption.Wysiwyg) { return(DrawWysiwygImageToBitmap(image, exportParams.DisplayRectangle, exportParams.Scale, exportParams.Dpi)); } else { return(DrawCompleteImageToBitmap(image, exportParams.Scale, exportParams.Dpi)); } } else if (exportParams.SizeMode == SizeMode.ScaleToFit) { if (exportParams.ExportOption == ExportOption.Wysiwyg) { var scale = ScaleToFit(exportParams.DisplayRectangle.Size, exportParams.OutputSize); return(DrawWysiwygImageToBitmap(image, exportParams.DisplayRectangle, scale, exportParams.Dpi)); } else { var sourceImage = (IImageGraphicProvider)image; var scale = ScaleToFit(new Size(sourceImage.ImageGraphic.Columns, sourceImage.ImageGraphic.Rows), exportParams.OutputSize); return(DrawCompleteImageToBitmap(image, scale, exportParams.Dpi)); } } else { Bitmap paddedImage = new Bitmap(exportParams.OutputSize.Width, exportParams.OutputSize.Height); using (System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(paddedImage)) { // paint background using (Brush b = new SolidBrush(exportParams.BackgroundColor)) { graphics.FillRectangle(b, new Rectangle(Point.Empty, exportParams.OutputSize)); } // paint image portion Bitmap bmp; if (exportParams.ExportOption == ExportOption.Wysiwyg) { float scale = ScaleToFit(exportParams.DisplayRectangle.Size, exportParams.OutputSize); bmp = DrawWysiwygImageToBitmap(image, exportParams.DisplayRectangle, scale, exportParams.Dpi); } else { IImageGraphicProvider sourceImage = (IImageGraphicProvider)image; float scale = ScaleToFit(new Size(sourceImage.ImageGraphic.Columns, sourceImage.ImageGraphic.Rows), exportParams.OutputSize); bmp = DrawCompleteImageToBitmap(image, scale, exportParams.Dpi); } graphics.DrawImageUnscaledAndClipped(bmp, new Rectangle(CenterRectangles(bmp.Size, exportParams.OutputSize), bmp.Size)); bmp.Dispose(); } return(paddedImage); } }
public bool ComputeProfile() { IPointsGraphic line = GetSelectedPolyline(); // For now, make sure the ROI is a polyline if (line == null || line.Points.Count != 2) { this.Enabled = false; return(false); } IImageGraphicProvider imageGraphicProvider = line.ParentPresentationImage as IImageGraphicProvider; if (imageGraphicProvider == null) { this.Enabled = false; return(false); } // For now, only allow ROIs of grayscale images GrayscaleImageGraphic image = imageGraphicProvider.ImageGraphic as GrayscaleImageGraphic; if (image == null) { this.Enabled = false; return(false); } line.CoordinateSystem = CoordinateSystem.Source; Point pt1 = new Point((int)line.Points[0].X, (int)line.Points[0].Y); Point pt2 = new Point((int)line.Points[1].X, (int)line.Points[1].Y); if (pt1.X < 0 || pt1.X > image.Columns - 1 || pt2.X < 0 || pt2.X > image.Columns - 1 || pt1.Y < 0 || pt1.Y > image.Rows - 1 || pt2.Y < 0 || pt2.Y > image.Rows - 1) { this.Enabled = false; return(false); } List <Point> pixels = BresenhamLine(pt1, pt2); _pixelIndices = new int[pixels.Count]; _pixelValues = new double[pixels.Count]; int i = 0; foreach (Point pixel in pixels) { int rawPixelValue = image.PixelData.GetPixel(pixel.X, pixel.Y); _pixelIndices[i] = i; _pixelValues[i] = (int)image.ModalityLut[rawPixelValue]; i++; } this.Enabled = true; return(true); }
private void AddSignedSliceToVolume(ushort[] volumeData, IImageGraphicProvider slice, int imageIndex) { byte[] sliceData = slice.ImageGraphic.PixelData.Raw; int start = imageIndex * sliceData.Length / 2; int end = start + sliceData.Length / 2; int j = 0; for (int i = start; i < end; i++) { ushort lowbyte = sliceData[j]; ushort highbyte = sliceData[j + 1]; short val = (short)((highbyte << 8) | lowbyte); volumeData[i] = (ushort)(val - _minimumPixelValue); j += 2; } }