core/vnl/vnl_matlab_read.cxx
Go to the documentation of this file.
00001 // This is core/vnl/vnl_matlab_read.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 #include "vnl_matlab_read.h"
00006 //:
00007 // \file
00008 // \author fsm
00009 #include <vxl_config.h>
00010 #include <vcl_ios.h> // for vcl_ios_cur
00011 #include <vcl_iostream.h>
00012 #include <vcl_cstring.h> // memset()
00013 #include <vcl_complex.h>
00014 #include <vnl/vnl_c_vector.h>
00015 
00016 //--------------------------------------------------------------------------------
00017 
00018 // SGI needs??
00019 void vnl_read_bytes(vcl_istream &s, void *p, unsigned bytes)
00020 {
00021   s.read((char *)p, bytes);
00022 }
00023 
00024 VCL_DEFINE_SPECIALIZATION
00025 void vnl_matlab_read_data(vcl_istream &s, float *p, unsigned n)
00026 { ::vnl_read_bytes(s, p, n*sizeof(*p)); }
00027 
00028 VCL_DEFINE_SPECIALIZATION
00029 void vnl_matlab_read_data(vcl_istream &s, double *p, unsigned n)
00030 { ::vnl_read_bytes(s, p, n*sizeof(*p)); }
00031 
00032 #define implement_read_complex_data(T) \
00033 VCL_DEFINE_SPECIALIZATION \
00034 void vnl_matlab_read_data(vcl_istream &s, vcl_complex<T > *ptr, unsigned n) { \
00035   T *re = vnl_c_vector<T >::allocate_T(n); \
00036   T *im = vnl_c_vector<T >::allocate_T(n); \
00037   ::vnl_read_bytes(s, re, n*sizeof(T)); \
00038   ::vnl_read_bytes(s, im, n*sizeof(T)); \
00039   for (unsigned i=0; i<n; ++i) \
00040     ptr[i] = vcl_complex<T >(re[i], im[i]); \
00041   vnl_c_vector<T >::deallocate(re, n); \
00042   vnl_c_vector<T >::deallocate(im, n); \
00043 }
00044 
00045 implement_read_complex_data(float )
00046 implement_read_complex_data(double)
00047 
00048 #undef implement_read_complex_data
00049 
00050 //--------------------------------------------------------------------------------
00051 
00052 vnl_matlab_readhdr::vnl_matlab_readhdr(vcl_istream &s_) : s(s_), varname(0), data_read(false), need_swap(false)
00053 {
00054   read_hdr();
00055 }
00056 
00057 vnl_matlab_readhdr::~vnl_matlab_readhdr()
00058 {
00059   if (varname)
00060     delete [] varname;
00061   varname = 0;
00062 }
00063 
00064 vnl_matlab_readhdr::operator vnl_matlab_readhdr::safe_bool () const
00065 {
00066   return (s.good() && !s.eof())? VCL_SAFE_BOOL_TRUE : 0; // FIXME
00067 }
00068 
00069 bool vnl_matlab_readhdr::operator!() const
00070 {
00071   return (s.good() && !s.eof())? false : true; // FIXME
00072 }
00073 
00074 bool vnl_matlab_readhdr::is_single() const
00075 {
00076   return (hdr.type % (10*vnl_matlab_header::vnl_SINGLE_PRECISION)) >= vnl_matlab_header::vnl_SINGLE_PRECISION;
00077 }
00078 
00079 bool vnl_matlab_readhdr::is_rowwise() const
00080 {
00081   return (hdr.type % (10*vnl_matlab_header::vnl_ROW_WISE)) >= vnl_matlab_header::vnl_ROW_WISE;
00082 }
00083 
00084 bool vnl_matlab_readhdr::is_bigendian() const
00085 {
00086   return (hdr.type % (10*vnl_matlab_header::vnl_BIG_ENDIAN)) >= vnl_matlab_header::vnl_BIG_ENDIAN;
00087 }
00088 
00089 //: internal
00090 // increment 'current', record the file position and read the header.
00091 void vnl_matlab_readhdr::read_hdr()
00092 {
00093   vcl_memset(&hdr, 0, sizeof hdr);
00094   ::vnl_read_bytes(s, &hdr, sizeof(hdr));
00095 
00096   // determine if data needs swapping when read
00097   // Everything else depends on this; if the header needs swapping
00098   // and is not, nothing good will happen.
00099   switch (hdr.type)
00100   {
00101     case 0:
00102       // 0 means double-precision values, column-major, little-endian,
00103       // so you need to swap if the system is big-endian
00104 #if VXL_BIG_ENDIAN
00105       need_swap = true;
00106 #endif
00107       break;
00108     case 10:
00109       // Regardless of endian-ness, these flag values are
00110       // what the writer puts in the header in the native format,
00111       // therefore if you see any of them, the file is the same-endian
00112       // as the system you're reading on.
00113     case 100:
00114     case 110:
00115     case 1000:
00116     case 1100:
00117     case 1110:
00118       need_swap = false;
00119       break;
00120     default:
00121       // any other values are either gibberish, or need to be byte-swapped
00122       // we hope that it means the file needs byte-swapping, and not that
00123       // the file is corrupt.
00124       need_swap = true;
00125   }
00126   if (need_swap)
00127   {
00128     byteswap::swap32(&hdr.type);
00129     byteswap::swap32(&hdr.rows);
00130     byteswap::swap32(&hdr.cols);
00131     byteswap::swap32(&hdr.imag);
00132     byteswap::swap32(&hdr.namlen);
00133   }
00134   if (varname)
00135     delete [] varname;
00136   varname = new char[hdr.namlen+1];
00137 #ifdef DEBUG
00138   vcl_cerr << "type:" << hdr.type << vcl_endl
00139            << "rows:" << hdr.rows << vcl_endl
00140            << "cols:" << hdr.cols << vcl_endl
00141            << "imag:" << hdr.imag << vcl_endl
00142            << "namlen:" << hdr.namlen << vcl_endl;
00143 #endif
00144   ::vnl_read_bytes(s, varname, hdr.namlen);
00145   varname[hdr.namlen] = '\0';
00146 
00147   data_read = false;
00148 }
00149 
00150 void vnl_matlab_readhdr::read_next()
00151 {
00152   if (!data_read) {
00153     // number of bytes to skip :
00154     unsigned long n = rows()*cols()*sizeof(float);
00155 
00156     if (!is_single())
00157       n *= 2;
00158 
00159     if (is_complex())
00160       n *= 2;
00161     s.seekg(n, vcl_ios_cur);
00162   }
00163 
00164   read_hdr();
00165 }
00166 
00167 //--------------------------------------------------------------------------------
00168 
00169 bool vnl_matlab_readhdr::type_chck(float &) { return is_single() && !is_complex(); }
00170 bool vnl_matlab_readhdr::type_chck(double &) { return !is_single() && !is_complex(); }
00171 bool vnl_matlab_readhdr::type_chck(vcl_complex<float> &) { return is_single() && is_complex(); }
00172 bool vnl_matlab_readhdr::type_chck(vcl_complex<double> &) { return !is_single() && is_complex(); }
00173 
00174 #define fsm_define_methods(T) \
00175 bool vnl_matlab_readhdr::read_data(T &v) { \
00176   if (!type_chck(v)) { vcl_cerr << "type_check\n"; return false; }\
00177   if (rows()!=1U || cols()!=1U) { vcl_cerr << "size0\n"; return false; } \
00178   vnl_matlab_read_data(s, &v, 1); \
00179   if (need_swap) { \
00180     if (sizeof(v) == 4U) byteswap::swap32(&v); else byteswap::swap64(&v); \
00181   } \
00182   data_read = true; return *this; \
00183 } \
00184 bool vnl_matlab_readhdr::read_data(T *p) { \
00185   if (!type_chck(p[0])) { vcl_cerr << "type_check\n"; return false; } \
00186   if (rows()!=1U && cols()!=1U) { vcl_cerr << "size1\n"; return false; } \
00187   vnl_matlab_read_data(s, p, rows()*cols()); \
00188   if (need_swap) { \
00189     for (long i = 0; i < rows()*cols(); ++i) { \
00190       if (sizeof(*p) == 4U) byteswap::swap32(&(p[i])); else byteswap::swap64(&(p[i])); \
00191     } \
00192   } \
00193   data_read = true; return *this; \
00194 } \
00195 bool vnl_matlab_readhdr::read_data(T * const *m) { \
00196   if (!type_chck(m[0][0])) { vcl_cerr << "type_check\n"; return false; } \
00197   T *tmp = vnl_c_vector<T >::allocate_T(rows()*cols()); \
00198   vnl_matlab_read_data(s, tmp, rows()*cols()); \
00199   if (need_swap) { \
00200     for (long i = 0; i < rows()*cols(); ++i) { \
00201       if (sizeof(T) == 4U) byteswap::swap32(&(tmp[i])); else byteswap::swap64(&(tmp[i])); \
00202     } \
00203   } \
00204   int a, b; \
00205   if (is_rowwise()) { a = cols(); b = 1; } \
00206   else { a = 1; b = rows(); } \
00207   for (long i=0; i<rows(); ++i) \
00208     for (long j=0; j<cols(); ++j) \
00209       m[i][j] = tmp[a*i + b*j]; \
00210   vnl_c_vector<T >::deallocate(tmp, rows()*cols()); \
00211   data_read = true; return *this; \
00212 }
00213 
00214 fsm_define_methods(float);
00215 fsm_define_methods(double);
00216 fsm_define_methods(vcl_complex<float>);
00217 fsm_define_methods(vcl_complex<double>);
00218 #undef fsm_define_methods
00219 
00220 //--------------------------------------------------------------------------------
00221 
00222 #include <vcl_cstdlib.h>
00223 #include <vcl_new.h>
00224 #include <vnl/vnl_vector.h>
00225 #include <vnl/vnl_matrix.h>
00226 
00227 template <class T>
00228 bool vnl_matlab_read_or_die(vcl_istream &s,
00229                             vnl_vector<T> &v,
00230                             char const *name)
00231 {
00232   vnl_matlab_readhdr h(s);
00233   if (!s) // eof?
00234     return false;
00235   if (name && *name) {
00236     if (vcl_strcmp(name, h.name())!=0) { /*wrong name?*/
00237       vcl_cerr << "vnl_matlab_read_or_die: names do not match\n";
00238       vcl_abort();
00239     }
00240   }
00241   if (v.size() != (unsigned long)(h.rows()*h.cols()))
00242   {
00243     vcl_destroy(&v);
00244     new (&v) vnl_vector<T>(h.rows()*h.cols());
00245   }
00246   if ( ! h.read_data(v.begin()) ) { /*wrong type?*/
00247     vcl_cerr << "vnl_matlab_read_or_die: failed to read data\n";
00248     vcl_abort();
00249   }
00250   return true;
00251 }
00252 
00253 template <class T>
00254 bool vnl_matlab_read_or_die(vcl_istream &s,
00255                             vnl_matrix<T> &M,
00256                             char const *name)
00257 {
00258   vnl_matlab_readhdr h(s);
00259   if (!s) // eof?
00260     return false;
00261   if (name && *name) {
00262     if (vcl_strcmp(name, h.name())!=0) { /*wrong name?*/
00263       vcl_cerr << "vnl_matlab_read_or_die: names do not match\n";
00264       vcl_abort();
00265     }
00266   }
00267   if (M.rows() != (unsigned long)(h.rows()) || M.cols() != (unsigned long)(h.cols()))
00268   {
00269     vcl_destroy(&M);
00270     new (&M) vnl_matrix<T>(h.rows(), h.cols());
00271   }
00272   if ( ! h.read_data(M.data_array()) ) { /*wrong type?*/
00273     vcl_cerr << "vnl_matlab_read_or_die: failed to read data\n";
00274     vcl_abort();
00275   }
00276   return true;
00277 }
00278 
00279 #define inst(T) \
00280 template bool vnl_matlab_read_or_die(vcl_istream &, vnl_vector<T> &, char const *); \
00281 template bool vnl_matlab_read_or_die(vcl_istream &, vnl_matrix<T> &, char const *);
00282 
00283 inst(double);
00284 inst(float);