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