public virtual bool RenderImage(System.IO.MemoryStream ms, out int w, out int h, bool bRotate90 = false) { int frame = 0; if (frame != CurrentFrame || _pixelData == null) { Load(Dataset, frame); } var graphic = new ImageGraphic(_pixelData); if (ShowOverlays) { foreach (var overlay in _overlays) { if ((frame + 1) < overlay.OriginFrame || (frame + 1) > (overlay.OriginFrame + overlay.NumberOfFrames - 1)) { continue; } var og = new OverlayGraphic( PixelDataFactory.Create(overlay), overlay.OriginX - 1, overlay.OriginY - 1, OverlayColor); graphic.AddOverlay(og); og.Scale(this._scale); } } return(graphic.RenderImage(this._pipeline.LUT, ms, out w, out h, bRotate90)); }
private static IPixelData CreatePixelData_ <T>( T[] data, ushort bitsAllocated, ushort bitsStored, ushort highBit, ushort pixelRepresentation, Func <T, byte[]> getBytes) { return (PixelDataFactory.Create( DicomPixelData.Create( new DicomDataset { { DicomTag.PhotometricInterpretation, PhotometricInterpretation.Monochrome1.Value }, { DicomTag.BitsAllocated, bitsAllocated }, { DicomTag.BitsStored, bitsStored }, { DicomTag.HighBit, highBit }, { DicomTag.PixelData, data.SelectMany(getBytes).ToArray() }, { DicomTag.PixelRepresentation, pixelRepresentation }, { DicomTag.Columns, (ushort)1 }, { DicomTag.Rows, (ushort)data.Length } }), 0)); }
public override DICOMImage Parse() { // Read the pixel data from the image, frame 0 IPixelData pixelData = PixelDataFactory.Create(image.PixelData, 0); // Get the pixels from the pixel data ushort[] pixels = ((GrayscalePixelDataU16)pixelData).Data; // Get the multiplier int min = image.PixelData.BitDepth.MinimumValue; int max = image.PixelData.BitDepth.MaximumValue; if (min != 0) { throw new FormatException("Error in the minimum value of the pixel data"); } float multiplier = ushort.MaxValue / max; // Apply the multiplier to the pixels for (int i = 0; i < pixels.Length; i++) { pixels[i] = (ushort)(pixels[i] * multiplier); } return(DICOMImage.FromData(image.Width, image.Height, pixels)); }
/// <summary>Renders DICOM image to <see cref="IImage"/>.</summary> /// <param name="frame">Zero indexed frame number</param> /// <returns>Rendered image</returns> public virtual IImage RenderImage(int frame = 0) { if (frame != CurrentFrame || _pixelData == null) { Load(Dataset, frame); } var graphic = new ImageGraphic(_pixelData); if (ShowOverlays) { foreach (var overlay in _overlays) { if ((frame + 1) < overlay.OriginFrame || (frame + 1) > (overlay.OriginFrame + overlay.NumberOfFrames - 1)) { continue; } var og = new OverlayGraphic( PixelDataFactory.Create(overlay), overlay.OriginX - 1, overlay.OriginY - 1, OverlayColor); graphic.AddOverlay(og); og.Scale(this._scale); } } return(graphic.RenderImage(this._pipeline.LUT)); }
/// <summary>Renders DICOM image to <see cref="IImage"/>.</summary> /// <param name="frame">Zero indexed frame number.</param> /// <returns>Rendered image</returns> public virtual IImage RenderImage(int frame = 0) { IPixelData pixels; lock (_lock) { var load = frame >= 0 && (frame != CurrentFrame || _rerender); CurrentFrame = frame; _rerender = false; if (load) { var frameIndex = GetFrameIndex(frame); pixels = PixelDataFactory.Create(_pixelData, frameIndex).Rescale(_scale); _pixels = pixels; } else { pixels = _pixels; } } if (ShowOverlays) { EstablishGraphicsOverlays(); } IImage image; var graphic = new ImageGraphic(pixels); if (ShowOverlays) { foreach (var overlay in _overlays) { if (overlay.Data is EmptyBuffer)//fixed overlay.data is null, exception thrown { continue; } if (frame + 1 < overlay.OriginFrame || frame + 1 > overlay.OriginFrame + overlay.NumberOfFrames - 1) { continue; } var og = new OverlayGraphic( PixelDataFactory.Create(overlay), overlay.OriginX - 1, overlay.OriginY - 1, OverlayColor); graphic.AddOverlay(og); og.Scale(_scale); } } image = graphic.RenderImage(_pipeline.LUT); return(image); }
public double GetHUValue(double ratioX, double ratioY) { var imagePoint = TransformToImage(ratioX, ratioY); var ipixelData = PixelDataFactory.Create(_originalDicomImage.PixelData, 0); return(ipixelData.GetPixel((int)imagePoint.X, (int)imagePoint.Y)); }
public void Create_YbrFull422PlanarConfigurationOne_ThrowsException() { // Arrange var dicomFile = DicomFile.Open(@"Test Data\GH1049_planar_1.dcm"); // Act Assert.Throws <DicomImagingException>(() => PixelDataFactory.Create(DicomPixelData.Create(dicomFile.Dataset), 0)); }
/// <summary>Renders DICOM image to <see cref="IImage"/>.</summary> /// <param name="frame">Zero indexed frame number.</param> /// <returns>Rendered image</returns> public virtual IImage RenderImage(int frame = 0) { bool load; lock (_lock) { load = frame >= 0 && (frame != CurrentFrame || _rerender); _currentFrame = frame; _rerender = false; } var frameIndex = GetFrameIndex(frame); if (load) { lock (_lock) { _pixels = PixelDataFactory.Create(_pixelData, frameIndex).Rescale(_scale); } } if (ShowOverlays) { EstablishGraphicsOverlays(); } IImage image; lock (_lock) { var graphic = new ImageGraphic(_pixels); if (ShowOverlays) { foreach (var overlay in _overlays) { if (frame + 1 < overlay.OriginFrame || frame + 1 > overlay.OriginFrame + overlay.NumberOfFrames - 1) { continue; } var og = new OverlayGraphic( PixelDataFactory.Create(overlay), overlay.OriginX - 1, overlay.OriginY - 1, OverlayColor); graphic.AddOverlay(og); og.Scale(_scale); } } image = graphic.RenderImage(_pipeline.LUT); } return(image); }
public ImageSource RenderImageSource() { ImageGraphic graphic = new ImageGraphic(_pixelData); foreach (var overlay in _overlays) { OverlayGraphic og = new OverlayGraphic(PixelDataFactory.Create(overlay), overlay.OriginX, overlay.OriginY, OverlayColor); graphic.AddOverlay(og); } return graphic.RenderImageSource(_pipeline.LUT); }
public ImageData(DicomDataset dataset) { Dataset = dataset .Clone(DicomTransferSyntax.ExplicitVRLittleEndian); // ensure decompressed Geometry = new FrameGeometry(Dataset); PixelData = DicomPixelData.Create(Dataset); Pixels = PixelDataFactory.Create(PixelData, 0); SortingValue = Geometry.DirectionNormal.DotProduct(Geometry.PointTopLeft); }
/// <summary> /// Loads the pixel data for specified frame and set the internal dataset /// /// </summary> /// <param name="dataset">dataset to load pixeldata from</param> /// <param name="frame">The frame number to create pixeldata for</param> private void Load(DicomDataset dataset, int frame) { Dataset = dataset; if (PixelData == null) { PixelData = DicomPixelData.Create(Dataset); PhotometricInterpretation = PixelData.PhotometricInterpretation; } if (Dataset.InternalTransferSyntax.IsEncapsulated) { // decompress single frame from source dataset DicomCodecParams cparams = null; if (Dataset.InternalTransferSyntax == DicomTransferSyntax.JPEGProcess1 || Dataset.InternalTransferSyntax == DicomTransferSyntax.JPEGProcess2_4) { cparams = new DicomJpegParams { ConvertColorspaceToRGB = true }; } var transcoder = new DicomTranscoder(Dataset.InternalTransferSyntax, DicomTransferSyntax.ExplicitVRLittleEndian); transcoder.InputCodecParams = cparams; transcoder.OutputCodecParams = cparams; var buffer = transcoder.DecodeFrame(Dataset, frame); // clone the dataset because modifying the pixel data modifies the dataset var clone = Dataset.Clone(); clone.InternalTransferSyntax = DicomTransferSyntax.ExplicitVRLittleEndian; var pixelData = DicomPixelData.Create(clone, true); pixelData.AddFrame(buffer); // temporary fix for JPEG compressed YBR images if ((Dataset.InternalTransferSyntax == DicomTransferSyntax.JPEGProcess1 || Dataset.InternalTransferSyntax == DicomTransferSyntax.JPEGProcess2_4) && pixelData.SamplesPerPixel == 3) { pixelData.PhotometricInterpretation = PhotometricInterpretation.Rgb; } _pixelData = PixelDataFactory.Create(pixelData, 0); } else { // pull uncompressed frame from source pixel data _pixelData = PixelDataFactory.Create(PixelData, frame); } _pixelData.Rescale(_scale); _overlays = DicomOverlayData.FromDataset(Dataset).Where(x => x.Type == DicomOverlayType.Graphics && x.Data != null).ToArray(); _currentFrame = frame; CreatePipeline(); }
private void Load(DcmDataset dataset) { Dataset = dataset; if (Dataset.InternalTransferSyntax.IsEncapsulated) Dataset.ChangeTransferSyntax(DicomTransferSyntax.ExplicitVRLittleEndian, null); DcmPixelData pixelData = new DcmPixelData(Dataset); _pixelData = PixelDataFactory.Create(pixelData, 0); _pipeline = PipelineFactory.Create(Dataset, pixelData); pixelData.Unload(); _overlays = DcmOverlayData.FromDataset(Dataset); }
public void Create_YbrFull422PlanarConfigurationZero_ReturnsPixelData() { // Arrange var dicomFile = DicomFile.Open(@"Test Data\GH1049_planar_0.dcm"); // Act var pixelData = PixelDataFactory.Create(DicomPixelData.Create(dicomFile.Dataset), 0); // Assert Assert.NotNull(pixelData); }
/// <summary> /// /// </summary> /// <param name="image"></param> /// <returns></returns> private static int[] GetIntPixels(DicomImage image) { var gro = GrayscaleRenderOptions.FromDataset(image.Dataset); var voilut = VOILUT.Create(gro); var ipd = PixelDataFactory.Create(image.PixelData, 0); int[] outPixelsInt = new int[image.Width * image.Height]; ipd.Render(voilut, outPixelsInt); return(outPixelsInt); }
public ImageData(string filename) { Dataset = DicomFile .Open(filename) // open file .Clone(DicomTransferSyntax.ExplicitVRLittleEndian) // ensure decompressed .Dataset; // the dataset of the decompressed file Geometry = new FrameGeometry(Dataset); PixelData = DicomPixelData.Create(Dataset); Pixels = PixelDataFactory.Create(PixelData, 0); SortingValue = Geometry.DirectionNormal.DotProduct(Geometry.PointTopLeft); }
/// <summary>Renders DICOM image to System.Drawing.Image</summary> /// <returns>Rendered image</returns> #if !SILVERLIGHT public Image RenderImage(Double resize = 0) { ImageGraphic graphic = new ImageGraphic(_pixelData, resize); foreach (var overlay in _overlays) { OverlayGraphic og = new OverlayGraphic(PixelDataFactory.Create(overlay), overlay.OriginX, overlay.OriginY, OverlayColor); graphic.AddOverlay(og); } return(graphic.RenderImage(_pipeline.LUT)); }
private static int[] GetGrayPixelData(DicomDataset dataset) { DicomPixelData pixelData = DicomPixelData.Create(dataset); IByteBuffer buffer = pixelData.GetFrame(0); IPixelData data = PixelDataFactory.Create(pixelData, 0); var renderOptions = GrayscaleRenderOptions.FromDataset(dataset); int[] output = new int[pixelData.Width * pixelData.Height]; data.Render(new ModalityLUT(renderOptions), output); return(output); }
/// <summary> /// Loads the pixel data for specified frame and set the internal dataset /// /// </summary> /// <param name="dataset">dataset to load pixeldata from</param> /// <param name="frame">The frame number to create pixeldata for</param> private void Load(DicomDataset dataset, int frame) { Dataset = DicomTranscoder.ExtractOverlays(dataset); if (PixelData == null) { PixelData = DicomPixelData.Create(Dataset); PhotometricInterpretation = PixelData.PhotometricInterpretation; } if (frame < 0) { CurrentFrame = frame; return; } if (Dataset.InternalTransferSyntax.IsEncapsulated) { // decompress single frame from source dataset var transcoder = new DicomTranscoder( this.Dataset.InternalTransferSyntax, DicomTransferSyntax.ExplicitVRLittleEndian); var buffer = transcoder.DecodeFrame(Dataset, frame); // clone the dataset because modifying the pixel data modifies the dataset var clone = Dataset.Clone(); clone.InternalTransferSyntax = DicomTransferSyntax.ExplicitVRLittleEndian; var pixelData = DicomPixelData.Create(clone, true); TrimDecodedPixelDataProperties(pixelData, Dataset.InternalTransferSyntax); pixelData.AddFrame(buffer); _pixelData = PixelDataFactory.Create(pixelData, 0); } else { // pull uncompressed frame from source pixel data _pixelData = PixelDataFactory.Create(PixelData, frame); } _pixelData = _pixelData.Rescale(_scale); _overlays = DicomOverlayData.FromDataset(Dataset) .Where(x => x.Type == DicomOverlayType.Graphics && x.Data != null) .ToArray(); CurrentFrame = frame; if (_pipeline == null) { CreatePipeline(); } }
/// <summary> /// Create <see cref="GrayscaleRenderOptions"/> from <paramref name="dataset"/> and populate the options properties with values: /// Bit Depth /// Rescale Slope /// Rescale Intercept /// Window Width /// Window Center /// </summary> /// <param name="dataset">Dataset to extract <see cref="GrayscaleRenderOptions"/> from</param> /// <returns>New grayscale render options instance</returns> public static GrayscaleRenderOptions FromDataset(DicomDataset dataset) { var bits = BitDepth.FromDataset(dataset); var options = new GrayscaleRenderOptions(bits); options.RescaleSlope = dataset.Get <double>(DicomTag.RescaleSlope, 1.0); options.RescaleIntercept = dataset.Get <double>(DicomTag.RescaleIntercept, 0.0); if (dataset.Contains(DicomTag.WindowWidth) && dataset.Get <double>(DicomTag.WindowWidth) != 0.0) { //If dataset contains WindowWidth and WindowCenter valid attributes used initially for the grayscale options options.WindowWidth = dataset.Get <double>(DicomTag.WindowWidth); options.WindowCenter = dataset.Get <double>(DicomTag.WindowCenter); } else if (dataset.Contains(DicomTag.SmallestImagePixelValue) && dataset.Contains(DicomTag.LargestImagePixelValue)) { //If dataset contains valid SmallesImagePixelValue and LargesImagePixelValue attributes, use range to calculage //WindowWidth and WindowCenter int smallValue = dataset.Get <int>(DicomTag.SmallestImagePixelValue, 0); int largeValue = dataset.Get <int>(DicomTag.LargestImagePixelValue, 0); largeValue = (int)((largeValue * options.RescaleSlope) + options.RescaleIntercept); smallValue = (int)((smallValue * options.RescaleSlope) + options.RescaleIntercept); if (smallValue != 0 || largeValue != 0) { options.WindowWidth = Math.Abs(largeValue - smallValue); options.WindowCenter = (largeValue + smallValue) / 2.0; } } else { //If reached here, minimum and maximum pixel values calculated from pixels data to calculate //WindowWidth and WindowCenter int padding = dataset.Get <int>(DicomTag.PixelPaddingValue, 0, bits.MinimumValue); var pixelData = DicomPixelData.Create(dataset); var pixels = PixelDataFactory.Create(pixelData, 0); var range = pixels.GetMinMax(padding); range.Maximum = (int)((range.Maximum * options.RescaleSlope) + options.RescaleIntercept); range.Minimum = (int)((range.Minimum * options.RescaleSlope) + options.RescaleIntercept); options.WindowWidth = Math.Abs(range.Maximum - range.Minimum); options.WindowCenter = (range.Maximum + range.Minimum) / 2.0; } options.VOILUTFunction = dataset.Get <string>(DicomTag.VOILUTFunction, "LINEAR"); options.Monochrome1 = dataset.Get <PhotometricInterpretation>(DicomTag.PhotometricInterpretation) == PhotometricInterpretation.Monochrome1; return(options); }
private void Load(DicomDataset dataset) { Dataset = dataset; if (Dataset.InternalTransferSyntax.IsEncapsulated) { Dataset = Dataset.ChangeTransferSyntax(DicomTransferSyntax.ExplicitVRLittleEndian, null); } DicomPixelData pixelData = DicomPixelData.Create(Dataset); _pixelData = PixelDataFactory.Create(pixelData, 0); _overlays = DicomOverlayData.FromDataset(Dataset); }
private static Scan LoadXA3DImageStorage(DicomFile dicomFile) { logger.LogInformation("Loading XA 3D Image file"); var volume = new ImageSet(); var dataSet = dicomFile.Dataset; var dicomPixelData = DicomPixelData.Create(dataSet); var nrFrames = dicomPixelData.NumberOfFrames; var functionalGroupShared = dataSet.GetSequence(DicomTag.SharedFunctionalGroupsSequence); var frameDataSet = functionalGroupShared.ElementAt(0); for (int i = 0; i < nrFrames; i++) { var pixelData = PixelDataFactory.Create(dicomPixelData, i); ImageData image = CreateImageData(pixelData); if (image == null) { continue; } volume.Slices.Add(image); var pixelMeasures = frameDataSet.GetSequence(DicomTag.PixelMeasuresSequence); var pixelMeasuresDataSet = pixelMeasures.ElementAt(0); GetPixelSpacing(pixelMeasuresDataSet, image); var planeOrientations = frameDataSet.GetSequence(DicomTag.PlaneOrientationSequence); var planeOrientationDataSet = planeOrientations.ElementAt(0); var dicomOrientationPatient = planeOrientationDataSet.GetDicomItem <DicomDecimalString>(DicomTag.ImageOrientationPatient); GetImageOrientationPatient(image, dicomOrientationPatient); var functionalGroupPerFrame = dataSet.GetSequence(DicomTag.PerFrameFunctionalGroupsSequence); var functionalGroupPerFrameDataSet = functionalGroupPerFrame.ElementAt(i); var planePositionSequence = functionalGroupPerFrameDataSet.GetSequence(DicomTag.PlanePositionSequence); var planePositionDataSet = planePositionSequence.ElementAt(0); GetPositionPatient(planePositionDataSet, image); ReadWindowing(image, frameDataSet); ReadPixelTransformation(image, frameDataSet, functionalGroupPerFrameDataSet); } DeriveVolumeFields(volume); var patient = GetPatient(dataSet); return(new Scan { Volume = volume, Patient = patient }); }
/// <summary>Renders DICOM image to System.Drawing.Image</summary> /// <param name="frame">Zero indexed frame number</param> /// <returns>Rendered image</returns> public Image RenderImage(int frame = 0) { if (frame != _currentFrame || _pixelData == null) { Load(Dataset, frame); } ImageGraphic graphic = new ImageGraphic(_pixelData); foreach (var overlay in _overlays) { OverlayGraphic og = new OverlayGraphic(PixelDataFactory.Create(overlay), overlay.OriginX, overlay.OriginY, OverlayColor); graphic.AddOverlay(og); } return(graphic.RenderImage(_pipeline.LUT)); }
public virtual bool RenderImage(string saveToBmp, bool bRotate90 = false) { ImageGraphic graphic = null; try { int frame = 0; if (frame != CurrentFrame || _pixelData == null) { Load(Dataset, frame); } graphic = new ImageGraphic(_pixelData); if (ShowOverlays) { foreach (var overlay in _overlays) { if ((frame + 1) < overlay.OriginFrame || (frame + 1) > (overlay.OriginFrame + overlay.NumberOfFrames - 1)) { continue; } var og = new OverlayGraphic( PixelDataFactory.Create(overlay), overlay.OriginX - 1, overlay.OriginY - 1, OverlayColor); graphic.AddOverlay(og); og.Scale(this._scale); } } //return graphic.RenderImage(this._pipeline.LUT, bRotate90, saveToBmp); return(graphic.RenderFileImage(this._pipeline.LUT, saveToBmp)); } finally { if (graphic != null) { graphic = null; } } //RenderFileImage直接将像素数据输出到文件,无需内存中转以节约内存占用 }
public void Open_BitsAllocated12_NonZeroPixelsInLastQuarter() { var file = DicomFile.Open(TestData.Resolve("GH340.dcm")); // Loop over last quarter of pixels; if one is non-zero test passes. var pixelData = PixelDataFactory.Create(DicomPixelData.Create(file.Dataset), 0); for (var y = 3 * pixelData.Height / 4; y < pixelData.Height; ++y) { for (var x = 0; x < pixelData.Width; ++x) { if (pixelData.GetPixel(x, y) != 0.0) { Assert.True(true); return; } } } Assert.True(false); }
/// <summary>Renders DICOM image to System.Drawing.Image</summary> /// <param name="frame">Zero indexed frame number</param> /// <returns>Rendered image</returns> public Image RenderImage(int frame = 0) { if (frame != _currentFrame || _pixelData == null) { Load(Dataset, frame); } var graphic = new ImageGraphic(_pixelData); try { if (ShowOverlays) { foreach (var overlay in _overlays) { if ((frame + 1) < overlay.OriginFrame || (frame + 1) > (overlay.OriginFrame + overlay.NumberOfFrames - 1)) { continue; } var og = new OverlayGraphic(PixelDataFactory.Create(overlay), overlay.OriginX - 1, overlay.OriginY - 1, OverlayColor); graphic.AddOverlay(og); og.Scale(this._scale); } } var image = graphic.RenderImage(_pipeline.LUT); return(new Bitmap(image)); } finally { if (graphic != null) { graphic.Dispose(); } } }
public void Open_BitsAllocated12_NonZeroPixelsInLastQuarter() { // Add missing mandatory tag. var file = DicomFile.Open(@"Test Data\GH340.dcm"); file.Dataset.Add(DicomTag.PhotometricInterpretation, PhotometricInterpretation.Monochrome2.Value); // Loop over last quarter of pixels; if one is non-zero test passes. var pixelData = PixelDataFactory.Create(new DicomImage(file.Dataset).PixelData, 0); for (var y = 3 * pixelData.Height / 4; y < pixelData.Height; ++y) { for (var x = 0; x < pixelData.Width; ++x) { if (pixelData.GetPixel(x, y) != 0.0) { Assert.True(true); return; } } } Assert.True(false); }
public IPixelData DecodePixelData(DicomDataset dataset, int frame) { var pixelData = DicomPixelData.Create(dataset, false); // is pixel data already uncompressed? if (!dataset.InternalTransferSyntax.IsEncapsulated) { return(PixelDataFactory.Create(pixelData, frame)); } var buffer = pixelData.GetFrame(frame); // clone dataset to prevent changes to source var cloneDataset = dataset.Clone(); var oldPixelData = DicomPixelData.Create(cloneDataset, true); oldPixelData.AddFrame(buffer); var newDataset = Decode(cloneDataset, OutputSyntax, InputCodec, InputCodecParams); var newPixelData = DicomPixelData.Create(newDataset, false); return(PixelDataFactory.Create(newPixelData, 0)); }
/// <summary> /// /// </summary> /// <param name="filePathToDir"></param> /// <returns></returns> public string[] DicomToGraphicalJSONArray(string filePathToDir) { string[] allFilePaths = System.IO.Directory.GetFiles(filePathToDir); // store all of the dicoms as a list of dicom files List <DicomFile> dicoms = new List <DicomFile>(); // the output datastructure for this method string[] jsonStrings = null; // loop though all of the files and open them foreach (string filePath in allFilePaths) { try { dicoms.Add(DicomFile.Open(filePath)); } catch (Exception) { Console.WriteLine("file at \"" + filePath + "\" readable as a dicom file"); } } // set the amount of output files to the amount of Json Strings jsonStrings = new string[dicoms.Count]; // sort the order of all the dicom objects so they work in the correct order dicoms.Sort((d1, d2) => d1.Dataset.GetSingleValue <int>(DicomTag.InstanceNumber).CompareTo(d2.Dataset.GetSingleValue <int>(DicomTag.InstanceNumber))); // loop though all of the dicoms in order now for (int index = 0; index < jsonStrings.Length; index++) { int bytesUsed = -1; if (!dicoms[index].Dataset.TryGetSingleValue(DicomTag.BitsAllocated, out bytesUsed)) { // this is required for all dicom images so if this code has been reached the code is invalid Console.WriteLine("A invalid file was found at index " + index); continue; } Console.WriteLine("Amount of Bytes Required: " + bytesUsed); // get the amount of data DicomFileData dicomFile = null; // get the pixel data out as much as possible DicomPixelData header = DicomPixelData.Create(dicoms[index].Dataset); var pixelData = PixelDataFactory.Create(header, 0); // Build the correct file for this data depending on what is stored in the dicom files if (pixelData is GrayscalePixelDataU16) { dicomFile = new U16DicomFileData(((GrayscalePixelDataU16)pixelData).Data); } else if (pixelData is GrayscalePixelDataS16) { dicomFile = new S16DicomFileData(((GrayscalePixelDataS16)pixelData).Data); } else if (pixelData is GrayscalePixelDataU8) { dicomFile = new U8bitDicomFileData(((GrayscalePixelDataU8)pixelData).Data); } else if (pixelData is GrayscalePixelDataS32) { dicomFile = new S32DicomDataFile(((GrayscalePixelDataS32)pixelData).Data); } else if (pixelData is GrayscalePixelDataU32) { dicomFile = new U32DicomDataFile(((GrayscalePixelDataU32)pixelData).Data); } else if (pixelData is ColorPixelData24) { // note that this one will take some work // 0 == red, 1 == Green, 2 == Blue and so on dicomFile = new RGBColourDicomFileData(((ColorPixelData24)pixelData).Data); } else if (pixelData is SingleBitPixelData) { dicomFile = new RGBColourDicomFileData(((SingleBitPixelData)pixelData).Data); } // get the amount of rows the image data set has out of the dicom file. if (!dicoms[index].Dataset.TryGetSingleValue(DicomTag.Rows, out dicomFile.width)) { if (!dicoms[index].Dataset.TryGetSingleValue(DicomTag.NumberOfVerticalPixels, out dicomFile.width)) { // if the value for rows dosn't exist mark the entry as -1 dicomFile.width = -1; } } // get the amount of coloumns in the image if (!dicoms[index].Dataset.TryGetSingleValue(DicomTag.Columns, out dicomFile.height)) { // try getting this data another way then if (!dicoms[index].Dataset.TryGetSingleValue(DicomTag.NumberOfHorizontalPixels, out dicomFile.height)) { // if the value for rows dosn't exist mark the entry as -1 dicomFile.height = -1; } } float[] temp = new float[2]; // get the amount of coloumns in the image if (!dicoms[index].Dataset.TryGetValues <float>(DicomTag.PixelSpacing, out temp)) { // all these methods will try to do it until one works or this feild will be made invalid if (!dicoms[index].Dataset.TryGetValues <float>(DicomTag.ImagerPixelSpacing, out temp)) { if (!dicoms[index].Dataset.TryGetValues <float>(DicomTag.NominalScannedPixelSpacing, out temp)) { if (!dicoms[index].Dataset.TryGetValues <float>(DicomTag.CompensatorPixelSpacing, out temp)) { if (!dicoms[index].Dataset.TryGetValues <float>(DicomTag.DetectorElementSpacing, out temp)) { if (!dicoms[index].Dataset.TryGetValues <float>(DicomTag.PresentationPixelSpacing, out temp)) { if (!dicoms[index].Dataset.TryGetValues <float>(DicomTag.PrinterPixelSpacing, out temp)) { if (!dicoms[index].Dataset.TryGetValues <float>(DicomTag.ObjectPixelSpacingInCenterOfBeam, out temp)) { // if none of the above methods work mark the objects as invalid temp[0] = -1; temp[1] = -1; // This could be valid in a case were only one row of data was colected } } } } } } } } // TODO this dosn't take into account what will happen if the user only recorded one line of pixels since my work dosn't focus on it // This should always return a value that is has a length of two // This will be the value for each row which should always be the first value found dicomFile.pixelSpacingX = temp[0]; dicomFile.pixelSpacingY = temp[1]; // try to get the thickness of the the slice or else set it to an invalid number if (!dicoms[index].Dataset.TryGetSingleValue(DicomTag.SliceThickness, out dicomFile.sliceThickness)) { dicomFile.sliceThickness = -1; } // try to get how much room is between each slice if (!dicoms[index].Dataset.TryGetSingleValue(DicomTag.SpacingBetweenSlices, out dicomFile.spacingBetweenSlices)) { dicomFile.spacingBetweenSlices = -1; } // get the JSON output as a string and place it to the correct place in the array jsonStrings[index] = Newtonsoft.Json.JsonConvert.SerializeObject(dicomFile); } // return the json strings here return(jsonStrings); }
string WorkerFunc(Tuple <string, Tuple <int, int, int, int>, List <string> > param, BackgroundWorker worker, DoWorkEventArgs e) { List <string> lFailed = new List <string>(); string strPath = param.Item1; Tuple <int, int, int, int> lCrop = param.Item2; List <string> files = param.Item3; bool bCrop = lCrop.Item1 + lCrop.Item2 + lCrop.Item3 + lCrop.Item4 > 0 ? true : false; DicomUIDGenerator uidGen = new DicomUIDGenerator(); List <Tuple <string, string, string, string> > listDCM = new List <Tuple <string, string, string, string> >(); int i = 0, k = 0; // Randomize input list Random rand = new Random(); // For each spot in the array, pick // a random item to swap into that spot. for (k = 0; k < files.Count - 1; k++) { int j = rand.Next(k, files.Count); string temp = files[k]; files[k] = files[j]; files[j] = temp; } DateTime dt = DateTime.Now; int nSuccess = 0; foreach (string strFile in files) { i++; DicomFile file; try { file = DicomFile.Open(strFile); } catch (Exception ex) { // Transmit message back with worker? lFailed.Add(strFile); System.Diagnostics.Debug.WriteLine(ex.ToString()); continue; } string strOriginalPatientID = ""; try { strOriginalPatientID = file.Dataset.GetValue <string>(DicomTag.PatientID, 0); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); } DicomAnonymizer anon = new DicomAnonymizer(); DicomFile fileAnon; try { fileAnon = anon.Anonymize(file); } catch (Exception ex) { // Transmit message back with worker? lFailed.Add(strFile); System.Diagnostics.Debug.WriteLine(ex.ToString()); continue; } DicomTag[] tagsToRemove = { DicomTag.StudyDate, DicomTag.StudyTime, DicomTag.PatientID, DicomTag.StudyID, DicomTag.StudyInstanceUID }; foreach (DicomTag d in tagsToRemove) { try { fileAnon.Dataset.Remove(d); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine("Error removing element: " + ex.ToString()); } } fileAnon.Dataset.Add(DicomTag.StudyInstanceUID, DicomUID.Generate()); fileAnon.Dataset.Add(DicomTag.StudyDate, dt.Year.ToString("0000") + dt.Month.ToString("00") + dt.Day.ToString("00")); fileAnon.Dataset.Add(DicomTag.StudyTime, dt.Hour.ToString("00") + dt.Minute.ToString("00") + dt.Second.ToString("00")); fileAnon.Dataset.Add(DicomTag.PatientID, i.ToString()); fileAnon.Dataset.Add(DicomTag.StudyID, i.ToString()); string strStudyID = fileAnon.Dataset.GetValue <string>(DicomTag.StudyInstanceUID, 0); try { var header = DicomPixelData.Create(fileAnon.Dataset); var pixelData = PixelDataFactory.Create(header, header.NumberOfFrames - 1); int rows = header.Height; int columns = header.Width; Array a; byte[] result; bool b16bit = false; if (pixelData is GrayscalePixelDataU16) { ushort[] pixels = ((GrayscalePixelDataU16)pixelData).Data; a = pixels; b16bit = true; } else if (pixelData is GrayscalePixelDataS16) { short[] pixels = ((GrayscalePixelDataS16)pixelData).Data; a = pixels; b16bit = true; } else if (pixelData is GrayscalePixelDataU32) { uint[] pixels = ((GrayscalePixelDataU32)pixelData).Data; a = pixels; } else if (pixelData is GrayscalePixelDataS32) { int[] pixels = ((GrayscalePixelDataS32)pixelData).Data; a = pixels; } else if (pixelData is GrayscalePixelDataU8) { byte[] pixels = ((GrayscalePixelDataU8)pixelData).Data; a = pixels; } else { throw new Exception("DICOM image format not supported (this program only supports greyscale)."); } // Can't seem to figure out the byte formatting between 16-bit greyscale DCM versus C#'s 16-bit greyscale. //b16bit = false; if (bCrop) { // Top if (lCrop.Item1 > 0) { Array cropped = Array.CreateInstance(a.GetValue(0).GetType(), a.Length - (columns * lCrop.Item1)); Array.Copy(a, columns * lCrop.Item1, cropped, 0, cropped.Length); a = cropped; rows -= lCrop.Item1; } // Right if (lCrop.Item2 > 0) { Array cropped = Array.CreateInstance(a.GetValue(0).GetType(), a.Length - (rows * lCrop.Item2)); for (k = 0; k < rows; k++) { Array.Copy(a, k * columns, cropped, k * (columns - lCrop.Item2), columns - lCrop.Item2); } a = cropped; columns -= lCrop.Item2; } // Bottom if (lCrop.Item3 > 0) { Array cropped = Array.CreateInstance(a.GetValue(0).GetType(), a.Length - (columns * lCrop.Item3)); Array.Copy(a, 0, cropped, 0, cropped.Length); a = cropped; rows -= lCrop.Item3; } // Left if (lCrop.Item4 > 0) { Array cropped = Array.CreateInstance(a.GetValue(0).GetType(), a.Length - (rows * lCrop.Item4)); for (k = 0; k < rows; k++) { Array.Copy(a, k * columns + lCrop.Item4, cropped, k * (columns - lCrop.Item4), columns - lCrop.Item4); } a = cropped; columns -= lCrop.Item4; } // Now we need to copy the Array "a" into a byte array. // But first! Should we make sure that it's actually a 16-bit array? int nBytes = a.Length * System.Runtime.InteropServices.Marshal.SizeOf(a.GetValue(0)); result = new byte[nBytes]; Buffer.BlockCopy(a, 0, result, 0, nBytes); Dicom.IO.Buffer.MemoryByteBuffer buffer = new Dicom.IO.Buffer.MemoryByteBuffer(result); DicomDataset dataset = new DicomDataset(); dataset = fileAnon.Dataset.Clone(); dataset.AddOrUpdate(DicomTag.Rows, (ushort)rows); dataset.AddOrUpdate(DicomTag.Columns, (ushort)columns); DicomPixelData newPixelData = DicomPixelData.Create(dataset, true); newPixelData.BitsStored = header.BitsStored; newPixelData.SamplesPerPixel = header.SamplesPerPixel; newPixelData.HighBit = header.HighBit; newPixelData.PhotometricInterpretation = header.PhotometricInterpretation; newPixelData.PixelRepresentation = header.PixelRepresentation; newPixelData.PlanarConfiguration = header.PlanarConfiguration; newPixelData.Height = (ushort)rows; newPixelData.Width = (ushort)columns; newPixelData.AddFrame(buffer); fileAnon = new DicomFile(dataset); } // Only do this if it's a 16bit file that we want a 16bit png for if (b16bit) { int nBytes = a.Length * System.Runtime.InteropServices.Marshal.SizeOf(a.GetValue(0)); result = new byte[nBytes]; // If we're using a format that's "16bit" but actually less, scale the values? if (header.BitsStored < header.BitsAllocated) { int nShift = header.BitsAllocated - header.BitsStored; int nFlag = (0x1 << header.BitsStored) - 1; for (k = 0; k < a.Length; k++) { a.SetValue((ushort)(((nFlag - ((ushort)a.GetValue(k) & nFlag)) << nShift) & 0xFFFF), k); } } Buffer.BlockCopy(a, 0, result, 0, nBytes); unsafe { fixed(byte *ptr = result) { using (Bitmap img16 = new Bitmap(columns, rows, 4 * ((2 * columns + 3) / 4), System.Drawing.Imaging.PixelFormat.Format16bppGrayScale, new IntPtr(ptr))) { SaveBmp(img16, strPath + "/Anonymised/" + strStudyID + "-16bitGreyscale.tif"); //img16.Save(strPath + "/Anonymised/" + strStudyID + "-16bitGreyscale.png"); } } } } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine("Failed to crop image"); System.Diagnostics.Debug.WriteLine(ex.ToString()); } fileAnon.Save(strPath + "/Anonymised/" + strStudyID + ".dcm"); listDCM.Add(new Tuple <string, string, string, string>(i.ToString(), strStudyID, strFile, strOriginalPatientID)); var img = new DicomImage(strPath + "/Anonymised/" + strStudyID + ".dcm"); // Convert DCM to a 32-bit per pixel (8-bit per each color RGB + 8-bit unused) PNG file try { Dicom.IO.PinnedIntArray px = img.RenderImage().Pixels; int[] pxi = px.Data; byte[] result = new byte[px.ByteSize]; Buffer.BlockCopy(pxi, 0, result, 0, result.Length); unsafe { fixed(byte *ptr = result) { using (Bitmap image = new Bitmap(img.Width, img.Height, img.Width * 4, System.Drawing.Imaging.PixelFormat.Format32bppRgb, new IntPtr(ptr))) { image.Save(strPath + "/Anonymised/" + strStudyID + ".png"); } } } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); } worker.ReportProgress(i * 100 / files.Count); nSuccess++; //Console.WriteLine("Anonymized image " + i + " (of " + nFrames + " frame" + (nFrames == 1 ? "" : "s") + "): " + strFile); } // Create a map file using (System.IO.StreamWriter file = new System.IO.StreamWriter(new FileStream(strPath + "/Anonymised/Map.csv", FileMode.Create, FileAccess.ReadWrite), Encoding.UTF8)) { file.WriteLine("NewPatientID,NewStudyInstanceUID,OriginalFile,OriginalPatientID"); foreach (Tuple <string, string, string, string> line in listDCM) { file.WriteLine(line.Item1 + "," + line.Item2 + "," + line.Item3 + "," + line.Item4); } } string strRet = nSuccess.ToString() + " images successfully anonymised, Map.csv created.\nOutput at:\n" + strPath + "\\Anonymised"; if (lFailed.Count > 0) { strRet += "\nThese files failed to anonymise:"; foreach (string sf in lFailed) { strRet += "\n" + sf; } } return(strRet); }
public string DicomToGraphicalJSON(string filePathToDir) { string[] allFilePaths = System.IO.Directory.GetFiles(filePathToDir); // store all of the dicoms as a list of dicom files List <DicomFile> dicoms = new List <DicomFile>(); // get the amount of data DicomFileData dicomFile = null; ArrayList data = new ArrayList(); // loop though all of the files and open them foreach (string filePath in allFilePaths) { try { dicoms.Add(DicomFile.Open(filePath)); } catch (Exception) { Console.WriteLine("file at \"" + filePath + "\" readable as a dicom file"); } } // sort the order of all the dicom objects so they work in the correct order dicoms.Sort((d1, d2) => d1.Dataset.GetSingleValue <int>(DicomTag.InstanceNumber).CompareTo(d2.Dataset.GetSingleValue <int>(DicomTag.InstanceNumber))); // sort out the intial values based on the first dicom in the list // get the pixel data out as much as possible DicomPixelData header = DicomPixelData.Create(dicoms[0].Dataset); IPixelData pixelData = PixelDataFactory.Create(header, 0); // Build the correct file for this data depending on what is stored in the dicom files if (pixelData is GrayscalePixelDataU16) { data.AddRange(((GrayscalePixelDataU16)pixelData).Data); dicomFile = new U16DicomFileData(); } else if (pixelData is GrayscalePixelDataS16) { data.AddRange(((GrayscalePixelDataS16)pixelData).Data); dicomFile = new S16DicomFileData(); } else if (pixelData is GrayscalePixelDataU8) { data.AddRange(((GrayscalePixelDataU8)pixelData).Data); dicomFile = new U8bitDicomFileData(); } else if (pixelData is GrayscalePixelDataS32) { data.AddRange(((GrayscalePixelDataS32)pixelData).Data); dicomFile = new S32DicomDataFile(); } else if (pixelData is GrayscalePixelDataU32) { data.AddRange(((GrayscalePixelDataU32)pixelData).Data); dicomFile = new U32DicomDataFile(); } else if (pixelData is ColorPixelData24) { // note that this one will take some work // 0 == red, 1 == Green, 2 == Blue and so on data.AddRange(((ColorPixelData24)pixelData).Data); dicomFile = new RGBColourDicomFileData(); } else if (pixelData is SingleBitPixelData) { data.AddRange(((SingleBitPixelData)pixelData).Data); dicomFile = new U8bitDicomFileData(); } // get the amount of rows the image data set has out of the dicom file. if (!dicoms[0].Dataset.TryGetSingleValue(DicomTag.Rows, out dicomFile.width)) { if (!dicoms[0].Dataset.TryGetSingleValue(DicomTag.NumberOfVerticalPixels, out dicomFile.width)) { // if the value for rows dosn't exist mark the entry as -1 dicomFile.width = -1; } } // get the amount of coloumns in the image if (!dicoms[0].Dataset.TryGetSingleValue(DicomTag.Columns, out dicomFile.height)) { // try getting this data another way then if (!dicoms[0].Dataset.TryGetSingleValue(DicomTag.NumberOfHorizontalPixels, out dicomFile.height)) { // if the value for rows dosn't exist mark the entry as -1 dicomFile.height = -1; } } // Datastucture that will hold the final DS float[] aspectOfPixel = new float[2]; // get the amount of coloumns in the image if (!dicoms[0].Dataset.TryGetValues <float>(DicomTag.PixelSpacing, out aspectOfPixel)) { // all these methods will try to do it until one works or this feild will be made invalid if (!dicoms[0].Dataset.TryGetValues <float>(DicomTag.ImagerPixelSpacing, out aspectOfPixel)) { if (!dicoms[0].Dataset.TryGetValues <float>(DicomTag.NominalScannedPixelSpacing, out aspectOfPixel)) { if (!dicoms[0].Dataset.TryGetValues <float>(DicomTag.CompensatorPixelSpacing, out aspectOfPixel)) { if (!dicoms[0].Dataset.TryGetValues <float>(DicomTag.DetectorElementSpacing, out aspectOfPixel)) { if (!dicoms[0].Dataset.TryGetValues <float>(DicomTag.PresentationPixelSpacing, out aspectOfPixel)) { if (!dicoms[0].Dataset.TryGetValues <float>(DicomTag.PrinterPixelSpacing, out aspectOfPixel)) { if (!dicoms[0].Dataset.TryGetValues <float>(DicomTag.ObjectPixelSpacingInCenterOfBeam, out aspectOfPixel)) { // if none of the above methods work mark the objects as invalid aspectOfPixel[0] = -1; aspectOfPixel[1] = -1; // This could be valid in a case were only one row of data was colected } } } } } } } } // TODO this dosn't take into account what will happen if the user only recorded one line of pixels since my work dosn't focus on it // Save the data from pixel spacing dicomFile.pixelSpacingX = aspectOfPixel[0]; dicomFile.pixelSpacingY = aspectOfPixel[1]; // try to get the thickness of the the slice or else set it to an invalid number if (dicoms[0].Dataset.TryGetSingleValue(DicomTag.SliceThickness, out dicomFile.sliceThickness)) { dicomFile.sliceThickness = -1; } // try to get how much room is between each slice if (!dicoms[0].Dataset.TryGetSingleValue(DicomTag.SpacingBetweenSlices, out dicomFile.spacingBetweenSlices)) { dicomFile.spacingBetweenSlices = -1; } dicomFile.breath = dicoms.Count; // loop though all of the dicoms in order now for (int index = 1; index < dicoms.Count; index++) { // get the pixel data out as much as possible header = DicomPixelData.Create(dicoms[index].Dataset); pixelData = PixelDataFactory.Create(header, 0); // Build the correct file for this data depending on what is stored in the dicom files if (pixelData is GrayscalePixelDataU16) { data.AddRange(((GrayscalePixelDataU16)pixelData).Data); } else if (pixelData is GrayscalePixelDataS16) { data.AddRange(((GrayscalePixelDataS16)pixelData).Data); } else if (pixelData is GrayscalePixelDataU8) { data.AddRange(((GrayscalePixelDataU8)pixelData).Data); } else if (pixelData is GrayscalePixelDataS32) { data.AddRange(((GrayscalePixelDataS32)pixelData).Data); } else if (pixelData is GrayscalePixelDataU32) { data.AddRange(((GrayscalePixelDataU32)pixelData).Data); } else if (pixelData is ColorPixelData24) { // note that this one will take some work // 0 == red, 1 == Green, 2 == Blue and so on data.AddRange(((ColorPixelData24)pixelData).Data); } else if (pixelData is SingleBitPixelData) { data.AddRange(((SingleBitPixelData)pixelData).Data); } int tempDicomRows = -1; // get the amount of rows the image data set has out of the dicom file. if (!dicoms[index].Dataset.TryGetSingleValue(DicomTag.Rows, out tempDicomRows)) { if (!dicoms[index].Dataset.TryGetSingleValue(DicomTag.NumberOfVerticalPixels, out tempDicomRows)) { if (dicomFile.height != tempDicomRows) { throw new NonConsistantDicomDirectoryException("The number of rows at index" + index); } } } else if (dicomFile.width != tempDicomRows) { throw new NonConsistantDicomDirectoryException("The number of rows at index" + index); } // get the amount of coloumns in the image and ensure it stays the same int tempDicomCols = -1; if (!dicoms[index].Dataset.TryGetSingleValue(DicomTag.Columns, out tempDicomCols)) { // try getting this data another way then if (dicoms[index].Dataset.TryGetSingleValue(DicomTag.NumberOfHorizontalPixels, out tempDicomCols)) { if (dicomFile.height != tempDicomCols) { throw new NonConsistantDicomDirectoryException("The number of columns at index" + index); } } } else if (dicomFile.height != tempDicomCols) { throw new NonConsistantDicomDirectoryException("The number of columns at index" + index); } // TODO Maybe change how this works going forward aspectOfPixel = new float[2]; // get the amount of coloumns in the image if (!dicoms[index].Dataset.TryGetValues <float>(DicomTag.PixelSpacing, out aspectOfPixel)) { // all these methods will try to do it until one works or this feild will be made invalid if (!dicoms[index].Dataset.TryGetValues <float>(DicomTag.ImagerPixelSpacing, out aspectOfPixel)) { if (!dicoms[index].Dataset.TryGetValues <float>(DicomTag.NominalScannedPixelSpacing, out aspectOfPixel)) { if (!dicoms[index].Dataset.TryGetValues <float>(DicomTag.CompensatorPixelSpacing, out aspectOfPixel)) { if (!dicoms[index].Dataset.TryGetValues <float>(DicomTag.DetectorElementSpacing, out aspectOfPixel)) { if (!dicoms[index].Dataset.TryGetValues <float>(DicomTag.PresentationPixelSpacing, out aspectOfPixel)) { if (!dicoms[index].Dataset.TryGetValues <float>(DicomTag.PrinterPixelSpacing, out aspectOfPixel)) { if (!dicoms[index].Dataset.TryGetValues <float>(DicomTag.ObjectPixelSpacingInCenterOfBeam, out aspectOfPixel)) { // if none of the above methods work mark the objects as invalid aspectOfPixel[0] = -1; aspectOfPixel[1] = -1; // This could be valid in a case were only one row of data was colected } } } } } } } } // check input data against the old data and throw an exception if the file isn't exact if (dicomFile.pixelSpacingX != aspectOfPixel[0] || dicomFile.pixelSpacingY != aspectOfPixel[1]) { throw new NonConsistantDicomDirectoryException("Pixel Spacing Dicom Tag at index " + index); } // check the slice thickness is constisant if (dicoms[index].Dataset.TryGetSingleValue(DicomTag.SliceThickness, out float tempSliceThickness)) { if (dicomFile.sliceThickness == -1) { dicomFile.sliceThickness = tempSliceThickness; } else if (tempSliceThickness != dicomFile.sliceThickness) { throw new NonConsistantDicomDirectoryException("Slice Thickness at index" + index); } } // try to get how much room is between each slice if (!dicoms[index].Dataset.TryGetSingleValue(DicomTag.SpacingBetweenSlices, out float tempSliceSpacing)) { if (dicomFile.spacingBetweenSlices == -1) { dicomFile.spacingBetweenSlices = tempSliceSpacing; } else if (tempSliceThickness != dicomFile.sliceThickness) { throw new NonConsistantDicomDirectoryException("Spacing between slices at index" + index); } } } dicomFile.SetPixelBuffer(data); // return the json strings here return(Newtonsoft.Json.JsonConvert.SerializeObject(dicomFile)); }