private static bool IsSupportedGantryTilt(IList <IFrameReference> frames) { try { using (IPresentationImage firstImage = PresentationImageFactory.Create(frames[0].Frame)) { using (IPresentationImage lastImage = PresentationImageFactory.Create(frames[frames.Count - 1].Frame)) { // neither of these should return null since we already checked for image orientation and position (patient) DicomImagePlane firstImagePlane = DicomImagePlane.FromImage(firstImage); DicomImagePlane lastImagePlane = DicomImagePlane.FromImage(lastImage); Vector3D stackZ = lastImagePlane.PositionPatientTopLeft - firstImagePlane.PositionPatientTopLeft; Vector3D imageX = firstImagePlane.PositionPatientTopRight - firstImagePlane.PositionPatientTopLeft; if (!stackZ.IsOrthogonalTo(imageX, _gantryTiltTolerance)) { // this is a gantry slew (gantry tilt about Y axis) return(false); } } } return(true); } catch (Exception ex) { Platform.Log(LogLevel.Debug, ex, "Unexpected exception encountered while checking for supported gantry tilts"); return(false); } }
protected static IPresentationImage GetImage(ImageKey key) { string filename = string.Format(_testImagePathFormat, key.ToString().ToLower()); try { LocalSopDataSource dataSource = new LocalSopDataSource(filename); ImageSop imageSop = new ImageSop(dataSource); IPresentationImage theOne = null; foreach (IPresentationImage image in PresentationImageFactory.Create(imageSop)) { if (theOne == null) { theOne = image; continue; } image.Dispose(); } imageSop.Dispose(); return(theOne); } catch (Exception ex) { throw new FileNotFoundException("Unable to load requested test image. Please check that the assembly has been built.", filename, ex); } }
public void TestAgentCodeSequence() { var agent1 = new CodeSequenceMacro { CodeMeaning = "Contrastinol", CodeValue = "123", CodingSchemeDesignator = "ABC" }; var agent2 = new CodeSequenceMacro { CodeMeaning = "Bolusinate", CodeValue = "456", CodingSchemeDesignator = "DEF" }; var dataset = TestDataSource.CreateImageSopDataSource(); dataset[DicomTags.ContrastBolusAgent].SetStringValue(@"Contrastinol and Bolusinate"); dataset[DicomTags.ContrastBolusAgentSequence].AddSequenceItem(agent1.DicomSequenceItem); using (var sop = (ImageSop)Sop.Create(dataset)) using (var images = new DisposableList <IPresentationImage>(PresentationImageFactory.Create(sop))) { Assert.AreEqual(@"Contrastinol", _annotationItems[_cbAgent].GetAnnotationText(images[0])); dataset[DicomTags.ContrastBolusAgentSequence].AddSequenceItem(agent2.DicomSequenceItem); Assert.AreEqual(@"Contrastinol\Bolusinate", _annotationItems[_cbAgent].GetAnnotationText(images[0])); agent1.CodeMeaning = string.Empty; Assert.AreEqual(@"123 (ABC)\Bolusinate", _annotationItems[_cbAgent].GetAnnotationText(images[0])); agent2.CodeMeaning = string.Empty; Assert.AreEqual(@"Contrastinol and Bolusinate", _annotationItems[_cbAgent].GetAnnotationText(images[0])); dataset[DicomTags.ContrastBolusAgent].SetNullValue(); Assert.AreEqual(@"123 (ABC)\456 (DEF)", _annotationItems[_cbAgent].GetAnnotationText(images[0])); } }
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); } } }
private static DisposableList <IPresentationImage> CreateImages(DicomFile dicomFile) { using (var dataSource = new LocalSopDataSource(dicomFile)) { using (var sop = new ImageSop(dataSource)) { return(new DisposableList <IPresentationImage>(PresentationImageFactory.Create(sop))); } } }
public void TestNil() { var dataset = TestDataSource.CreateImageSopDataSource(); using (var sop = (ImageSop)Sop.Create(dataset)) using (var images = new DisposableList <IPresentationImage>(PresentationImageFactory.Create(sop))) { Assert.IsEmpty(_annotationItems[_cbAgent].GetAnnotationText(images[0])); } }
public Bitmap GetBitmap(int n) { IPresentationImage presentationImage = PresentationImageFactory.Create(ImageSop.Frames[n]); int width = imageSop.Frames[n].Columns; int height = imageSop.Frames[n].Rows; return(presentationImage.DrawToBitmap(width, height)); }
private void FillPresentationImages() { foreach (MprSliceSop sop in _sliceSet.SliceSops) { foreach (IPresentationImage image in PresentationImageFactory.Create(sop)) { base.PresentationImages.Add(image); } } }
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(); } } }
public void TestAgentDescriptorOnly() { var dataset = TestDataSource.CreateImageSopDataSource(); dataset[DicomTags.ContrastBolusAgent].SetStringValue(@"Contrastinol and Bolusinate"); using (var sop = (ImageSop)Sop.Create(dataset)) using (var images = new DisposableList <IPresentationImage>(PresentationImageFactory.Create(sop))) { Assert.AreEqual(@"Contrastinol and Bolusinate", _annotationItems[_cbAgent].GetAnnotationText(images[0])); } }
private static IPresentationImage CreateResultImage(Bitmap bitmap, ColorMode colorMode, string filePath) { DicomFile file = new DicomFile(); file.DataSet[DicomTags.BitsAllocated].SetInt32(0, 8); file.DataSet[DicomTags.BitsStored].SetInt32(0, 8); file.DataSet[DicomTags.HighBit].SetInt32(0, 7); file.DataSet.RemoveAttribute(DicomTags.WindowCenter); file.DataSet.RemoveAttribute(DicomTags.WindowWidth); file.DataSet[DicomTags.PixelSpacing].SetInt32(0, 0); file.DataSet[DicomTags.RescaleIntercept].SetInt32(0, 0); file.DataSet[DicomTags.RescaleSlope].SetInt32(0, 1); file.DataSet[DicomTags.Rows].SetInt32(0, bitmap.Height); file.DataSet[DicomTags.Columns].SetInt32(0, bitmap.Width); file.DataSet[DicomTags.PixelRepresentation].SetInt32(0, 0); file.DataSet[DicomTags.NumberOfFrames].SetInt32(0, 1); file.DataSet[DicomTags.PhotometricInterpretation].SetStringValue("MONOCHROME2"); file.DataSet[DicomTags.SopClassUid].SetStringValue("1.2.840.10008.5.1.4.1.1.7"); file.DataSet[DicomTags.Modality].SetStringValue("OT"); file.DataSet[DicomTags.TransferSyntaxUid].SetStringValue("1.2.840.10008.1.2"); file.DataSet[DicomTags.StudyId].SetStringValue("1"); file.DataSet[DicomTags.StudyInstanceUid].SetStringValue("1.2.276.0.7230010.3.1.2.2866517296.296.1377417571.2"); file.DataSet[DicomTags.SeriesNumber].SetInt32(0, 1); file.DataSet[DicomTags.SamplesPerPixel].SetInt32(0, 1); file.DataSet[DicomTags.SeriesInstanceUid].SetStringValue(" 1.2.276.0.7230010.3.1.3.2866517296.296.1377417571.3"); file.DataSet[DicomTags.SopInstanceUid].SetStringValue(DicomUid.GenerateUid().UID); file.DataSet[DicomTags.PixelData].Values = null; byte[] pixelData = BitMapUtility.GetBitmap(bitmap, colorMode); file.DataSet[DicomTags.PixelData].Values = pixelData; file.MediaStorageSopClassUid = file.DataSet[DicomTags.SopClassUid]; file.MediaStorageSopInstanceUid = file.DataSet[DicomTags.SopInstanceUid]; string fileName = string.Format("{0}\\{1}", filePath, DateTime.Now.Ticks.ToString()); file.Save(fileName); var dataSource = new LocalSopDataSource(file); Sop dstSop = Sop.Create(dataSource); IPresentationImage presentation = (PresentationImageFactory.Create((ImageSop)dstSop))[0]; if (presentation is IAnnotationLayoutProvider) { foreach (AnnotationBox box in ((IAnnotationLayoutProvider)presentation).AnnotationLayout.AnnotationBoxes) { box.Visible = false; } } return(presentation); }
private static DisplaySet CreateDisplaySet(IEnumerable <ImageSop> sops) { var descriptor = new XDisplaySetDescriptor(CollectionUtils.FirstElement(sops).DataSource); var displaySet = new DisplaySet(descriptor); foreach (var sop in sops) { foreach (var image in PresentationImageFactory.Create(sop)) { if (image is IVoiLutProvider) { ((IVoiLutProvider)image).VoiLutManager.InstallVoiLut(new IdentityVoiLinearLut()); } displaySet.PresentationImages.Add(image); } } return(displaySet); }
private static Bitmap DrawDefaultFrame(Frame f) { var presentationImage = PresentationImageFactory.Create(f); var bitmap = presentationImage.DrawToBitmap(f.Columns, f.Rows); try { var bmp = presentationImage.DrawToBitmap(f.Columns, f.Rows); if (f.Columns == f.Rows) { if (f.Columns < 512) { bmp = ResizeBitmap(bmp, 512, 512); } } return(bmp); } catch { return(null); } }
/// <summary> /// Gets the initial VOI LUT for the source frames (base or overlay). This is NOT the LUT used on the fusion image! See <see cref="InstallVoiLut"/>. /// </summary> private static IVoiLut GetInitialVoiLut(Frame frame) { if (frame != null) { using (var image = PresentationImageFactory.Create(frame)) { var voiLut = InitialVoiLutProvider.Instance.GetLut(image); if (voiLut == null && image is IImageGraphicProvider) { var pixelData = ((IImageGraphicProvider)image).ImageGraphic.PixelData; if (pixelData is GrayscalePixelData) { voiLut = new MinMaxPixelCalculatedLinearLut((GrayscalePixelData)pixelData); } } return(voiLut); } } return(null); }
public DicomElement(string filePath) { this.FilePath = filePath; DicomFile = new DicomFile(filePath); DicomFile.Load(); ImageSop = new ClearCanvas.ImageViewer.StudyManagement.LocalImageSop(filePath); PresentationImage = PresentationImageFactory.Create(ImageSop.Frames[1]); int width = ImageSop.Frames[1].Columns; int height = ImageSop.Frames[1].Rows; this.Bitmap = PresentationImage.DrawToBitmap(width, height); if (DicomFile.DataSet[DicomTags.InstanceNumber] == null) { throw new Exception("Tag 'Instance Number' not found!"); } this.InstanceNumber = DicomFile.DataSet[DicomTags.InstanceNumber].GetInt32(0, 1); }
private static Bitmap DrawLutFrame(Frame f, double ww, double wc) { IPresentationImage pres = PresentationImageFactory.Create(f); IVoiLutProvider provider = ((IVoiLutProvider)pres); IVoiLutManager manager = provider.VoiLutManager; var linearLut = manager.VoiLut as IVoiLutLinear; if (linearLut != null) { var standardLut = linearLut as IBasicVoiLutLinear; if (standardLut == null) { var installLut = new BasicVoiLutLinear(ww, wc); manager.InstallVoiLut(installLut); } else { standardLut.WindowWidth = ww; standardLut.WindowCenter = wc; } provider.Draw(); } try { var bmp = pres.DrawToBitmap(f.Columns, f.Rows); if (f.Columns == f.Rows) { if (f.Columns < 512) { bmp = ResizeBitmap(bmp, 512, 512); } } return(bmp); } catch { return(null); } }
public void TestEnhancedAgentCodeSequence() { var agent1 = new CodeSequenceMacro { CodeMeaning = "Contrastinol", CodeValue = "123", CodingSchemeDesignator = "ABC" }; var agent2 = new CodeSequenceMacro { CodeMeaning = "Bolusinate", CodeValue = "456", CodingSchemeDesignator = "DEF" }; var agent3 = new CodeSequenceMacro { CodeMeaning = "Dilithium", CodeValue = "789", CodingSchemeDesignator = "GHI" }; var usageFrame1 = new ContrastBolusUsageFunctionalGroup { ContrastBolusUsageSequence = new[] { new ContrastBolusUsageSequenceItem { ContrastBolusAgentNumber = 1 }, new ContrastBolusUsageSequenceItem { ContrastBolusAgentNumber = 3 } } }; var usageFrame2 = new ContrastBolusUsageFunctionalGroup { ContrastBolusUsageSequence = new[] { new ContrastBolusUsageSequenceItem { ContrastBolusAgentNumber = 2 } } }; var usageFrame3 = new ContrastBolusUsageFunctionalGroup(new DicomSequenceItem()) { ContrastBolusUsageSequence = new[] { new ContrastBolusUsageSequenceItem { ContrastBolusAgentNumber = 999 }, new ContrastBolusUsageSequenceItem { ContrastBolusAgentNumber = 2 } } }; var usageFrame4 = new ContrastBolusUsageFunctionalGroup(new DicomSequenceItem()); var dataset = TestDataSource.CreateImageSopDataSource(4); dataset[DicomTags.ContrastBolusAgent].SetStringValue(@"Contrastinol and Bolusinate"); dataset[DicomTags.ContrastBolusAgentSequence].AddSequenceItem(agent1.DicomSequenceItem); dataset[DicomTags.ContrastBolusAgentSequence].AddSequenceItem(agent2.DicomSequenceItem); dataset[DicomTags.ContrastBolusAgentSequence].AddSequenceItem(agent3.DicomSequenceItem); dataset[DicomTags.PerFrameFunctionalGroupsSequence].AddSequenceItem(usageFrame1.DicomSequenceItem); dataset[DicomTags.PerFrameFunctionalGroupsSequence].AddSequenceItem(usageFrame2.DicomSequenceItem); dataset[DicomTags.PerFrameFunctionalGroupsSequence].AddSequenceItem(usageFrame3.DicomSequenceItem); dataset[DicomTags.PerFrameFunctionalGroupsSequence].AddSequenceItem(usageFrame4.DicomSequenceItem); agent1.DicomSequenceItem[DicomTags.ContrastBolusAgentNumber].SetInt32(0, 1); agent2.DicomSequenceItem[DicomTags.ContrastBolusAgentNumber].SetInt32(0, 2); agent3.DicomSequenceItem[DicomTags.ContrastBolusAgentNumber].SetInt32(0, 3); using (var sop = (ImageSop)Sop.Create(dataset)) using (var images = new DisposableList <IPresentationImage>(PresentationImageFactory.Create(sop))) { Assert.AreEqual(@"Contrastinol\Dilithium", _annotationItems[_cbAgent].GetAnnotationText(images[0]), "Frame 1"); Assert.AreEqual(@"Bolusinate", _annotationItems[_cbAgent].GetAnnotationText(images[1]), "Frame 2"); Assert.AreEqual(@"Bolusinate", _annotationItems[_cbAgent].GetAnnotationText(images[2]), "Frame 3"); Assert.IsEmpty(_annotationItems[_cbAgent].GetAnnotationText(images[3]), "Frame 4"); agent1.CodeMeaning = string.Empty; agent2.CodeMeaning = string.Empty; Assert.AreEqual(@"123 (ABC)\Dilithium", _annotationItems[_cbAgent].GetAnnotationText(images[0]), "Frame 1"); Assert.AreEqual(@"456 (DEF)", _annotationItems[_cbAgent].GetAnnotationText(images[1]), "Frame 2"); Assert.AreEqual(@"456 (DEF)", _annotationItems[_cbAgent].GetAnnotationText(images[2]), "Frame 3"); Assert.IsEmpty(_annotationItems[_cbAgent].GetAnnotationText(images[3]), "Frame 4"); agent3.CodeMeaning = string.Empty; Assert.AreEqual(@"123 (ABC)\789 (GHI)", _annotationItems[_cbAgent].GetAnnotationText(images[0])); Assert.AreEqual(@"456 (DEF)", _annotationItems[_cbAgent].GetAnnotationText(images[1]), "Frame 2"); Assert.AreEqual(@"456 (DEF)", _annotationItems[_cbAgent].GetAnnotationText(images[2]), "Frame 3"); Assert.IsEmpty(_annotationItems[_cbAgent].GetAnnotationText(images[3]), "Frame 4"); } }
public IPresentationImage CreateSecondaryCapture(IPresentationImage image) { var imageSopProvider = image as IImageSopProvider; if (imageSopProvider == null) { const string msg = "image must implement IImageSopProvider"; throw new ArgumentException(msg, "image"); } SeriesInfo seriesInfo; var seriesKey = MakeSeriesKey(imageSopProvider.Frame.StudyInstanceUid, imageSopProvider.Sop.Modality); if (!_seriesInfo.TryGetValue(seriesKey, out seriesInfo)) { _seriesInfo[seriesKey] = seriesInfo = new SeriesInfo(_nextSeriesNumberDelegate.Invoke(imageSopProvider.Frame.StudyInstanceUid)); } var dcf = CreatePrototypeFile(imageSopProvider.Sop.DataSource); FillGeneralSeriesModule(dcf.DataSet, imageSopProvider.Frame, seriesInfo); FillScEquipmentModule(dcf.DataSet, Manufacturer, ManufacturersModelName, SoftwareVersions); FillFrameOfReferenceModule(dcf.DataSet, imageSopProvider.Frame); FillGeneralImageModule(dcf.DataSet, imageSopProvider.Frame, seriesInfo); FillScImageModule(dcf.DataSet, imageSopProvider.Frame); FillImagePlaneModule(dcf.DataSet, imageSopProvider.Frame); FillSopCommonModule(dcf.DataSet, SopClass.SecondaryCaptureImageStorageUid); FillAuxiliaryImageData(dcf.DataSet, imageSopProvider.Frame); if (image is GrayscalePresentationImage) { FillModalityLutModule(dcf.DataSet, imageSopProvider.Frame); FillVoiLutModule(dcf.DataSet, imageSopProvider.Frame); // create image pixel last - this method may need to override some attributes set previously CreateImagePixelModuleGrayscale(dcf.DataSet, imageSopProvider.Frame); } else if (image is ColorPresentationImage) { // create image pixel last - this method may need to override some attributes set previously CreateImagePixelModuleColor(dcf.DataSet, imageSopProvider.Frame); } else { // create image pixel last - this method may need to override some attributes set previously CreateImagePixelModuleRasterRgb(dcf.DataSet, image); } dcf.MediaStorageSopClassUid = dcf.DataSet[DicomTags.SopClassUid].ToString(); dcf.MediaStorageSopInstanceUid = dcf.DataSet[DicomTags.SopInstanceUid].ToString(); _files.Add(dcf); using (var sop = new ImageSop(new LocalSopDataSource(dcf))) { var secondaryCapture = PresentationImageFactory.Create(sop).Single(); try { var presentationState = DicomSoftcopyPresentationState.IsSupported(image) ? DicomSoftcopyPresentationState.Create(image) : null; if (presentationState != null) { presentationState.DeserializeOptions |= DicomSoftcopyPresentationStateDeserializeOptions.IgnoreImageRelationship; presentationState.Deserialize(secondaryCapture); // override the spatial transform of the secondary capture because the presentation state doesn't save exact parameters var sourceTransform = image as ISpatialTransformProvider; var targetTransform = secondaryCapture as ISpatialTransformProvider; if (sourceTransform != null && targetTransform != null) { targetTransform.SpatialTransform.CenterOfRotationXY = sourceTransform.SpatialTransform.CenterOfRotationXY; targetTransform.SpatialTransform.FlipX = sourceTransform.SpatialTransform.FlipX; targetTransform.SpatialTransform.FlipY = sourceTransform.SpatialTransform.FlipY; targetTransform.SpatialTransform.RotationXY = sourceTransform.SpatialTransform.RotationXY; targetTransform.SpatialTransform.Scale = sourceTransform.SpatialTransform.Scale; targetTransform.SpatialTransform.TranslationX = sourceTransform.SpatialTransform.TranslationX; targetTransform.SpatialTransform.TranslationY = sourceTransform.SpatialTransform.TranslationY; var sourceImageTransform = sourceTransform as IImageSpatialTransform; var targetImageTransform = targetTransform as IImageSpatialTransform; if (sourceImageTransform != null && targetImageTransform != null) { targetImageTransform.ScaleToFit = sourceImageTransform.ScaleToFit; } } } // force a render to update the client rectangle and scaling of the image secondaryCapture.RenderImage(image.ClientRectangle).Dispose(); } catch (Exception ex) { Platform.Log(LogLevel.Warn, ex, "An error has occurred while deserializing the image presentation state."); } return(secondaryCapture); } }
/// <summary> /// Reference implementation of the image fusion operator. /// </summary> private static IPresentationImage Fuse(IPresentationImage baseImage, IPresentationImage overlayImage, IColorMap colorMap, float opacity, bool thresholding) { Platform.CheckTrue(baseImage is IImageSopProvider, "baseImage must be a IImageSopProvider."); Platform.CheckTrue(overlayImage is IImageSopProvider, "overlayImage must be a IImageSopProvider."); Platform.CheckTrue(baseImage is IImageGraphicProvider, "baseImage must be a IImageGraphicProvider."); Platform.CheckTrue(overlayImage is IImageGraphicProvider, "overlayImage must be a IImageGraphicProvider."); var baseImageSopProvider = (IImageSopProvider)baseImage; var baseImageGraphicProvider = (IImageGraphicProvider)baseImage; var overlayImageSopProvider = (IImageSopProvider)overlayImage; var overlayImageGraphicProvider = (IImageGraphicProvider)overlayImage; var rows = baseImageSopProvider.Frame.Rows; var cols = baseImageSopProvider.Frame.Columns; var pixelData = new byte[3 * rows * cols]; colorMap.MinInputValue = ushort.MinValue; colorMap.MaxInputValue = ushort.MaxValue; // this here is the magic baseImageGraphicProvider.ImageGraphic.PixelData.ForEachPixel( (n, x, y, i) => { // and this is why the base and overlay slices must be unsigned precisely coincident var patientLocation = baseImageSopProvider.Frame.ImagePlaneHelper.ConvertToPatient(new PointF(x, y)); var overlayCoordinate = overlayImageSopProvider.Frame.ImagePlaneHelper.ConvertToImagePlane(patientLocation); var baseValue = (ushort)baseImageGraphicProvider.ImageGraphic.PixelData.GetPixel(i); var overlayValue = overlayImageGraphicProvider.ImageGraphic.PixelData.GetPixel((int)overlayCoordinate.X, (int)overlayCoordinate.Y); // the fusion operator: output = underlyingGrey*(1-alpha) + overlayingColour*(alpha) (see DICOM 2009 PS 3.4 N.2.4.3) var compositeColor = ToRgbVectorFromGrey(baseValue) * (1 - opacity) + ToRgbVector(colorMap[overlayValue]) * opacity; pixelData[3 * n] = (byte)compositeColor.X; pixelData[3 * n + 1] = (byte)compositeColor.Y; pixelData[3 * n + 2] = (byte)compositeColor.Z; }); var dicomFile = new DicomFile(); var dataset = dicomFile.DataSet; dataset[DicomTags.PatientId].SetStringValue(baseImageSopProvider.ImageSop.PatientId); dataset[DicomTags.PatientsName].SetStringValue(baseImageSopProvider.ImageSop.PatientsName); dataset[DicomTags.StudyId].SetStringValue(baseImageSopProvider.ImageSop.StudyId); dataset[DicomTags.StudyInstanceUid].SetStringValue(baseImageSopProvider.ImageSop.StudyInstanceUid); dataset[DicomTags.SeriesDescription].SetStringValue(baseImageSopProvider.ImageSop.SeriesDescription); dataset[DicomTags.SeriesNumber].SetInt32(0, 9001); dataset[DicomTags.SeriesInstanceUid].SetStringValue(DicomUid.GenerateUid().UID); dataset[DicomTags.SopInstanceUid].SetStringValue(DicomUid.GenerateUid().UID); dataset[DicomTags.SopClassUid].SetStringValue(ModalityConverter.ToSopClassUid(Modality.SC)); dataset[DicomTags.Modality].SetStringValue("SC"); dataset[DicomTags.FrameOfReferenceUid].SetStringValue(baseImageSopProvider.Frame.FrameOfReferenceUid); dataset[DicomTags.ImageOrientationPatient].SetStringValue(baseImageSopProvider.Frame.ImageOrientationPatient.ToString()); dataset[DicomTags.ImagePositionPatient].SetStringValue(baseImageSopProvider.Frame.ImagePositionPatient.ToString()); dataset[DicomTags.PixelSpacing].SetStringValue(baseImageSopProvider.Frame.PixelSpacing.ToString()); dataset[DicomTags.PhotometricInterpretation].SetStringValue("RGB"); dataset[DicomTags.SamplesPerPixel].SetInt32(0, 3); dataset[DicomTags.BitsStored].SetInt32(0, 8); dataset[DicomTags.BitsAllocated].SetInt32(0, 8); dataset[DicomTags.HighBit].SetInt32(0, 7); dataset[DicomTags.PixelRepresentation].SetInt32(0, 0); dataset[DicomTags.Rows].SetInt32(0, rows); dataset[DicomTags.Columns].SetInt32(0, cols); dataset[DicomTags.PixelData].Values = pixelData; dicomFile.MediaStorageSopClassUid = dataset[DicomTags.SopClassUid]; dicomFile.MediaStorageSopInstanceUid = dataset[DicomTags.SopInstanceUid]; using (var sopDataSource = new XSopDataSource(dicomFile)) { return(PresentationImageFactory.Create(new ImageSop(sopDataSource))[0]); } }