GDCM 2.2.0

- Main Page
- Related Pages
- Namespaces
- Classes
- Files
- Directories
- Examples

DumpADAC.cxx

    /*=========================================================================

      Program: GDCM (Grassroots DICOM). A DICOM library

      Copyright (c) 2006-2011 Mathieu Malaterre
      All rights reserved.
      See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.

         This software is distributed WITHOUT ANY WARRANTY; without even
         the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
         PURPOSE.  See the above copyright notice for more information.

    =========================================================================*/
    /*
     * the goal of this example is to mimic the behavior of disp_img_header
     * see http://www.gmecorp-usa.com/IM/NM/GC/ADAC/SV/adactechtips/Released_01Q3.pdf
     */
    #include "gdcmReader.h"
    #include "gdcmPrivateTag.h"
    #include "gdcmAttribute.h"
    #include "gdcmImageWriter.h"

    #include <iostream>
    #include <fstream>
    #include <vector>

    #include <string.h>
    #include <assert.h>
    #include <stdint.h>

    struct dict
    {
      uint16_t key;
      const char *name;
    };

    dict Array[] = {
      { 0x01, "Patient name" },
      { 0x02, "Patient ID" },
      { 0x03, "Patient sex" },
      { 0x04, "Patient age" },
      { 0x05, "Patient height" },
      { 0x06, "Patient weight" },
      { 0x07, "Exam date" },
      { 0x08, "Dose admin. time" },
      { 0x09, "Unique exam key" },
      { 0x0a, "Exam procedure" },
      { 0x0b, "Referring physician" },
      { 0x0c, "Attending physician" },
      { 0x0d, "Imaging modality" },
      { 0x0e, "Hospital ID" },
      { 0x0f, "Histogram crv file" },
      { 0x10, "Acq. start time" },
      { 0x11, "Object data type" },
      { 0x12, "Image viewid" },
      { 0x13, "Imaging device name" },
      { 0x14, "Device serial number" },
      { 0x15, "Collimator" },
      { 0x16, "Software version" },
      { 0x17, "Radiopharmaceutical #1" },
      { 0x18, "Energy window #1 center" },
      { 0x19, "Radiopharmaceutical #2" },
      { 0x1a, "Energy window #1 width" },
      { 0x1b, "Isotope imaging mode" },
      { 0x1c, "Energy window #2 center" },
      { 0x1d, "Energy window #2 width" },
      { 0x1e, "Energy window #3 center" },
      { 0x1f, "Energy window #3 width" },
      { 0x20, "Energy window #4 center" },
      { 0x21, "Energy window #4 width" },
      { 0x22, "??Energy window #5 center" },
      { 0x23, "??Energy window #5 width" },
      { 0x24, "Patient orientation" },
      { 0x25, "Spatial resolution" },
      { 0x26, "Slice thickness" },
      { 0x27, "Image X dimension" },
      { 0x28, "Image Y dimension" },
      { 0x29, "Image Z dimension" },
      { 0x2a, "Image pixel width" },
      { 0x2b, "Uniformity corr. file" },
      { 0x2c, "Acquisition zoom factor" },
      { 0x2d, "Total counts in set" },
      { 0x2e, "Time / frame" },
      { 0x2f, "Total acq. time" },
      { 0x30, "Maximum pixel value" },
      { 0x31, "Minimum pixel value" },
      { 0x32, "R-R interval time" },
      { 0x33, "Percent of cycle imaged" },
      { 0x34, "# of cycles accepted" },
      { 0x35, "# of cycles rejected" },
      { 0x36, "Approximate ED frame" },
      { 0x37, "Approximate ES frame" },
      { 0x38, "Approximate EF" },
      { 0x39, "Starting angle" },
      { 0x3a, "Degrees of rotation" },
      { 0x3b, "Direction of rotation" },
      { 0x3c, "Cont. or step/shoot" },
      { 0x3d, "Lim recon start frame" },
      { 0x3e, "Upper window grey shade" },
      { 0x3f, "Lower lvl grey shade" },
      { 0x40, "Associated color map" },
      { 0x41, "Custom color map file" },
      { 0x42, "Manipulated image" },
      { 0x43, "Axis of rotation corr." },
      { 0x44, "Reorientation azimuth" },
      { 0x45, "Reorientation elevation" },
      { 0x46, "Filter type" },
      { 0x47, "Filter order" },
      { 0x48, "Filter cutoff frequency" },
      { 0x49, "Reconstruction type" },
      { 0x4a, "Attenuation coefficient" },
      { 0x4b, "Associated parent file" },
      { 0x4c, "Unique patient key" },
      { 0x52, "Normalization crv file" },
      { 0x53, "Unique object key" },
      { 0x54, "This phase of VFR is" },
      { 0x55, "True color value" },
      { 0x56, "# of sets of x,y,z grps" },
      { 0x57, "Scale factor of set" },
      { 0x6d, "Date of birth" },
      { 0x6e, "Directional orientation" },
      { 0x6f, "Number of VFR studies" },
      { 0x70, "R-R low tolerance" },
      { 0x71, "R-R high tolerance" },
      { 0x72, "Prog specific results:" },

      { 0x99, NULL }
    };

    void printname( int , int , uint16_t v )
    {
      if( v == 0x1 )
        {
        std::cout << "DATABASE PARAMETERS" << std::endl;
        std::cout << "___________________" << std::endl;
        }
      else if( v == 0x27 )
        {
        std::cout << "IMAGE PARAMETERS" << std::endl;
        std::cout << "________________" << std::endl;
        }
      else if( v == 0x13 )
        {
        std::cout << "EXTRA PARAMETERS" << std::endl;
        std::cout << "________________" << std::endl;
        }
      else if( v == 0x2e )
        {
        std::cout << "*** NOT CURRENTLY USED :" << std::endl;
        }
      static const unsigned int n = sizeof( Array ) / sizeof( *Array ) - 1;
      for( unsigned int i = 0; i < n; ++i )
        {
        if( v == Array[i].key )
          {
          std::cout << /*"" << std::dec << len << "," << mult << " " << */ Array[i].name;
          std::cout << " : ";
          return;
          }
        }
      std::cout << /*"\t# " << std::dec << len << "," << mult << */ std::hex << v << "\t: ";
    }

    uint16_t readint16(std::istream &is )
    {
      uint16_t val;
      is.read( (char*)&val, sizeof( val ));
      return (val>>8) | (val<<8);
    }

    uint32_t readint32(std::istream &is )
    {
      uint32_t val;
      is.read( (char*)&val, sizeof( val ));
      val= ((val<<8)&0xFF00FF00) | ((val>>8)&0x00FF00FF);
      return (val>>16) | (val<<16);
    }

    float readfloat32(std::istream &is )
    {
      union { uint32_t val; float f;} dual;
      dual.val = readint32(is);
      return dual.f;
    }

    struct el
    {
      uint16_t v1;
      uint16_t v2;
      uint16_t v3;
      void read( std::istream & is )
        {
        v1 = readint16(is);
        v2 = readint16(is);
        v3 = readint16(is);
        }
      void print( std::ostream & os )
        {
        os << std::hex << v1 << "\t" << v2 << "\t" << v3 << std::endl;
        }
    };

    std::vector<el> Vel;

    void readelement( std::istream & is )
    {
      el e;
      e.read( is );
      Vel.push_back( e );
    }

    void printascii( uint16_t tag, const char *buffer, size_t len )
    {
      std::ostream & os = std::cout;
      if( tag == 0x72 )
        {
        os << "\n  ";
        for(size_t i = 0; i < len; ++i)
          {
          const char &c = buffer[i];
          if( c == 0x0 ) os << "!";
          else if( c == 0x0f ) os << " ";
          else if( c == 0x17 ) os << ":";
          else if( c == 0x14 ) os << ":";
          else if( c == 0x10 ) os << ":";
          else if( c == 0x16 ) os << ":";
          else if( c == 0x08 ) os << ":";
          else if( c == 0x0b ) os << ":";
          else if( c == 0x0e ) os << ":";
          else if( c == 0x07 ) os << ":";
          else os << c;
          }
        os << "";
        }
      else
        {
        (void)len;
        os << "" << buffer << "";
        }
    }

    bool DumpADAC( std::istream & is )
    {
      std::ostream &os = std::cout;

      char magic[6 + 1];
      magic[6] = 0;
      is.read( magic, 6);
    //  std::cout << magic << " ";
      assert( strcmp( magic, "adac01" ) == 0 );
      char c = is.get();
      assert( c == 0 );
      c = is.get();
      assert( c == 'X' );

      uint16_t v;
      v = readint16(is);
    //  std::cout << v << std::endl;
      assert( v == 512 ); // ??

      int nel = 87;
      for (int i = 0; i <= nel; ++i )
        {
        readelement( is );
        }

      char buffer[512];
      for( int i = 0; i <= nel; ++i )
        {
        const el &e = Vel[i];
        int diff;
        if( i == nel )
          {
          diff = 2048 - e.v3;
          if( diff > 512 ) diff = 512;
          }
        else
          {
          const el &enext = Vel[i+1];
          diff = enext.v3 - e.v3;
          }
        is.seekg( e.v3, std::ios::beg );
        //std::cout << "(" << std::hex << std::setw( 2 ) << std::setfill( '0' ) << e.v1 << ") " << std::hex << std::setw( 3 ) << std::setfill( '0' ) << e.v2 << " ";
        printname( diff, 0, e.v1 );
        int mult = 1;
        if( e.v2 == 0 )
          {
          is.read( buffer, diff);
          buffer[ diff ] = 0;
          printascii( e.v1, buffer, diff);
          }
        else if( e.v2 == 0x100 )
          {
          mult = diff / 2;
          assert( diff == 2 * mult );
          for ( int ii = 0; ii < mult; ++ii )
            {
            if ( ii ) os << "\\";
            uint16_t val = readint16(is);
            os << "" << std::dec << val << "";
            }
          }
        else if( e.v2 == 0x200 )
          {
          assert( diff == 4 );
          uint32_t val = readint32(is);
          os << "" << std::dec << val << "";
          }
        else if( e.v2 == 0x300 )
          {
          assert( diff == 4 );
          float val = readfloat32(is);
          os << "" << std::dec << val << "";
          }
         else
          {
          assert( 0 );
          }
        os << std::endl;
        }
      return true;
    }

    int main(int argc, char *argv[])
    {
      if( argc < 2 ) return 1;
      const char *filename = argv[1];
      gdcm::Reader reader;
      reader.SetFileName( filename );
      if( !reader.Read() )
        {
        std::cerr << "Failed to read: " << filename << std::endl;
        return 1;
        }
      const gdcm::DataSet& ds = reader.GetFile().GetDataSet();

      // (0019,1061) UN (OB) 61\64\61\63\30         # 2048,1 Ver200 ADAC Pegasys Headers
      const gdcm::PrivateTag tver200adacpegasysheaders(0x0019,0x61,"ADAC_IMG");
      if( !ds.FindDataElement( tver200adacpegasysheaders ) ) return 1;
      const gdcm::DataElement& ver200adacpegasysheaders = ds.GetDataElement( tver200adacpegasysheaders );
      if ( ver200adacpegasysheaders.IsEmpty() ) return 1;
      const gdcm::ByteValue * bv = ver200adacpegasysheaders.GetByteValue();

      // (0019,1021) US 1               # 2,1 Ver200 Number of ADAC Headers
      // TODO

      // (0019,1041) IS [2048\221184 ]  # 12,1-n Ver200 ADAC Header/Image Size
      if( bv->GetLength() != 2048 ) return 1;

      gdcm::Element<gdcm::VR::IS,gdcm::VM::VM2> el;
      const gdcm::PrivateTag tver200adacheaderimagesize(0x0019,0x41,"ADAC_IMG");
      if( !ds.FindDataElement( tver200adacheaderimagesize ) ) return 1;
      const gdcm::DataElement& ver200adacheaderimagesize = ds.GetDataElement( tver200adacheaderimagesize );
      el.SetFromDataElement( ver200adacheaderimagesize );
      if( el.GetValue(0) != 2048 ) return 1;

      std::istringstream is;
      std::string dup( bv->GetPointer(), bv->GetLength() );
      is.str( dup );
      bool b = DumpADAC( is );
      if( !b ) return 1;

      return 0;
    }