]> Creatis software - gdcm.git/commitdiff
* vtk/vtkGdcmWriter.[h|cxx] : add a first version of vtkGdcmWriter
authorregrain <regrain>
Tue, 7 Dec 2004 17:28:49 +0000 (17:28 +0000)
committerregrain <regrain>
Tue, 7 Dec 2004 17:28:49 +0000 (17:28 +0000)
   * src/gdcmValEntry.cxx : bug fix when setting the value. Problems of odd
     length
   * src/gdcmHeader.cxx : Remove a useless call to Util::DicomString
   * Add vtkGdcmWriter example and test
   -- BeNours

12 files changed:
ChangeLog
Testing/CMakeLists.txt
src/gdcmDicomDir.cxx
src/gdcmFile.cxx
src/gdcmFile.h
src/gdcmHeader.cxx
src/gdcmValEntry.cxx
vtk/CMakeLists.txt
vtk/vtkGdcmReader.cxx
vtk/vtkGdcmWriter.cxx [new file with mode: 0644]
vtk/vtkGdcmWriter.h [new file with mode: 0644]
vtk/vtkWriteDicom.cxx [new file with mode: 0644]

index 3557fc481ec5e76903ecbcac5b0de238c1544ef3..a4db53cdb74def1637ce9310b63323fdf50b1d6f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2004-12-07 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * vtk/vtkGdcmWriter.[h|cxx] : add a first version of vtkGdcmWriter
+   * src/gdcmValEntry.cxx : bug fix when setting the value. Problems of odd
+     length
+   * src/gdcmHeader.cxx : Remove a useless call to Util::DicomString
+   * Add vtkGdcmWriter example and test
+
 2004-12-07 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
    * Test/TestUtil.cxx : reformat the source code
    * vtk/vtkGdcmReader.cxx : remove and change prints
index 011b9a3be5644fecac95404338d24cd9691d156a..268f52fe7689ff18ffdae278cc49501c53c3575a 100644 (file)
@@ -41,6 +41,7 @@ IF (GDCM_DATA_ROOT)
       )
     SET(TEST_SOURCES ${TEST_SOURCES}
       ShowDicom.cxx
+      TestWriteWithVTK.cxx
       )
   ENDIF(GDCM_VTK)
 ENDIF (GDCM_DATA_ROOT)
index 7ab7f7d6d3c3b7c0f6add43c6d8de4c5044b6f46..e5cc92d0d2260d147984c2bba2a8f6325387bb38 100644 (file)
@@ -3,8 +3,8 @@
   Program:   gdcm
   Module:    $RCSfile: gdcmDicomDir.cxx,v $
   Language:  C++
-  Date:      $Date: 2004/12/07 13:39:33 $
-  Version:   $Revision: 1.88 $
+  Date:      $Date: 2004/12/07 17:28:50 $
+  Version:   $Revision: 1.89 $
   
   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
   l'Image). All rights reserved. See Doc/License.txt or
@@ -422,7 +422,6 @@ void DicomDir::CreateDicomDirChainedList(std::string const & path)
          break;
       }
 
-std::cerr<<"File : "<<it->c_str()<<std::endl;
       header = new Header( it->c_str() );
       if( !header )
       {
index 43804b36618688ba894e783abefa4f94850b8ea6..03df5b7046dfe768f8ac42b1ffe9679f31856c51 100644 (file)
@@ -3,8 +3,8 @@
   Program:   gdcm
   Module:    $RCSfile: gdcmFile.cxx,v $
   Language:  C++
-  Date:      $Date: 2004/12/07 13:39:33 $
-  Version:   $Revision: 1.173 $
+  Date:      $Date: 2004/12/07 17:28:50 $
+  Version:   $Revision: 1.174 $
                                                                                 
   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
   l'Image). All rights reserved. See Doc/License.txt or
@@ -34,6 +34,26 @@ typedef std::pair<TagDocEntryHT::iterator,TagDocEntryHT::iterator> IterHT;
 
 //-------------------------------------------------------------------------
 // Constructor / Destructor
+/**
+ * \brief Constructor dedicated to deal with the *pixels* area of a ACR/DICOMV3
+ *        file (Header only deals with the ... header)
+ *        Opens (in read only and when possible) an existing file and checks
+ *        for DICOM compliance. Returns NULL on failure.
+ *        It will be up to the user to load the pixels into memory
+ *        (see GetImageData, GetImageDataRaw)
+ * \note  the in-memory representation of all available tags found in
+ *        the DICOM header is post-poned to first header information access.
+ *        This avoid a double parsing of public part of the header when
+ *        one sets an a posteriori shadow dictionary (efficiency can be
+ *        seen as a side effect).   
+ */
+File::File( )
+{
+   HeaderInternal = new Header( );
+   SelfHeader = true;
+   Initialise();
+}
+
 /**
  * \brief Constructor dedicated to deal with the *pixels* area of a ACR/DICOMV3
  *        file (Header only deals with the ... header)
@@ -82,7 +102,7 @@ File::File(std::string const & filename )
 void File::Initialise()
 {
    WriteMode = WMODE_DECOMPRESSED;
-   WriteType = ImplicitVR;
+   WriteType = ExplicitVR;
 
    PixelReadConverter = new PixelReadConvert;
    PixelWriteConverter = new PixelWriteConvert;
@@ -383,8 +403,19 @@ bool File::Write(std::string const& fileName)
 bool File::SetEntryByNumber(std::string const& content,
                             uint16_t group, uint16_t element)
 { 
-   HeaderInternal->SetEntryByNumber(content,group,element);
-   return true;
+   return HeaderInternal->SetEntryByNumber(content,group,element);
+}
+
+bool File::SetEntryByNumber(uint8_t* content, int lgth,
+                            uint16_t group, uint16_t element)
+{
+   return HeaderInternal->SetEntryByNumber(content,lgth,group,element);
+}
+
+bool File::ReplaceOrCreateByNumber(std::string const& content,
+                                   uint16_t group, uint16_t element)
+{
+   return HeaderInternal->ReplaceOrCreateByNumber(content,group,element) != NULL;
 }
 
 /**
index f72484188d77d0a8363eaa7d4f457398996aed20..23f87ff6edc4f47298a05aa82e310512ade5bd6e 100644 (file)
@@ -3,8 +3,8 @@
   Program:   gdcm
   Module:    $RCSfile: gdcmFile.h,v $
   Language:  C++
-  Date:      $Date: 2004/12/04 09:41:02 $
-  Version:   $Revision: 1.84 $
+  Date:      $Date: 2004/12/07 17:28:50 $
+  Version:   $Revision: 1.85 $
                                                                                 
   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
   l'Image). All rights reserved. See Doc/License.txt or
@@ -45,6 +45,7 @@ public:
    };
      
 public:
+   File( );
    File( Header* header );
    File( std::string const& filename );
  
@@ -72,7 +73,14 @@ public:
    bool Write(std::string const& fileName);
 
    bool SetEntryByNumber(std::string const& content,
+                         uint16_t group, uint16_t element);
+   bool SetEntryByNumber(uint8_t* content, int lgth,
+                         uint16_t group, uint16_t element);
+   bool ReplaceOrCreateByNumber(std::string const& content,
                                 uint16_t group, uint16_t element);
+   bool ReplaceOrCreateByNumber(uint8_t* binArea, int lgth,
+                                uint16_t group, uint16_t elem);
+
    uint8_t* GetLutRGBA();
 
    // Write mode
index 9bef4bd08c26b596dbb4d9815f9041485ad35070..e15c9c28aadabb5388502339a82e43f98d4b723c 100644 (file)
@@ -3,8 +3,8 @@
   Program:   gdcm
   Module:    $RCSfile: gdcmHeader.cxx,v $
   Language:  C++
-  Date:      $Date: 2004/12/07 13:39:33 $
-  Version:   $Revision: 1.213 $
+  Date:      $Date: 2004/12/07 17:28:50 $
+  Version:   $Revision: 1.214 $
                                                                                 
   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
   l'Image). All rights reserved. See Doc/License.txt or
@@ -1311,7 +1311,7 @@ void Header::InitializeDefaultHeader()
    std::string uid  = Util::CreateUniqueUID();
 
    static DICOM_DEFAULT_VALUE defaultvalue[] = {
-    { "76", 0x0002, 0x0000},         // MetaElementGroup Length // FIXME: how to recompute ?
+    { "76 ",      0x0002, 0x0000},         // MetaElementGroup Length // FIXME: how to recompute ?
     { "1.2.840.10008.5.1.4.1.1.2", 0x0002, 0x0002},  // MediaStorageSOPInstanceUID (CT Image Storage)
     { uid.c_str(), 0x0002, 0x0012},  // META Implementation Class UID
     { "ISO_IR 100",0x0008, 0x0005},  // Specific Character Set
@@ -1331,10 +1331,9 @@ void Header::InitializeDefaultHeader()
     { "",          0x0020, 0x0011},   // AcquisitionNumber
     { "1\\0\\0\\0\\1\\0", 0x0020, 0x0037},  // Image Orientation Patient
     { "1",         0x0028, 0x0002},  // Samples per pixel 1 or 3
-    { "MONOCHROME2",0x0028, 0x0004},  // photochromatic interpretation
+    { "MONOCHROME1",0x0028, 0x0004},  // photochromatic interpretation
 
 // Date and timeG
-
     { date.c_str(), 0x0008, 0x0012 } ,  // Instance Creation Date
     { time.c_str(), 0x0008, 0x0013 } ,  // Instance Creation Time
     { date.c_str(), 0x0008, 0x0020 } ,  // Study Date
@@ -1352,8 +1351,8 @@ void Header::InitializeDefaultHeader()
     { "64",         0x0028, 0x0010 } ,  // nbRows
     { "64",         0x0028, 0x0011 } ,  // nbCols
     { "16",         0x0028, 0x0100 } ,  // BitsAllocated 8 or 16
-    { "12",         0x0028, 0x0101 } ,  // BitsStored    8 or 12
-    { "11",         0x0028, 0x0102 } ,  // HighBit       7 or 11
+    { "12",         0x0028, 0x0101 } ,  // BitsStored    8 or 12 or 16
+    { "11",         0x0028, 0x0102 } ,  // HighBit       7 or 11 or 15
     { "0",          0x0028, 0x0103 } ,  // Pixel Representation 0(unsigned) or 1(signed)
     { "1000.0",     0x0028, 0x1051 } ,  // Window Width
     { "500.0",      0x0028, 0x1050 } ,  // Window Center
@@ -1371,8 +1370,7 @@ void Header::InitializeDefaultHeader()
    DICOM_DEFAULT_VALUE current = defaultvalue[i];
    while( current.value )
    {
-      std::string value = Util::DicomString( current.value ); //pad the string properly
-      ReplaceOrCreateByNumber(value, current.group, current.elem);
+      ReplaceOrCreateByNumber(current.value, current.group, current.elem);
       current = defaultvalue[++i];
    }
 }
index 270fdd3a047f92553a2f3d5681ed19b14691c87d..a3f17d8003475362dbbd9acddaaf415554e44ea6 100644 (file)
@@ -3,8 +3,8 @@
   Program:   gdcm
   Module:    $RCSfile: gdcmValEntry.cxx,v $
   Language:  C++
-  Date:      $Date: 2004/12/07 13:39:33 $
-  Version:   $Revision: 1.39 $
+  Date:      $Date: 2004/12/07 17:28:50 $
+  Version:   $Revision: 1.40 $
                                                                                 
   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
   l'Image). All rights reserved. See Doc/License.txt or
@@ -188,13 +188,22 @@ void ValEntry::SetValue(std::string const & val)
       {
          // for multivaluated items
          l = (Util::CountSubstring(val, "\\") + 1) * 2;
+         SetValueOnly(val);
       }
       else if( vr == "UL" || vr == "SL" )
       {
          // for multivaluated items
          l = (Util::CountSubstring(val, "\\") + 1) * 4;;
+         SetValueOnly(val);
+      }
+      else
+      {
+         std::string finalVal = Util::DicomString( val.c_str() );
+         assert( !(finalVal.size() % 2) );
+
+         l = finalVal.length();
+         SetValueOnly(finalVal);
       }
-      SetValueOnly(val);
    }
    else
    {
index c3b68cc298440fa2b1004edd1fa51f10c72dabda..69028cc66a7f569b902b7117c9dd90c2df00c113 100644 (file)
@@ -13,6 +13,7 @@ INCLUDE_DIRECTORIES(
 
 SET(VTKGDCM_LIB_SRCS
   vtkGdcmReader.cxx
+  vtkGdcmWriter.cxx
 )
 
 #-----------------------------------------------------------------------------
@@ -46,6 +47,17 @@ TARGET_LINK_LIBRARIES(vtkgdcmViewer
   vtkRendering
 )
 
+#-----------------------------------------------------------------------------
+SET(vtkWriteDicom_SOURCES
+  vtkWriteDicom.cxx
+)
+ADD_EXECUTABLE(vtkWriteDicom ${vtkWriteDicom_SOURCES})
+TARGET_LINK_LIBRARIES(vtkWriteDicom
+  vtkgdcm
+  vtkIO
+  vtkRendering
+)
+
 #-----------------------------------------------------------------------------
 SET(GdcmToBaseline_SOURCES
   GdcmToBaseline.cxx
index 584305bcebb3b4a66b685c567227178a90232bba..539d5fc8643b21c118d61a8183a5655fe64952a3 100644 (file)
@@ -58,7 +58,7 @@
 #include <vtkPointData.h>
 #include <vtkLookupTable.h>
 
-vtkCxxRevisionMacro(vtkGdcmReader, "$Revision: 1.61 $");
+vtkCxxRevisionMacro(vtkGdcmReader, "$Revision: 1.62 $");
 vtkStandardNewMacro(vtkGdcmReader);
 
 //-----------------------------------------------------------------------------
@@ -548,9 +548,9 @@ int vtkGdcmReader::CheckFileCoherence()
          this->DataSpacing[2] = GdcmHeader.GetZSpacing();
 
          //Set image origin
-         this->DataOrigin[0] = GdcmHeader.GetXOrigin();
-         this->DataOrigin[1] = GdcmHeader.GetYOrigin();
-         this->DataOrigin[2] = GdcmHeader.GetZOrigin();
+         //this->DataOrigin[0] = GdcmHeader.GetXOrigin();
+         //this->DataOrigin[1] = GdcmHeader.GetYOrigin();
+         //this->DataOrigin[2] = GdcmHeader.GetZOrigin();
 
       }
    } // End of loop on filename
diff --git a/vtk/vtkGdcmWriter.cxx b/vtk/vtkGdcmWriter.cxx
new file mode 100644 (file)
index 0000000..755b57f
--- /dev/null
@@ -0,0 +1,197 @@
+// vtkGdcmWriter.cxx
+//-----------------------------------------------------------------------------
+// //////////////////////////////////////////////////////////////
+// WARNING TODO CLEANME 
+// Actual limitations of this code:
+//
+// /////// Redundant and unnecessary header parsing
+// In it's current state this code actually parses three times the Dicom
+// header of a file before the corresponding image gets loaded in the
+// ad-hoc vtkData !
+// Here is the process:
+//  1/ First loading happens in ExecuteInformation which in order to
+//     positionate the vtk extents calls CheckFileCoherence. The purpose
+//     of CheckFileCoherence is to make sure all the images in the future
+//     stack are "homogenous" (same size, same representation...). This
+//     can only be achieved by parsing all the Dicom headers...
+//  2/ ExecuteData is then responsible for the next two loadings:
+//  2a/ ExecuteData calls AllocateOutputData that in turn seems to 
+//      (indirectely call) ExecuteInformation which ends up in a second
+//      header parsing
+//      This is fixed by adding a test at the beginning of ExecuteInformation
+//      on the modification of the object instance. If a modification have been
+//      made (method Modified() ), the MTime value is increased. The fileTime
+//      is compared to this new value to find a modification in the class
+//      parameters
+//  2b/ the core of ExecuteData then needs gdcmFile (which in turns
+//      initialises gdcmHeader in the constructor) in order to access
+//      the data-image.
+//
+// Possible solution:
+// maintain a list of gdcmFiles (created by say ExecuteInformation) created
+// once and for all accross the life of vtkGdcmHeader (it would only load
+// new gdcmFile if the user changes the list). ExecuteData would then use 
+// those gdcmFile and hence avoid calling the construtor:
+//  - advantage: the header of the files would only be parser once.
+//  - drawback: once execute information is called (i.e. on creation of
+//              a vtkGdcmHeader) the gdcmFile structure is loaded in memory.
+//              The average size of a gdcmHeader being of 100Ko, is one
+//              loads 10 stacks of images with say 200 images each, you
+//              end-up with a loss of 200Mo...
+//
+// /////// Never unallocated memory:
+// ExecuteData allocates space for the pixel data [which will get pointed
+// by the vtkPointData() through the call
+// data->GetPointData()->GetScalars()->SetVoidArray(mem, StackNumPixels, 0);]
+// This data is never "freed" neither in the destructor nor when the
+// filename list is extended, ExecuteData is called a second (or third)
+// time...
+// //////////////////////////////////////////////////////////////
+
+#include "gdcmHeader.h"
+#include "gdcmFile.h"
+#include "gdcmDebug.h"
+#include "vtkGdcmWriter.h"
+
+#include <vtkObjectFactory.h>
+#include <vtkImageData.h>
+#include <vtkPointData.h>
+#include <vtkLookupTable.h>
+
+vtkCxxRevisionMacro(vtkGdcmWriter, "$Revision: 1.1 $");
+vtkStandardNewMacro(vtkGdcmWriter);
+
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+vtkGdcmWriter::vtkGdcmWriter()
+{
+   this->LookupTable = NULL;
+}
+
+vtkGdcmWriter::~vtkGdcmWriter()
+{
+}
+
+//-----------------------------------------------------------------------------
+// Print
+void vtkGdcmWriter::PrintSelf(ostream& os, vtkIndent indent)
+{
+   this->Superclass::PrintSelf(os,indent);
+}
+
+//-----------------------------------------------------------------------------
+// Public
+
+//-----------------------------------------------------------------------------
+// Protected
+void SetImageInformation(gdcm::File *file,vtkImageData *image)
+{
+   std::ostringstream str;
+
+   // Image size
+   int *dim = image->GetDimensions();
+
+   str.str("");
+   str<<dim[0];
+   file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0011);
+
+   str.str("");
+   str<<dim[1];
+   file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0010);
+
+   if(dim[2]>1)
+   {
+      str.str("");
+      str<<dim[2];
+      file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0012);
+   }
+
+   // Pixel type
+   str.str("");
+   str<<image->GetScalarSize()*8;
+   file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0100);
+   file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0101);
+
+   str.str("");
+   str<<image->GetScalarSize()*8-1;
+   file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0102);
+
+   // Samples per pixel
+   str.str("");
+   str<<image->GetNumberOfScalarComponents();
+   file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0002);
+   std::cout<<file->GetHeader()->GetEntryByNumber(0x0028,0x0002)<<"-"<<file->GetHeader()->GetNumberOfScalarComponents()<<"\n";
+
+   // Spacing
+   double *sp = image->GetSpacing();
+
+   str.str("");
+   str<<sp[0]<<"\\"<<sp[1];
+   file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0030);
+   str.str("");
+   str<<sp[2];
+   file->ReplaceOrCreateByNumber(str.str(),0x0018,0x0088);
+
+   // Origin
+   double *org = image->GetOrigin();
+
+   str.str("");
+   str<<org[0]<<"\\"<<org[1]<<"\\"<<org[2];
+   file->ReplaceOrCreateByNumber(str.str(),0x0020,0x0032);
+
+   // Window / Level
+   double *rng=image->GetScalarRange();
+
+   str.str("");
+   str<<rng[1]-rng[0];
+   file->ReplaceOrCreateByNumber(str.str(),0x0028,0x1051);
+   str.str("");
+   str<<(rng[1]+rng[0])/2.0;
+   file->ReplaceOrCreateByNumber(str.str(),0x0028,0x1050);
+
+   // Pixels
+   size_t size = dim[0] * dim[1] * dim[2] 
+               * image->GetScalarSize()
+               * image->GetNumberOfScalarComponents();
+   file->SetImageData((unsigned char *)image->GetScalarPointer(),size);
+}
+
+void vtkGdcmWriter::RecursiveWrite(int dim, vtkImageData *region, ofstream *file)
+{
+   if(file)
+   {
+      vtkErrorMacro(<< "File musn't be opened");
+      return;
+   }
+
+   if( region->GetScalarType() == VTK_FLOAT 
+     || region->GetScalarType() == VTK_DOUBLE )
+   {
+      vtkErrorMacro(<< "Bad input type. Scalar type musn't be of type "
+                    << "VTK_FLOAT or VTKDOUBLE (found:"
+                    << region->GetScalarTypeAsString());
+      return;
+   }
+
+   gdcm::File *dcmFile = new gdcm::File();
+
+   ///////////////////////////////////////////////////////////////////////////
+   // Set the image informations
+   SetImageInformation(dcmFile,region);
+
+   ///////////////////////////////////////////////////////////////////////////
+   // Write the image
+   if(!dcmFile->Write(this->FileName))
+   {
+      vtkErrorMacro(<< "File " << this->FileName << "couldn't be written by "
+                    << " the gdcm library");
+      std::cerr<<"not written \n";
+   }
+
+   delete dcmFile;
+}
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
diff --git a/vtk/vtkGdcmWriter.h b/vtk/vtkGdcmWriter.h
new file mode 100644 (file)
index 0000000..592daec
--- /dev/null
@@ -0,0 +1,38 @@
+// vtkGdcmWriter.h
+//-----------------------------------------------------------------------------
+#ifndef __vtkGdcmWriter_h
+#define __vtkGdcmWriter_h
+
+#include "gdcmCommon.h" // To avoid warnings concerning the std
+
+#include <vtkImageWriter.h>
+#include <vtkLookupTable.h>
+#include <list>
+#include <string>
+
+//-----------------------------------------------------------------------------
+class VTK_EXPORT vtkGdcmWriter : public vtkImageWriter
+{
+public:
+   static vtkGdcmWriter *New();
+   vtkTypeRevisionMacro(vtkGdcmWriter, vtkImageWriter);
+
+   void PrintSelf(ostream& os, vtkIndent indent);
+
+   vtkSetObjectMacro(LookupTable,vtkLookupTable);
+   vtkGetObjectMacro(LookupTable,vtkLookupTable);
+
+protected:
+   vtkGdcmWriter();
+   ~vtkGdcmWriter();
+
+  virtual void RecursiveWrite(int dim, vtkImageData *region, ofstream *file);
+
+private:
+// Variables
+   vtkLookupTable *LookupTable;
+};
+
+//-----------------------------------------------------------------------------
+#endif
+
diff --git a/vtk/vtkWriteDicom.cxx b/vtk/vtkWriteDicom.cxx
new file mode 100644 (file)
index 0000000..19452b2
--- /dev/null
@@ -0,0 +1,74 @@
+// This example illustrates how the vtkGdcmWriter vtk class can be
+// used in order to:
+//
+// Usage:
+// 
+//----------------------------------------------------------------------------
+#include <iostream>
+
+#include <vtkImageMapToColors.h>
+#include <vtkLookupTable.h>
+#include <vtkImageData.h>
+
+#include "vtkGdcmReader.h"
+#include "vtkGdcmWriter.h"
+
+#ifndef vtkFloatingPointType
+#define vtkFloatingPointType float
+#endif
+
+//----------------------------------------------------------------------------
+int main(int argc, char *argv[])
+{
+   if( argc < 2 )
+      return 0;
+  
+   vtkGdcmReader *reader = vtkGdcmReader::New();
+   reader->AllowLookupTableOff();
+
+   if( argc == 2 )
+      reader->SetFileName( argv[1] );
+   else
+      for(int i=1; i< argc; i++)
+         reader->AddFileName( argv[i] );
+
+   reader->Update();
+
+   vtkImageData *output;
+   if( reader->GetLookupTable() )
+   {
+      //convert to color:
+      vtkImageMapToColors *map = vtkImageMapToColors::New ();
+      map->SetInput (reader->GetOutput());
+      map->SetLookupTable (reader->GetLookupTable());
+      map->SetOutputFormatToRGB();
+      output = map->GetOutput();
+      map->Delete();
+   }
+   else
+   {
+      output = reader->GetOutput();
+   }
+  
+   //print debug info:
+   output->Print( cout );
+
+   //////////////////////////////////////////////////////////
+   // WRITE...
+   //if you wish you can export dicom to a vtk file 
+   // this file will have the add of .tmp.dcm extention
+   std::string fileName = argv[1];
+   fileName += ".tmp.dcm";
+
+   vtkGdcmWriter *writer = vtkGdcmWriter::New();
+   writer->SetFileName(fileName.c_str());
+   writer->SetInput(output);
+   writer->Write();
+   //////////////////////////////////////////////////////////
+
+   // Clean up
+   writer->Delete();
+   reader->Delete();
+
+   return 0;
+}