<div class="gmail_quote">Hi,<div><br></div><div>So far I was using gdcm 2.0.14 and I was able to read any image with no problem, but I upgraded recently to gdcm 2.0.15 and I found a problem reading some CT and MR DICOM image files.</div>
<div>The way I'm reading DICOM files is using itkGDCMImageIO with itkImageSeriesReader and then filtering the output to vtk for the image rendering.</div><div><br></div><div>The problem is that some images are now (gdcm 2.0.15) loaded with a different scalar range than before (gdcm 2.0.14), hence they are not displayed properly with the default window/level setting (almost completely white in most CT cases for instance). I observed that the images with trouble were those containing rescale intercept/slope tags with some value. The images with no rescale intercept/slope present are displayed as expected, so my guess is there is some problem regarding the intercept/slope rescale computation.</div>
<div><br></div><div>I've written a little program which reads a DICOM image and renders it with vtk to reproduce the bug. Then I compiled it against gdcm 2.0.14 and 2.0.15 to see the differences between each other. The source code is at the end of this e-mail.</div>
<div><br></div><div>I've been testing with some DICOM images from <a href="http://www.creatis.insa-lyon.fr/~jpr/PUBLIC/gdcm/gdcmData.tar.gz" target="_blank">http://www.creatis.insa-lyon.fr/~jpr/PUBLIC/gdcm/gdcmData.tar.gz</a>. Some of these test images are valid to reproduce the problem, in this case I'll show you the results with MR-MONO2-12-shoulder.dcm, CT-SIEMENS-Icone-With-PaletteColor.dcm and 05119865-mr-siemens-avanto-syngo.dcm.</div>
<div><br></div><div>In the following table I show some of the relevant information of each image and the scalar range I get building the program against gdcm 2.0.14 and 2.0.15. The right scalar range is the one obtained with gdcm 2.0.14. The result is specially bad with the MR-MONO2-12-shoulder.dcm image.</div>
<div><br></div><div><div><b>File</b><span style="white-space:pre-wrap"><b>         </b></span><b>WW<span style="white-space:pre-wrap">,</span></b><b>WL</b><span style="white-space:pre-wrap"><b> </b></span><b>Bits Allocated<span style="white-space:pre-wrap">/</span></b><b>Stored</b><span style="white-space:pre-wrap"><b>        </b></span><b>Rescale Slope<span style="white-space:pre-wrap">/</span></b><b>Intercept</b><span style="white-space:pre-wrap"><b>        </b></span><b>Scalar Range:</b><span style="white-space:pre-wrap"><b>        </b></span><b>2.0.14 Build </b><b>2.0.15 Build</b></div>
<div>MR-MONO2-12-shoulder.dcm<span style="white-space:pre-wrap">         </span>2000<span style="white-space:pre-wrap">,</span>1000<span style="white-space:pre-wrap">         </span>16<span style="white-space:pre-wrap">/</span>12<span style="white-space:pre-wrap">         </span>3.774114<span style="white-space:pre-wrap">, </span>0.000061<span style="white-space:pre-wrap">         </span>0..2245 <span style="white-space:pre-wrap"> </span>-32065..32556</div>
<div>CT-SIEMENS-Icone-With-PaletteColor.dcm<span style="white-space:pre-wrap">         </span>350<span style="white-space:pre-wrap">,</span>40<span style="white-space:pre-wrap">         </span>16<span style="white-space:pre-wrap">/</span>12<span style="white-space:pre-wrap">         </span>1<span style="white-space:pre-wrap">, </span>-1024<span style="white-space:pre-wrap">         </span>-1024..981<span style="white-space:pre-wrap">         </span>0..2005</div>
<div>05119865-mr-siemens-avanto-syngo.dcm<span style="white-space:pre-wrap">         </span>1538,98<span style="white-space:pre-wrap">         </span>16/12<span style="white-space:pre-wrap">         </span>2<span style="white-space:pre-wrap">, </span>-4096<span style="white-space:pre-wrap">         </span>-1186..526<span style="white-space:pre-wrap">         </span>1455..2311</div>
</div><div><br></div><div><br></div><div>I tested with itk 3.18 and vtk 5.6, (the vtk version might not make any sense in the results because the problem is just in the reading stage).</div><div>(Look at <a href="https://docs.google.com/uc?id=0B-5DPBfN4U4FMzUzNjI5YjQtNTU5MS00ODlkLThhNDMtNjA3NDRiZjUyMjJh&export=download&hl=en">some screenshots</a> of the results)</div>
<div><br></div><div><font face="'courier new', monospace">//</font></div>
<div><font face="'courier new', monospace">// SOURCE CODE</font></div><div><font face="'courier new', monospace">//</font></div><div><font face="'courier new', monospace"><br>
</font></div><div><font face="'courier new', monospace">//</font></div><div><font face="'courier new', monospace">// You'll need also</font> <span style="font-family:'courier new', monospace">itkImageToVTKImageFilter class, available in the <a href="http://voxel.dl.sourceforge.net/sourceforge/itk/InsightApplications-3.20.0.zip" target="_blank">InsightApplications</a> </span><span style="font-family:'courier new', monospace">package under "Auxiliary\vtk" folder</span></div>
<div><font face="'courier new', monospace">//</font></div><div><br></div><div><font face="'courier new', monospace">// </font><span style="font-family:'courier new', monospace">Usage: main.exe DICOMFilename [WindowWidth WindowLevel]</span></div>
<div><br></div><div><div><font face="'courier new', monospace">#include <vtkImageviewer2.h></font></div><div><font face="'courier new', monospace">#include <vtkRenderWindowInteractor.h></font></div>
<div><font face="'courier new', monospace">#include <vtkRenderWindow.h></font></div><div><font face="'courier new', monospace"><br></font></div><div>
<font face="'courier new', monospace">#include <itkImage.h></font></div><div><font face="'courier new', monospace">#include <itkImageSeriesReader.h></font></div>
<div><font face="'courier new', monospace">#include <itkGDCMImageIO.h></font></div><div><font face="'courier new', monospace">#include "itkImageToVTKImageFilter.h" //Converts an ITK image into a VTK image and plugs a itk data pipeline to a VTK datapipeline.</font></div>
<div><font face="'courier new', monospace"><br></font></div><div><font face="'courier new', monospace">int main(int argc, char* argv[])</font></div><div><font face="'courier new', monospace">{</font></div>
<div><font face="'courier new', monospace"> // Voxel type and image dimension</font></div><div><font face="'courier new', monospace"> typedef signed short int VoxelType;</font></div>
<div><font face="'courier new', monospace"> typedef VoxelType ItkPixelType;</font></div><div><font face="'courier new', monospace"> static const unsigned int VDimension = 3;</font></div>
<div><font face="'courier new', monospace"><br></font></div><div><font face="'courier new', monospace"> // Itk Image type</font></div><div><font face="'courier new', monospace"> typedef itk::Image<ItkPixelType, VDimension> ItkImageType;</font></div>
<div><font face="'courier new', monospace"> typedef ItkImageType::Pointer ItkImageTypePointer;</font></div><div><font face="'courier new', monospace"> </font></div>
<div><font face="'courier new', monospace"> // Series reader</font></div><div><font face="'courier new', monospace"> typedef itk::ImageSeriesReader<ItkImageType> SeriesReaderType;</font></div>
<div><font face="'courier new', monospace"> typedef itk::GDCMImageIO ImageIOType;</font></div><div><font face="'courier new', monospace"><br></font></div>
<div><font face="'courier new', monospace"> // itk2vtk filter</font></div><div><font face="'courier new', monospace"> typedef itk::ImageToVTKImageFilter<ItkImageType> ItkToVtkFilterType;</font></div>
<div><font face="'courier new', monospace"><br></font></div><div><font face="'courier new', monospace"> /// DICOM Reader</font></div><div><font face="'courier new', monospace"> SeriesReaderType::Pointer m_seriesReader = SeriesReaderType::New();</font></div>
<div><font face="'courier new', monospace"> ImageIOType::Pointer m_gdcmIO = ImageIOType::New();</font></div><div><font face="'courier new', monospace"> </font></div>
<div><font face="'courier new', monospace"> m_seriesReader->SetImageIO(m_gdcmIO);</font></div><div><font face="'courier new', monospace"> ItkToVtkFilterType::Pointer m_itkToVtkFilter = ItkToVtkFilterType::New(); </font></div>
<div><font face="'courier new', monospace"><br></font></div><div><font face="'courier new', monospace"> // Check the number of parameters given</font></div>
<div><font face="'courier new', monospace"> if (argc >= 2)</font></div><div><font face="'courier new', monospace"> { </font></div><div><font face="'courier new', monospace"> // Create the renderer object and configure it</font></div>
<div><font face="'courier new', monospace"> vtkImageViewer2 *viewer = vtkImageViewer2::New();</font></div><div><font face="'courier new', monospace"> vtkRenderWindowInteractor *interactor = vtkRenderWindowInteractor::New();</font></div>
<div><font face="'courier new', monospace"> viewer->SetupInteractor(interactor);</font></div><div><font face="'courier new', monospace"><br></font></div>
<div><font face="'courier new', monospace"> // Set the first argument as the input filename to read</font></div><div><font face="'courier new', monospace"> // Atention: We don't check whether the file is valid or not</font></div>
<div><font face="'courier new', monospace"> m_seriesReader->SetFileName(argv[1]);</font></div><div><font face="'courier new', monospace"> m_itkToVtkFilter->SetInput(m_seriesReader->GetOutput());</font></div>
<div><font face="'courier new', monospace"> try</font></div><div><font face="'courier new', monospace"> {</font></div><div><font face="'courier new', monospace"> m_itkToVtkFilter->Update();</font></div>
<div><font face="'courier new', monospace"> }</font></div><div><font face="'courier new', monospace"> catch (itk::ExceptionObject & exception)</font></div>
<div><font face="'courier new', monospace"> {</font></div><div><font face="'courier new', monospace"> std::cerr << "Exception caught!" << exception.GetDescription() << std::endl;</font></div>
<div><font face="'courier new', monospace"> }</font></div><div><font face="'courier new', monospace"><br></font></div><div><font face="'courier new', monospace"> // Show some information about the image</font></div>
<div><font face="'courier new', monospace"><div> m_itkToVtkFilter->GetOutput()->Print(std::cout);</div><div> std::cerr << "** Scalar Range **" << std::endl;</div>
<div> std::cerr << m_itkToVtkFilter->GetOutput()->GetScalarRange()[0] << ".." << m_itkToVtkFilter->GetOutput()->GetScalarRange()[1] << std::endl;</div></font></div><div>
<font face="'courier new', monospace"><br></font></div><div><font face="'courier new', monospace"> // Set the viewer input (DICOM File) and do the rendering stuff</font></div>
<div><font face="'courier new', monospace"> viewer->SetInput(m_itkToVtkFilter->GetOutput());</font></div><div><span style="font-family:'courier new', monospace"> </span></div>
<div><font face="'courier new', monospace"> // We can optionally set the window/level through the arguments</font></div><div><font face="'courier new', monospace"> if (argc >=4)</font></div>
<div><font face="'courier new', monospace"> {</font></div><div><font face="'courier new', monospace"> std::cout << "Applying given ww/wl: " << argv[2] << ", " << argv[3] << std::endl;</font></div>
<div><font face="'courier new', monospace"> viewer->SetColorWindow(atof(argv[2]));</font></div><div><font face="'courier new', monospace"> viewer->SetColorLevel(atof(argv[3]));</font></div>
<div><font face="'courier new', monospace"> }</font></div><div><font face="'courier new', monospace"> else</font></div><div><font face="'courier new', monospace"> {</font></div>
<div><font face="'courier new', monospace"> std::cout << "Applying default ww/wl: 256, 128" << std::endl;</font></div><div><font face="'courier new', monospace"> viewer->SetColorWindow(256);</font></div>
<div><font face="'courier new', monospace"> viewer->SetColorLevel(128);</font></div><div><font face="'courier new', monospace"> }</font></div>
<div><font face="'courier new', monospace"> </font></div><div><font face="'courier new', monospace"> viewer->Render();</font></div><div><font face="'courier new', monospace"> interactor->Start();</font></div>
<div><font face="'courier new', monospace"> }</font></div><div><font face="'courier new', monospace"> else</font></div><div><font face="'courier new', monospace"> {</font></div>
<div><font face="'courier new', monospace"> std::cerr << "Usage: main.exe DICOMFilename [WindowWidth WindowLevel]" << std::endl;</font></div><div><font face="'courier new', monospace"> }</font></div>
<div><span style="font-family:'courier new', monospace"><br></span></div><div><font face="'courier new', monospace"></font><span style="font-family:'courier new', monospace"> return 0;</span></div>
<div><font face="'courier new', monospace">}</font></div></div></div><br>-- <br>Jesús Spínola<br>