[med-svn] [gdcm] 01/01: New upstream version 2.8.2

Gert Wollny gewo at moszumanska.debian.org
Tue Aug 1 17:21:04 UTC 2017


This is an automated email from the git hooks/post-receive script.

gewo pushed a commit to branch upstream
in repository gdcm.

commit 363b32c3336bab7f4e7c662de0fe6f6b6aa1ab93
Author: Gert Wollny <gewo at debian.org>
Date:   Tue Aug 1 06:39:18 2017 +0000

    New upstream version 2.8.2
---
 .travis.yml                                        |   6 +-
 Applications/Cxx/gdcmdump.cxx                      |  35 ++
 Applications/Cxx/gdcminfo.cxx                      |  35 +-
 Applications/Cxx/gdcmtar.cxx                       |  70 ++-
 CMakeLists.txt                                     |   2 +-
 Examples/Cxx/EmptyMask.cxx                         | 242 +-------
 Examples/Cxx/MrProtocol.cxx                        |   6 +
 Source/Common/gdcmMD5.cxx                          |   1 +
 Source/Common/gdcmSystem.cxx                       |   2 +-
 Source/DataDictionary/gdcmUIDs.cxx                 |   2 +
 .../CMakeLists.txt                                 |   1 +
 .../gdcmCSAHeader.cxx                              |  49 ++
 .../gdcmCSAHeader.h                                |  12 +-
 .../gdcmMrProtocol.cxx                             | 210 +++++++
 .../gdcmMrProtocol.h                               |  83 +++
 Source/MediaStorageAndFileFormat/CMakeLists.txt    |   1 +
 .../gdcmDirectionCosines.cxx                       |  26 +-
 .../gdcmDirectionCosines.h                         |   6 +
 .../gdcmEmptyMaskGenerator.cxx                     | 465 ++++++++++++++
 .../gdcmEmptyMaskGenerator.h                       |  80 +++
 .../MediaStorageAndFileFormat/gdcmPixmapWriter.cxx |   2 +-
 Source/MediaStorageAndFileFormat/gdcmPrinter.cxx   |   2 +-
 .../gdcmSplitMosaicFilter.cxx                      | 190 +++++-
 .../gdcmSplitMosaicFilter.h                        |   6 +
 .../MediaStorageAndFileFormat/Cxx/CMakeLists.txt   |   2 +
 .../Cxx/TestSplitMosaicFilter.cxx                  |  15 +-
 .../Cxx/TestSplitMosaicFilter2.cxx                 | 220 +++++++
 .../Cxx/TestSplitMosaicFilter3.cxx                 | 173 ++++++
 Utilities/doxygen/man/gdcmdump.xml                 | 680 +++++++++++++++++++++
 Utilities/doxygen/man/gdcminfo.xml                 |   7 +
 Utilities/doxygen/man/gdcmtar.xml                  |   8 +-
 Wrapping/Python/gdcmswig.i                         |   6 +-
 32 files changed, 2391 insertions(+), 254 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 8b3a54e..94c1958 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -29,10 +29,12 @@ matrix:
         - CPACK_NAME=Linux
     - compiler: gcc
       os: linux
+        # No docbook-xsl-ns
       addons: {apt: {packages: [default-jdk, mono-devel, swig, libcharls-dev, libvtk5-dev, libexpat-dev, libz-dev, uuid-dev, python-all-dev, libpoppler-dev, xsltproc, docbook-xsl, dcmtk]}}
       env:
         - CFLAGS="-Wall -Wextra -m64"
         - CXXFLAGS="-Wall -Wextra -m64"
+        # Cant use manpage with old docbook
         - CMAKE_EXTRA="-DGDCM_USE_SYSTEM_OPENSSL:BOOL=ON -DGDCM_WRAP_PYTHON:BOOL=ON -DGDCM_WRAP_CSHARP:BOOL=ON -DGDCM_WRAP_JAVA:BOOL=ON -DGDCM_WRAP_PHP:BOOL=OFF -DGDCM_USE_SYSTEM_EXPAT:BOOL=ON -DGDCM_USE_SYSTEM_JSON:BOOL=OFF -DGDCM_USE_SYSTEM_LIBXML2:BOOL=ON -DGDCM_USE_SYSTEM_OPENJPEG:BOOL=OFF -DGDCM_USE_SYSTEM_POPPLER:BOOL=ON -DGDCM_USE_SYSTEM_UUID:BOOL=ON -DGDCM_USE_SYSTEM_ZLIB:BOOL=ON -DGDCM_WEAK_SWIG_CHECK:BOOL=ON -DGDCM_LEGACY_SILENT:BOOL=ON -DGDCM_BUILD_DOCBOOK_MANPAGES:BOOL=OFF"
         - B_NAME=system
         - CPACK_NAME=Linux
@@ -51,7 +53,7 @@ matrix:
         - CXXFLAGS="-Wall -Wextra" # -m64 -fsanitize=address,undefined
         # http://stackoverflow.com/questions/15678153/homebrew-python-on-mac-os-x-10-8-fatal-python-error-pythreadstate-get-no-cu
         #- CMAKE_EXTRA="-DGDCM_WRAP_PYTHON:BOOL=ON -DGDCM_BUILD_DOCBOOK_MANPAGES:BOOL=OFF -DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/python2.7"
-        - CMAKE_EXTRA="-DGDCM_WRAP_PYTHON:BOOL=ON -DGDCM_BUILD_DOCBOOK_MANPAGES:BOOL=OFF"
+        - CMAKE_EXTRA="-DGDCM_WRAP_PYTHON:BOOL=ON -DGDCM_WRAP_CSHARP:BOOL=OFF -DGDCM_WRAP_JAVA:BOOL=ON -DGDCM_USE_SYSTEM_UUID:BOOL=ON -DGDCM_USE_SYSTEM_ZLIB:BOOL=ON -DGDCM_BUILD_DOCBOOK_MANPAGES:BOOL=OFF"
         - B_NAME=default
         - CPACK_NAME=Darwin
 
@@ -64,7 +66,7 @@ before_install:
   # https://docs.travis-ci.com/user/osx-ci-environment/#Environment-variables
   - if [ "$TRAVIS_OS_NAME" == "osx" ]; then mv Testing/Data Testing/Data.old; fi
   - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew update                     ; fi
-  - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install swig python3       ; fi
+  - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install swig docbook-xsl   ; fi
   # https://github.com/travis-ci/travis-ci/issues/2312
   #- if [ "$TRAVIS_OS_NAME" == "osx" ]; then virtualenv env -p python3       ; fi
   #- if [ "$TRAVIS_OS_NAME" == "osx" ]; then source env/bin/activate         ; fi
diff --git a/Applications/Cxx/gdcmdump.cxx b/Applications/Cxx/gdcmdump.cxx
index 41ba9e4..24a6176 100644
--- a/Applications/Cxx/gdcmdump.cxx
+++ b/Applications/Cxx/gdcmdump.cxx
@@ -964,6 +964,30 @@ static int PrintCSA(const std::string & filename)
   return ret;
 }
 
+static int PrintMrProtocol(const std::string & filename)
+{
+  gdcm::Reader reader;
+  reader.SetFileName( filename.c_str() );
+  if( !reader.Read() )
+  {
+    std::cerr << "Failed to read: " << filename << std::endl;
+    return 1;
+  }
+
+  gdcm::CSAHeader csa;
+  const gdcm::DataSet& ds = reader.GetFile().GetDataSet();
+  gdcm::MrProtocol mrprot;
+  if( csa.GetMrProtocol(ds, mrprot))
+  {
+    std::cout << mrprot;
+  }
+  else
+  {
+    std::cout << "Could not find MrProtocol/MrPhoenixProtocol ASCII section" << std::endl;
+  }
+
+  return 0;
+}
 
 
 static void PrintVersion()
@@ -989,6 +1013,7 @@ static void PrintHelp()
   std::cout << "  -C --csa            print SIEMENS CSA Header (0029,[12]0,SIEMENS CSA HEADER)." << std::endl;
   std::cout << "     --csa-asl        print decoded SIEMENS CSA MR_ASL (base64)." << std::endl;
   std::cout << "     --csa-diffusion  print decoded SIEMENS CSA MRDiffusion (base64)." << std::endl;
+  std::cout << "     --mrprotocol     print SIEMENS CSA MrProtocol only (within ASCCONV BEGIN/END)." << std::endl;
   std::cout << "  -P --pdb            print GEMS Protocol Data Block (0025,1b,GEMS_SERS_01)." << std::endl;
   std::cout << "     --elscint        print ELSCINT Protocol Information (01f7,26,ELSCINT1)." << std::endl;
   std::cout << "     --vepro          print VEPRO Protocol Information (0055,20,VEPRO VIF 3.0 DATA)." << std::endl;
@@ -1018,6 +1043,7 @@ int main (int argc, char *argv[])
   int dump = 0;
   int print = 0;
   int printcsa = 0;
+  int printmrprotocol = 0;
   int printcsabase64 = 0;
   int printcsaasl = 0;
   int printcsadiffusion = 0;
@@ -1070,6 +1096,7 @@ int main (int argc, char *argv[])
         {"ct3", 0, &printct3, 1},
         {"csa-asl", 0, &printcsaasl, 1},
         {"csa-diffusion", 0, &printcsadiffusion, 1},
+        {"mrprotocol", 0, &printmrprotocol, 1},
         {0, 0, 0, 0} // required
     };
     static const char short_options[] = "i:xrpdcCPAVWDEhvI";
@@ -1299,6 +1326,10 @@ int main (int argc, char *argv[])
         {
         res += PrintCSA(*it);
         }
+      else if( printmrprotocol )
+        {
+        res += PrintMrProtocol(*it);
+        }
       else if( printcsabase64 )
         {
         res += PrintCSABase64(*it, csaname);
@@ -1350,6 +1381,10 @@ int main (int argc, char *argv[])
       {
       res += PrintCSA(filename);
       }
+    else if( printmrprotocol )
+      {
+      res += PrintMrProtocol(filename);
+      }
     else if( printcsabase64 )
       {
       res += PrintCSABase64(filename, csaname);
diff --git a/Applications/Cxx/gdcminfo.cxx b/Applications/Cxx/gdcminfo.cxx
index be862f3..bf8b013 100644
--- a/Applications/Cxx/gdcminfo.cxx
+++ b/Applications/Cxx/gdcminfo.cxx
@@ -31,6 +31,7 @@
 #include "gdcmSystem.h"
 #include "gdcmDirectory.h"
 #include "gdcmImageHelper.h"
+#include "gdcmSplitMosaicFilter.h"
 
 #ifdef GDCM_USE_SYSTEM_POPPLER
 #include <poppler/poppler-config.h>
@@ -319,6 +320,7 @@ static void PrintHelp()
 //  std::cout << "  -b --check-big-endian   check if file is ." << std::endl;
   std::cout << "     --force-rescale    force rescale." << std::endl;
   std::cout << "     --force-spacing    force spacing." << std::endl;
+  std::cout << "     --mosaic           dump image information of MOSAIC." << std::endl;
 
   std::cout << "General Options:" << std::endl;
   std::cout << "  -V --verbose   more verbose (warning+error)." << std::endl;
@@ -334,6 +336,7 @@ static void PrintHelp()
   int deflated = 0; // check deflated
   int checkcompression = 0;
   int md5sum = 0;
+  int mosaic = 0;
 
 static int ProcessOneFile( std::string const & filename, gdcm::Defs const & defs )
 {
@@ -382,27 +385,42 @@ static int ProcessOneFile( std::string const & filename, gdcm::Defs const & defs
       std::cerr << "Could not read image from: " << filename << std::endl;
       return 1;
       }
-    //const gdcm::File &file = reader.GetFile();
-    //const gdcm::DataSet &ds = file.GetDataSet();
+    gdcm::SplitMosaicFilter filter;
+    const gdcm::Image *pimage = NULL;
     const gdcm::Image &image = reader.GetImage();
-    const double *dircos = image.GetDirectionCosines();
+    if( mosaic )
+    {
+      filter.SetImage( image );
+      filter.SetFile( reader.GetFile() );
+      if( !filter.Split() )
+      {
+      std::cerr << "Could not split mosaic : " << filename << std::endl;
+      return 1;
+      }
+      pimage = &filter.GetImage();
+    }
+    else
+    {
+    pimage = ℑ
+    }
+    const double *dircos = pimage->GetDirectionCosines();
     gdcm::Orientation::OrientationType type = gdcm::Orientation::GetType(dircos);
     const char *label = gdcm::Orientation::GetLabel( type );
-    image.Print( std::cout );
+    pimage->Print( std::cout );
     std::cout << "Orientation Label: " << label << std::endl;
     if( checkcompression )
       {
-      bool lossy = image.IsLossy();
+      bool lossy = pimage->IsLossy();
       std::cout << "Encapsulated Stream was found to be: " << (lossy ? "lossy" : "lossless") << std::endl;
       }
 
     if( md5sum )
       {
-      char *buffer = new char[ image.GetBufferLength() ];
-      if( image.GetBuffer( buffer ) )
+      char *buffer = new char[ pimage->GetBufferLength() ];
+      if( pimage->GetBuffer( buffer ) )
         {
         char digest[33] = {};
-        gdcm::MD5::Compute( buffer, image.GetBufferLength(), digest );
+        gdcm::MD5::Compute( buffer, pimage->GetBufferLength(), digest );
         std::cout << "md5sum: " << digest << std::endl;
         }
       else
@@ -563,6 +581,7 @@ int main(int argc, char *argv[])
         {"check-compression", 0, &checkcompression, 1},
         {"force-rescale", 0, &forcerescale, 1},
         {"force-spacing", 0, &forcespacing, 1},
+        {"mosaic", 0, &mosaic, 1},
 
         {"verbose", 0, &verbose, 1},
         {"warning", 0, &warning, 1},
diff --git a/Applications/Cxx/gdcmtar.cxx b/Applications/Cxx/gdcmtar.cxx
index 7ac126a..f16f39b 100644
--- a/Applications/Cxx/gdcmtar.cxx
+++ b/Applications/Cxx/gdcmtar.cxx
@@ -37,6 +37,9 @@
 #include "gdcmScanner.h"
 #include "gdcmIPPSorter.h"
 #include "gdcmAttribute.h"
+#include "gdcmAnonymizer.h"
+#include "gdcmTagKeywords.h"
+#include "gdcmMrProtocol.h"
 
 #include <string>
 #include <iostream>
@@ -65,6 +68,7 @@ static void PrintHelp()
   std::cout << "     --enhance    enhance (default)" << std::endl;
   std::cout << "  -U --unenhance  unenhance" << std::endl;
   std::cout << "  -M --mosaic     Split SIEMENS Mosaic image into multiple frames." << std::endl;
+  std::cout << "     --mosaic-private When splitting SIEMENS Mosaic image into multiple frames, ppreserve private attributes (advanced user only)." << std::endl;
   std::cout << "  -p --pattern    Specify trailing file pattern." << std::endl;
   std::cout << "     --root-uid        Root UID." << std::endl;
   //std::cout << "     --resources-path     Resources path." << std::endl;
@@ -957,6 +961,7 @@ int main (int argc, char *argv[])
   std::string root;
   int resourcespath = 0;
   int mosaic = 0;
+  int mosaic_private = 0;
   int enhance = 1;
   int unenhance = 0;
   std::string xmlpath;
@@ -981,6 +986,7 @@ int main (int argc, char *argv[])
         {"unenhance", 0, &unenhance, 1},               // unenhance
         {"root-uid", 1, &rootuid, 1}, // specific Root (not GDCM)
         //{"resources-path", 0, &resourcespath, 1},
+        {"mosaic-private", 0, &mosaic_private, 1}, // keep private attributes
 
 // General options !
         {"verbose", 0, &verbose, 1},
@@ -1246,8 +1252,7 @@ int main (int argc, char *argv[])
     const unsigned int *dims = image.GetDimensions();
     const gdcm::DataElement &pixeldata = image.GetDataElement();
     const gdcm::ByteValue *bv = pixeldata.GetByteValue();
-    unsigned long slice_len = image.GetBufferLength() / dims[2];
-    //assert( image.GetBufferLength() == bv->GetLength() );
+    size_t slice_len = image.GetBufferLength() / dims[2];
 
     gdcm::FilenameGenerator fg;
     fg.SetNumberOfFilenames( dims[2] );
@@ -1265,17 +1270,78 @@ int main (int argc, char *argv[])
     const double *origin = image.GetOrigin();
     double zspacing = image.GetSpacing(2);
 
+    gdcm::CSAHeader csa;
+    gdcm::DataSet & ds = reader.GetFile().GetDataSet();
+
+    gdcm::MrProtocol mrprot;
+    if( !csa.GetMrProtocol(ds, mrprot) ) return 1;
+
+    gdcm::MrProtocol::SliceArray sa;
+    b = mrprot.GetSliceArray(sa);
+    if( !b ) return 1;
+
+    size_t size = sa.Slices.size();
+    if( !size ) return 1;
+
+    if( !mosaic_private )
+    {
+      gdcm::Anonymizer ano;
+      ano.SetFile( reader.GetFile() );
+      // Remove CSA header
+      ano.RemovePrivateTags();
+    }
+
+    double slicePos[3];
+    double sliceNor[3];
+    namespace kwd = gdcm::Keywords;
+    gdcm::UIDGenerator ug;
+
+    kwd::InstanceNumber instart;
+    instart.Set(ds);
+    int istart = instart.GetValue();
+
     for(unsigned int i = 0; i < dims[2]; ++i)
       {
+      gdcm::MrProtocol::Slice & protSlice = sa.Slices[i];
+      gdcm::MrProtocol::Vector3 & protV = protSlice.Position;
+      gdcm::MrProtocol::Vector3 & protN = protSlice.Normal;
+      slicePos[0] = protV.dSag;
+      slicePos[1] = protV.dCor;
+      slicePos[2] = protV.dTra;
+      sliceNor[0] = protN.dSag;
+      sliceNor[1] = protN.dCor;
+      sliceNor[2] = protN.dTra;
+
       double new_origin[3];
       for (int j = 0; j < 3; j++)
         {
         // the n'th slice is n * z-spacing aloung the IOP-derived
         // z-axis
         new_origin[j] = origin[j] + normal[j] * i * zspacing;
+        if( std::fabs(slicePos[j] - new_origin[j]) > 1e-3 )
+          {
+          gdcmErrorMacro("Invalid position found");
+          return 1;
+          }
+        const double snv_dot = gdcm::DirectionCosines::Dot( normal, sliceNor );
+        if( std::fabs(1. - snv_dot) > 1e-6 )
+          {
+          gdcmErrorMacro("Invalid direction found");
+          return false;
+          }
         }
 
+      kwd::SOPInstanceUID sid;
+      sid.SetValue( ug.Generate() );
+      ds.Replace( sid.GetAsDataElement() );
+
       const char *outfilenamei = fg.GetFilename(i);
+      kwd::SliceLocation sl;
+      sl.SetValue( new_origin[2] );
+      ds.Replace( sl.GetAsDataElement() );
+      kwd::InstanceNumber in;
+      in.SetValue( istart + i ); // Start at mosaic instance number
+      ds.Replace( in.GetAsDataElement() );
       gdcm::ImageWriter writer;
       writer.SetFileName( outfilenamei );
       //writer.SetFile( filter.GetFile() );
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d8be715..1342e89 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -35,7 +35,7 @@ set(GDCM_PACKAGE_CONTACT "GDCM Developers <gdcm-developers at lists.sourceforge.net
 #----------------------------------------------------------------------------
 set(GDCM_MAJOR_VERSION 2)
 set(GDCM_MINOR_VERSION 8)
-set(GDCM_BUILD_VERSION 0)
+set(GDCM_BUILD_VERSION 2)
 set(GDCM_VERSION
   "${GDCM_MAJOR_VERSION}.${GDCM_MINOR_VERSION}.${GDCM_BUILD_VERSION}")
 # let advanced user the option to define GDCM_API_VERSION:
diff --git a/Examples/Cxx/EmptyMask.cxx b/Examples/Cxx/EmptyMask.cxx
index f829a22..7ee8009 100644
--- a/Examples/Cxx/EmptyMask.cxx
+++ b/Examples/Cxx/EmptyMask.cxx
@@ -11,224 +11,44 @@
      PURPOSE.  See the above copyright notice for more information.
 
 =========================================================================*/
-#include "gdcmImage.h"
-#include "gdcmImageWriter.h"
-#include "gdcmFileDerivation.h"
-#include "gdcmUIDGenerator.h"
-#include "gdcmImageRegionReader.h"
-#include "gdcmDirectory.h"
-#include "gdcmScanner.h"
-#include "gdcmFilename.h"
-#include "gdcmFileStreamer.h"
-#include "gdcmAnonymizer.h"
-#include "gdcmAttribute.h"
+#include "gdcmEmptyMaskGenerator.h"
 
-static gdcm::Tag t1(0x8,0x16);
-static gdcm::Tag t2(0x8,0x18);
-static gdcm::Tag t3(0x20,0xe);
-static gdcm::Tag t4(0x20,0x52);
- 
-static bool EmptyMaskDICOMFile( gdcm::UIDGenerator & uid, const gdcm::Scanner & s,
-  const std::map< std::string, std::string > & seriesuidhash,
-  const std::map< std::string, std::string > & framerefuidhash,
-  const char * outfile, const char * filename )
-{
-  if( s.IsKey( filename ) )
-  {
-    gdcm::ImageRegionReader irr;
-    irr.SetFileName( filename );
-    const bool b3 = irr.ReadInformation();
-    (void)b3;
-    size_t buflen = irr.ComputeBufferLength();
-
-    // Step 2: DERIVED object
-    gdcm::FileDerivation fd;
-    const char * ReferencedSOPClassUID =  s.GetValue (filename, t1);
-    const char * ReferencedSOPInstanceUID =  s.GetValue (filename, t2);
-    if( !fd.AddReference( ReferencedSOPClassUID, ReferencedSOPInstanceUID ) )
-    {
-      //std::cerr << "AddRef: " << (ReferencedSOPClassUID ? ReferencedSOPClassUID : "") << "," << (ReferencedSOPInstanceUID ? ReferencedSOPInstanceUID : "") << std::endl;
-      std::cerr << "AddRef: " << filename << std::endl;
-      // This is not considered an error to not reference, eg. UID padded with 0
-    }
-
-    // CID 7202 Source Image Purposes of Reference
-    // DCM 121321 Mask image for image processing operation
-    fd.SetPurposeOfReferenceCodeSequenceCodeValue( 121321 );
-    // CID 7203 Image Derivation
-    // DCM 113047 Pixel by pixel mask
-    fd.SetDerivationCodeSequenceCodeValue( 113047 );
-    fd.SetDerivationDescription( "Empty Mask Derivation" );
-    fd.SetAppendDerivationHistory( true );
-    fd.SetFile( irr.GetFile() );
-    if( !fd.Derive() )
-    {
-      std::cerr << "Sorry could not derive using input info" << std::endl;
-      return false;
-    }
-
-    gdcm::Anonymizer ano;
-    ano.SetFile( fd.GetFile() );
-    ano.RemoveGroupLength();
-    ano.Replace (t2, uid.Generate());
-    const char * oldseriesuid =  s.GetValue (filename, t3);
-    const char * oldframerefuid =  s.GetValue (filename, t4);
-    if( oldseriesuid )
-    {
-      std::map< std::string, std::string >::const_iterator it1 = seriesuidhash.find( oldseriesuid );
-      ano.Replace (t3, it1->second.c_str() );
-    }
-    if( oldframerefuid )
-    {
-      std::map< std::string, std::string >::const_iterator it2 = framerefuidhash.find( oldframerefuid );
-      ano.Replace (t4, it2->second.c_str() );
-    }
-
-    {
-      gdcm::DataSet& ds = ano.GetFile().GetDataSet();
-      gdcm::Attribute<0x0008,0x0008> at3;
-      gdcm::Attribute<0x0008,0x0008> at4;
-      at3.SetFromDataSet( ds );
-      unsigned int nvalues = at3.GetNumberOfValues();
-      unsigned int newvalues = std::max( nvalues, 4u );
-      at4.SetNumberOfValues( newvalues );
-      // copy original ones:
-      for( unsigned int i = 0u; i < nvalues; ++i )
-      {
-        at4.SetValue(i, at3.GetValue(i) );
-      }
-      // Make up non empty values:
-      static const gdcm::CSComp values[] = {"DERIVED","SECONDARY","OTHER"};
-      for( unsigned int i = nvalues; i < 3u;  ++i )
-      {
-        at4.SetValue(i, values[i] );
-      }
-      // why not:
-      at4.SetValue( 3u, "MASK" );
-      ds.Replace( at4.GetAsDataElement() );
-    }
-
-    gdcm::File & file = ano.GetFile();
-    gdcm::FileMetaInformation & fmi = file.GetHeader();
-    const gdcm::TransferSyntax & orits = fmi.GetDataSetTransferSyntax();
-    gdcm::TransferSyntax::TSType newts = gdcm::TransferSyntax::ImplicitVRLittleEndian;
-    if( orits.IsExplicit() )
-    {
-      newts = gdcm::TransferSyntax::ExplicitVRLittleEndian;
-    }
-    fmi.Clear();
-    fmi.SetDataSetTransferSyntax( newts );
-
-    gdcm::Writer w;
-    w.SetFile( ano.GetFile() );
-
-    // Set the filename:
-    w.SetFileName( outfile );
-    if( !w.Write() )
-    {
-      return false;
-    }
-    gdcm::FileStreamer fs;
-    fs.SetTemplateFileName(outfile);
-    fs.SetOutputFileName(outfile);
-    gdcm::Tag pixeldata (0x7fe0, 0x0010);
-    fs.CheckDataElement( pixeldata );
-    if( !fs.StartDataElement( pixeldata ) )
-    {
-      std::cerr << "StartDataElement" << std::endl;
-      return false;
-    }
-    {
-      const size_t chunk = 4096;
-      char bytes[chunk] = {};
-      const size_t nchunks = buflen / chunk;
-      const size_t remain = buflen % chunk;
-      for( size_t i = 0; i < nchunks; ++i )
-      {
-        // Read the source file into a byte array.
-        fs.AppendToDataElement( pixeldata, bytes, chunk );
-      }
-      fs.AppendToDataElement( pixeldata, bytes, remain );
-    }
-    if( !fs.StopDataElement( pixeldata ) )
-    {
-      // Most likely an issue with Pixel Data Length computation:
-      std::cerr << "StopDataElement" << std::endl;
-      return false;
-    }
-  }
-  else
-  {
-    std::cerr << "Not DICOM file: " << filename << std::endl;
-    return false;
-  }
-  return true;
-}
+#include <string>
+#include <cstring>
 
-int main(int, char *argv[])
+int main( int argc, char *argv[] )
 {
-  gdcm::FileMetaInformation::SetSourceApplicationEntityTitle( "EmptyMask" );
-  const char * dirname = argv[1];
-  const char * outdir = argv[2];
-  gdcm::System::FileIsDirectory( dirname );
-  gdcm::System::MakeDirectory( outdir );
-  gdcm::Directory d;
-  const unsigned int nfiles = d.Load( dirname, true );
-  (void)nfiles;
-  gdcm::Directory::FilenamesType const & filenames = d.GetFilenames();
-
-  gdcm::Trace::WarningOff();
-  gdcm::Trace::ErrorOff();
-
-  gdcm::Scanner s;
-  s.AddTag( t1 );
-  s.AddTag( t2 );
-  s.AddTag( t3 );
-  s.AddTag( t4 );
-  const bool b2 = s.Scan( filenames );
-  (void)b2;
-  gdcm::UIDGenerator uid;
-  int ret = 0;
-  std::map< std::string, std::string > seriesuidhash;
+  std::string inputdir;
+  std::string outputdir;
+  bool input_sopclassuid = true;
+  bool grayscale_secondary_sopclassuid = false;
+  if( argc < 3 ) return 1;
+  inputdir = argv[1];
+  outputdir = argv[2];
+  // input_sopclassuid -> Use original SOP Class UID from input DICOM (Default).
+  // grayscale_secondary_sopclassuid -> Use Grayscale Secondary Image Storage SOP Class UID.
+  if( argc >= 3 )
   {
-    gdcm::Scanner::ValuesType vt = s.GetValues(t3);
-    for(
-        gdcm::Scanner::ValuesType::const_iterator it = vt.begin();
-        it != vt.end(); ++it )
-    {
-      const char * newseriesuid = uid.Generate();
-      seriesuidhash.insert( 
-          std::make_pair( *it, newseriesuid ) );
+    input_sopclassuid = false;
+    if( strcmp("input_sopclassuid", argv[3]) == 0 )
+      input_sopclassuid = true;
+    else if (strcmp("grayscale_secondary_sopclassuid", argv[3]) == 0 ) {
+      grayscale_secondary_sopclassuid = true;
     }
   }
-  std::map< std::string, std::string > framerefuidhash;
-  {
-    gdcm::Scanner::ValuesType vt = s.GetValues(t4);
-    // Frame of Reference are relative to Series UID
-    // http://dicom.nema.org/medical/Dicom/2015a/output/chtml/part03/sect_C.7.4.html
-    for(
-        gdcm::Scanner::ValuesType::const_iterator it = vt.begin();
-        it != vt.end(); ++it )
-    {
-      const char * newframerefuid = uid.Generate();
-      framerefuidhash.insert( 
-          std::make_pair( *it, newframerefuid ) );
-    }
-  }
-  for( gdcm::Directory::FilenamesType::const_iterator it =  filenames.begin(); it != filenames.end(); ++it )
+
+  // 
+  gdcm::EmptyMaskGenerator emg;
+  if( input_sopclassuid )
+    emg.SetSOPClassUIDMode( gdcm::EmptyMaskGenerator::UseOriginalSOPClassUID );
+  else if( grayscale_secondary_sopclassuid )
+    emg.SetSOPClassUIDMode( gdcm::EmptyMaskGenerator::UseGrayscaleSecondaryImageStorage );
+  emg.SetInputDirectory( inputdir.c_str() );
+  emg.SetOutputDirectory( outputdir.c_str() );
+  if( !emg.Execute() )
   {
-    const char * filename = it->c_str();
-    gdcm::Filename fn( filename );
-    std::string outfile = outdir;
-    outfile += '/';
-    outfile += fn.GetName();
-    if( !EmptyMaskDICOMFile( uid, s, seriesuidhash, framerefuidhash, outfile.c_str(), filename ) )
-    {
-      std::cerr << "Failure to EmptyMask" << std::endl;
-      gdcm::System::RemoveFile(outfile.c_str());
-      ret = 1;
-    }
+    return 1;
   }
 
-  return ret;
+  return 0;
 }
diff --git a/Examples/Cxx/MrProtocol.cxx b/Examples/Cxx/MrProtocol.cxx
index 5f0a313..67bc0c3 100644
--- a/Examples/Cxx/MrProtocol.cxx
+++ b/Examples/Cxx/MrProtocol.cxx
@@ -540,5 +540,11 @@ One can find it also in the protocol:
     return 1;
     }
 
+  gdcm::MrProtocol mrprot;
+  if(  csa.GetMrProtocol(ds, mrprot) )
+  {
+    std::cout << mrprot << std::endl;
+  }
+
   return 0;
 }
diff --git a/Source/Common/gdcmMD5.cxx b/Source/Common/gdcmMD5.cxx
index a60d4d0..7b3bf03 100644
--- a/Source/Common/gdcmMD5.cxx
+++ b/Source/Common/gdcmMD5.cxx
@@ -53,6 +53,7 @@ bool MD5::Compute(const char *buffer, size_t buf_len, char digest_str[33])
   digest_str[2*16] = '\0';
   return true;
 #else
+  (void)digest_str;
   return false;
 #endif
 }
diff --git a/Source/Common/gdcmSystem.cxx b/Source/Common/gdcmSystem.cxx
index a33e533..0721bdf 100644
--- a/Source/Common/gdcmSystem.cxx
+++ b/Source/Common/gdcmSystem.cxx
@@ -977,7 +977,7 @@ static const char *CharsetAliasToName(const char *alias)
       }
     }
   // We need to tell the user...
-  gdcmWarningMacro( "Could not find Charset from alias: " + alias );
+  gdcmWarningMacro( std::string("Could not find Charset from alias: ") + alias );
   return NULL;
 }
 #endif //_WIN32
diff --git a/Source/DataDictionary/gdcmUIDs.cxx b/Source/DataDictionary/gdcmUIDs.cxx
index 62c7a66..f7764f0 100644
--- a/Source/DataDictionary/gdcmUIDs.cxx
+++ b/Source/DataDictionary/gdcmUIDs.cxx
@@ -363,6 +363,8 @@ DICOM_Conformance_Statement_MR_R2.6.pdf
 {"1.2.840.10008.1.2.4.102","MPEG-4 AVC/H.264 High Profile / Level 4.1"},
 {"1.2.840.10008.1.2.4.103","MPEG-4 AVC/H.264 BD-compatible High Profile / Level 4.1"},
 {"1.2.840.10008.5.1.4.1.1.130", "Enhanced PET Image Storage" },
+{"1.2.840.10008.5.1.4.1.1.14.1","Intravascular Optical Coherence Tomography Image Storage - For Presentation"},
+{"1.2.840.10008.5.1.4.1.1.14.2","Intravascular Optical Coherence Tomography Image Storage - For Processing"},
 { 0, 0 }
 };
 
diff --git a/Source/DataStructureAndEncodingDefinition/CMakeLists.txt b/Source/DataStructureAndEncodingDefinition/CMakeLists.txt
index 9fb6965..b9b428e 100644
--- a/Source/DataStructureAndEncodingDefinition/CMakeLists.txt
+++ b/Source/DataStructureAndEncodingDefinition/CMakeLists.txt
@@ -52,6 +52,7 @@ set(DSED_SRCS
   gdcmWriter.cxx
   #gdcmParser.cxx
   gdcmCSAHeader.cxx
+  gdcmMrProtocol.cxx
   gdcmPDBHeader.cxx
   gdcmTransferSyntax.cxx
   gdcmVM.cxx
diff --git a/Source/DataStructureAndEncodingDefinition/gdcmCSAHeader.cxx b/Source/DataStructureAndEncodingDefinition/gdcmCSAHeader.cxx
index fc3c0b2..15baa69 100644
--- a/Source/DataStructureAndEncodingDefinition/gdcmCSAHeader.cxx
+++ b/Source/DataStructureAndEncodingDefinition/gdcmCSAHeader.cxx
@@ -1261,4 +1261,53 @@ const PrivateTag & CSAHeader::GetCSADataInfo()
   return t3;
 }
 
+bool CSAHeader::GetMrProtocol( const DataSet & ds, MrProtocol & mrProtocol )
+{
+  if(!ds.FindDataElement( t2 ) )
+    return false;
+  if( !LoadFromDataElement( ds.GetDataElement( t2 ) ) )
+    return false;
+
+  //  28 - 'MrProtocolVersion' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '21710006'
+  int mrprotocolversion = 0;
+  static const char version[] = "MrProtocolVersion";
+  // This is not an error if we do not find the version:
+  if( FindCSAElementByName( version ) )
+  {
+    const CSAElement &csavers = GetCSAElementByName( version );
+    if( !csavers.IsEmpty() )
+    {
+      const ByteValue* bv = csavers.GetByteValue();
+      std::string str( bv->GetPointer(), bv->GetLength() );
+      std::istringstream is(str);
+      is >> mrprotocolversion;
+    }
+  }
+
+  static const char * candidates[] = {
+    "MrProtocol",
+    "MrPhoenixProtocol" 
+  };
+  static const int n = sizeof candidates / sizeof * candidates;
+  bool found = false;
+  for( int i = 0; i < n; ++i )
+  {
+    const char * candidate = candidates[i];
+    if( FindCSAElementByName( candidate ) )
+    {
+      // assume the correct one is the one that is not empty,
+      // ideally we should rely on the version...
+      const gdcm::CSAElement &csael = GetCSAElementByName( candidate );
+      if( !csael.IsEmpty() )
+      {
+        if( mrProtocol.Load(csael.GetByteValue(), candidate, mrprotocolversion) )
+        {
+          found = true;
+        }
+      }
+    }
+  }
+  return found;
+}
+
 } // end namespace gdcm
diff --git a/Source/DataStructureAndEncodingDefinition/gdcmCSAHeader.h b/Source/DataStructureAndEncodingDefinition/gdcmCSAHeader.h
index a886efa..2782a68 100644
--- a/Source/DataStructureAndEncodingDefinition/gdcmCSAHeader.h
+++ b/Source/DataStructureAndEncodingDefinition/gdcmCSAHeader.h
@@ -17,6 +17,7 @@
 #include "gdcmTypes.h"
 #include "gdcmDataSet.h"
 #include "gdcmCSAElement.h"
+#include "gdcmMrProtocol.h"
 
 namespace gdcm
 {
@@ -76,11 +77,11 @@ public :
     ZEROED_OUT
   } CSAHeaderType;
 
-  template <typename TSwap>
-  std::istream &Read(std::istream &is);
+  GDCM_LEGACY(template <typename TSwap>
+  std::istream &Read(std::istream &is));
 
-  template <typename TSwap>
-  const std::ostream &Write(std::ostream &os) const;
+  GDCM_LEGACY(template <typename TSwap>
+  const std::ostream &Write(std::ostream &os) const);
 
   /// Decode the CSAHeader from element 'de'
   bool LoadFromDataElement(DataElement const &de);
@@ -118,6 +119,9 @@ public :
   /// \warning Case Sensitive
   bool FindCSAElementByName(const char *name);
 
+  /// Retrieve the ASCII portion stored within the MrProtocol/MrPhoenixProtocol:
+  bool GetMrProtocol( const DataSet & ds, MrProtocol & mrProtocol );
+
 protected:
   const CSAElement& GetCSAEEnd() const;
 
diff --git a/Source/DataStructureAndEncodingDefinition/gdcmMrProtocol.cxx b/Source/DataStructureAndEncodingDefinition/gdcmMrProtocol.cxx
new file mode 100644
index 0000000..b22b92f
--- /dev/null
+++ b/Source/DataStructureAndEncodingDefinition/gdcmMrProtocol.cxx
@@ -0,0 +1,210 @@
+/*=========================================================================
+
+  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.
+
+=========================================================================*/
+#include "gdcmMrProtocol.h"
+
+#include <map>
+#include <string>
+
+namespace gdcm
+{
+
+struct MrProtocol::Element {
+};
+
+typedef std::map< std::string, std::string > MyMapType;
+struct MrProtocol::Internals {
+  MyMapType mymap;
+  std::string csastr;
+  int version;
+};
+
+static inline bool starts_with(const std::string& s1, const std::string& s2)
+{
+  return s2.size() <= s1.size() && s1.compare(0, s2.size(), s2) == 0;
+}
+
+MrProtocol::MrProtocol()
+{
+  Pimpl = new MrProtocol::Internals;
+}
+
+bool MrProtocol::Load( const ByteValue * bv, const char * csastr, int version )
+{
+  if( bv )
+  {
+    std::string str(bv->GetPointer(), bv->GetLength());
+    std::istringstream is(str);
+    std::string s;
+    Pimpl->version = version;
+    if( csastr ) Pimpl->csastr = csastr;
+    else Pimpl->csastr = "";
+    MyMapType &mymap = Pimpl->mymap;
+    mymap.clear();
+    // Need to handle both:
+    // ### ASCCONV BEGIN ###
+    // as well as:
+    // ### ASCCONV BEGIN object=MrProtDataImpl at MrProtocolData version=41310008 converter=%MEASCONST%/ConverterList/Prot_Converter.txt ###
+    static const char begin[] = "### ASCCONV BEGIN ";
+    static const char end[] = "### ASCCONV END ###";
+    bool hasstarted = false;
+    while( std::getline(is, s ) )
+    {
+      if( !hasstarted )
+      {
+        hasstarted = starts_with(s, begin);
+      }
+      if( !hasstarted ) continue;
+      if( starts_with(s, end) ) break;
+      std::string::size_type pos = s.find( '=' );
+      if( pos != std::string::npos )
+      {
+        std::string sub1 = s.substr(0, pos);
+        sub1.erase( sub1.find_last_not_of(" \t") + 1);
+        std::string sub2 = s.substr(pos+1); // skip the '=' char
+        sub2.erase( 0, sub2.find_first_not_of(" \t"));
+        mymap.insert( MyMapType::value_type(sub1, sub2) );
+      }
+      else
+      {
+        // ### ASCCONV BEGIN ###
+        // ### ASCCONV END ###
+      }
+    }
+  }
+  else
+  {
+    Pimpl->version = 0;
+    Pimpl->csastr = "";
+    Pimpl->mymap.clear();
+    return false;
+  }
+  return true;
+}
+
+MrProtocol::~MrProtocol()
+{
+  delete Pimpl;
+}
+
+int MrProtocol::GetVersion() const
+{
+  return Pimpl->version;
+}
+
+static inline std::string trim(std::string str)
+{
+  str.erase(0, str.find_first_not_of('"'));
+  str.erase(str.find_last_not_of('"')+1);
+  return str;
+}
+
+void MrProtocol::Print(std::ostream &os) const
+{
+  {
+    os << Pimpl->csastr << " / Version: " << Pimpl->version << std::endl;
+    os << std::endl;
+    MyMapType &mymap = Pimpl->mymap;
+    for( MyMapType::const_iterator it = mymap.begin();
+        it != mymap.end(); ++it)
+    {
+      os << it->first << " : " << trim(std::string(it->second)) << std::endl;
+    }
+  }
+}
+
+const char * MrProtocol::GetMrProtocolByName(const char *name) const
+{
+  if( name )
+  {
+    MyMapType &mymap = Pimpl->mymap;
+    MyMapType::const_iterator it = mymap.find ( name );
+    if( it == mymap.end() ) return NULL;
+    return it->second.c_str();
+  }
+  return NULL;
+}
+
+bool MrProtocol::FindMrProtocolByName(const char *name) const
+{
+  if( name )
+  {
+    MyMapType &mymap = Pimpl->mymap;
+    MyMapType::const_iterator it = mymap.find ( name );
+    if( it != mymap.end() ) return true;
+  }
+  return false;
+}
+
+bool MrProtocol::GetSliceArray( MrProtocol::SliceArray & sa ) const
+{
+  // Technically this is all boilerplate code, since we could infer the type
+  // from the first few leters, eg:
+  // us -> unsigned char
+  // d -> double
+  // ...
+  sa.Slices.clear();
+  static const char saSize[] = "sSliceArray.lSize";
+  const char * sizestr = GetMrProtocolByName(saSize);
+  if( sizestr == NULL ) return false;
+  const int size = atoi( sizestr );
+  sa.Slices.resize( size );
+
+  // sSliceArray.asSlice[*].sPosition.dSag
+  // sSliceArray.asSlice[*].sPosition.dCor
+  // sSliceArray.asSlice[*].sPosition.dTra
+  char buf[512];
+  static const char templ1[] = "sSliceArray.asSlice[%d].sPosition.%s";
+  static const char templ2[] = "sSliceArray.asSlice[%d].sNormal.%s";
+  static const char *dir[3] = { "dSag", "dCor", "dTra"};
+  for( int i = 0; i < size; ++i )
+  {
+    Slice & slice = sa.Slices[i];
+    {
+      double v[3];
+      for( int j = 0; j < 3; ++j )
+      {
+        sprintf( buf, templ1, i, dir[j] );
+        const char * valstr = GetMrProtocolByName(buf);
+        // when not present this means 0.0
+        double val = 0.0;
+        if( valstr ) val = atof( valstr );
+        v[j] = val;
+      }
+      Vector3 & pos = slice.Position;
+      pos.dSag = v[0];
+      pos.dCor = v[1];
+      pos.dTra = v[2];
+    }
+    {
+      double v[3];
+      for( int j = 0; j < 3; ++j )
+      {
+        sprintf( buf, templ2, i, dir[j] );
+        const char * valstr = GetMrProtocolByName(buf);
+        // when not present this means 0.0
+        double val = 0.0;
+        if( valstr ) val = atof( valstr );
+        v[j] = val;
+      }
+      Vector3 & pos = slice.Normal;
+      pos.dSag = v[0];
+      pos.dCor = v[1];
+      pos.dTra = v[2];
+    }
+  }
+
+  return true;
+}
+
+} // end namespace gdcm
diff --git a/Source/DataStructureAndEncodingDefinition/gdcmMrProtocol.h b/Source/DataStructureAndEncodingDefinition/gdcmMrProtocol.h
new file mode 100644
index 0000000..4954da5
--- /dev/null
+++ b/Source/DataStructureAndEncodingDefinition/gdcmMrProtocol.h
@@ -0,0 +1,83 @@
+/*=========================================================================
+
+  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.
+
+=========================================================================*/
+#ifndef GDCMMRPROTOCOL_H
+#define GDCMMRPROTOCOL_H
+
+#include "gdcmTypes.h"
+#include "gdcmDataSet.h"
+
+namespace gdcm
+{
+class ByteValue;
+/*
+ * Everything done in this code is for the sole purpose of writing interoperable
+ * software under Sect. 1201 (f) Reverse Engineering exception of the DMCA.
+ * If you believe anything in this code violates any law or any of your rights,
+ * please contact us (gdcm-developers at lists.sourceforge.net) so that we can
+ * find a solution.
+ */
+//-----------------------------------------------------------------------------
+
+class DataElement;
+/**
+ * \brief Class for MrProtocol
+ */
+class GDCM_EXPORT MrProtocol
+{
+  friend std::ostream& operator<<(std::ostream &_os, const MrProtocol &d);
+public :
+  MrProtocol();
+  ~MrProtocol();
+
+  bool Load( const ByteValue * bv, const char * str, int version );
+  void Print(std::ostream &os) const;
+
+  int GetVersion() const;
+
+  const char * GetMrProtocolByName(const char *name) const;
+
+  bool FindMrProtocolByName(const char *name) const;
+
+  struct Vector3
+  {
+    double dSag;
+    double dCor;
+    double dTra;
+  };
+  struct Slice
+  {
+    Vector3 Normal;
+    Vector3 Position;
+  };
+  struct SliceArray
+  {
+    std::vector< Slice > Slices;
+  };
+  bool GetSliceArray( MrProtocol::SliceArray & sa ) const;
+
+private:
+  struct Element;
+  struct Internals;
+  Internals *Pimpl;
+};
+//-----------------------------------------------------------------------------
+inline std::ostream& operator<<(std::ostream &os, const MrProtocol &d)
+{
+  d.Print( os );
+  return os;
+}
+
+} // end namespace gdcm
+//-----------------------------------------------------------------------------
+#endif //GDCMMRPROTOCOL_H
diff --git a/Source/MediaStorageAndFileFormat/CMakeLists.txt b/Source/MediaStorageAndFileFormat/CMakeLists.txt
index c408a17..b8bdb8a 100644
--- a/Source/MediaStorageAndFileFormat/CMakeLists.txt
+++ b/Source/MediaStorageAndFileFormat/CMakeLists.txt
@@ -1,6 +1,7 @@
 # Define the srcs for Media Storage And FileFormat
 # MSFF
 set(MSFF_SRCS
+  gdcmEmptyMaskGenerator.cxx
   gdcmFileStreamer.cxx
   gdcmJSON.cxx
   gdcmFileChangeTransferSyntax.cxx
diff --git a/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.cxx b/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.cxx
index dada2d8..7f5e3f1 100644
--- a/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.cxx
+++ b/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.cxx
@@ -84,19 +84,39 @@ void DirectionCosines::Cross(double z[3]) const
   z[0] = Zx; z[1] = Zy; z[2] = Zz;
 }
 
-double DirectionCosines::Dot() const
+static inline double DotImpl(const double x[3], const double y[3])
 {
-  const double *x = Values;
-  const double *y = x+3;
   return x[0]*y[0] + x[1]*y[1] + x[2]*y[2];
 }
 
+double DirectionCosines::Dot(const double x[3], const double y[3])
+{
+  return DotImpl(x, y);
+}
+
+double DirectionCosines::Dot() const
+{
+  return DotImpl(Values, Values+3);
+}
+
 // static function is within gdcm:: namespace, so should not pollute too much on UNIX
 static inline double Norm(const double x[3])
 {
   return sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]);
 }
 
+void DirectionCosines::Normalize(double v[3])
+{
+  double den;
+  if ( (den = Norm(v)) != 0.0 )
+    {
+    for (int i=0; i < 3; i++)
+      {
+      v[i] /= den;
+      }
+    }
+}
+
 void DirectionCosines::Normalize()
 {
   double *x = Values;
diff --git a/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.h b/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.h
index ce0842b..d03eafb 100644
--- a/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.h
+++ b/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.h
@@ -40,9 +40,15 @@ public:
   /// Compute Dot
   double Dot() const;
 
+  /// Compute Dot
+  static double Dot(const double x[3], const double y[3]);
+
   /// Normalize in-place
   void Normalize();
 
+  /// Normalize in-place
+  static void Normalize(double v[3]);
+
   /// Make the class behave like a const double *
   operator const double* () const { return Values; }
 
diff --git a/Source/MediaStorageAndFileFormat/gdcmEmptyMaskGenerator.cxx b/Source/MediaStorageAndFileFormat/gdcmEmptyMaskGenerator.cxx
new file mode 100644
index 0000000..acbf8b1
--- /dev/null
+++ b/Source/MediaStorageAndFileFormat/gdcmEmptyMaskGenerator.cxx
@@ -0,0 +1,465 @@
+/*=========================================================================
+
+  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.
+
+=========================================================================*/
+#include "gdcmEmptyMaskGenerator.h"
+
+#include "gdcmImage.h"
+#include "gdcmImageWriter.h"
+#include "gdcmFileDerivation.h"
+#include "gdcmUIDGenerator.h"
+#include "gdcmImageRegionReader.h"
+#include "gdcmDirectory.h"
+#include "gdcmScanner.h"
+#include "gdcmFilename.h"
+#include "gdcmFileStreamer.h"
+#include "gdcmAnonymizer.h"
+#include "gdcmAttribute.h"
+#include "gdcmTagKeywords.h"
+
+namespace gdcm {
+
+struct EmptyMaskGenerator::impl
+{
+  static const Tag TSOPClassUID;
+  static const Tag TSOPInstanceUID;
+  static const Tag TSeriesInstanceUID;
+  static const Tag TFrameOfReferenceUID;
+
+  SOPClassUIDMode mode;
+  std::string inputdir;
+  std::string outputdir;
+  UIDGenerator uid;
+  std::map< std::string, std::string > seriesuidhash;
+  std::map< std::string, std::string > framerefuidhash;
+  Scanner s;
+  bool collectuids(Tag const & tag, std::map< std::string, std::string > & hash);
+  bool setup(const char * dirname, const char * outdir);
+  bool setmask( File & file );
+  bool derive( const char * filename, File & file );
+  bool anonymizeattributes( const char * filename, File & file );
+  bool populateattributes( const char * filename, File const & orifile, File & file );
+  bool setts( File & file );
+  bool run(const char * filename, const char * outfile);
+};
+
+const Tag EmptyMaskGenerator::impl::TSOPClassUID = Tag(0x0008,0x0016);
+const Tag EmptyMaskGenerator::impl::TSOPInstanceUID = Tag(0x0008,0x0018);
+const Tag EmptyMaskGenerator::impl::TSeriesInstanceUID = Tag(0x0020,0x000e);
+const Tag EmptyMaskGenerator::impl::TFrameOfReferenceUID = Tag(0x0020,0x0052);
+
+bool EmptyMaskGenerator::impl::collectuids( Tag const & tag, std::map< std::string, std::string > & hash)
+{
+  Scanner::ValuesType vt = s.GetValues(tag);
+  for( Scanner::ValuesType::const_iterator it = vt.begin();
+    it != vt.end(); ++it )
+    {
+    const char * newuid = uid.Generate();
+    hash.insert( std::make_pair( *it, newuid ) );
+    }
+  return true;
+}
+
+bool EmptyMaskGenerator::impl::setmask( File & file )
+{
+  DataSet& ds = file.GetDataSet();
+  namespace kwd = Keywords;
+  kwd::ImageType imtype;
+  kwd::ImageType copy;
+  imtype.SetFromDataSet( ds );
+  unsigned int nvalues = imtype.GetNumberOfValues();
+  unsigned int newvalues = std::max( nvalues, 4u );
+  copy.SetNumberOfValues( newvalues );
+  // copy original ones:
+  for( unsigned int i = 0u; i < nvalues; ++i )
+    {
+    copy.SetValue(i, imtype.GetValue(i) );
+    }
+  // Make up non empty values:
+  static const CSComp values[] = {"DERIVED","SECONDARY","OTHER"};
+  for( unsigned int i = nvalues; i < 3u;  ++i )
+    {
+    copy.SetValue(i, values[i] );
+    }
+  // The fourth value is required to be set to 'MASK' for SD
+  copy.SetValue( 3u, "MASK" );
+  ds.Replace( copy.GetAsDataElement() );
+  return true;
+}
+
+bool EmptyMaskGenerator::impl::setup(const char * dirname, const char * outdir)
+{
+  if( !System::FileIsDirectory( dirname ) )
+    return false;
+  if( !System::MakeDirectory( outdir ) )
+    return false;
+  Directory d;
+  // recursive search by default
+  const unsigned int nfiles = d.Load( dirname, true );
+  if( nfiles == 0 )
+    {
+    gdcmDebugMacro( "No files found in: " << dirname );
+    return false;
+    }
+  Directory::FilenamesType const & filenames = d.GetFilenames();
+
+  s.AddTag( TSOPClassUID );
+  s.AddTag( TSOPInstanceUID );
+  s.AddTag( TSeriesInstanceUID );
+  s.AddTag( TFrameOfReferenceUID );
+  // reduce verbosity when looping over a set of files:
+  Trace::WarningOff();
+  if( !s.Scan( filenames ) )
+    {
+    gdcmDebugMacro( "Scanner failure for directory: " << dirname );
+    return false;
+    }
+  if( !collectuids( TSeriesInstanceUID, seriesuidhash ) ) return false;
+  // Frame of Reference are relative to Series UID
+  // http://dicom.nema.org/medical/Dicom/2015a/output/chtml/part03/sect_C.7.4.html
+  if( !collectuids( TFrameOfReferenceUID, framerefuidhash ) ) return false;
+
+  return true;
+}
+
+bool EmptyMaskGenerator::impl::derive( const char * filename, File & file )
+{
+  FileDerivation fd;
+  const char * referencedsopclassuid = s.GetValue (filename, TSOPClassUID);
+  const char * referencedsopinstanceuid = s.GetValue (filename, TSOPInstanceUID);
+  if( !fd.AddReference( referencedsopclassuid, referencedsopinstanceuid ) )
+    {
+    gdcmDebugMacro( "Impossible to AddRef: " << filename );
+    // This is not considered an error to not reference, eg. UID padded with 0
+    }
+
+  // CID 7202 Source Image Purposes of Reference
+  // DCM 121321 Mask image for image processing operation
+  fd.SetPurposeOfReferenceCodeSequenceCodeValue( 121321 );
+  // CID 7203 Image Derivation
+  // DCM 113047 Pixel by pixel mask
+  fd.SetDerivationCodeSequenceCodeValue( 113047 );
+  fd.SetDerivationDescription( "Empty Mask Derivation" );
+  // always append derivation history to any existing one:
+  fd.SetAppendDerivationHistory( true );
+  fd.SetFile( file );
+  if( !fd.Derive() )
+    {
+    gdcmDebugMacro( "Sorry could not derive using input info" );
+    return false;
+    }
+  return true;
+}
+
+bool EmptyMaskGenerator::impl::anonymizeattributes( const char * filename, File & file )
+{
+  Anonymizer ano;
+  ano.SetFile( file );
+  ano.RemoveGroupLength();
+  ano.RemovePrivateTags();
+  namespace kwd = Keywords;
+  ano.Remove( kwd::WindowCenter::GetTag() );
+  ano.Remove( kwd::WindowWidth::GetTag() );
+  if( !ano.Replace (TSOPInstanceUID, uid.Generate()) ) return false;
+  const char * oldseriesuid = s.GetValue (filename, TSeriesInstanceUID);
+  const char * oldframerefuid = s.GetValue (filename, TFrameOfReferenceUID);
+  if( oldseriesuid )
+    {
+    std::map< std::string, std::string >::const_iterator it1 = seriesuidhash.find( oldseriesuid );
+    if( !ano.Replace (TSeriesInstanceUID, it1->second.c_str() ) ) return false;
+    }
+  if( oldframerefuid )
+    {
+    std::map< std::string, std::string >::const_iterator it2 = framerefuidhash.find( oldframerefuid );
+    if( !ano.Replace (TFrameOfReferenceUID, it2->second.c_str() ) ) return false;
+    }
+  return true;
+}
+
+bool EmptyMaskGenerator::impl::populateattributes( const char * filename, File const & orifile, File & file )
+{
+  namespace kwd = Keywords;
+  DataSet & ds = file.GetDataSet();
+
+  // ContentDate
+  char date[22];
+  const size_t datelen = 8;
+  System::GetCurrentDateTime(date);
+  kwd::ContentDate contentdate;
+  // Do not copy the whole cstring:
+  contentdate.SetValue( DAComp( date, datelen ) );
+  ds.Insert( contentdate.GetAsDataElement() );
+  // ContentTime
+  const size_t timelen = 6 + 1 + 6; // time + milliseconds
+  kwd::ContentTime contenttime;
+  // Do not copy the whole cstring:
+  contenttime.SetValue( TMComp(date+datelen, timelen) );
+  ds.Insert( contenttime.GetAsDataElement() );
+
+  const DataSet & orids = orifile.GetDataSet();
+  kwd::SeriesInstanceUID seriesinstanceuid;
+  seriesinstanceuid.SetValue( uid.Generate() ); // In case original instance is missing Series Instance UID
+  kwd::SeriesNumber seriesnumber = { 1 };
+  const char * oldseriesuid = s.GetValue (filename, TSeriesInstanceUID);
+  if( oldseriesuid )
+    {
+    std::map< std::string, std::string >::iterator it =
+      seriesuidhash.find( oldseriesuid );
+    seriesinstanceuid.SetValue( it->second.c_str() );
+    std::map< std::string, std::string >::difference_type diff =
+      std::distance(seriesuidhash.begin(),it);
+    seriesnumber.SetValue( 1 + (int)diff ); // Start at one
+    }
+  ds.Insert( seriesinstanceuid.GetAsDataElement() );
+  ds.Insert( seriesnumber.GetAsDataElement() );
+  kwd::FrameOfReferenceUID frameref;
+  frameref.SetValue( uid.Generate() );
+  const char * oldframerefuid = s.GetValue (filename, TFrameOfReferenceUID);
+  if( oldframerefuid )
+    {
+    std::map< std::string, std::string >::const_iterator it = framerefuidhash.find( oldframerefuid );
+    frameref.SetValue( it->second.c_str() );
+    }
+  ds.Insert( frameref.GetAsDataElement() );
+  kwd::InstanceNumber instancenum = { 1 };
+  if( orids.FindDataElement( instancenum.GetTag() ) )
+    {
+    instancenum.SetFromDataSet( orids );
+    }
+  else
+    {
+    static unsigned int counter = 0; // unsigned will wrap properly
+    instancenum.SetValue( counter++ );
+    }
+  ds.Insert( instancenum.GetAsDataElement() );
+  kwd::StudyInstanceUID studyinstanceuid;
+  studyinstanceuid.SetFromDataSet( orids );
+  ds.Insert( studyinstanceuid.GetAsDataElement() );
+  kwd::StudyID studyid = { "ST1" };
+  studyid.SetFromDataSet( orids );
+  ds.Insert( studyid.GetAsDataElement() );
+  kwd::PatientID patientid;
+  patientid.SetFromDataSet( orids );
+  ds.Insert( patientid.GetAsDataElement() );
+  kwd::PositionReferenceIndicator pri;
+  ds.Insert( pri.GetAsDataElement() );
+  kwd::BodyPartExamined bodypartex;
+  bodypartex.SetFromDataSet( orids );
+  ds.Insert( bodypartex.GetAsDataElement() );
+  // Sync with Body Part Examined:
+  kwd::Laterality lat;
+  if( orids.FindDataElement( lat.GetTag() ) )
+    {
+    lat.SetFromDataSet( orids );
+    ds.Insert( lat.GetAsDataElement() );
+    }
+  kwd::PatientOrientation pator;
+  pator.SetFromDataSet( orids );
+  ds.Insert( pator.GetAsDataElement() );
+  kwd::BurnedInAnnotation bia = { "NO" };
+  ds.Insert( bia.GetAsDataElement() );
+  kwd::ConversionType convtype = { "SYN" };
+  ds.Insert( convtype.GetAsDataElement() );
+  kwd::PresentationLUTShape plutshape = { "IDENTITY" }; // MONOCHROME2
+  ds.Insert( plutshape.GetAsDataElement() );
+  kwd::SOPClassUID sopclassuid;
+  // gdcm will pick the Word in case Byte class is not compatible:
+  MediaStorage ms = MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage;
+  sopclassuid.SetValue( ms.GetString() );
+  ds.Insert( sopclassuid.GetAsDataElement() );
+  return true;
+}
+
+bool EmptyMaskGenerator::impl::setts( File & file )
+{
+  FileMetaInformation & fmi = file.GetHeader();
+  const TransferSyntax & orits = fmi.GetDataSetTransferSyntax();
+  TransferSyntax::TSType newts = TransferSyntax::ImplicitVRLittleEndian;
+  if( orits.IsExplicit() )
+    {
+    newts = TransferSyntax::ExplicitVRLittleEndian;
+    }
+  fmi.Clear();
+  fmi.SetDataSetTransferSyntax( newts );
+  return true;
+}
+
+bool EmptyMaskGenerator::impl::run(const char * filename, const char * outfile)
+{
+  if( !s.IsKey( filename ) )
+    {
+    gdcmErrorMacro( "Not DICOM file: " << filename );
+    return false;
+    }
+
+  ImageRegionReader irr;
+  irr.SetFileName( filename );
+  if( !irr.ReadInformation() )
+    {
+    gdcmErrorMacro( "Impossible to ReadInformation (not an image?): " << filename );
+    return false;
+    }
+  size_t buflen = irr.ComputeBufferLength();
+  Image & img = irr.GetImage();
+  if( img.GetPhotometricInterpretation() != PhotometricInterpretation::MONOCHROME1
+   && img.GetPhotometricInterpretation() != PhotometricInterpretation::MONOCHROME2 )
+    {
+    gdcmErrorMacro( "Cannot process PhotometricInterpretation from: " << filename );
+    return false;
+    }
+
+  if( mode == UseOriginalSOPClassUID )
+    {
+    File & file = irr.GetFile();
+    // derive operation needs to operate on original attributes (before anonymization):
+    if( !derive( filename, file ) ) return false;
+    // copy original attributes:
+    if( !anonymizeattributes( filename, file ) ) return false;
+    if( !setmask( file ) ) return false;
+    if( !setts( file ) ) return false;
+
+    Writer w;
+    w.SetFile( file );
+    w.SetFileName( outfile );
+    if( !w.Write() )
+      {
+      return false;
+      }
+    }
+  else if ( mode == UseGrayscaleSecondaryImageStorage )
+    {
+    ImageWriter w;
+    File & file = w.GetFile();
+    if( !derive( filename, file ) ) return false;
+    // create attributes:
+    if( !populateattributes( filename, irr.GetFile(), file ) ) return false;
+    if( !setmask( file ) ) return false;
+    if( !setts( file ) ) return false;
+
+    PixelFormat & pf = img.GetPixelFormat();
+    pf.SetPixelRepresentation(0); // always overwrite to unsigned
+    img.SetSlope(1);
+    img.SetIntercept(0);
+    w.SetImage( img );
+    w.SetFileName( outfile );
+    // sentinel, SC is never acceptable:
+    if( w.ComputeTargetMediaStorage() == MediaStorage::SecondaryCaptureImageStorage )
+      {
+      gdcmErrorMacro( "Failure to compute MediaStorage: " << filename );
+      return false;
+      }
+    if( !w.Write() )
+      {
+      return false;
+      }
+    }
+  else
+    {
+    // possibly dead code, but make sure to report an error for invalid state:
+    return false;
+    }
+
+  // now create the empty pixel data element, a chunk at a time:
+  FileStreamer fs;
+  fs.SetTemplateFileName(outfile);
+  fs.SetOutputFileName(outfile);
+  Tag pixeldata (0x7fe0, 0x0010);
+  fs.CheckDataElement( pixeldata ); // double check generated output
+  if( !fs.StartDataElement( pixeldata ) )
+    {
+    gdcmErrorMacro( "StartDataElement" );
+    return false;
+    }
+    {
+    const unsigned int chunk = 4096u;
+    char bytes[chunk] = {};
+    const unsigned int nchunks = (unsigned int)( buflen / chunk);
+    const unsigned int remain = buflen % chunk;
+    for( unsigned int i = 0; i < nchunks; ++i )
+      {
+      // Read the source file into a byte array.
+      fs.AppendToDataElement( pixeldata, bytes, chunk );
+      }
+    fs.AppendToDataElement( pixeldata, bytes, remain );
+    }
+  if( !fs.StopDataElement( pixeldata ) )
+    {
+    // Most likely an issue with Pixel Data Length computation:
+    gdcmErrorMacro( "StopDataElement" );
+    return false;
+    }
+
+  return true;
+}
+
+EmptyMaskGenerator::EmptyMaskGenerator():pimpl(new impl)
+{
+}
+
+EmptyMaskGenerator::~EmptyMaskGenerator()
+{
+  delete pimpl;
+}
+
+void EmptyMaskGenerator::SetSOPClassUIDMode( SOPClassUIDMode mode )
+{
+  pimpl->mode = mode;
+}
+
+void EmptyMaskGenerator::SetInputDirectory(const char * dirname)
+{
+  if( dirname )
+    pimpl->inputdir = dirname;
+}
+
+void EmptyMaskGenerator::SetOutputDirectory(const char * dirname)
+{
+  if( dirname )
+    pimpl->outputdir = dirname;
+}
+
+
+bool EmptyMaskGenerator::Execute()
+{
+  const char * dirname = pimpl->inputdir.c_str();
+  const char * outdir = pimpl->outputdir.c_str();
+  if( !pimpl->setup(dirname, outdir) )
+    {
+    return false;
+    }
+  bool success = true;
+  Directory::FilenamesType const & filenames = pimpl->s.GetFilenames();
+  for( Directory::FilenamesType::const_iterator it =  filenames.begin(); it != filenames.end(); ++it )
+    {
+    const char * filename = it->c_str();
+    Filename fn( filename );
+    std::string outfile = outdir;
+    outfile += '/';
+    outfile += fn.GetName();
+    if( !pimpl->run( filename, outfile.c_str() ) )
+      {
+      gdcmErrorMacro( "Failure to EmptyMask" );
+      // Since we may have failed in the middle of writing of the file, remove it:
+      if( System::FileExists(outfile.c_str()) && !System::RemoveFile(outfile.c_str()) )
+        {
+        gdcmErrorMacro( "Failure to RemoveFile: " << outfile );
+        // may want to call exit() here, since we failed to remove a file we created in this process:
+        return false;
+        }
+      // declare failure to process a file, but continue main loop:
+      success = false;
+      }
+    }
+  return success;
+}
+
+} // end namespace gdcm
diff --git a/Source/MediaStorageAndFileFormat/gdcmEmptyMaskGenerator.h b/Source/MediaStorageAndFileFormat/gdcmEmptyMaskGenerator.h
new file mode 100644
index 0000000..a9f9459
--- /dev/null
+++ b/Source/MediaStorageAndFileFormat/gdcmEmptyMaskGenerator.h
@@ -0,0 +1,80 @@
+/*=========================================================================
+
+  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.
+
+=========================================================================*/
+#ifndef GDCMEMPTYMASKGENERATOR_H
+#define GDCMEMPTYMASKGENERATOR_H
+
+#include "gdcmSubject.h"
+
+namespace gdcm {
+/**
+ * \brief EmptyMaskGenerator
+ * Main class to generate a Empty Mask Series from an input Series.  This class
+ * takes an input folder and generates a series of DICOM files in the specified
+ * output directory.
+ * This class handles multiples DICOM Series within the same input directory.
+ *
+ * The class allow two mode of operations:
+ * - UseOriginalSOPClassUID
+ * - UseGrayscaleSecondaryImageStorage
+ *
+ * UseOriginalSOPClassUID is the mode where original attributes are copied from
+ * the original DICOM instance.
+ *
+ * UseGrayscaleSecondaryImageStorage is the mode where attributes are generated
+ * so as to create a MultiframeGrayscaleByteSecondaryCaptureImageStorage
+ * (MultiframeGrayscaleWordSecondaryCaptureImageStorage) instance.
+ *
+ * In both mode:
+ * - the Study references (StudyInstanceUID and StudyID) are preserved.
+ * - the PatientID reference is preserved.
+ * - the Image Type attribute will be setup so that the fourth
+ *   element is set to 'MASK'.
+ * - a new Series Instance UID is generated. It is thus required to run the process
+ *   over all files using the same input Series Instance UID so that a proper mapping
+ *   from the old Series UID is done to the new one.
+ *   Since a new Series Instance UID is generated, there is no sense to
+ *   preserve the original Frame of Reference UID, altough it would have made
+ *   sense here.
+ */
+class GDCM_EXPORT EmptyMaskGenerator
+{
+public:
+  EmptyMaskGenerator();
+  ~EmptyMaskGenerator();
+
+  enum SOPClassUIDMode {
+    UseOriginalSOPClassUID = 0, // default
+    UseGrayscaleSecondaryImageStorage
+  };
+
+  /// Select generation of SOP Class UID method:
+  /// Default is UseOriginalSOPClassUID
+  void SetSOPClassUIDMode( SOPClassUIDMode mode );
+
+  /// Specify input directory
+  void SetInputDirectory( const char * dirname );
+
+  /// Specify output directory
+  void SetOutputDirectory( const char * dirname );
+
+  /// Main loop
+  bool Execute();
+
+private:
+  struct impl;
+  // PIMPL idiom
+  impl* pimpl;
+};
+} // end namespace gdcm
+#endif //GDCMEMPTYMASKGENERATOR_H
diff --git a/Source/MediaStorageAndFileFormat/gdcmPixmapWriter.cxx b/Source/MediaStorageAndFileFormat/gdcmPixmapWriter.cxx
index 3773f33..57f6026 100644
--- a/Source/MediaStorageAndFileFormat/gdcmPixmapWriter.cxx
+++ b/Source/MediaStorageAndFileFormat/gdcmPixmapWriter.cxx
@@ -493,7 +493,7 @@ bool PixmapWriter::PrepareWrite( MediaStorage const & ref_ms )
 
   // Pixel Data
   DataElement depixdata( Tag(0x7fe0,0x0010) );
-  gdcm::DataElement & pde = PixelData->GetDataElement();
+  DataElement & pde = PixelData->GetDataElement();
   const ByteValue *bvpixdata = NULL;
   // Sometime advanced user may use a gdcm::ImageRegionReader to feed an empty gdcm::Image
   if( !pde.IsEmpty() )
diff --git a/Source/MediaStorageAndFileFormat/gdcmPrinter.cxx b/Source/MediaStorageAndFileFormat/gdcmPrinter.cxx
index 6cd4108..0970115 100644
--- a/Source/MediaStorageAndFileFormat/gdcmPrinter.cxx
+++ b/Source/MediaStorageAndFileFormat/gdcmPrinter.cxx
@@ -756,7 +756,7 @@ VR Printer::PrintDataElement(std::ostringstream &os, const Dicts &dicts, const D
     assert( refvr & VR::VRASCII );
     if( bv )
       {
-      unsigned int count = VM::GetNumberOfElementsFromArray(bv->GetPointer(), bv->GetLength());
+      size_t count = VM::GetNumberOfElementsFromArray(bv->GetPointer(), bv->GetLength());
       guessvm = VM::GetVMTypeFromLength(count, 1); // hackish...
       }
     }
diff --git a/Source/MediaStorageAndFileFormat/gdcmSplitMosaicFilter.cxx b/Source/MediaStorageAndFileFormat/gdcmSplitMosaicFilter.cxx
index 1267ac2..f1c07da 100644
--- a/Source/MediaStorageAndFileFormat/gdcmSplitMosaicFilter.cxx
+++ b/Source/MediaStorageAndFileFormat/gdcmSplitMosaicFilter.cxx
@@ -15,6 +15,8 @@
 #include "gdcmCSAHeader.h"
 #include "gdcmAttribute.h"
 #include "gdcmImageHelper.h"
+#include "gdcmDirectionCosines.h"
+#include "gdcmAnonymizer.h"
 
 #include <math.h>
 
@@ -45,6 +47,28 @@ static bool reorganize_mosaic(const unsigned short *input, const unsigned int *i
     }
   return true;
 }
+
+#ifdef SNVINVERT
+static bool reorganize_mosaic_invert(const unsigned short *input, const unsigned int *inputdims,
+  unsigned int square, const unsigned int *outputdims, unsigned short *output )
+{
+  for(unsigned int x = 0; x < outputdims[0]; ++x)
+    {
+    for(unsigned int y = 0; y < outputdims[1]; ++y)
+      {
+      for(unsigned int z = 0; z < outputdims[2]; ++z)
+        {
+        const size_t outputidx = x + y*outputdims[0] + (outputdims[2]-1-z)*outputdims[0]*outputdims[1];
+        const size_t inputidx = (x + (z%square)*outputdims[0]) +
+          (y + (z/square)*outputdims[1])*inputdims[0];
+        output[ outputidx ] = input[ inputidx ];
+        }
+      }
+    }
+  return true;
+}
+#endif
+
 }
 
 void SplitMosaicFilter::SetImage(const Image& image)
@@ -61,7 +85,6 @@ bool SplitMosaicFilter::ComputeMOSAICDimensions( unsigned int dims[3] )
   int numberOfImagesInMosaic = 0;
   if( csa.LoadFromDataElement( ds.GetDataElement( t1 ) ) )
   {
-    // SliceThickness ??
     if( csa.FindCSAElementByName( "NumberOfImagesInMosaic" ) )
     {
       const CSAElement &csael4 = csa.GetCSAElementByName( "NumberOfImagesInMosaic" );
@@ -79,15 +102,18 @@ bool SplitMosaicFilter::ComputeMOSAICDimensions( unsigned int dims[3] )
     // oh well, let try harder:
     // (0019,100a) US 72   # 2,1 NumberOfImagesInMosaic
     PrivateTag t2 (0x0019,0x0a, "SIEMENS MR HEADER");
-    const DataElement &de = ds.GetDataElement( t2 );
-    const ByteValue * bv = de.GetByteValue();
-    if( bv )
+    if( ds.FindDataElement( t2 ) )
     {
-      Element<VR::US, VM::VM1> el1 = {{0}};
-      std::istringstream is;
-      is.str( std::string( bv->GetPointer(), bv->GetLength() ) );
-      el1.Read( is );
-      numberOfImagesInMosaic = el1.GetValue();
+      const DataElement &de = ds.GetDataElement( t2 );
+      const ByteValue * bv = de.GetByteValue();
+      if( bv )
+      {
+        Element<VR::US, VM::VM1> el1 = {{0}};
+        std::istringstream is;
+        is.str( std::string( bv->GetPointer(), bv->GetLength() ) );
+        el1.Read( is );
+        numberOfImagesInMosaic = el1.GetValue();
+      }
     }
   }
   if( !numberOfImagesInMosaic )
@@ -108,6 +134,110 @@ bool SplitMosaicFilter::ComputeMOSAICDimensions( unsigned int dims[3] )
   return true;
 }
 
+bool SplitMosaicFilter::ComputeMOSAICSliceNormal( double slicenormalvector[3], bool & inverted )
+{
+  CSAHeader csa;
+  DataSet& ds = GetFile().GetDataSet();
+
+  double normal[3];
+  bool snvfound = false;
+  const PrivateTag &t1 = csa.GetCSAImageHeaderInfoTag();
+  static const char snvstr[] = "SliceNormalVector";
+  if( csa.LoadFromDataElement( ds.GetDataElement( t1 ) ) )
+  {
+    if( csa.FindCSAElementByName( snvstr ) )
+    {
+      const CSAElement &snv_csa = csa.GetCSAElementByName( snvstr );
+      if( !snv_csa.IsEmpty() )
+      {
+        const ByteValue * bv = snv_csa.GetByteValue();
+        const std::string str(bv->GetPointer(), bv->GetLength());
+        std::istringstream is;
+        is.str( str );
+        char sep;
+        double *snv = normal;
+        if( is >> snv[0] >> sep >> snv[1] >> sep >> snv[2] )
+        {
+          snvfound = true;
+        }
+      }
+    }
+  }
+  if( snvfound )
+  {
+    Attribute<0x20,0x37> iop;
+    iop.SetFromDataSet( ds );
+    DirectionCosines dc( iop.GetValues() );
+    double z[3];
+    dc.Cross (z);
+    const double snv_dot = dc.Dot( normal, z );
+    if( (1. - snv_dot) < 1e-6 )
+    {
+      gdcmDebugMacro("Same direction");
+      inverted = false;
+    }
+    else if( (-1. - snv_dot) < 1e-6 )
+    {
+      gdcmWarningMacro("SliceNormalVector is opposite direction");
+      inverted = true;
+    }
+    else
+    {
+      gdcmErrorMacro( "Unexpected normal for SliceNormalVector, dot is: " << snv_dot );
+      return false;
+    }
+  }
+ 
+  for( int i = 0; i < 3; ++i)
+    slicenormalvector[i] = normal[i];
+
+  return snvfound;
+}
+
+bool SplitMosaicFilter::ComputeMOSAICSlicePosition( double pos[3], bool )
+{
+  CSAHeader csa;
+  DataSet& ds = GetFile().GetDataSet();
+
+  MrProtocol mrprot;
+  if( !csa.GetMrProtocol(ds, mrprot) ) return false;
+
+  MrProtocol::SliceArray sa;
+  bool b = mrprot.GetSliceArray(sa);
+  if( !b ) return false;
+
+  size_t size = sa.Slices.size();
+  if( !size ) return false;
+#if 0
+  {
+    double z[3];
+    for( int i = 0; i < size; ++i )
+    {
+      MrProtocol::Slice & slice = sa.Slices[i];
+      MrProtocol::Vector3 & p = slice.Position;
+      z[0] = p.dSag;
+      z[1] = p.dCor;
+      z[2] = p.dTra;
+      const double snv_dot = DirectionCosines::Dot( slicenormalvector, z );
+      if( (1. - snv_dot) < 1e-6 )
+      {
+        gdcmErrorMacro("Invalid direction found");
+        return false;
+      }
+    }
+  }
+#endif
+
+  size_t index = 0;
+  MrProtocol::Slice & slice = sa.Slices[index];
+  MrProtocol::Vector3 & p = slice.Position;
+  pos[0] = p.dSag;
+  pos[1] = p.dCor;
+  pos[2] = p.dTra;
+
+  return true;
+}
+
 bool SplitMosaicFilter::Split()
 {
   bool success = true;
@@ -118,12 +248,23 @@ bool SplitMosaicFilter::Split()
     {
     return false;
     }
-  unsigned int div = (unsigned int )ceil(sqrt( (double)dims[2]) );
+  const unsigned int div = (unsigned int )ceil(sqrt( (double)dims[2]) );
+  bool inverted;
+  double normal[3];
+  if( !ComputeMOSAICSliceNormal( normal, inverted ) )
+  {
+    return false;
+  }
+  double origin[3];
+  if( !ComputeMOSAICSlicePosition( origin, inverted ) )
+  {
+    return false;
+  }
 
   const Image &inputimage = GetImage();
   if( inputimage.GetPixelFormat() != PixelFormat::UINT16 )
     {
-    gdcmDebugMacro( "Expecting UINT16 PixelFormat" );
+    gdcmErrorMacro( "Expecting UINT16 PixelFormat" );
     return false;
     }
   unsigned long l = inputimage.GetBufferLength();
@@ -135,29 +276,44 @@ bool SplitMosaicFilter::Split()
   std::vector<char> outbuf;
   outbuf.resize(l);
 
-  bool b = details::reorganize_mosaic(
-    (unsigned short*)&buf[0], inputimage.GetDimensions(), div, dims,
-    (unsigned short*)&outbuf[0] );
+  bool b;
+#ifdef SNVINVERT
+  if( inverted )
+  {
+    b = details::reorganize_mosaic_invert(
+        (unsigned short*)&buf[0], inputimage.GetDimensions(), div, dims,
+        (unsigned short*)&outbuf[0] );
+  }
+  else
+#endif
+  {
+    b = details::reorganize_mosaic(
+        (unsigned short*)&buf[0], inputimage.GetDimensions(), div, dims,
+        (unsigned short*)&outbuf[0] );
+  }
   if( !b ) return false;
 
   VL::Type outbufSize = (VL::Type)outbuf.size();
   pixeldata.SetByteValue( &outbuf[0], outbufSize );
 
   Image &image = GetImage();
-  const gdcm::TransferSyntax &ts = image.GetTransferSyntax();
+  const TransferSyntax &ts = image.GetTransferSyntax();
   if( ts.IsExplicit() )
      {
-     image.SetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian );
+     image.SetTransferSyntax( TransferSyntax::ExplicitVRLittleEndian );
      }
    else
      {
-     image.SetTransferSyntax( gdcm::TransferSyntax::ImplicitVRLittleEndian );
+     image.SetTransferSyntax( TransferSyntax::ImplicitVRLittleEndian );
      }
   image.SetNumberOfDimensions( 3 );
   image.SetDimension(0, dims[0] );
   image.SetDimension(1, dims[1] );
   image.SetDimension(2, dims[2] );
 
+  // Fix origin (direction is ok since we reorganize the tiles):
+  image.SetOrigin( origin );
+
   PhotometricInterpretation pi;
   pi = PhotometricInterpretation::MONOCHROME2;
 
diff --git a/Source/MediaStorageAndFileFormat/gdcmSplitMosaicFilter.h b/Source/MediaStorageAndFileFormat/gdcmSplitMosaicFilter.h
index 717a4e8..588d924 100644
--- a/Source/MediaStorageAndFileFormat/gdcmSplitMosaicFilter.h
+++ b/Source/MediaStorageAndFileFormat/gdcmSplitMosaicFilter.h
@@ -47,6 +47,12 @@ public:
   /// stored in the MOSAIC header.
   bool ComputeMOSAICDimensions(unsigned int dims[3]);
 
+  /// Extract the value for SliceNormalVector (CSA header)
+  bool ComputeMOSAICSliceNormal( double dims[3], bool & inverted );
+
+  /// Extract the value for ImagePositionPatient (requires inverted flag)
+  bool ComputeMOSAICSlicePosition( double pos[3], bool inverted );
+
   void SetImage(const Image& image);
   const Image &GetImage() const { return *I; }
   Image &GetImage() { return *I; }
diff --git a/Testing/Source/MediaStorageAndFileFormat/Cxx/CMakeLists.txt b/Testing/Source/MediaStorageAndFileFormat/Cxx/CMakeLists.txt
index d22a082..ff59d92 100644
--- a/Testing/Source/MediaStorageAndFileFormat/Cxx/CMakeLists.txt
+++ b/Testing/Source/MediaStorageAndFileFormat/Cxx/CMakeLists.txt
@@ -103,6 +103,7 @@ set(MSFF_TEST_SRCS
 if(GDCM_DATA_ROOT)
   set(MSFF_TEST_SRCS
     ${MSFF_TEST_SRCS}
+    TestSplitMosaicFilter3
     TestStrictScanner1
     TestStrictScanner2
     TestScanner1
@@ -139,6 +140,7 @@ if(GDCM_DATA_EXTRA_ROOT)
   set(MSFF_TEST_SRCS
     ${MSFF_TEST_SRCS}
     TestSplitMosaicFilter
+    TestSplitMosaicFilter2
     TestOverlay2
     TestImageRegionReader4
     )
diff --git a/Testing/Source/MediaStorageAndFileFormat/Cxx/TestSplitMosaicFilter.cxx b/Testing/Source/MediaStorageAndFileFormat/Cxx/TestSplitMosaicFilter.cxx
index bb63114..ddf3855 100644
--- a/Testing/Source/MediaStorageAndFileFormat/Cxx/TestSplitMosaicFilter.cxx
+++ b/Testing/Source/MediaStorageAndFileFormat/Cxx/TestSplitMosaicFilter.cxx
@@ -28,7 +28,7 @@ static bool reorganize_mosaic_invert(unsigned short *input,
         {
         size_t outputidx = x + y*outputdims[0] + z*outputdims[0]*outputdims[1];
         size_t inputidx = (x + (z%square)*outputdims[0]) +
-          (y + (z/square)*outputdims[0])*inputdims[0];
+          (y + (z/square)*outputdims[1])*inputdims[0];
         input[ inputidx ] = output[ outputidx ];
         }
       }
@@ -89,6 +89,19 @@ int TestSplitMosaicFilter(int argc, char *argv[])
     std::cerr << "Could not split << " << filename << std::endl;
     return 1;
     }
+  unsigned int modims[3];
+  b = filter.ComputeMOSAICDimensions( modims );
+  if( !b )
+    {
+    std::cerr << "Could not ComputeMOSAICDimensions << " << filename << std::endl;
+    return 1;
+    }
+  const unsigned int ref[3] = { 64u, 64u, 31u };
+  if( modims[0] != ref[0] || modims[1] != ref[1] || modims[2] != ref[2] )
+  {
+    std::cerr << "Invalid ComputeMOSAICDimensions << " << filename << std::endl;
+    return 1;
+  }
 
 //  const gdcm::Image &image = filter.GetImage();
 
diff --git a/Testing/Source/MediaStorageAndFileFormat/Cxx/TestSplitMosaicFilter2.cxx b/Testing/Source/MediaStorageAndFileFormat/Cxx/TestSplitMosaicFilter2.cxx
new file mode 100644
index 0000000..0a0136c
--- /dev/null
+++ b/Testing/Source/MediaStorageAndFileFormat/Cxx/TestSplitMosaicFilter2.cxx
@@ -0,0 +1,220 @@
+/*=========================================================================
+
+  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.
+
+=========================================================================*/
+#include "gdcmSplitMosaicFilter.h"
+#include "gdcmTesting.h"
+#include "gdcmSystem.h"
+#include "gdcmReader.h"
+#include "gdcmAnonymizer.h"
+#include "gdcmPrivateTag.h"
+#include "gdcmCSAHeader.h"
+#include "gdcmElement.h"
+#include "gdcmDirectionCosines.h"
+
+int TestSplitMosaicFilter2(int argc, char *argv[])
+{
+  std::string filename;
+  if( argc == 2 )
+    {
+    filename = argv[1];
+    }
+  else
+    {
+    const char *extradataroot = gdcm::Testing::GetDataExtraRoot();
+    if( !extradataroot )
+      {
+      return 1;
+      }
+    if( !gdcm::System::FileIsDirectory(extradataroot) )
+      {
+      std::cerr << "No such directory: " << extradataroot <<  std::endl;
+      return 1;
+      }
+
+    filename = extradataroot;
+    filename += "/gdcmSampleData/images_of_interest/MR-sonata-3D-as-Tile.dcm";
+    }
+  gdcm::SplitMosaicFilter s;
+  if( !gdcm::System::FileExists(filename.c_str()) )
+    {
+    return 1;
+    }
+
+  gdcm::Reader reader;
+  reader.SetFileName( filename.c_str() );
+  if( !reader.Read() )
+    {
+    std::cerr << "could not read: " << filename << std::endl;
+    return 1;
+    }
+
+  gdcm::SplitMosaicFilter filter;
+  filter.SetFile( reader.GetFile() );
+  bool inverted;
+  double slicenormal[3];
+  bool b = filter.ComputeMOSAICSliceNormal( slicenormal, inverted );
+  if( !b )
+  {
+    std::cerr << "Could not ComputeMOSAICSliceNormal: " << filename << std::endl;
+    return 1;
+  }
+
+  // SliceNormalVector is slightly less precise that sNormal:
+  //const double refnormal[3] = {-0.08193696,0.08808136,0.99273763};
+  // Value as read from sNormal (sSlice)
+  const double refnor[3] = { -0.08193693363, 0.08808135446, 0.992737636 };
+  const double eps = 1e-6;
+  gdcm::DirectionCosines dc;
+  const double dot = dc.Dot( slicenormal, refnor );
+  if( std::fabs( 1.0 - dot ) > eps )
+  {
+    std::cerr << "Invalid ComputeMOSAICSliceNormal: " << filename << std::endl;
+    return 1;
+  }
+
+  double slicepos[3];
+  b = filter.ComputeMOSAICSlicePosition( slicepos, inverted );
+  if( !b )
+  {
+    std::cerr << "Could not ComputeMOSAICSlicePosition: " << filename << std::endl;
+    return 1;
+  }
+
+  const double refpos[3] = { 2.24891108,-52.65585315,-26.94105767 };
+  for( int i = 0; i < 3; ++i ) 
+  {
+    if( std::fabs( refpos[i] - slicepos[i] ) > eps )
+    {
+      std::cerr << "Invalid ComputeMOSAICSlicePosition: " << filename << std::endl;
+      return 1;
+    }
+  }
+
+  gdcm::CSAHeader csa;
+  gdcm::DataSet & ds = reader.GetFile().GetDataSet();
+  gdcm::MrProtocol mrprot;
+  if( !csa.GetMrProtocol(ds, mrprot))
+  {
+    std::cerr << "No MrProtocol" << filename << std::endl;
+    return 1;
+  }
+
+  gdcm::MrProtocol::SliceArray sa;
+  b = mrprot.GetSliceArray(sa);
+  if( !b || sa.Slices.size() != 31 )
+  {
+    return 1;
+  }
+
+  gdcm::MrProtocol::Slice & slice0 = sa.Slices[0];
+  gdcm::MrProtocol::Vector3 & p0 = slice0.Position;
+  double pos0[3];
+  pos0[0] = p0.dSag;
+  pos0[1] = p0.dCor;
+  pos0[2] = p0.dTra;
+  for( int i = 0; i < 3; ++i ) 
+  {
+    if( std::fabs( refpos[i] - pos0[i] ) > eps )
+    {
+      std::cerr << "Invalid slice0: " << filename << std::endl;
+      return 1;
+    }
+  }
+
+  gdcm::MrProtocol::Slice & slice1 = sa.Slices[1];
+  gdcm::MrProtocol::Vector3 & p1 = slice1.Position;
+  double pos1[3];
+  pos1[0] = p1.dSag;
+  pos1[1] = p1.dCor;
+  pos1[2] = p1.dTra;
+  double altnor[3];
+  for( int i = 0; i < 3; ++i ) 
+  {
+    altnor[i] = pos1[i] - pos0[i];
+  }
+  dc.Normalize( altnor );
+  const double dot2 = dc.Dot( altnor, refnor );
+  if( std::fabs( 1.0 - dot2 ) > eps )
+  {
+    std::cerr << "Incompatible alt " << filename << std::endl;
+    return 1;
+  }
+
+  for( int k = 0; k < 31; ++k )
+  {
+    gdcm::MrProtocol::Slice & slice = sa.Slices[k];
+    gdcm::MrProtocol::Vector3 & nor = slice.Normal;
+    double normal[3];
+    normal[0] = nor.dSag;
+    normal[1] = nor.dCor;
+    normal[2] = nor.dTra;
+    for( int i = 0; i < 3; ++i ) 
+    {
+      if( std::fabs( refnor[i] - normal[i] ) > eps )
+      {
+        std::cerr << "Invalid normal: " << filename << std::endl;
+        return 1;
+      }
+    }
+  }
+
+ 
+  gdcm::Anonymizer ano;
+  ano.SetFile( reader.GetFile() );
+  const gdcm::PrivateTag &t1 = csa.GetCSAImageHeaderInfoTag();
+  ano.Remove( t1 );
+
+  unsigned int modims[3];
+  b = filter.ComputeMOSAICDimensions( modims );
+  if( b ) return 1;
+ 
+  // alternate code path:
+  gdcm::PrivateTag t2 (0x0019,0x0a, "SIEMENS MR HEADER");
+  if( ds.FindDataElement( t2 ) )
+  {
+    return 1;
+  }
+  else
+  {
+    // Create a fake one:
+    std::string creator = ds.GetPrivateCreator( t2 );
+    if( !creator.empty() ) return 1;
+    gdcm::Tag t3 (0x0019,0x10);
+    ano.Replace( t3, t2.GetOwner() );
+    gdcm::Element<gdcm::VR::US, gdcm::VM::VM1> elem;
+    elem.SetValue( 31 );
+    gdcm::DataElement de = elem.GetAsDataElement();
+    de.SetTag( t2 );
+    const uint16_t el = de.GetTag().GetElement();
+    de.GetTag().SetElement( 0x1000 + el );
+    if( de.GetVR() != gdcm::VR::US ) return 1;
+    ds.Insert( de );
+    creator = ds.GetPrivateCreator( de.GetTag() );
+    if( creator.empty() ) return 1;
+  }
+
+  b = filter.ComputeMOSAICDimensions( modims );
+  if( !b )
+    {
+    std::cerr << "Could not ComputeMOSAICDimensions " << filename << std::endl;
+    return 1;
+    }
+  const unsigned int ref[3] = { 64u, 64u, 31u };
+  if( modims[0] != ref[0] || modims[1] != ref[1] || modims[2] != ref[2] )
+  {
+    std::cerr << "Invalid ComputeMOSAICDimensions " << filename << std::endl;
+    return 1;
+  }
+
+  return 0;
+}
diff --git a/Testing/Source/MediaStorageAndFileFormat/Cxx/TestSplitMosaicFilter3.cxx b/Testing/Source/MediaStorageAndFileFormat/Cxx/TestSplitMosaicFilter3.cxx
new file mode 100644
index 0000000..58260ae
--- /dev/null
+++ b/Testing/Source/MediaStorageAndFileFormat/Cxx/TestSplitMosaicFilter3.cxx
@@ -0,0 +1,173 @@
+/*=========================================================================
+
+  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.
+
+=========================================================================*/
+#include "gdcmSplitMosaicFilter.h"
+#include "gdcmTesting.h"
+#include "gdcmSystem.h"
+#include "gdcmReader.h"
+#include "gdcmAnonymizer.h"
+#include "gdcmPrivateTag.h"
+#include "gdcmCSAHeader.h"
+#include "gdcmElement.h"
+#include "gdcmDirectionCosines.h"
+
+int TestSplitMosaicFilter3(int , char *[])
+{
+  const char *directory = gdcm::Testing::GetDataRoot();
+  std::string filename = std::string(directory) + "/SIEMENS_MOSAIC_12BitsStored-16BitsJPEG.dcm";
+  gdcm::SplitMosaicFilter s;
+  if( !gdcm::System::FileExists(filename.c_str()) )
+    {
+    return 1;
+    }
+
+  gdcm::Reader reader;
+  reader.SetFileName( filename.c_str() );
+  if( !reader.Read() )
+    {
+    std::cerr << "could not read: " << filename << std::endl;
+    return 1;
+    }
+
+  gdcm::SplitMosaicFilter filter;
+  filter.SetFile( reader.GetFile() );
+  bool inverted;
+  double slicenormal[3];
+  bool b = filter.ComputeMOSAICSliceNormal( slicenormal, inverted );
+  if( !b )
+  {
+    std::cerr << "Could not ComputeMOSAICSliceNormal: " << filename << std::endl;
+    return 1;
+  }
+
+  const double refnor[3] = { -0.03737130908,-0.314588168,0.9484923141 };
+  const double eps = 1e-6;
+  gdcm::DirectionCosines dc;
+  const double dot = dc.Dot( slicenormal, refnor );
+  if( std::fabs( 1.0 - dot ) > eps )
+  {
+    std::cerr << "Invalid ComputeMOSAICSliceNormal: " << filename << std::endl;
+    return 1;
+  }
+
+  double slicepos[3];
+  b = filter.ComputeMOSAICSlicePosition( slicepos, inverted );
+  if( !b )
+  {
+    std::cerr << "Could not ComputeMOSAICSlicePosition: " << filename << std::endl;
+    return 1;
+  }
+
+  const double refpos[3] = { -10.48860023,-7.82515782,-28.87523447 };
+
+  for( int i = 0; i < 3; ++i ) 
+  {
+    if( std::fabs( refpos[i] - slicepos[i] ) > eps )
+    {
+      std::cerr << "Invalid ComputeMOSAICSlicePosition: " << filename << std::endl;
+      return 1;
+    }
+  }
+
+  gdcm::CSAHeader csa;
+  gdcm::DataSet & ds = reader.GetFile().GetDataSet();
+  gdcm::MrProtocol mrprot;
+  if( !csa.GetMrProtocol(ds, mrprot))
+  {
+    std::cerr << "No MrProtocol" << filename << std::endl;
+    return 1;
+  }
+
+  gdcm::MrProtocol::SliceArray sa;
+  b = mrprot.GetSliceArray(sa);
+  if( !b || sa.Slices.size() != 18 )
+  {
+    std::cerr << "Size" << filename << std::endl;
+    return 1;
+  }
+
+  gdcm::MrProtocol::Slice & slice0 = sa.Slices[0];
+  gdcm::MrProtocol::Vector3 & p0 = slice0.Position;
+  double pos0[3];
+  pos0[0] = p0.dSag;
+  pos0[1] = p0.dCor;
+  pos0[2] = p0.dTra;
+  for( int i = 0; i < 3; ++i ) 
+  {
+    if( std::fabs( refpos[i] - pos0[i] ) > eps )
+    {
+      std::cerr << "Invalid slice0: " << filename << std::endl;
+      return 1;
+    }
+  }
+
+  gdcm::MrProtocol::Slice & slice1 = sa.Slices[1];
+  gdcm::MrProtocol::Vector3 & p1 = slice1.Position;
+  double pos1[3];
+  pos1[0] = p1.dSag;
+  pos1[1] = p1.dCor;
+  pos1[2] = p1.dTra;
+  double altnor[3];
+  for( int i = 0; i < 3; ++i ) 
+  {
+    altnor[i] = pos1[i] - pos0[i];
+  }
+  dc.Normalize( altnor );
+  const double dot2 = dc.Dot( altnor, refnor );
+  if( std::fabs( 1.0 - dot2 ) > eps )
+  {
+    std::cerr << "Incompatible alt " << filename << std::endl;
+    return 1;
+  }
+
+  for( int k = 0; k < 18; ++k )
+  {
+    gdcm::MrProtocol::Slice & slice = sa.Slices[k];
+    gdcm::MrProtocol::Vector3 & nor = slice.Normal;
+    double normal[3];
+    normal[0] = nor.dSag;
+    normal[1] = nor.dCor;
+    normal[2] = nor.dTra;
+    for( int i = 0; i < 3; ++i ) 
+    {
+      if( std::fabs( refnor[i] - normal[i] ) > eps )
+      {
+        std::cerr << "Invalid normal: " << filename << std::endl;
+        return 1;
+      }
+    }
+  }
+
+ 
+  gdcm::Anonymizer ano;
+  ano.SetFile( reader.GetFile() );
+  const gdcm::PrivateTag &t1 = csa.GetCSAImageHeaderInfoTag();
+  ano.Remove( t1 );
+
+  unsigned int modims[3];
+  b = filter.ComputeMOSAICDimensions( modims );
+  if(! b )
+  {
+    std::cerr << "ComputeMOSAICDimensions: " << filename << std::endl;
+    return 1;
+  }
+
+  const unsigned int ref[3] = { 64u, 64u, 18u };
+  if( modims[0] != ref[0] || modims[1] != ref[1] || modims[2] != ref[2] )
+  {
+    std::cerr << "Invalid ComputeMOSAICDimensions " << filename << std::endl;
+    return 1;
+  }
+
+  return 0;
+}
diff --git a/Utilities/doxygen/man/gdcmdump.xml b/Utilities/doxygen/man/gdcmdump.xml
index a3ff2de..8dae04c 100644
--- a/Utilities/doxygen/man/gdcmdump.xml
+++ b/Utilities/doxygen/man/gdcmdump.xml
@@ -53,6 +53,7 @@ dcm_directory   DICOM input directory
   -C --csa            print SIEMENS CSA Header (0029,[12]0,SIEMENS CSA HEADER).
      --csa-asl        print decoded SIEMENS CSA MR_ASL (base64).
      --csa-diffusion  print decoded SIEMENS CSA MRDiffusion (base64).
+     --mrprotocol     print SIEMENS CSA MrProtocol only (within ASCCONV BEGIN/END).
   -P --pdb            print GEMS Protocol Data Block (0025,1b,GEMS_SERS_01).
      --elscint        print ELSCINT Protocol Information (01f7,26,ELSCINT1).
      --vepro          print VEPRO Protocol Information (0055,20,VEPRO VIF 3.0 DATA).
@@ -264,6 +265,685 @@ $ dcmdump -f asl.dcm
 (fffe,e0dd)
 </literallayout></para>
 </refsection>
+<refsection xml:id="gdcmdump_1siemens_mrprotocol">
+<title>SIEMENS CSA Header: MrProtocol</title>
+
+<para>Using this option it is possible to dump a sorted version of MrProtocol (extra '"' are trimmed).</para>
+
+<para>Eg.:</para>
+
+<para><literallayout>$ gdcmdump --mrprotocol input.dcm
+</literallayout></para>
+
+<para><literallayout>
+MrProtocolVersion: 12510002
+acFlowComp[0] : 1
+adFlipAngleDegree[0] : 90
+alTE[0] : 60000
+alTR[0] : 3000000
+dRefSNR : 181090.7706
+dRefSNR_VOI : 181090.7706
+lAverages : 1
+lCombinedEchoes : 1
+lContrasts : 1
+lParadigmPeriodicity : 1
+lRepetitions : 79
+lScanTimeSec : 3
+lTotalScanTimeSec : 246
+sAdjFreSpec.ulMode : 0x1
+sAdjShimSpec.ulMode : 0x2
+sAdjWatSupSpec.ulMode : 0x1
+sAngio.ucPCFlowMode : 0x2
+sAngio.ucTOFInflow : 0x4
+sAutoAlign.dAAMatrix[0] : 1
+sAutoAlign.dAAMatrix[10] : 1
+sAutoAlign.dAAMatrix[15] : 1
+sAutoAlign.dAAMatrix[5] : 1
+sCOIL_SELECT_MEAS.asList[0].lElementSelected : 1
+sCOIL_SELECT_MEAS.asList[0].lRxChannelConnected : 1
+sCOIL_SELECT_MEAS.asList[0].sCoilElementID.lCoilCopy : 1
+sCOIL_SELECT_MEAS.asList[0].sCoilElementID.tCoilID : 8_Channel_Head
+sCOIL_SELECT_MEAS.asList[0].sCoilElementID.tElement : PH7
+sCOIL_SELECT_MEAS.asList[1].lElementSelected : 1
+sCOIL_SELECT_MEAS.asList[1].lRxChannelConnected : 2
+sCOIL_SELECT_MEAS.asList[1].sCoilElementID.lCoilCopy : 1
+sCOIL_SELECT_MEAS.asList[1].sCoilElementID.tCoilID : 8_Channel_Head
+sCOIL_SELECT_MEAS.asList[1].sCoilElementID.tElement : PH5
+sCOIL_SELECT_MEAS.asList[2].lElementSelected : 1
+sCOIL_SELECT_MEAS.asList[2].lRxChannelConnected : 3
+sCOIL_SELECT_MEAS.asList[2].sCoilElementID.lCoilCopy : 1
+sCOIL_SELECT_MEAS.asList[2].sCoilElementID.tCoilID : 8_Channel_Head
+sCOIL_SELECT_MEAS.asList[2].sCoilElementID.tElement : PH3
+sCOIL_SELECT_MEAS.asList[3].lElementSelected : 1
+sCOIL_SELECT_MEAS.asList[3].lRxChannelConnected : 4
+sCOIL_SELECT_MEAS.asList[3].sCoilElementID.lCoilCopy : 1
+sCOIL_SELECT_MEAS.asList[3].sCoilElementID.tCoilID : 8_Channel_Head
+sCOIL_SELECT_MEAS.asList[3].sCoilElementID.tElement : PH1
+sCOIL_SELECT_MEAS.asList[4].lElementSelected : 1
+sCOIL_SELECT_MEAS.asList[4].lRxChannelConnected : 5
+sCOIL_SELECT_MEAS.asList[4].sCoilElementID.lCoilCopy : 1
+sCOIL_SELECT_MEAS.asList[4].sCoilElementID.tCoilID : 8_Channel_Head
+sCOIL_SELECT_MEAS.asList[4].sCoilElementID.tElement : PH8
+sCOIL_SELECT_MEAS.asList[5].lElementSelected : 1
+sCOIL_SELECT_MEAS.asList[5].lRxChannelConnected : 6
+sCOIL_SELECT_MEAS.asList[5].sCoilElementID.lCoilCopy : 1
+sCOIL_SELECT_MEAS.asList[5].sCoilElementID.tCoilID : 8_Channel_Head
+sCOIL_SELECT_MEAS.asList[5].sCoilElementID.tElement : PH6
+sCOIL_SELECT_MEAS.asList[6].lElementSelected : 1
+sCOIL_SELECT_MEAS.asList[6].lRxChannelConnected : 7
+sCOIL_SELECT_MEAS.asList[6].sCoilElementID.lCoilCopy : 1
+sCOIL_SELECT_MEAS.asList[6].sCoilElementID.tCoilID : 8_Channel_Head
+sCOIL_SELECT_MEAS.asList[6].sCoilElementID.tElement : PH4
+sCOIL_SELECT_MEAS.asList[7].lElementSelected : 1
+sCOIL_SELECT_MEAS.asList[7].lRxChannelConnected : 8
+sCOIL_SELECT_MEAS.asList[7].sCoilElementID.lCoilCopy : 1
+sCOIL_SELECT_MEAS.asList[7].sCoilElementID.tCoilID : 8_Channel_Head
+sCOIL_SELECT_MEAS.asList[7].sCoilElementID.tElement : PH2
+sCOIL_SELECT_MEAS.sCOILPLUGS.auiNmbrOfNibbles[0] : 0x2
+sCOIL_SELECT_MEAS.sCOILPLUGS.auiNmbrOfNibbles[1] : 0x2
+sCOIL_SELECT_MEAS.sCOILPLUGS.auiNmbrOfNibbles[2] : 0x2
+sCOIL_SELECT_MEAS.sCOILPLUGS.auiNmbrOfNibbles[3] : 0x2
+sCOIL_SELECT_MEAS.sCOILPLUGS.auiNmbrOfNibbles[4] : 0x2
+sCOIL_SELECT_MEAS.sCOILPLUGS.aulPlugId[0] : 0xff
+sCOIL_SELECT_MEAS.sCOILPLUGS.aulPlugId[1] : 0xaa
+sCOIL_SELECT_MEAS.sCOILPLUGS.aulPlugId[2] : 0xee
+sCOIL_SELECT_MEAS.sCOILPLUGS.aulPlugId[3] : 0xee
+sCOIL_SELECT_MEAS.sCOILPLUGS.aulPlugId[4] : 0xa4
+sDiffusion.ulMode : 0x1
+sEFISPEC.bEFIDataValid : 1
+sEllipticalFilter.ucMode : 0x1
+sFastImaging.lEPIFactor : 128
+sFastImaging.lSegments : 1
+sFastImaging.lTurboFactor : 1
+sGRADSPEC.alShimCurrent[0] : -166
+sGRADSPEC.alShimCurrent[1] : 596
+sGRADSPEC.alShimCurrent[2] : -516
+sGRADSPEC.alShimCurrent[3] : 84
+sGRADSPEC.alShimCurrent[4] : -295
+sGRADSPEC.bB0CompensationValid : 1
+sGRADSPEC.bCrossTermCompensationValid : 1
+sGRADSPEC.bDelayValid : 1
+sGRADSPEC.bEddyCompensationValid : 1
+sGRADSPEC.bOffsetValid : 1
+sGRADSPEC.bSensitivityValid : 1
+sGRADSPEC.bShimCurrentValid : 1
+sGRADSPEC.flGSWDMinRiseTime : 5
+sGRADSPEC.flSensitivityX : 0.000353238
+sGRADSPEC.flSensitivityY : 0.000364826
+sGRADSPEC.flSensitivityZ : 0.000356804
+sGRADSPEC.lDelayX : 14
+sGRADSPEC.lDelayY : 15
+sGRADSPEC.lDelayZ : 13
+sGRADSPEC.lOffsetX : -10
+sGRADSPEC.lOffsetY : 22
+sGRADSPEC.lOffsetZ : 34
+sGRADSPEC.sB0CompensationX.aflAmplitude[0] : -0.0110937
+sGRADSPEC.sB0CompensationX.aflAmplitude[1] : -0.0276212
+sGRADSPEC.sB0CompensationX.aflAmplitude[2] : 0.00261628
+sGRADSPEC.sB0CompensationX.aflTimeConstant[0] : 1.86006
+sGRADSPEC.sB0CompensationX.aflTimeConstant[1] : 0.0451358
+sGRADSPEC.sB0CompensationX.aflTimeConstant[2] : 0.00199924
+sGRADSPEC.sB0CompensationY.aflAmplitude[0] : 0.0647921
+sGRADSPEC.sB0CompensationY.aflAmplitude[1] : 0.0207167
+sGRADSPEC.sB0CompensationY.aflAmplitude[2] : -0.0131878
+sGRADSPEC.sB0CompensationY.aflTimeConstant[0] : 0.852499
+sGRADSPEC.sB0CompensationY.aflTimeConstant[1] : 0.0633158
+sGRADSPEC.sB0CompensationY.aflTimeConstant[2] : 0.00199999
+sGRADSPEC.sB0CompensationZ.aflAmplitude[0] : 0.119857
+sGRADSPEC.sB0CompensationZ.aflAmplitude[1] : 0.0106907
+sGRADSPEC.sB0CompensationZ.aflAmplitude[2] : -0.0159243
+sGRADSPEC.sB0CompensationZ.aflTimeConstant[0] : 1.03958
+sGRADSPEC.sB0CompensationZ.aflTimeConstant[1] : 0.019543
+sGRADSPEC.sB0CompensationZ.aflTimeConstant[2] : 0.00141055
+sGRADSPEC.sCrossTermCompensationXY.aflAmplitude[0] : 0.000779649
+sGRADSPEC.sCrossTermCompensationXY.aflTimeConstant[0] : 0.609972
+sGRADSPEC.sCrossTermCompensationXZ.aflAmplitude[0] : -0.000357764
+sGRADSPEC.sCrossTermCompensationXZ.aflTimeConstant[0] : 0.757463
+sGRADSPEC.sCrossTermCompensationYX.aflAmplitude[0] : 0.00028701
+sGRADSPEC.sCrossTermCompensationYX.aflTimeConstant[0] : 0.692162
+sGRADSPEC.sCrossTermCompensationYZ.aflAmplitude[0] : 0.000341002
+sGRADSPEC.sCrossTermCompensationYZ.aflTimeConstant[0] : 0.643997
+sGRADSPEC.sEddyCompensationX.aflAmplitude[0] : 0.00321033
+sGRADSPEC.sEddyCompensationX.aflAmplitude[1] : 0.0764387
+sGRADSPEC.sEddyCompensationX.aflAmplitude[2] : -0.0119296
+sGRADSPEC.sEddyCompensationX.aflAmplitude[3] : 0.002806
+sGRADSPEC.sEddyCompensationX.aflAmplitude[4] : 0.00131044
+sGRADSPEC.sEddyCompensationX.aflTimeConstant[0] : 1.92825
+sGRADSPEC.sEddyCompensationX.aflTimeConstant[1] : 0.530542
+sGRADSPEC.sEddyCompensationX.aflTimeConstant[2] : 0.348189
+sGRADSPEC.sEddyCompensationX.aflTimeConstant[3] : 0.0172583
+sGRADSPEC.sEddyCompensationX.aflTimeConstant[4] : 0.00199055
+sGRADSPEC.sEddyCompensationY.aflAmplitude[0] : 0.00129643
+sGRADSPEC.sEddyCompensationY.aflAmplitude[1] : 0.0657945
+sGRADSPEC.sEddyCompensationY.aflAmplitude[2] : -0.00875319
+sGRADSPEC.sEddyCompensationY.aflAmplitude[3] : 0.00247817
+sGRADSPEC.sEddyCompensationY.aflAmplitude[4] : 0.00136282
+sGRADSPEC.sEddyCompensationY.aflTimeConstant[0] : 2.18733
+sGRADSPEC.sEddyCompensationY.aflTimeConstant[1] : 0.554603
+sGRADSPEC.sEddyCompensationY.aflTimeConstant[2] : 0.363992
+sGRADSPEC.sEddyCompensationY.aflTimeConstant[3] : 0.0174167
+sGRADSPEC.sEddyCompensationY.aflTimeConstant[4] : 0.0019934
+sGRADSPEC.sEddyCompensationZ.aflAmplitude[0] : 0.0106364
+sGRADSPEC.sEddyCompensationZ.aflAmplitude[1] : 0.0644895
+sGRADSPEC.sEddyCompensationZ.aflAmplitude[2] : -0.0116849
+sGRADSPEC.sEddyCompensationZ.aflAmplitude[3] : 0.00245425
+sGRADSPEC.sEddyCompensationZ.aflAmplitude[4] : -0.000382604
+sGRADSPEC.sEddyCompensationZ.aflTimeConstant[0] : 2.45763
+sGRADSPEC.sEddyCompensationZ.aflTimeConstant[1] : 0.728919
+sGRADSPEC.sEddyCompensationZ.aflTimeConstant[2] : 0.490303
+sGRADSPEC.sEddyCompensationZ.aflTimeConstant[3] : 0.0146871
+sGRADSPEC.sEddyCompensationZ.aflTimeConstant[4] : 0.00198729
+sGRADSPEC.ucMode : 0x11
+sGroupArray.anMember[10] : 10
+sGroupArray.anMember[11] : 11
+sGroupArray.anMember[12] : 12
+sGroupArray.anMember[13] : 13
+sGroupArray.anMember[14] : 14
+sGroupArray.anMember[15] : 15
+sGroupArray.anMember[16] : 16
+sGroupArray.anMember[17] : 17
+sGroupArray.anMember[18] : 18
+sGroupArray.anMember[19] : 19
+sGroupArray.anMember[1] : 1
+sGroupArray.anMember[20] : 20
+sGroupArray.anMember[21] : 21
+sGroupArray.anMember[22] : 22
+sGroupArray.anMember[23] : 23
+sGroupArray.anMember[24] : 24
+sGroupArray.anMember[25] : 25
+sGroupArray.anMember[26] : 26
+sGroupArray.anMember[27] : 27
+sGroupArray.anMember[28] : 28
+sGroupArray.anMember[29] : 29
+sGroupArray.anMember[2] : 2
+sGroupArray.anMember[30] : 30
+sGroupArray.anMember[31] : -1
+sGroupArray.anMember[3] : 3
+sGroupArray.anMember[4] : 4
+sGroupArray.anMember[5] : 5
+sGroupArray.anMember[6] : 6
+sGroupArray.anMember[7] : 7
+sGroupArray.anMember[8] : 8
+sGroupArray.anMember[9] : 9
+sGroupArray.asGroup[0].dDistFact : 0.1
+sGroupArray.asGroup[0].nSize : 31
+sGroupArray.lSize : 1
+sGroupArray.sPSat.dGap : 10
+sGroupArray.sPSat.dThickness : 50
+sKSpace.dPhaseResolution : 1
+sKSpace.dSliceResolution : 1
+sKSpace.lBaseResolution : 64
+sKSpace.lImagesPerSlab : 64
+sKSpace.lPartitions : 64
+sKSpace.lPhaseEncodingLines : 64
+sKSpace.ucAveragingMode : 0x2
+sKSpace.ucDimension : 0x2
+sKSpace.ucMultiSliceMode : 0x2
+sKSpace.ucPhasePartialFourier : 0x10
+sKSpace.ucSlicePartialFourier : 0x10
+sKSpace.unReordering : 0x1
+sNavigatorPara.ucRespComp : 0x4
+sPat.lAccelFact3D : 1
+sPat.lAccelFactPE : 1
+sPat.ucPATMode : 0x1
+sPat.ucRefScanMode : 0x1
+sPhysioImaging.lMethod1 : 1
+sPhysioImaging.lMethod2 : 1
+sPhysioImaging.lPhases : 1
+sPhysioImaging.lRetroGatedImages : 16
+sPhysioImaging.lSignal1 : 1
+sPhysioImaging.lSignal2 : 1
+sPhysioImaging.sPhysioECG.lArrhythmiaDetection : 1
+sPhysioImaging.sPhysioECG.lCardiacGateOffThreshold : 700000
+sPhysioImaging.sPhysioECG.lCardiacGateOnThreshold : 100000
+sPhysioImaging.sPhysioECG.lTriggerPulses : 1
+sPhysioImaging.sPhysioECG.lTriggerWindow : 5
+sPhysioImaging.sPhysioExt.lCardiacGateOffThreshold : 700000
+sPhysioImaging.sPhysioExt.lCardiacGateOnThreshold : 100000
+sPhysioImaging.sPhysioExt.lTriggerPulses : 1
+sPhysioImaging.sPhysioExt.lTriggerWindow : 5
+sPhysioImaging.sPhysioPulse.lCardiacGateOffThreshold : 700000
+sPhysioImaging.sPhysioPulse.lCardiacGateOnThreshold : 100000
+sPhysioImaging.sPhysioPulse.lTriggerPulses : 1
+sPhysioImaging.sPhysioPulse.lTriggerWindow : 5
+sPhysioImaging.sPhysioResp.dGatingRatio : 0.3
+sPhysioImaging.sPhysioResp.lRespGatePhase : 2
+sPhysioImaging.sPhysioResp.lRespGateThreshold : 20
+sPrepPulses.ucFatSat : 0x1
+sPrepPulses.ucFatSatMode : 0x2
+sPrepPulses.ucInversion : 0x4
+sPrepPulses.ucSatRecovery : 0x1
+sPrepPulses.ucWaterSat : 0x4
+sProtConsistencyInfo.flGMax : 26
+sProtConsistencyInfo.flNominalB0 : 1.494
+sProtConsistencyInfo.flRiseTime : 5
+sRXSPEC.aFFT_SCALE[0].bValid : 1
+sRXSPEC.aFFT_SCALE[0].flFactor : 0.720612
+sRXSPEC.aFFT_SCALE[0].lRxChannel : 1
+sRXSPEC.aFFT_SCALE[1].bValid : 1
+sRXSPEC.aFFT_SCALE[1].flFactor : 0.719059
+sRXSPEC.aFFT_SCALE[1].lRxChannel : 2
+sRXSPEC.aFFT_SCALE[2].bValid : 1
+sRXSPEC.aFFT_SCALE[2].flFactor : 0.705708
+sRXSPEC.aFFT_SCALE[2].lRxChannel : 3
+sRXSPEC.aFFT_SCALE[3].bValid : 1
+sRXSPEC.aFFT_SCALE[3].flFactor : 0.731533
+sRXSPEC.aFFT_SCALE[3].lRxChannel : 4
+sRXSPEC.aFFT_SCALE[4].bValid : 1
+sRXSPEC.aFFT_SCALE[4].flFactor : 0.722418
+sRXSPEC.aFFT_SCALE[4].lRxChannel : 5
+sRXSPEC.aFFT_SCALE[5].bValid : 1
+sRXSPEC.aFFT_SCALE[5].flFactor : 0.738751
+sRXSPEC.aFFT_SCALE[5].lRxChannel : 6
+sRXSPEC.aFFT_SCALE[6].bValid : 1
+sRXSPEC.aFFT_SCALE[6].flFactor : 0.719098
+sRXSPEC.aFFT_SCALE[6].lRxChannel : 7
+sRXSPEC.aFFT_SCALE[7].bValid : 1
+sRXSPEC.aFFT_SCALE[7].flFactor : 0.733029
+sRXSPEC.aFFT_SCALE[7].lRxChannel : 8
+sRXSPEC.alDwellTime[0] : 3000
+sRXSPEC.bGainValid : 1
+sRXSPEC.bVariCapVoltagesValid : 1
+sRXSPEC.lGain : 1
+sSliceArray.anAsc[10] : 10
+sSliceArray.anAsc[11] : 11
+sSliceArray.anAsc[12] : 12
+sSliceArray.anAsc[13] : 13
+sSliceArray.anAsc[14] : 14
+sSliceArray.anAsc[15] : 15
+sSliceArray.anAsc[16] : 16
+sSliceArray.anAsc[17] : 17
+sSliceArray.anAsc[18] : 18
+sSliceArray.anAsc[19] : 19
+sSliceArray.anAsc[1] : 1
+sSliceArray.anAsc[20] : 20
+sSliceArray.anAsc[21] : 21
+sSliceArray.anAsc[22] : 22
+sSliceArray.anAsc[23] : 23
+sSliceArray.anAsc[24] : 24
+sSliceArray.anAsc[25] : 25
+sSliceArray.anAsc[26] : 26
+sSliceArray.anAsc[27] : 27
+sSliceArray.anAsc[28] : 28
+sSliceArray.anAsc[29] : 29
+sSliceArray.anAsc[2] : 2
+sSliceArray.anAsc[30] : 30
+sSliceArray.anAsc[3] : 3
+sSliceArray.anAsc[4] : 4
+sSliceArray.anAsc[5] : 5
+sSliceArray.anAsc[6] : 6
+sSliceArray.anAsc[7] : 7
+sSliceArray.anAsc[8] : 8
+sSliceArray.anAsc[9] : 9
+sSliceArray.anPos[10] : 10
+sSliceArray.anPos[11] : 11
+sSliceArray.anPos[12] : 12
+sSliceArray.anPos[13] : 13
+sSliceArray.anPos[14] : 14
+sSliceArray.anPos[15] : 15
+sSliceArray.anPos[16] : 16
+sSliceArray.anPos[17] : 17
+sSliceArray.anPos[18] : 18
+sSliceArray.anPos[19] : 19
+sSliceArray.anPos[1] : 1
+sSliceArray.anPos[20] : 20
+sSliceArray.anPos[21] : 21
+sSliceArray.anPos[22] : 22
+sSliceArray.anPos[23] : 23
+sSliceArray.anPos[24] : 24
+sSliceArray.anPos[25] : 25
+sSliceArray.anPos[26] : 26
+sSliceArray.anPos[27] : 27
+sSliceArray.anPos[28] : 28
+sSliceArray.anPos[29] : 29
+sSliceArray.anPos[2] : 2
+sSliceArray.anPos[30] : 30
+sSliceArray.anPos[3] : 3
+sSliceArray.anPos[4] : 4
+sSliceArray.anPos[5] : 5
+sSliceArray.anPos[6] : 6
+sSliceArray.anPos[7] : 7
+sSliceArray.anPos[8] : 8
+sSliceArray.anPos[9] : 9
+sSliceArray.asSlice[0].dPhaseFOV : 230
+sSliceArray.asSlice[0].dReadoutFOV : 230
+sSliceArray.asSlice[0].dThickness : 4
+sSliceArray.asSlice[0].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[0].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[0].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[0].sPosition.dCor : -52.65585315
+sSliceArray.asSlice[0].sPosition.dSag : 2.24891108
+sSliceArray.asSlice[0].sPosition.dTra : -26.94105767
+sSliceArray.asSlice[10].dPhaseFOV : 230
+sSliceArray.asSlice[10].dReadoutFOV : 230
+sSliceArray.asSlice[10].dThickness : 4
+sSliceArray.asSlice[10].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[10].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[10].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[10].sPosition.dCor : -48.78027355
+sSliceArray.asSlice[10].sPosition.dSag : -1.356313999
+sSliceArray.asSlice[10].sPosition.dTra : 16.73939831
+sSliceArray.asSlice[11].dPhaseFOV : 230
+sSliceArray.asSlice[11].dReadoutFOV : 230
+sSliceArray.asSlice[11].dThickness : 4
+sSliceArray.asSlice[11].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[11].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[11].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[11].sPosition.dCor : -48.39271559
+sSliceArray.asSlice[11].sPosition.dSag : -1.716836507
+sSliceArray.asSlice[11].sPosition.dTra : 21.10744391
+sSliceArray.asSlice[12].dPhaseFOV : 230
+sSliceArray.asSlice[12].dReadoutFOV : 230
+sSliceArray.asSlice[12].dThickness : 4
+sSliceArray.asSlice[12].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[12].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[12].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[12].sPosition.dCor : -48.00515763
+sSliceArray.asSlice[12].sPosition.dSag : -2.077359015
+sSliceArray.asSlice[12].sPosition.dTra : 25.47548951
+sSliceArray.asSlice[13].dPhaseFOV : 230
+sSliceArray.asSlice[13].dReadoutFOV : 230
+sSliceArray.asSlice[13].dThickness : 4
+sSliceArray.asSlice[13].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[13].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[13].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[13].sPosition.dCor : -47.61759967
+sSliceArray.asSlice[13].sPosition.dSag : -2.437881523
+sSliceArray.asSlice[13].sPosition.dTra : 29.84353511
+sSliceArray.asSlice[14].dPhaseFOV : 230
+sSliceArray.asSlice[14].dReadoutFOV : 230
+sSliceArray.asSlice[14].dThickness : 4
+sSliceArray.asSlice[14].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[14].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[14].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[14].sPosition.dCor : -47.23004171
+sSliceArray.asSlice[14].sPosition.dSag : -2.798404031
+sSliceArray.asSlice[14].sPosition.dTra : 34.21158071
+sSliceArray.asSlice[15].dPhaseFOV : 230
+sSliceArray.asSlice[15].dReadoutFOV : 230
+sSliceArray.asSlice[15].dThickness : 4
+sSliceArray.asSlice[15].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[15].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[15].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[15].sPosition.dCor : -46.84248375
+sSliceArray.asSlice[15].sPosition.dSag : -3.158926539
+sSliceArray.asSlice[15].sPosition.dTra : 38.57962631
+sSliceArray.asSlice[16].dPhaseFOV : 230
+sSliceArray.asSlice[16].dReadoutFOV : 230
+sSliceArray.asSlice[16].dThickness : 4
+sSliceArray.asSlice[16].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[16].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[16].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[16].sPosition.dCor : -46.45492579
+sSliceArray.asSlice[16].sPosition.dSag : -3.519449047
+sSliceArray.asSlice[16].sPosition.dTra : 42.9476719
+sSliceArray.asSlice[17].dPhaseFOV : 230
+sSliceArray.asSlice[17].dReadoutFOV : 230
+sSliceArray.asSlice[17].dThickness : 4
+sSliceArray.asSlice[17].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[17].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[17].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[17].sPosition.dCor : -46.06736783
+sSliceArray.asSlice[17].sPosition.dSag : -3.879971555
+sSliceArray.asSlice[17].sPosition.dTra : 47.3157175
+sSliceArray.asSlice[18].dPhaseFOV : 230
+sSliceArray.asSlice[18].dReadoutFOV : 230
+sSliceArray.asSlice[18].dThickness : 4
+sSliceArray.asSlice[18].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[18].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[18].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[18].sPosition.dCor : -45.67980987
+sSliceArray.asSlice[18].sPosition.dSag : -4.240494063
+sSliceArray.asSlice[18].sPosition.dTra : 51.6837631
+sSliceArray.asSlice[19].dPhaseFOV : 230
+sSliceArray.asSlice[19].dReadoutFOV : 230
+sSliceArray.asSlice[19].dThickness : 4
+sSliceArray.asSlice[19].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[19].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[19].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[19].sPosition.dCor : -45.29225191
+sSliceArray.asSlice[19].sPosition.dSag : -4.601016571
+sSliceArray.asSlice[19].sPosition.dTra : 56.0518087
+sSliceArray.asSlice[1].dPhaseFOV : 230
+sSliceArray.asSlice[1].dReadoutFOV : 230
+sSliceArray.asSlice[1].dThickness : 4
+sSliceArray.asSlice[1].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[1].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[1].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[1].sPosition.dCor : -52.26829519
+sSliceArray.asSlice[1].sPosition.dSag : 1.888388572
+sSliceArray.asSlice[1].sPosition.dTra : -22.57301207
+sSliceArray.asSlice[20].dPhaseFOV : 230
+sSliceArray.asSlice[20].dReadoutFOV : 230
+sSliceArray.asSlice[20].dThickness : 4
+sSliceArray.asSlice[20].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[20].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[20].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[20].sPosition.dCor : -44.90469395
+sSliceArray.asSlice[20].sPosition.dSag : -4.961539079
+sSliceArray.asSlice[20].sPosition.dTra : 60.4198543
+sSliceArray.asSlice[21].dPhaseFOV : 230
+sSliceArray.asSlice[21].dReadoutFOV : 230
+sSliceArray.asSlice[21].dThickness : 4
+sSliceArray.asSlice[21].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[21].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[21].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[21].sPosition.dCor : -44.51713599
+sSliceArray.asSlice[21].sPosition.dSag : -5.322061587
+sSliceArray.asSlice[21].sPosition.dTra : 64.7878999
+sSliceArray.asSlice[22].dPhaseFOV : 230
+sSliceArray.asSlice[22].dReadoutFOV : 230
+sSliceArray.asSlice[22].dThickness : 4
+sSliceArray.asSlice[22].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[22].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[22].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[22].sPosition.dCor : -44.12957804
+sSliceArray.asSlice[22].sPosition.dSag : -5.682584095
+sSliceArray.asSlice[22].sPosition.dTra : 69.15594549
+sSliceArray.asSlice[23].dPhaseFOV : 230
+sSliceArray.asSlice[23].dReadoutFOV : 230
+sSliceArray.asSlice[23].dThickness : 4
+sSliceArray.asSlice[23].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[23].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[23].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[23].sPosition.dCor : -43.74202008
+sSliceArray.asSlice[23].sPosition.dSag : -6.043106603
+sSliceArray.asSlice[23].sPosition.dTra : 73.52399109
+sSliceArray.asSlice[24].dPhaseFOV : 230
+sSliceArray.asSlice[24].dReadoutFOV : 230
+sSliceArray.asSlice[24].dThickness : 4
+sSliceArray.asSlice[24].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[24].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[24].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[24].sPosition.dCor : -43.35446212
+sSliceArray.asSlice[24].sPosition.dSag : -6.403629111
+sSliceArray.asSlice[24].sPosition.dTra : 77.89203669
+sSliceArray.asSlice[25].dPhaseFOV : 230
+sSliceArray.asSlice[25].dReadoutFOV : 230
+sSliceArray.asSlice[25].dThickness : 4
+sSliceArray.asSlice[25].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[25].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[25].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[25].sPosition.dCor : -42.96690416
+sSliceArray.asSlice[25].sPosition.dSag : -6.764151619
+sSliceArray.asSlice[25].sPosition.dTra : 82.26008229
+sSliceArray.asSlice[26].dPhaseFOV : 230
+sSliceArray.asSlice[26].dReadoutFOV : 230
+sSliceArray.asSlice[26].dThickness : 4
+sSliceArray.asSlice[26].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[26].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[26].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[26].sPosition.dCor : -42.5793462
+sSliceArray.asSlice[26].sPosition.dSag : -7.124674127
+sSliceArray.asSlice[26].sPosition.dTra : 86.62812789
+sSliceArray.asSlice[27].dPhaseFOV : 230
+sSliceArray.asSlice[27].dReadoutFOV : 230
+sSliceArray.asSlice[27].dThickness : 4
+sSliceArray.asSlice[27].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[27].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[27].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[27].sPosition.dCor : -42.19178824
+sSliceArray.asSlice[27].sPosition.dSag : -7.485196635
+sSliceArray.asSlice[27].sPosition.dTra : 90.99617349
+sSliceArray.asSlice[28].dPhaseFOV : 230
+sSliceArray.asSlice[28].dReadoutFOV : 230
+sSliceArray.asSlice[28].dThickness : 4
+sSliceArray.asSlice[28].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[28].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[28].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[28].sPosition.dCor : -41.80423028
+sSliceArray.asSlice[28].sPosition.dSag : -7.845719143
+sSliceArray.asSlice[28].sPosition.dTra : 95.36421908
+sSliceArray.asSlice[29].dPhaseFOV : 230
+sSliceArray.asSlice[29].dReadoutFOV : 230
+sSliceArray.asSlice[29].dThickness : 4
+sSliceArray.asSlice[29].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[29].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[29].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[29].sPosition.dCor : -41.41667232
+sSliceArray.asSlice[29].sPosition.dSag : -8.206241651
+sSliceArray.asSlice[29].sPosition.dTra : 99.73226468
+sSliceArray.asSlice[2].dPhaseFOV : 230
+sSliceArray.asSlice[2].dReadoutFOV : 230
+sSliceArray.asSlice[2].dThickness : 4
+sSliceArray.asSlice[2].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[2].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[2].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[2].sPosition.dCor : -51.88073723
+sSliceArray.asSlice[2].sPosition.dSag : 1.527866064
+sSliceArray.asSlice[2].sPosition.dTra : -18.20496647
+sSliceArray.asSlice[30].dPhaseFOV : 230
+sSliceArray.asSlice[30].dReadoutFOV : 230
+sSliceArray.asSlice[30].dThickness : 4
+sSliceArray.asSlice[30].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[30].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[30].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[30].sPosition.dCor : -41.02911436
+sSliceArray.asSlice[30].sPosition.dSag : -8.566764159
+sSliceArray.asSlice[30].sPosition.dTra : 104.1003103
+sSliceArray.asSlice[3].dPhaseFOV : 230
+sSliceArray.asSlice[3].dReadoutFOV : 230
+sSliceArray.asSlice[3].dThickness : 4
+sSliceArray.asSlice[3].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[3].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[3].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[3].sPosition.dCor : -51.49317927
+sSliceArray.asSlice[3].sPosition.dSag : 1.167343556
+sSliceArray.asSlice[3].sPosition.dTra : -13.83692088
+sSliceArray.asSlice[4].dPhaseFOV : 230
+sSliceArray.asSlice[4].dReadoutFOV : 230
+sSliceArray.asSlice[4].dThickness : 4
+sSliceArray.asSlice[4].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[4].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[4].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[4].sPosition.dCor : -51.10562131
+sSliceArray.asSlice[4].sPosition.dSag : 0.8068210485
+sSliceArray.asSlice[4].sPosition.dTra : -9.468875277
+sSliceArray.asSlice[5].dPhaseFOV : 230
+sSliceArray.asSlice[5].dReadoutFOV : 230
+sSliceArray.asSlice[5].dThickness : 4
+sSliceArray.asSlice[5].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[5].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[5].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[5].sPosition.dCor : -50.71806335
+sSliceArray.asSlice[5].sPosition.dSag : 0.4462985405
+sSliceArray.asSlice[5].sPosition.dTra : -5.100829679
+sSliceArray.asSlice[6].dPhaseFOV : 230
+sSliceArray.asSlice[6].dReadoutFOV : 230
+sSliceArray.asSlice[6].dThickness : 4
+sSliceArray.asSlice[6].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[6].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[6].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[6].sPosition.dCor : -50.33050539
+sSliceArray.asSlice[6].sPosition.dSag : 0.08577603254
+sSliceArray.asSlice[6].sPosition.dTra : -0.7327840804
+sSliceArray.asSlice[7].dPhaseFOV : 230
+sSliceArray.asSlice[7].dReadoutFOV : 230
+sSliceArray.asSlice[7].dThickness : 4
+sSliceArray.asSlice[7].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[7].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[7].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[7].sPosition.dCor : -49.94294743
+sSliceArray.asSlice[7].sPosition.dSag : -0.2747464754
+sSliceArray.asSlice[7].sPosition.dTra : 3.635261518
+sSliceArray.asSlice[8].dPhaseFOV : 230
+sSliceArray.asSlice[8].dReadoutFOV : 230
+sSliceArray.asSlice[8].dThickness : 4
+sSliceArray.asSlice[8].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[8].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[8].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[8].sPosition.dCor : -49.55538947
+sSliceArray.asSlice[8].sPosition.dSag : -0.6352689834
+sSliceArray.asSlice[8].sPosition.dTra : 8.003307116
+sSliceArray.asSlice[9].dPhaseFOV : 230
+sSliceArray.asSlice[9].dReadoutFOV : 230
+sSliceArray.asSlice[9].dThickness : 4
+sSliceArray.asSlice[9].sNormal.dCor : 0.08808135446
+sSliceArray.asSlice[9].sNormal.dSag : -0.08193693363
+sSliceArray.asSlice[9].sNormal.dTra : 0.992737636
+sSliceArray.asSlice[9].sPosition.dCor : -49.16783151
+sSliceArray.asSlice[9].sPosition.dSag : -0.9957914914
+sSliceArray.asSlice[9].sPosition.dTra : 12.37135271
+sSliceArray.lConc : 1
+sSliceArray.lSize : 31
+sSliceArray.sTSat.dThickness : 50
+sSliceArray.ucMode : 0x4
+sSpecPara.lDecouplingType : 1
+sSpecPara.lExcitationType : 1
+sSpecPara.lNOEType : 1
+sSpecPara.lPhaseCyclingType : 1
+sSpecPara.lPhaseEncodingType : 1
+sSpecPara.lRFExcitationBandwidth : 1
+sSpecPara.lSpectralSuppression : 1
+sSpecPara.ucRemoveOversampling : 0x1
+sTXSPEC.aRFPULSE[0].bAmplitudeValid : 0x1
+sTXSPEC.aRFPULSE[0].flAmplitude : 263.068
+sTXSPEC.aRFPULSE[0].tName : SincRFPulse
+sTXSPEC.aRFPULSE[1].bAmplitudeValid : 0x1
+sTXSPEC.aRFPULSE[1].flAmplitude : 31.9334
+sTXSPEC.aRFPULSE[1].tName : SLoopFCSatNS
+sTXSPEC.asNucleusInfo[0].bAmplitudeCorrectionValid : 1
+sTXSPEC.asNucleusInfo[0].bFrequencyValid : 1
+sTXSPEC.asNucleusInfo[0].bReferenceAmplitudeValid : 1
+sTXSPEC.asNucleusInfo[0].flAmplitudeCorrection : 1
+sTXSPEC.asNucleusInfo[0].flReferenceAmplitude : 259.084
+sTXSPEC.asNucleusInfo[0].lFrequency : 63644057
+sTXSPEC.asNucleusInfo[0].tNucleus : 1H
+sTXSPEC.asNucleusInfo[1].bAmplitudeCorrectionValid : 1
+sTXSPEC.asNucleusInfo[1].bFrequencyValid : 1
+sTXSPEC.asNucleusInfo[1].bReferenceAmplitudeValid : 1
+sTXSPEC.bBTBValid : 1
+sTXSPEC.bKDynValid : 1
+sTXSPEC.flKDynMagnitudeClipHigh : 1.04
+sTXSPEC.flKDynMagnitudeClipLow : 0.96
+sTXSPEC.flKDynMagnitudeMax : 1.5
+sTXSPEC.flKDynMagnitudeMin : 0.5
+sTXSPEC.flKDynPhaseClip : 0.174533
+sTXSPEC.flKDynPhaseMax : 0.698132
+sTXSPEC.lBTB1ParallelCapacity : 9
+sTXSPEC.lBTB1SerialCapacity : 16
+sTXSPEC.lBTB2ParallelCapacity : 8
+sTXSPEC.lBTB2SerialCapacity : 16
+sTXSPEC.lNoOfTraPulses : 2
+sTXSPEC.ucExcitMode : 0x1
+sTXSPEC.ucRFPulseType : 0x2
+sTXSPEC.ucSimultaneousExcitation : 0x1
+tProtocolName : ep2d+AF8-BOLD+AF8-evntX4
+tReferenceImage0 : 1.3.12.2.1107.5.2.12.21296.30000006070308044128100000804
+tReferenceImage1 : 1.3.12.2.1107.5.2.12.21296.30000006070308044128100000798
+tReferenceImage2 : 1.3.12.2.1107.5.2.12.21296.30000006070308044128100000797
+tSequenceFileName : %SiemensSeq%\ep2d_pace
+tcurrentEVAProt : %CURRENTEVAPROT%\EVA6A.tmp
+tdefaultEVAProt : %SiemensEvaDefProt%\BOLD\t-test_10B10A_moco.evp
+ucDisableChangeStoreImages : 0x1
+ucDixon : 0x1
+ucOneSeriesForAllMeas : 0x1
+ucPHAPSMode : 0x1
+ucReconstructionMode : 0x1
+ucScanRegionPosValid : 0x1
+ulVersion : 0xbee332
+</literallayout></para>
+</refsection>
 <refsection xml:id="gdcmdump_1gems_pdb">
 <title>GEMS Protocol Data Block</title>
 
diff --git a/Utilities/doxygen/man/gdcminfo.xml b/Utilities/doxygen/man/gdcminfo.xml
index e2e495b..795a9d2 100644
--- a/Utilities/doxygen/man/gdcminfo.xml
+++ b/Utilities/doxygen/man/gdcminfo.xml
@@ -163,6 +163,13 @@ Orientation Label: SAGITTAL
 <para>Pay attention that this tool also checks the Image Lossy Compression attribute (0028,2110). This means <option>--check-compression</option> will also returns a value of lossy if a predecessor was found to be lossy compressed.</para>
 </refsection>
 </refsection>
+<refsection xml:id="gdcminfo_1mosaic">
+<title>Checking image as if MOSAIC</title>
+<para>Dump the image as if MOSAIC. If the input is really MOSAIC image, then print the information of the true underlying MOSAIC volume.</para>
+<para><literallayout>$ gdcminfo --mosaic siemens_mosaic.dcm
+</literallayout></para>
+
+</refsection>
 <refsection xml:id="gdcminfo_1see_also">
 <title>SEE ALSO</title>
 
diff --git a/Utilities/doxygen/man/gdcmtar.xml b/Utilities/doxygen/man/gdcmtar.xml
index 0d042d6..5d43f5b 100644
--- a/Utilities/doxygen/man/gdcmtar.xml
+++ b/Utilities/doxygen/man/gdcmtar.xml
@@ -43,6 +43,7 @@ file-out  DICOM output filename
 <para><literallayout>     --enhance    enhance (default)
   -U --unenhance  unenhance
   -M --mosaic     Split SIEMENS Mosaic image into multiple frames.
+     --mosaic-private When splitting SIEMENS Mosaic image into multiple frames, ppreserve private attributes (advanced user only).
   -p --pattern    Specify trailing file pattern.
      --root-uid        Root UID.
 </literallayout></para>
@@ -80,7 +81,7 @@ file-out  DICOM output filename
 <title>Typical usage</title>
 <refsection xml:id="gdcmtar_1mosaic">
 <title>SIEMENS Mosaic</title>
-
+<para>This option will turn a 2D frame containing sub-frame of a SIEMENS MOSAIC into a set of MR Image Storage (legacy).</para>
 <para><literallayout>$ gdcminfo MR-sonata-3D-as-Tile.dcm
 </literallayout></para>
 
@@ -138,6 +139,11 @@ NumberOfDimensions: 2
 Dimensions: (64,64,1)
 ...
 </literallayout></para>
+<para>By default all private attributes are removed since they may not match the newly generated SOP Instance. One way to preserver the private attributes is to use the --mosaic-private command line option</para>
+<para><literallayout>$ gdcmtar --mosaic --mosaic-private -i MR-sonata-3D-as-Tile.dcm -o mosaic --pattern %03d.dcm
+</literallayout></para>
+
+
 </refsection>
 </refsection>
 <refsection xml:id="gdcmtar_1see_also">
diff --git a/Wrapping/Python/gdcmswig.i b/Wrapping/Python/gdcmswig.i
index d4f71ee..26722ee 100644
--- a/Wrapping/Python/gdcmswig.i
+++ b/Wrapping/Python/gdcmswig.i
@@ -26,7 +26,6 @@
 // "There is no option to suppress all SWIG warning messages."
 #pragma SWIG nowarn=302,303,312,362,383,389,401,503,504,509,510,514,516
 %{
-#define SWIG_PYTHON_STRICT_BYTE_CHAR
 #include <cstddef> // ptrdiff_t
 #include "gdcmTypes.h"
 #include "gdcmASN1.h"
@@ -71,6 +70,7 @@
 #include "gdcmBasicOffsetTable.h"
 //#include "gdcmLO.h"
 #include "gdcmCSAElement.h"
+#include "gdcmMrProtocol.h"
 #include "gdcmPDBElement.h"
 #include "gdcmFileSet.h"
 
@@ -195,6 +195,7 @@
 #include "gdcmImageRegionReader.h"
 #include "gdcmJSON.h"
 #include "gdcmFileDecompressLookupTable.h"
+#include "gdcmEmptyMaskGenerator.h"
 
 using namespace gdcm;
 %}
@@ -444,6 +445,8 @@ EXTEND_CLASS_PRINT(gdcm::Fragment)
 EXTEND_CLASS_PRINT(gdcm::PDBElement)
 %include "gdcmPDBHeader.h"
 EXTEND_CLASS_PRINT(gdcm::PDBHeader)
+%include "gdcmMrProtocol.h"
+EXTEND_CLASS_PRINT(gdcm::MrProtocol)
 %include "gdcmCSAElement.h"
 EXTEND_CLASS_PRINT(gdcm::CSAElement)
 %include "gdcmCSAHeader.h"
@@ -797,3 +800,4 @@ EXTEND_CLASS_PRINT(gdcm::BoxRegion)
 %clear char* inreadbuffer;
 %include "gdcmJSON.h"
 %include "gdcmFileDecompressLookupTable.h"
+%include "gdcmEmptyMaskGenerator.h"

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/gdcm.git



More information about the debian-med-commit mailing list