Visualization Library 2.0.0

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
ioMHD.cpp
Go to the documentation of this file.
1 /**************************************************************************************/
2 /* */
3 /* Visualization Library */
4 /* http://visualizationlibrary.org */
5 /* */
6 /* Copyright (c) 2005-2020, Michele Bosi */
7 /* All rights reserved. */
8 /* */
9 /* Redistribution and use in source and binary forms, with or without modification, */
10 /* are permitted provided that the following conditions are met: */
11 /* */
12 /* - Redistributions of source code must retain the above copyright notice, this */
13 /* list of conditions and the following disclaimer. */
14 /* */
15 /* - Redistributions in binary form must reproduce the above copyright notice, this */
16 /* list of conditions and the following disclaimer in the documentation and/or */
17 /* other materials provided with the distribution. */
18 /* */
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
20 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
21 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
23 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
24 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
25 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
26 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
27 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
28 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
29 /* */
30 /**************************************************************************************/
31 
32 #include "ioMHD.hpp"
36 #include <vlCore/FileSystem.hpp>
37 #include <vlCore/VirtualFile.hpp>
38 #include <vlCore/Image.hpp>
39 #include <vlCore/TextStream.hpp>
40 
41 using namespace vl;
42 
43 //-----------------------------------------------------------------------------
45 {
47  if ( !file )
48  {
49  Log::error( Say("File '%s' not found.\n") << path );
50  return NULL;
51  }
52 
53  return loadMHD(file.get());
54 }
55 //-----------------------------------------------------------------------------
57 {
58  if ( ! file->open( OM_ReadOnly ) )
59  {
60  Log::error( Say( "%s: could not find MHD file '%s'.\n" ) << __FUNCTION__ << file->path() );
61  return NULL;
62  }
63 
64  ref<TextStream> stream = new TextStream(file);
65  std::string line;
66  vl::ref<KeyValues> keyvals = new KeyValues;
67  std::vector<String> keyval;
68  String entry;
69 
70  while( stream->readLine( line ) )
71  {
72  entry = line;
73  entry.split( '=', keyval, true );
74  if ( keyval.size() == 2 ) {
75  keyval[0].trim();
76  keyval[1].trim();
77  keyvals->set( keyval[0] ) = keyval[1];
78  }
79  }
80 
81  //int ndims = 0;
82  ivec3 offset;
83  fvec3 center_of_rotation;
84  fvec3 element_spacing;
85  int width=0, height=0, depth=0, bytealign=1;
87  EImageType type = vl::IT_SHORT;
88  String raw_file;
89 
90  for( std::map<String, String>::const_iterator it = keyvals->keyValueMap().begin(); it != keyvals->keyValueMap().end(); ++it )
91  {
92  const String& key = it->first;
93  const String& val = it->second;
94 
95  if ( key == "ObjectType" ) {
96  if ( val != "Image" ) {
97  Log::error( Say("%s: ObjectType must be Image ('%s').\n") << __FUNCTION__ << file->path() );
98  return NULL;
99  }
100  } else
101  if ( key == "NDims" ) {
102  if ( val != "3" ) {
103  Log::error( Say("%s: NDims must be 3 ('%s').\n") << __FUNCTION__ << file->path() );
104  return NULL;
105  }
106  // ndims = 3;
107  } else
108  if ( key == "BinaryData" ) {
109  if ( val != "True" ) {
110  Log::error( Say("%s: BinaryData must be True ('%s').\n") << __FUNCTION__ << file->path() );
111  return NULL;
112  }
113  } else
114  if ( key == "BinaryDataByteOrderMSB" ) {
115  if ( val != "False" ) {
116  Log::error( Say("%s: BinaryDataByteOrderMSB must be False ('%s').\n") << __FUNCTION__ << file->path() );
117  return NULL;
118  }
119  } else
120  if ( key == "CompressedData" ) {
121  if ( val != "False" ) {
122  Log::error( Say("%s: CompressedData must be False ('%s').\n") << __FUNCTION__ << file->path() );
123  return NULL;
124  }
125  } else
126  if ( key == "TransformMatrix" ) {
127  if ( val != "1 0 0 0 1 0 0 0 1" ) {
128  Log::error( Say("%s: TransformMatrix must be set to identity matrix ('%s').\n") << __FUNCTION__ << file->path() );
129  // return NULL;
130  }
131  } else
132  if ( key == "Offset" ) {
133  if ( sscanf( val.toStdString().c_str(), "%d %d %d", &offset.x(), &offset.y(), &offset.z() ) != 3 ) {
134  Log::error( Say("%s: invalid Offset value, must be three ints ('%s').\n") << __FUNCTION__ << file->path() );
135  return NULL;
136  }
137  } else
138  if ( key == "CenterOfRotation" ) {
139  if ( sscanf( val.toStdString().c_str(), "%f %f %f", &center_of_rotation.x(), &center_of_rotation.y(), &center_of_rotation.z() ) != 3 ) {
140  Log::error( Say("%s: invalid CenterOfRotation value, must be three floats ('%s') (%n).\n") << __FUNCTION__ << file->path() );
141  return NULL;
142  }
143  } else
144  if ( key == "ElementSpacing" ) {
145  if ( sscanf( val.toStdString().c_str(), "%f %f %f", &element_spacing.x(), &element_spacing.y(), &element_spacing.z() ) != 3 ) {
146  Log::error( Say("%s: invalid ElementSpacing value, must be three floats ('%s').\n") << __FUNCTION__ << file->path() );
147  return NULL;
148  }
149  } else
150  if ( key == "DimSize" ) {
151  if ( sscanf( val.toStdString().c_str(), "%d %d %d", &width, &height, &depth ) != 3 ) {
152  Log::error( Say("%s: invalid DimSize value, must be three ints ('%s').\n") << __FUNCTION__ << file->path() );
153  return NULL;
154  }
155  } else
156  if ( key == "AnatomicalOrientation" ) {
157  // TODO: ???
158  } else
159  if ( key == "ElementType" ) {
160  if ( val != "MET_SHORT" ) {
161  Log::error( Say("%s: invalid ElementType value, only MET_SHORT is supported ('%s').\n") << __FUNCTION__ << file->path() );
162  return NULL;
163  }
164  } else
165  if ( key == "ElementDataFile" ) {
166  raw_file = file->path().extractPath() + val;
167  }
168  }
169 
170  ref<VirtualFile> rawf = defFileSystem()->locateFile( raw_file );
171  if (rawf)
172  {
173  vl::ref<Image> img = loadRAW( rawf.get(), 0, width, height, depth, bytealign, format, type );
174  img->setTags( keyvals.get() );
175  return img;
176  }
177  else
178  {
179  Log::error( Say("loadMHD('%s'): could not find RAW file '%s'.\n") << file->path() << raw_file );
180  return NULL;
181  }
182 }
183 //-----------------------------------------------------------------------------
185 {
186  // Simplistic way to determine if it's an MHD file
187  return file->path().toLowerCase().endsWith(".mhd");
188 }
189 //-----------------------------------------------------------------------------
String toLowerCase() const
Returns the lower-case version of a String.
Definition: String.cpp:755
const std::map< String, String > & keyValueMap() const
Definition: KeyValues.hpp:61
VLCORE_EXPORT FileSystem * defFileSystem()
Returns the default FileSystem used by VisualizationLibrary.
Definition: pimpl.cpp:97
VLCORE_EXPORT bool isMHD(VirtualFile *file)
Definition: ioMHD.cpp:184
const T * get() const
Definition: Object.hpp:128
An abstract class representing a file.
Definition: VirtualFile.hpp:60
bool readLine(std::string &utf8)
Definition: TextStream.hpp:67
A simple String formatting class.
Definition: Say.hpp:124
The String class implements an advanced UTF16 (Unicode BMP) string manipulation engine.
Definition: String.hpp:62
const T_Scalar & z() const
Definition: Vector3.hpp:91
VLCORE_EXPORT ref< Image > loadRAW(VirtualFile *file, long long file_offset, int width, int height, int depth, int bytealign, EImageFormat format, EImageType type)
Loads a raw image file.
Definition: Image.cpp:1280
static void error(const String &message)
Use this function to provide information about run-time errors: file not found, out of memory...
Definition: Log.cpp:165
String extractPath() const
If the String contains a file path the function returns the path with trailing slash, without the file name.
Definition: String.cpp:830
virtual ref< VirtualFile > locateFile(const String &full_path, const String &alternate_path=String()) const
Looks for a VirtualFile on the disk and in the currently active FileSystem.
Definition: FileSystem.cpp:61
const String & path() const
Returns the path of the file.
Definition: VirtualFile.hpp:98
Visualization Library main namespace.
The TextStream class can be used to conveniently read or parse utf8-encoded text files.
Definition: TextStream.hpp:46
const T_Scalar & y() const
Definition: Vector3.hpp:90
virtual bool open(EOpenMode mode)=0
Opens the file in the specified mode.
VLCORE_EXPORT ref< Image > loadMHD(VirtualFile *file)
Definition: ioMHD.cpp:56
void split(wchar_t separator, std::vector< String > &fields, bool remove_empty_fields=false) const
Splits a String into a set of fields. The fields are separated by the specified separator and are ret...
Definition: String.cpp:386
EImageFormat
#define NULL
Definition: OpenGLDefs.hpp:81
EImageType
void setTags(KeyValues *tags)
A set of key/value couples that can be used to attach extra information to an image like DICOM inform...
Definition: Image.hpp:158
const T_Scalar & x() const
Definition: Vector3.hpp:89
The ref<> class is used to reference-count an Object.
Definition: Object.hpp:55
std::string toStdString() const
Returns a UTF8 encoded std::string.
Definition: String.cpp:1156
String & set(const String &key)
Definition: KeyValues.hpp:53
bool endsWith(const String &str) const
Returns true if a String ends with the specified String str.
Definition: String.cpp:705
A set of key/value pairs usually used to associate generic information, tags, attributes etc...
Definition: KeyValues.hpp:42