public static GrayscaleRenderOptions FromImagePixelValueTags(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); int smallValue = dataset.Get <int>(DicomTag.SmallestImagePixelValue, 0); int largeValue = dataset.Get <int>(DicomTag.LargestImagePixelValue, 0); if (smallValue != 0 || largeValue != 0) { options.WindowWidth = Math.Abs(largeValue - smallValue); options.WindowCenter = (largeValue + smallValue) / 2.0; } options.VOILUTFunction = dataset.Get <string>(DicomTag.VOILUTFunction, "LINEAR"); options.Monochrome1 = dataset.Get <PhotometricInterpretation>(DicomTag.PhotometricInterpretation) == PhotometricInterpretation.Monochrome1; return(options); }
/// <summary> /// Create grayscale render options based on identified minimum and maximum pixel values. /// </summary> /// <param name="dataset">DICOM dataset from which render options should be obtained.</param> /// <returns>Grayscale render options based on identified minimum and maximum pixel values.</returns> public static GrayscaleRenderOptions FromMinMax(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); int padding = dataset.Get <int>(DicomTag.PixelPaddingValue, 0, Int32.MinValue); var transcoder = new DicomTranscoder( dataset.InternalTransferSyntax, DicomTransferSyntax.ExplicitVRLittleEndian); var pixels = transcoder.DecodePixelData(dataset, 0); var range = pixels.GetMinMax(padding); if (range.Minimum < bits.MinimumValue || range.Minimum == Double.MaxValue) { range.Minimum = bits.MinimumValue; } if (range.Maximum > bits.MaximumValue || range.Maximum == Double.MinValue) { range.Maximum = bits.MaximumValue; } var min = range.Minimum * options.RescaleSlope + options.RescaleIntercept; var max = range.Maximum * options.RescaleSlope + options.RescaleIntercept; options.WindowWidth = Math.Abs(max - min); options.WindowCenter = (max + min) / 2.0; options.VOILUTFunction = dataset.Get <string>(DicomTag.VOILUTFunction, "LINEAR"); options.ColorMap = GetColorMap(dataset); return(options); }
public static GrayscaleRenderOptions FromWindowLevel(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); options.WindowWidth = dataset.Get<double>(DicomTag.WindowWidth); options.WindowCenter = dataset.Get<double>(DicomTag.WindowCenter); options.VOILUTFunction = dataset.Get<string>(DicomTag.VOILUTFunction, "LINEAR"); options.Monochrome1 = dataset.Get<PhotometricInterpretation>(DicomTag.PhotometricInterpretation) == PhotometricInterpretation.Monochrome1; return options; }
public static GrayscaleRenderOptions FromMinMax(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); int padding = dataset.Get<int>(DicomTag.PixelPaddingValue, 0, Int32.MinValue); var transcoder = new DicomTranscoder(dataset.InternalTransferSyntax, DicomTransferSyntax.ExplicitVRLittleEndian); var pixels = transcoder.DecodePixelData(dataset, 0); var range = pixels.GetMinMax(padding); if (range.Minimum < bits.MinimumValue || range.Minimum == Double.MaxValue) range.Minimum = bits.MinimumValue; if (range.Maximum > bits.MaximumValue || range.Maximum == Double.MinValue) range.Maximum = bits.MaximumValue; options.WindowWidth = Math.Abs(range.Maximum - range.Minimum); options.WindowCenter = range.Minimum + (options.WindowWidth / 2.0); options.VOILUTFunction = dataset.Get<string>(DicomTag.VOILUTFunction, "LINEAR"); options.Monochrome1 = dataset.Get<PhotometricInterpretation>(DicomTag.PhotometricInterpretation) == PhotometricInterpretation.Monochrome1; return options; }
public static GrayscaleRenderOptions FromImagePixelValueTags(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); int smallValue = dataset.Get<int>(DicomTag.SmallestImagePixelValue, 0); int largeValue = dataset.Get<int>(DicomTag.LargestImagePixelValue, 0); if (smallValue != 0 || largeValue != 0) { options.WindowWidth = Math.Abs(largeValue - smallValue); options.WindowCenter = (largeValue + smallValue) / 2.0; } options.VOILUTFunction = dataset.Get<string>(DicomTag.VOILUTFunction, "LINEAR"); options.Monochrome1 = dataset.Get<PhotometricInterpretation>(DicomTag.PhotometricInterpretation) == PhotometricInterpretation.Monochrome1; return options; }
public static GrayscaleRenderOptions FromHistogram(DicomDataset dataset, int percent = 90) { 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); var transcoder = new DicomTranscoder(dataset.InternalTransferSyntax, DicomTransferSyntax.ExplicitVRLittleEndian); var pixels = transcoder.DecodePixelData(dataset, 0); var histogram = pixels.GetHistogram(0); int padding = dataset.Get<int>(DicomTag.PixelPaddingValue, 0, Int32.MinValue); if (padding != Int32.MinValue) histogram.Clear(padding); histogram.ApplyWindow(percent); options.WindowWidth = histogram.WindowEnd - histogram.WindowStart; options.WindowCenter = histogram.WindowStart + (options.WindowWidth / 2.0); options.VOILUTFunction = dataset.Get<string>(DicomTag.VOILUTFunction, "LINEAR"); options.Monochrome1 = dataset.Get<PhotometricInterpretation>(DicomTag.PhotometricInterpretation) == PhotometricInterpretation.Monochrome1; return options; }
/// <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 return FromWindowLevel(dataset); } else if (dataset.Contains(DicomTag.SmallestImagePixelValue) && dataset.Contains(DicomTag.LargestImagePixelValue)) { //If dataset contains valid SmallesImagePixelValue and LargesImagePixelValue attributes, use range to calculate //WindowWidth and WindowCenter return FromImagePixelValueTags(dataset); } else { //If reached here, minimum and maximum pixel values calculated from pixels data to calculate //WindowWidth and WindowCenter return FromMinMax(dataset); } options.VOILUTFunction = dataset.Get<string>(DicomTag.VOILUTFunction, "LINEAR"); options.Monochrome1 = dataset.Get<PhotometricInterpretation>(DicomTag.PhotometricInterpretation) == PhotometricInterpretation.Monochrome1; return options; }
/// <summary> /// Create image rendering pipeline according to the Dataset <see cref="PhotometricInterpretation"/>. /// </summary> private void CreatePipeline() { if (_pipeline != null) { return; } var pi = Dataset.Get <PhotometricInterpretation>(DicomTag.PhotometricInterpretation); var samples = Dataset.Get <ushort>(DicomTag.SamplesPerPixel, 0, 0); // temporary fix for JPEG compressed YBR images if ((Dataset.InternalTransferSyntax == DicomTransferSyntax.JPEGProcess1 || Dataset.InternalTransferSyntax == DicomTransferSyntax.JPEGProcess2_4) && samples == 3) { pi = PhotometricInterpretation.Rgb; } // temporary fix for JPEG 2000 Lossy images if (pi == PhotometricInterpretation.YbrIct || pi == PhotometricInterpretation.YbrRct) { pi = PhotometricInterpretation.Rgb; } if (pi == null) { // generally ACR-NEMA if (samples == 0 || samples == 1) { if (Dataset.Contains(DicomTag.RedPaletteColorLookupTableData)) { pi = PhotometricInterpretation.PaletteColor; } else { pi = PhotometricInterpretation.Monochrome2; } } else { // assume, probably incorrectly, that the image is RGB pi = PhotometricInterpretation.Rgb; } } if (pi == PhotometricInterpretation.Monochrome1 || pi == PhotometricInterpretation.Monochrome2) { //Monochrom1 or Monochrome2 for grayscale image if (_renderOptions == null) { _renderOptions = GrayscaleRenderOptions.FromDataset(Dataset); } _pipeline = new GenericGrayscalePipeline(_renderOptions); } else if (pi == PhotometricInterpretation.Rgb) { //RGB for color image _pipeline = new RgbColorPipeline(); } else if (pi == PhotometricInterpretation.PaletteColor) { //PALETTE COLOR for Palette image _pipeline = new PaletteColorPipeline(PixelData); } else { throw new DicomImagingException("Unsupported pipeline photometric interpretation: {0}", pi.Value); } }
/// <summary> /// Create image rendering pipeline according to the Dataset <see cref="PhotometricInterpretation"/>. /// </summary> private void CreatePipeline() { if (_pipeline != null) return; var pi = Dataset.Get<PhotometricInterpretation>(DicomTag.PhotometricInterpretation); var samples = Dataset.Get<ushort>(DicomTag.SamplesPerPixel, 0, 0); // temporary fix for JPEG compressed YBR images if ((Dataset.InternalTransferSyntax == DicomTransferSyntax.JPEGProcess1 || Dataset.InternalTransferSyntax == DicomTransferSyntax.JPEGProcess2_4) && samples == 3) pi = PhotometricInterpretation.Rgb; // temporary fix for JPEG 2000 Lossy images if (pi == PhotometricInterpretation.YbrIct || pi == PhotometricInterpretation.YbrRct) pi = PhotometricInterpretation.Rgb; if (pi == null) { // generally ACR-NEMA if (samples == 0 || samples == 1) { if (Dataset.Contains(DicomTag.RedPaletteColorLookupTableData)) pi = PhotometricInterpretation.PaletteColor; else pi = PhotometricInterpretation.Monochrome2; } else { // assume, probably incorrectly, that the image is RGB pi = PhotometricInterpretation.Rgb; } } if (pi == PhotometricInterpretation.Monochrome1 || pi == PhotometricInterpretation.Monochrome2) { //Monochrom1 or Monochrome2 for grayscale image if (_renderOptions == null) _renderOptions = GrayscaleRenderOptions.FromDataset(Dataset); _pipeline = new GenericGrayscalePipeline(_renderOptions); } else if (pi == PhotometricInterpretation.Rgb) { //RGB for color image _pipeline = new RgbColorPipeline(); } else if (pi == PhotometricInterpretation.PaletteColor) { //PALETTE COLOR for Palette image _pipeline = new PaletteColorPipeline(PixelData); } else { throw new DicomImagingException("Unsupported pipeline photometric interpretation: {0}", pi.Value); } }
/// <summary> /// Create image rendering pipeline according to the <see cref="DicomPixelData.PhotometricInterpretation">photometric interpretation</see> /// of the pixel data. /// </summary> private static PipelineData CreatePipelineData(DicomDataset dataset, DicomPixelData pixelData) { var pi = pixelData.PhotometricInterpretation; var samples = dataset.GetSingleValueOrDefault(DicomTag.SamplesPerPixel, (ushort)0); // temporary fix for JPEG compressed YBR images if ((dataset.InternalTransferSyntax == DicomTransferSyntax.JPEGProcess1 || dataset.InternalTransferSyntax == DicomTransferSyntax.JPEGProcess2_4) && samples == 3) { pi = PhotometricInterpretation.Rgb; } // temporary fix for JPEG 2000 Lossy images if (pi == PhotometricInterpretation.YbrIct || pi == PhotometricInterpretation.YbrRct) { pi = PhotometricInterpretation.Rgb; } if (pi == null) { // generally ACR-NEMA if (samples == 0 || samples == 1) { pi = dataset.Contains(DicomTag.RedPaletteColorLookupTableData) ? PhotometricInterpretation.PaletteColor : PhotometricInterpretation.Monochrome2; } else { // assume, probably incorrectly, that the image is RGB pi = PhotometricInterpretation.Rgb; } } IPipeline pipeline; GrayscaleRenderOptions renderOptions = null; if (pi == PhotometricInterpretation.Monochrome1 || pi == PhotometricInterpretation.Monochrome2) { //Monochrome1 or Monochrome2 for grayscale image renderOptions = GrayscaleRenderOptions.FromDataset(dataset); pipeline = new GenericGrayscalePipeline(renderOptions); } else if (pi == PhotometricInterpretation.Rgb || pi == PhotometricInterpretation.YbrFull || pi == PhotometricInterpretation.YbrFull422 || pi == PhotometricInterpretation.YbrPartial422) { //RGB for color image pipeline = new RgbColorPipeline(); } else if (pi == PhotometricInterpretation.PaletteColor) { //PALETTE COLOR for Palette image pipeline = new PaletteColorPipeline(pixelData); } else { throw new DicomImagingException("Unsupported pipeline photometric interpretation: {0}", pi); } return(new PipelineData { Pipeline = pipeline, RenderOptions = renderOptions }); }
/// <summary> /// Create grayscale render options based on pixel data histogram. /// </summary> /// <param name="dataset">DICOM dataset from which render options should be obtained.</param> /// <param name="percent">Percentage of histogram window to include.</param> /// <returns>Grayscale render options based on pixel data histogram.</returns> public static GrayscaleRenderOptions FromHistogram(DicomDataset dataset, int percent = 90) { 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); var transcoder = new DicomTranscoder( dataset.InternalTransferSyntax, DicomTransferSyntax.ExplicitVRLittleEndian); var pixels = transcoder.DecodePixelData(dataset, 0); var histogram = pixels.GetHistogram(0); int padding = dataset.Get<int>(DicomTag.PixelPaddingValue, 0, Int32.MinValue); if (padding != Int32.MinValue) histogram.Clear(padding); histogram.ApplyWindow(percent); var min = histogram.WindowStart * options.RescaleSlope + options.RescaleIntercept; var max = histogram.WindowEnd * options.RescaleSlope + options.RescaleIntercept; options.WindowWidth = Math.Abs(max - min); options.WindowCenter = (max + min) / 2.0; options.VOILUTFunction = dataset.Get<string>(DicomTag.VOILUTFunction, "LINEAR"); options.ColorMap = GetColorMap(dataset); return options; }
/// <summary> /// Create grayscale render options based on bit range. /// </summary> /// <param name="dataset">DICOM dataset from which render options should be obtained.</param> /// <returns>Grayscale render options based on bit range.</returns> public static GrayscaleRenderOptions FromBitRange(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); var min = bits.MinimumValue * options.RescaleSlope + options.RescaleIntercept; var max = bits.MaximumValue * options.RescaleSlope + options.RescaleIntercept; options.WindowWidth = Math.Abs(max - min); options.WindowCenter = (max + min) / 2.0; options.VOILUTFunction = dataset.Get<string>(DicomTag.VOILUTFunction, "LINEAR"); options.ColorMap = GetColorMap(dataset); return options; }
/// <summary> /// Create grayscale render options based on identified minimum and maximum pixel values. /// </summary> /// <param name="dataset">DICOM dataset from which render options should be obtained.</param> /// <returns>Grayscale render options based on identified minimum and maximum pixel values.</returns> public static GrayscaleRenderOptions FromMinMax(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); int padding = dataset.Get<int>(DicomTag.PixelPaddingValue, 0, Int32.MinValue); var transcoder = new DicomTranscoder( dataset.InternalTransferSyntax, DicomTransferSyntax.ExplicitVRLittleEndian); var pixels = transcoder.DecodePixelData(dataset, 0); var range = pixels.GetMinMax(padding); if (range.Minimum < bits.MinimumValue || range.Minimum == Double.MaxValue) range.Minimum = bits.MinimumValue; if (range.Maximum > bits.MaximumValue || range.Maximum == Double.MinValue) range.Maximum = bits.MaximumValue; var min = range.Minimum * options.RescaleSlope + options.RescaleIntercept; var max = range.Maximum * options.RescaleSlope + options.RescaleIntercept; options.WindowWidth = Math.Abs(max - min); options.WindowCenter = (max + min) / 2.0; options.VOILUTFunction = dataset.Get<string>(DicomTag.VOILUTFunction, "LINEAR"); options.ColorMap = GetColorMap(dataset); return options; }
/// <summary> /// Create grayscale render options based on specified image pixel values. /// </summary> /// <param name="dataset">DICOM dataset from which render options should be obtained.</param> /// <returns>Grayscale render options based on specified image pixel values.</returns> public static GrayscaleRenderOptions FromImagePixelValueTags(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); int smallValue = dataset.Get<int>(DicomTag.SmallestImagePixelValue); int largeValue = dataset.Get<int>(DicomTag.LargestImagePixelValue); if (smallValue >= largeValue) { throw new DicomImagingException( string.Format("Smallest Image Pixel Value ({0}) > Largest Value ({1})", smallValue, largeValue)); } options.WindowWidth = Math.Abs(largeValue - smallValue); options.WindowCenter = (largeValue + smallValue) / 2.0; options.VOILUTFunction = dataset.Get<string>(DicomTag.VOILUTFunction, "LINEAR"); options.ColorMap = GetColorMap(dataset); return options; }
/// <summary> /// Create grayscale render options based on window level data. /// </summary> /// <param name="dataset">DICOM dataset from which render options should be obtained.</param> /// <returns>Grayscale render options based on window level data.</returns> public static GrayscaleRenderOptions FromWindowLevel(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); options.WindowWidth = dataset.Get<double>(DicomTag.WindowWidth); options.WindowCenter = dataset.Get<double>(DicomTag.WindowCenter); options.VOILUTFunction = dataset.Get<string>(DicomTag.VOILUTFunction, "LINEAR"); options.ColorMap = GetColorMap(dataset); return options; }
/// <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; }