private static IEnumerable <ISopDataSource> CreateSopSeries(int sopCount, string patientId, string patientName, string studyId, string studyInstanceUid, string seriesDesc, int seriesNumber, string seriesInstanceUid, string frameOfReferenceUid, Modality modality, bool attnCorrected, bool lossyCompressed) { for (int n = 0; n < sopCount; n++) { var dicomFile = new DicomFile(); var dataset = dicomFile.DataSet; dataset[DicomTags.PatientId].SetStringValue(patientId); dataset[DicomTags.PatientsName].SetStringValue(patientName); dataset[DicomTags.StudyId].SetStringValue(studyId); dataset[DicomTags.StudyInstanceUid].SetStringValue(studyInstanceUid); dataset[DicomTags.SeriesDescription].SetStringValue(seriesDesc); dataset[DicomTags.SeriesNumber].SetInt32(0, seriesNumber); dataset[DicomTags.SeriesInstanceUid].SetStringValue(seriesInstanceUid); dataset[DicomTags.SopInstanceUid].SetStringValue(DicomUid.GenerateUid().UID); dataset[DicomTags.SopClassUid].SetStringValue(ModalityConverter.ToSopClassUid(modality)); dataset[DicomTags.Modality].SetStringValue(modality.ToString()); dataset[DicomTags.LossyImageCompression].SetStringValue(lossyCompressed ? "01" : "00"); dataset[DicomTags.LossyImageCompressionRatio].SetFloat32(0, lossyCompressed ? 9999 : 1); dataset[DicomTags.LossyImageCompressionMethod].SetStringValue(lossyCompressed ? "IDUNNO" : string.Empty); dataset[DicomTags.CorrectedImage].SetStringValue(attnCorrected ? "ATTN" : string.Empty); dataset[DicomTags.FrameOfReferenceUid].SetStringValue(frameOfReferenceUid); dataset[DicomTags.ImageOrientationPatient].SetStringValue(string.Format(@"{0}\{1}\{2}\{3}\{4}\{5}", 1, 0, 0, 0, 1, 0)); dataset[DicomTags.ImagePositionPatient].SetStringValue(string.Format(@"{0}\{1}\{2}", 0, 0, n)); dataset[DicomTags.PixelSpacing].SetStringValue(string.Format(@"{0}\{1}", 0.5, 0.5)); dataset[DicomTags.PhotometricInterpretation].SetStringValue("MONOCHROME2"); dataset[DicomTags.SamplesPerPixel].SetInt32(0, 1); dataset[DicomTags.BitsStored].SetInt32(0, 16); dataset[DicomTags.BitsAllocated].SetInt32(0, 16); dataset[DicomTags.HighBit].SetInt32(0, 15); dataset[DicomTags.PixelRepresentation].SetInt32(0, 1); dataset[DicomTags.Rows].SetInt32(0, 100); dataset[DicomTags.Columns].SetInt32(0, 100); dataset[DicomTags.WindowCenter].SetInt32(0, 0); dataset[DicomTags.WindowWidth].SetInt32(0, 65536); dataset[DicomTags.WindowCenterWidthExplanation].SetString(0, "Full Window"); dataset[DicomTags.PixelData].Values = new byte[2 * 100 * 100]; dicomFile.MediaStorageSopClassUid = dataset[DicomTags.SopClassUid]; dicomFile.MediaStorageSopInstanceUid = dataset[DicomTags.SopInstanceUid]; yield return(new XSopDataSource(dicomFile)); } }
/// <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]); } }