max@0: // Copyright (C) 2008-2011 NICTA (www.nicta.com.au) max@0: // Copyright (C) 2008-2011 Conrad Sanderson max@0: // Copyright (C) 2009-2010 Ian Cullinan max@0: // max@0: // This file is part of the Armadillo C++ library. max@0: // It is provided without any warranty of fitness max@0: // for any purpose. You can redistribute this file max@0: // and/or modify it under the terms of the GNU max@0: // Lesser General Public License (LGPL) as published max@0: // by the Free Software Foundation, either version 3 max@0: // of the License or (at your option) any later version. max@0: // (see http://www.opensource.org/licenses for more info) max@0: max@0: max@0: //! \addtogroup diskio max@0: //! @{ max@0: max@0: max@0: //! Generate the first line of the header used for saving matrices in text format. max@0: //! Format: "ARMA_MAT_TXT_ABXYZ". max@0: //! A is one of: I (for integral types) or F (for floating point types). max@0: //! B is one of: U (for unsigned types), S (for signed types), N (for not appliable) or C (for complex types). max@0: //! XYZ specifies the width of each element in terms of bytes, e.g. "008" indicates eight bytes. max@0: template max@0: inline max@0: std::string max@0: diskio::gen_txt_header(const Mat& x) max@0: { max@0: arma_type_check(( is_supported_elem_type::value == false )); max@0: max@0: arma_ignore(x); max@0: max@0: if(is_u8::value == true) max@0: { max@0: return std::string("ARMA_MAT_TXT_IU001"); max@0: } max@0: else max@0: if(is_s8::value == true) max@0: { max@0: return std::string("ARMA_MAT_TXT_IS001"); max@0: } max@0: else max@0: if(is_u16::value == true) max@0: { max@0: return std::string("ARMA_MAT_TXT_IU002"); max@0: } max@0: else max@0: if(is_s16::value == true) max@0: { max@0: return std::string("ARMA_MAT_TXT_IS002"); max@0: } max@0: else max@0: if(is_u32::value == true) max@0: { max@0: return std::string("ARMA_MAT_TXT_IU004"); max@0: } max@0: else max@0: if(is_s32::value == true) max@0: { max@0: return std::string("ARMA_MAT_TXT_IS004"); max@0: } max@0: #if defined(ARMA_64BIT_WORD) max@0: else max@0: if(is_u64::value == true) max@0: { max@0: return std::string("ARMA_MAT_TXT_IU008"); max@0: } max@0: else max@0: if(is_s64::value == true) max@0: { max@0: return std::string("ARMA_MAT_TXT_IS008"); max@0: } max@0: #endif max@0: else max@0: if(is_float::value == true) max@0: { max@0: return std::string("ARMA_MAT_TXT_FN004"); max@0: } max@0: else max@0: if(is_double::value == true) max@0: { max@0: return std::string("ARMA_MAT_TXT_FN008"); max@0: } max@0: else max@0: if(is_complex_float::value == true) max@0: { max@0: return std::string("ARMA_MAT_TXT_FC008"); max@0: } max@0: else max@0: if(is_complex_double::value == true) max@0: { max@0: return std::string("ARMA_MAT_TXT_FC016"); max@0: } max@0: else max@0: { max@0: return std::string(); max@0: } max@0: max@0: } max@0: max@0: max@0: max@0: //! Generate the first line of the header used for saving matrices in binary format. max@0: //! Format: "ARMA_MAT_BIN_ABXYZ". max@0: //! A is one of: I (for integral types) or F (for floating point types). max@0: //! B is one of: U (for unsigned types), S (for signed types), N (for not appliable) or C (for complex types). max@0: //! XYZ specifies the width of each element in terms of bytes, e.g. "008" indicates eight bytes. max@0: template max@0: inline max@0: std::string max@0: diskio::gen_bin_header(const Mat& x) max@0: { max@0: arma_type_check(( is_supported_elem_type::value == false )); max@0: max@0: arma_ignore(x); max@0: max@0: if(is_u8::value == true) max@0: { max@0: return std::string("ARMA_MAT_BIN_IU001"); max@0: } max@0: else max@0: if(is_s8::value == true) max@0: { max@0: return std::string("ARMA_MAT_BIN_IS001"); max@0: } max@0: else max@0: if(is_u16::value == true) max@0: { max@0: return std::string("ARMA_MAT_BIN_IU002"); max@0: } max@0: else max@0: if(is_s16::value == true) max@0: { max@0: return std::string("ARMA_MAT_BIN_IS002"); max@0: } max@0: else max@0: if(is_u32::value == true) max@0: { max@0: return std::string("ARMA_MAT_BIN_IU004"); max@0: } max@0: else max@0: if(is_s32::value == true) max@0: { max@0: return std::string("ARMA_MAT_BIN_IS004"); max@0: } max@0: #if defined(ARMA_64BIT_WORD) max@0: else max@0: if(is_u64::value == true) max@0: { max@0: return std::string("ARMA_MAT_BIN_IU008"); max@0: } max@0: else max@0: if(is_s64::value == true) max@0: { max@0: return std::string("ARMA_MAT_BIN_IS008"); max@0: } max@0: #endif max@0: else max@0: if(is_float::value == true) max@0: { max@0: return std::string("ARMA_MAT_BIN_FN004"); max@0: } max@0: else max@0: if(is_double::value == true) max@0: { max@0: return std::string("ARMA_MAT_BIN_FN008"); max@0: } max@0: else max@0: if(is_complex_float::value == true) max@0: { max@0: return std::string("ARMA_MAT_BIN_FC008"); max@0: } max@0: else max@0: if(is_complex_double::value == true) max@0: { max@0: return std::string("ARMA_MAT_BIN_FC016"); max@0: } max@0: else max@0: { max@0: return std::string(); max@0: } max@0: max@0: } max@0: max@0: max@0: max@0: //! Generate the first line of the header used for saving cubes in text format. max@0: //! Format: "ARMA_CUB_TXT_ABXYZ". max@0: //! A is one of: I (for integral types) or F (for floating point types). max@0: //! B is one of: U (for unsigned types), S (for signed types), N (for not appliable) or C (for complex types). max@0: //! XYZ specifies the width of each element in terms of bytes, e.g. "008" indicates eight bytes. max@0: template max@0: inline max@0: std::string max@0: diskio::gen_txt_header(const Cube& x) max@0: { max@0: arma_type_check(( is_supported_elem_type::value == false )); max@0: max@0: arma_ignore(x); max@0: max@0: if(is_u8::value == true) max@0: { max@0: return std::string("ARMA_CUB_TXT_IU001"); max@0: } max@0: else max@0: if(is_s8::value == true) max@0: { max@0: return std::string("ARMA_CUB_TXT_IS001"); max@0: } max@0: else max@0: if(is_u16::value == true) max@0: { max@0: return std::string("ARMA_CUB_TXT_IU002"); max@0: } max@0: else max@0: if(is_s16::value == true) max@0: { max@0: return std::string("ARMA_CUB_TXT_IS002"); max@0: } max@0: else max@0: if(is_u32::value == true) max@0: { max@0: return std::string("ARMA_CUB_TXT_IU004"); max@0: } max@0: else max@0: if(is_s32::value == true) max@0: { max@0: return std::string("ARMA_CUB_TXT_IS004"); max@0: } max@0: #if defined(ARMA_64BIT_WORD) max@0: else max@0: if(is_u64::value == true) max@0: { max@0: return std::string("ARMA_CUB_TXT_IU008"); max@0: } max@0: else max@0: if(is_s64::value == true) max@0: { max@0: return std::string("ARMA_CUB_TXT_IS008"); max@0: } max@0: #endif max@0: else max@0: if(is_float::value == true) max@0: { max@0: return std::string("ARMA_CUB_TXT_FN004"); max@0: } max@0: else max@0: if(is_double::value == true) max@0: { max@0: return std::string("ARMA_CUB_TXT_FN008"); max@0: } max@0: else max@0: if(is_complex_float::value == true) max@0: { max@0: return std::string("ARMA_CUB_TXT_FC008"); max@0: } max@0: else max@0: if(is_complex_double::value == true) max@0: { max@0: return std::string("ARMA_CUB_TXT_FC016"); max@0: } max@0: else max@0: { max@0: return std::string(); max@0: } max@0: max@0: } max@0: max@0: max@0: max@0: //! Generate the first line of the header used for saving cubes in binary format. max@0: //! Format: "ARMA_CUB_BIN_ABXYZ". max@0: //! A is one of: I (for integral types) or F (for floating point types). max@0: //! B is one of: U (for unsigned types), S (for signed types), N (for not appliable) or C (for complex types). max@0: //! XYZ specifies the width of each element in terms of bytes, e.g. "008" indicates eight bytes. max@0: template max@0: inline max@0: std::string max@0: diskio::gen_bin_header(const Cube& x) max@0: { max@0: arma_type_check(( is_supported_elem_type::value == false )); max@0: max@0: arma_ignore(x); max@0: max@0: if(is_u8::value == true) max@0: { max@0: return std::string("ARMA_CUB_BIN_IU001"); max@0: } max@0: else max@0: if(is_s8::value == true) max@0: { max@0: return std::string("ARMA_CUB_BIN_IS001"); max@0: } max@0: else max@0: if(is_u16::value == true) max@0: { max@0: return std::string("ARMA_CUB_BIN_IU002"); max@0: } max@0: else max@0: if(is_s16::value == true) max@0: { max@0: return std::string("ARMA_CUB_BIN_IS002"); max@0: } max@0: else max@0: if(is_u32::value == true) max@0: { max@0: return std::string("ARMA_CUB_BIN_IU004"); max@0: } max@0: else max@0: if(is_s32::value == true) max@0: { max@0: return std::string("ARMA_CUB_BIN_IS004"); max@0: } max@0: #if defined(ARMA_64BIT_WORD) max@0: else max@0: if(is_u64::value == true) max@0: { max@0: return std::string("ARMA_CUB_BIN_IU008"); max@0: } max@0: else max@0: if(is_s64::value == true) max@0: { max@0: return std::string("ARMA_CUB_BIN_IS008"); max@0: } max@0: #endif max@0: else max@0: if(is_float::value == true) max@0: { max@0: return std::string("ARMA_CUB_BIN_FN004"); max@0: } max@0: else max@0: if(is_double::value == true) max@0: { max@0: return std::string("ARMA_CUB_BIN_FN008"); max@0: } max@0: else max@0: if(is_complex_float::value == true) max@0: { max@0: return std::string("ARMA_CUB_BIN_FC008"); max@0: } max@0: else max@0: if(is_complex_double::value == true) max@0: { max@0: return std::string("ARMA_CUB_BIN_FC016"); max@0: } max@0: else max@0: { max@0: return std::string(); max@0: } max@0: max@0: } max@0: max@0: max@0: max@0: inline max@0: file_type max@0: diskio::guess_file_type(std::istream& f) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: f.clear(); max@0: const std::fstream::pos_type pos1 = f.tellg(); max@0: max@0: f.clear(); max@0: f.seekg(0, ios::end); max@0: max@0: f.clear(); max@0: const std::fstream::pos_type pos2 = f.tellg(); max@0: max@0: const uword N = ( (pos1 >= 0) && (pos2 >= 0) ) ? uword(pos2 - pos1) : 0; max@0: max@0: f.clear(); max@0: f.seekg(pos1); max@0: max@0: podarray data(N); max@0: max@0: unsigned char* ptr = data.memptr(); max@0: max@0: f.clear(); max@0: f.read( reinterpret_cast(ptr), std::streamsize(N) ); max@0: max@0: const bool load_okay = f.good(); max@0: max@0: f.clear(); max@0: f.seekg(pos1); max@0: max@0: bool has_binary = false; max@0: bool has_comma = false; max@0: max@0: if(load_okay == true) max@0: { max@0: uword i = 0; max@0: uword j = (N >= 2) ? 1 : 0; max@0: max@0: for(; j= 123)) || ((val_j <= 8) || (val_j >= 123)) ) max@0: { max@0: has_binary = true; max@0: break; max@0: } max@0: max@0: if( (val_i == ',') || (val_j == ',') ) max@0: { max@0: has_comma = true; max@0: break; max@0: } max@0: } max@0: } max@0: else max@0: { max@0: return file_type_unknown; max@0: } max@0: max@0: if(has_binary) max@0: { max@0: return raw_binary; max@0: } max@0: max@0: if(has_comma) max@0: { max@0: return csv_ascii; max@0: } max@0: max@0: return raw_ascii; max@0: } max@0: max@0: max@0: max@0: inline max@0: char max@0: diskio::conv_to_hex_char(const u8 x) max@0: { max@0: char out; max@0: max@0: switch(x) max@0: { max@0: case 0: out = '0'; break; max@0: case 1: out = '1'; break; max@0: case 2: out = '2'; break; max@0: case 3: out = '3'; break; max@0: case 4: out = '4'; break; max@0: case 5: out = '5'; break; max@0: case 6: out = '6'; break; max@0: case 7: out = '7'; break; max@0: case 8: out = '8'; break; max@0: case 9: out = '9'; break; max@0: case 10: out = 'a'; break; max@0: case 11: out = 'b'; break; max@0: case 12: out = 'c'; break; max@0: case 13: out = 'd'; break; max@0: case 14: out = 'e'; break; max@0: case 15: out = 'f'; break; max@0: default: out = '-'; break; max@0: } max@0: max@0: return out; max@0: } max@0: max@0: max@0: max@0: inline max@0: void max@0: diskio::conv_to_hex(char* out, const u8 x) max@0: { max@0: const u8 a = x / 16; max@0: const u8 b = x - 16*a; max@0: max@0: out[0] = conv_to_hex_char(a); max@0: out[1] = conv_to_hex_char(b); max@0: } max@0: max@0: max@0: max@0: //! Append a quasi-random string to the given filename. max@0: //! The rand() function is deliberately not used, max@0: //! as rand() has an internal state that changes max@0: //! from call to call. Such states should not be max@0: //! modified in scientific applications, where the max@0: //! results should be reproducable and not affected max@0: //! by saving data. max@0: inline max@0: std::string max@0: diskio::gen_tmp_name(const std::string& x) max@0: { max@0: const std::string* ptr_x = &x; max@0: const u8* ptr_ptr_x = reinterpret_cast(&ptr_x); max@0: max@0: const char* extra = ".tmp_"; max@0: const uword extra_size = 5; max@0: max@0: const uword tmp_size = 2*sizeof(u8*) + 2*2; max@0: char tmp[tmp_size]; max@0: max@0: uword char_count = 0; max@0: max@0: for(uword i=0; i(x.size()); max@0: u8 sum = 0; max@0: max@0: for(uword i=0; i max@0: inline max@0: bool max@0: diskio::save_raw_ascii(const Mat& x, const std::string& final_name) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: const std::string tmp_name = diskio::gen_tmp_name(final_name); max@0: max@0: std::fstream f(tmp_name.c_str(), std::fstream::out); max@0: max@0: bool save_okay = f.is_open(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::save_raw_ascii(x, f); max@0: max@0: f.flush(); max@0: f.close(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::safe_rename(tmp_name, final_name); max@0: } max@0: } max@0: max@0: return save_okay; max@0: } max@0: max@0: max@0: max@0: //! Save a matrix as raw text (no header, human readable). max@0: //! Matrices can be loaded in Matlab and Octave, as long as they don't have complex elements. max@0: template max@0: inline max@0: bool max@0: diskio::save_raw_ascii(const Mat& x, std::ostream& f) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: uword cell_width; max@0: max@0: // TODO: need sane values for complex numbers max@0: max@0: if( (is_float::value == true) || (is_double::value == true) ) max@0: { max@0: f.setf(ios::scientific); max@0: f.precision(10); max@0: cell_width = 18; max@0: } max@0: max@0: for(uword row=0; row < x.n_rows; ++row) max@0: { max@0: for(uword col=0; col < x.n_cols; ++col) max@0: { max@0: f.put(' '); max@0: max@0: if( (is_float::value == true) || (is_double::value == true) ) max@0: { max@0: f.width(cell_width); max@0: } max@0: max@0: f << x.at(row,col); max@0: } max@0: max@0: f.put('\n'); max@0: } max@0: max@0: return f.good(); max@0: } max@0: max@0: max@0: max@0: //! Save a matrix as raw binary (no header) max@0: template max@0: inline max@0: bool max@0: diskio::save_raw_binary(const Mat& x, const std::string& final_name) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: const std::string tmp_name = diskio::gen_tmp_name(final_name); max@0: max@0: std::ofstream f(tmp_name.c_str(), std::fstream::binary); max@0: max@0: bool save_okay = f.is_open(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::save_raw_binary(x, f); max@0: max@0: f.flush(); max@0: f.close(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::safe_rename(tmp_name, final_name); max@0: } max@0: } max@0: max@0: return save_okay; max@0: } max@0: max@0: max@0: max@0: template max@0: inline max@0: bool max@0: diskio::save_raw_binary(const Mat& x, std::ostream& f) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: f.write( reinterpret_cast(x.mem), std::streamsize(x.n_elem*sizeof(eT)) ); max@0: max@0: return f.good(); max@0: } max@0: max@0: max@0: max@0: //! Save a matrix in text format (human readable), max@0: //! with a header that indicates the matrix type as well as its dimensions max@0: template max@0: inline max@0: bool max@0: diskio::save_arma_ascii(const Mat& x, const std::string& final_name) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: const std::string tmp_name = diskio::gen_tmp_name(final_name); max@0: max@0: std::ofstream f(tmp_name.c_str()); max@0: max@0: bool save_okay = f.is_open(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::save_arma_ascii(x, f); max@0: max@0: f.flush(); max@0: f.close(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::safe_rename(tmp_name, final_name); max@0: } max@0: } max@0: max@0: return save_okay; max@0: } max@0: max@0: max@0: max@0: //! Save a matrix in text format (human readable), max@0: //! with a header that indicates the matrix type as well as its dimensions max@0: template max@0: inline max@0: bool max@0: diskio::save_arma_ascii(const Mat& x, std::ostream& f) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: const ios::fmtflags orig_flags = f.flags(); max@0: max@0: f << diskio::gen_txt_header(x) << '\n'; max@0: f << x.n_rows << ' ' << x.n_cols << '\n'; max@0: max@0: uword cell_width; max@0: max@0: // TODO: need sane values for complex numbers max@0: max@0: if( (is_float::value == true) || (is_double::value == true) ) max@0: { max@0: f.setf(ios::scientific); max@0: f.precision(10); max@0: cell_width = 18; max@0: } max@0: max@0: for(uword row=0; row < x.n_rows; ++row) max@0: { max@0: for(uword col=0; col < x.n_cols; ++col) max@0: { max@0: f.put(' '); max@0: max@0: if( (is_float::value == true) || (is_double::value == true) ) max@0: { max@0: f.width(cell_width); max@0: } max@0: max@0: f << x.at(row,col); max@0: } max@0: max@0: f.put('\n'); max@0: } max@0: max@0: const bool save_okay = f.good(); max@0: max@0: f.flags(orig_flags); max@0: max@0: return save_okay; max@0: } max@0: max@0: max@0: max@0: //! Save a matrix in CSV text format (human readable) max@0: template max@0: inline max@0: bool max@0: diskio::save_csv_ascii(const Mat& x, const std::string& final_name) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: const std::string tmp_name = diskio::gen_tmp_name(final_name); max@0: max@0: std::ofstream f(tmp_name.c_str()); max@0: max@0: bool save_okay = f.is_open(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::save_csv_ascii(x, f); max@0: max@0: f.flush(); max@0: f.close(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::safe_rename(tmp_name, final_name); max@0: } max@0: } max@0: max@0: return save_okay; max@0: } max@0: max@0: max@0: max@0: //! Save a matrix in CSV text format (human readable) max@0: template max@0: inline max@0: bool max@0: diskio::save_csv_ascii(const Mat& x, std::ostream& f) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: const ios::fmtflags orig_flags = f.flags(); max@0: max@0: // TODO: need sane values for complex numbers max@0: max@0: if( (is_float::value == true) || (is_double::value == true) ) max@0: { max@0: f.setf(ios::scientific); max@0: f.precision(10); max@0: } max@0: max@0: uword x_n_rows = x.n_rows; max@0: uword x_n_cols = x.n_cols; max@0: max@0: for(uword row=0; row < x_n_rows; ++row) max@0: { max@0: for(uword col=0; col < x_n_cols; ++col) max@0: { max@0: f << x.at(row,col); max@0: max@0: if( col < (x_n_cols-1) ) max@0: { max@0: f.put(','); max@0: } max@0: } max@0: max@0: f.put('\n'); max@0: } max@0: max@0: const bool save_okay = f.good(); max@0: max@0: f.flags(orig_flags); max@0: max@0: return save_okay; max@0: } max@0: max@0: max@0: max@0: //! Save a matrix in binary format, max@0: //! with a header that stores the matrix type as well as its dimensions max@0: template max@0: inline max@0: bool max@0: diskio::save_arma_binary(const Mat& x, const std::string& final_name) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: const std::string tmp_name = diskio::gen_tmp_name(final_name); max@0: max@0: std::ofstream f(tmp_name.c_str(), std::fstream::binary); max@0: max@0: bool save_okay = f.is_open(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::save_arma_binary(x, f); max@0: max@0: f.flush(); max@0: f.close(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::safe_rename(tmp_name, final_name); max@0: } max@0: } max@0: max@0: return save_okay; max@0: } max@0: max@0: max@0: max@0: //! Save a matrix in binary format, max@0: //! with a header that stores the matrix type as well as its dimensions max@0: template max@0: inline max@0: bool max@0: diskio::save_arma_binary(const Mat& x, std::ostream& f) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: f << diskio::gen_bin_header(x) << '\n'; max@0: f << x.n_rows << ' ' << x.n_cols << '\n'; max@0: max@0: f.write( reinterpret_cast(x.mem), std::streamsize(x.n_elem*sizeof(eT)) ); max@0: max@0: return f.good(); max@0: } max@0: max@0: max@0: max@0: //! Save a matrix as a PGM greyscale image max@0: template max@0: inline max@0: bool max@0: diskio::save_pgm_binary(const Mat& x, const std::string& final_name) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: const std::string tmp_name = diskio::gen_tmp_name(final_name); max@0: max@0: std::fstream f(tmp_name.c_str(), std::fstream::out | std::fstream::binary); max@0: max@0: bool save_okay = f.is_open(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::save_pgm_binary(x, f); max@0: max@0: f.flush(); max@0: f.close(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::safe_rename(tmp_name, final_name); max@0: } max@0: } max@0: max@0: return save_okay; max@0: } max@0: max@0: max@0: max@0: // max@0: // TODO: max@0: // add functionality to save the image in a normalised format, max@0: // i.e. scaled so that every value falls in the [0,255] range. max@0: max@0: //! Save a matrix as a PGM greyscale image max@0: template max@0: inline max@0: bool max@0: diskio::save_pgm_binary(const Mat& x, std::ostream& f) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: f << "P5" << '\n'; max@0: f << x.n_cols << ' ' << x.n_rows << '\n'; max@0: f << 255 << '\n'; max@0: max@0: const uword n_elem = x.n_rows * x.n_cols; max@0: podarray tmp(n_elem); max@0: max@0: uword i = 0; max@0: max@0: for(uword row=0; row < x.n_rows; ++row) max@0: { max@0: for(uword col=0; col < x.n_cols; ++col) max@0: { max@0: tmp[i] = u8( x.at(row,col) ); // TODO: add round() ? max@0: ++i; max@0: } max@0: } max@0: max@0: f.write(reinterpret_cast(tmp.mem), std::streamsize(n_elem) ); max@0: max@0: return f.good(); max@0: } max@0: max@0: max@0: max@0: //! Save a matrix as a PGM greyscale image max@0: template max@0: inline max@0: bool max@0: diskio::save_pgm_binary(const Mat< std::complex >& x, const std::string& final_name) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: const uchar_mat tmp = conv_to::from(x); max@0: max@0: return diskio::save_pgm_binary(tmp, final_name); max@0: } max@0: max@0: max@0: max@0: //! Save a matrix as a PGM greyscale image max@0: template max@0: inline max@0: bool max@0: diskio::save_pgm_binary(const Mat< std::complex >& x, std::ostream& f) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: const uchar_mat tmp = conv_to::from(x); max@0: max@0: return diskio::save_pgm_binary(tmp, f); max@0: } max@0: max@0: max@0: max@0: //! Load a matrix as raw text (no header, human readable). max@0: //! Can read matrices saved as text in Matlab and Octave. max@0: //! NOTE: this is much slower than reading a file with a header. max@0: template max@0: inline max@0: bool max@0: diskio::load_raw_ascii(Mat& x, const std::string& name, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: std::fstream f; max@0: f.open(name.c_str(), std::fstream::in); max@0: max@0: bool load_okay = f.is_open(); max@0: max@0: if(load_okay == true) max@0: { max@0: load_okay = diskio::load_raw_ascii(x, f, err_msg); max@0: f.close(); max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: //! Load a matrix as raw text (no header, human readable). max@0: //! Can read matrices saved as text in Matlab and Octave. max@0: //! NOTE: this is much slower than reading a file with a header. max@0: template max@0: inline max@0: bool max@0: diskio::load_raw_ascii(Mat& x, std::istream& f, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: bool load_okay = f.good(); max@0: max@0: f.clear(); max@0: const std::fstream::pos_type pos1 = f.tellg(); max@0: max@0: // max@0: // work out the size max@0: max@0: uword f_n_rows = 0; max@0: uword f_n_cols = 0; max@0: max@0: bool f_n_cols_found = false; max@0: max@0: std::string line_string; max@0: std::string token; max@0: max@0: while( (f.good() == true) && (load_okay == true) ) max@0: { max@0: std::getline(f, line_string); max@0: max@0: if(line_string.size() == 0) max@0: { max@0: break; max@0: } max@0: max@0: std::stringstream line_stream(line_string); max@0: max@0: uword line_n_cols = 0; max@0: max@0: while (line_stream >> token) max@0: { max@0: ++line_n_cols; max@0: } max@0: max@0: if(f_n_cols_found == false) max@0: { max@0: f_n_cols = line_n_cols; max@0: f_n_cols_found = true; max@0: } max@0: else max@0: { max@0: if(line_n_cols != f_n_cols) max@0: { max@0: err_msg = "inconsistent number of columns in "; max@0: load_okay = false; max@0: } max@0: } max@0: max@0: ++f_n_rows; max@0: } max@0: max@0: if(load_okay == true) max@0: { max@0: f.clear(); max@0: f.seekg(pos1); max@0: max@0: x.set_size(f_n_rows, f_n_cols); max@0: max@0: eT val; max@0: max@0: for(uword row=0; (row < x.n_rows) && (load_okay == true); ++row) max@0: { max@0: for(uword col=0; (col < x.n_cols) && (load_okay == true); ++col) max@0: { max@0: f >> val; max@0: max@0: if(f.fail() == false) max@0: { max@0: x.at(row,col) = val; max@0: } max@0: else max@0: { max@0: load_okay = false; max@0: err_msg = "couldn't interpret data in "; max@0: //break; max@0: } max@0: } max@0: } max@0: } max@0: max@0: max@0: // an empty file indicates an empty matrix max@0: if( (f_n_cols_found == false) && (load_okay == true) ) max@0: { max@0: x.reset(); max@0: } max@0: max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: //! Load a matrix in binary format (no header); max@0: //! the matrix is assumed to have one column max@0: template max@0: inline max@0: bool max@0: diskio::load_raw_binary(Mat& x, const std::string& name, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: std::ifstream f; max@0: f.open(name.c_str(), std::fstream::binary); max@0: max@0: bool load_okay = f.is_open(); max@0: max@0: if(load_okay == true) max@0: { max@0: load_okay = diskio::load_raw_binary(x, f, err_msg); max@0: f.close(); max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: template max@0: inline max@0: bool max@0: diskio::load_raw_binary(Mat& x, std::istream& f, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: arma_ignore(err_msg); max@0: max@0: f.clear(); max@0: const std::streampos pos1 = f.tellg(); max@0: max@0: f.clear(); max@0: f.seekg(0, ios::end); max@0: max@0: f.clear(); max@0: const std::streampos pos2 = f.tellg(); max@0: max@0: const uword N = ( (pos1 >= 0) && (pos2 >= 0) ) ? uword(pos2 - pos1) : 0; max@0: max@0: f.clear(); max@0: //f.seekg(0, ios::beg); max@0: f.seekg(pos1); max@0: max@0: x.set_size(N / sizeof(eT), 1); max@0: max@0: f.clear(); max@0: f.read( reinterpret_cast(x.memptr()), std::streamsize(N) ); max@0: max@0: return f.good(); max@0: } max@0: max@0: max@0: max@0: //! Load a matrix in text format (human readable), max@0: //! with a header that indicates the matrix type as well as its dimensions max@0: template max@0: inline max@0: bool max@0: diskio::load_arma_ascii(Mat& x, const std::string& name, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: std::ifstream f(name.c_str()); max@0: max@0: bool load_okay = f.is_open(); max@0: max@0: if(load_okay == true) max@0: { max@0: load_okay = diskio::load_arma_ascii(x, f, err_msg); max@0: f.close(); max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: //! Load a matrix in text format (human readable), max@0: //! with a header that indicates the matrix type as well as its dimensions max@0: template max@0: inline max@0: bool max@0: diskio::load_arma_ascii(Mat& x, std::istream& f, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: bool load_okay = true; max@0: max@0: std::string f_header; max@0: uword f_n_rows; max@0: uword f_n_cols; max@0: max@0: f >> f_header; max@0: f >> f_n_rows; max@0: f >> f_n_cols; max@0: max@0: if(f_header == diskio::gen_txt_header(x)) max@0: { max@0: x.set_size(f_n_rows, f_n_cols); max@0: max@0: for(uword row=0; row < x.n_rows; ++row) max@0: { max@0: for(uword col=0; col < x.n_cols; ++col) max@0: { max@0: f >> x.at(row,col); max@0: } max@0: } max@0: max@0: load_okay = f.good(); max@0: } max@0: else max@0: { max@0: load_okay = false; max@0: err_msg = "incorrect header in "; max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: //! Load a matrix in CSV text format (human readable) max@0: template max@0: inline max@0: bool max@0: diskio::load_csv_ascii(Mat& x, const std::string& name, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: std::fstream f; max@0: f.open(name.c_str(), std::fstream::in); max@0: max@0: bool load_okay = f.is_open(); max@0: max@0: if(load_okay == true) max@0: { max@0: load_okay = diskio::load_csv_ascii(x, f, err_msg); max@0: f.close(); max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: //! Load a matrix in CSV text format (human readable) max@0: template max@0: inline max@0: bool max@0: diskio::load_csv_ascii(Mat& x, std::istream& f, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: bool load_okay = f.good(); max@0: max@0: f.clear(); max@0: const std::fstream::pos_type pos1 = f.tellg(); max@0: max@0: // max@0: // work out the size max@0: max@0: uword f_n_rows = 0; max@0: uword f_n_cols = 0; max@0: max@0: std::string line_string; max@0: std::string token; max@0: max@0: while( (f.good() == true) && (load_okay == true) ) max@0: { max@0: std::getline(f, line_string); max@0: max@0: if(line_string.size() == 0) max@0: { max@0: break; max@0: } max@0: max@0: std::stringstream line_stream(line_string); max@0: max@0: uword line_n_cols = 0; max@0: max@0: while(line_stream.good() == true) max@0: { max@0: getline(line_stream, token, ','); max@0: ++line_n_cols; max@0: } max@0: max@0: if(f_n_cols < line_n_cols) max@0: { max@0: f_n_cols = line_n_cols; max@0: } max@0: max@0: ++f_n_rows; max@0: } max@0: max@0: f.clear(); max@0: f.seekg(pos1); max@0: max@0: x.zeros(f_n_rows, f_n_cols); max@0: max@0: uword row = 0; max@0: max@0: while(f.good() == true) max@0: { max@0: std::getline(f, line_string); max@0: max@0: if(line_string.size() == 0) max@0: { max@0: break; max@0: } max@0: max@0: std::stringstream line_stream(line_string); max@0: max@0: uword col = 0; max@0: max@0: while(line_stream.good() == true) max@0: { max@0: getline(line_stream, token, ','); max@0: max@0: eT val; max@0: max@0: std::stringstream ss(token); max@0: max@0: ss >> val; max@0: max@0: if(ss.fail() == false) max@0: { max@0: x.at(row,col) = val; max@0: } max@0: max@0: ++col; max@0: } max@0: max@0: ++row; max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: //! Load a matrix in binary format, max@0: //! with a header that indicates the matrix type as well as its dimensions max@0: template max@0: inline max@0: bool max@0: diskio::load_arma_binary(Mat& x, const std::string& name, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: std::ifstream f; max@0: f.open(name.c_str(), std::fstream::binary); max@0: max@0: bool load_okay = f.is_open(); max@0: max@0: if(load_okay == true) max@0: { max@0: load_okay = diskio::load_arma_binary(x, f, err_msg); max@0: f.close(); max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: template max@0: inline max@0: bool max@0: diskio::load_arma_binary(Mat& x, std::istream& f, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: bool load_okay = true; max@0: max@0: std::string f_header; max@0: uword f_n_rows; max@0: uword f_n_cols; max@0: max@0: f >> f_header; max@0: f >> f_n_rows; max@0: f >> f_n_cols; max@0: max@0: if(f_header == diskio::gen_bin_header(x)) max@0: { max@0: //f.seekg(1, ios::cur); // NOTE: this may not be portable, as on a Windows machine a newline could be two characters max@0: f.get(); max@0: max@0: x.set_size(f_n_rows,f_n_cols); max@0: f.read( reinterpret_cast(x.memptr()), std::streamsize(x.n_elem*sizeof(eT)) ); max@0: max@0: load_okay = f.good(); max@0: } max@0: else max@0: { max@0: load_okay = false; max@0: err_msg = "incorrect header in "; max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: inline max@0: void max@0: diskio::pnm_skip_comments(std::istream& f) max@0: { max@0: while( isspace(f.peek()) ) max@0: { max@0: while( isspace(f.peek()) ) max@0: { max@0: f.get(); max@0: } max@0: max@0: if(f.peek() == '#') max@0: { max@0: while( (f.peek() != '\r') && (f.peek()!='\n') ) max@0: { max@0: f.get(); max@0: } max@0: } max@0: } max@0: } max@0: max@0: max@0: max@0: //! Load a PGM greyscale image as a matrix max@0: template max@0: inline max@0: bool max@0: diskio::load_pgm_binary(Mat& x, const std::string& name, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: std::fstream f; max@0: f.open(name.c_str(), std::fstream::in | std::fstream::binary); max@0: max@0: bool load_okay = f.is_open(); max@0: max@0: if(load_okay == true) max@0: { max@0: load_okay = diskio::load_pgm_binary(x, f, err_msg); max@0: f.close(); max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: //! Load a PGM greyscale image as a matrix max@0: template max@0: inline max@0: bool max@0: diskio::load_pgm_binary(Mat& x, std::istream& f, std::string& err_msg) max@0: { max@0: bool load_okay = true; max@0: max@0: std::string f_header; max@0: f >> f_header; max@0: max@0: if(f_header == "P5") max@0: { max@0: uword f_n_rows = 0; max@0: uword f_n_cols = 0; max@0: int f_maxval = 0; max@0: max@0: diskio::pnm_skip_comments(f); max@0: max@0: f >> f_n_cols; max@0: diskio::pnm_skip_comments(f); max@0: max@0: f >> f_n_rows; max@0: diskio::pnm_skip_comments(f); max@0: max@0: f >> f_maxval; max@0: f.get(); max@0: max@0: if( (f_maxval > 0) || (f_maxval <= 65535) ) max@0: { max@0: x.set_size(f_n_rows,f_n_cols); max@0: max@0: if(f_maxval <= 255) max@0: { max@0: const uword n_elem = f_n_cols*f_n_rows; max@0: podarray tmp(n_elem); max@0: max@0: f.read( reinterpret_cast(tmp.memptr()), std::streamsize(n_elem) ); max@0: max@0: uword i = 0; max@0: max@0: //cout << "f_n_cols = " << f_n_cols << endl; max@0: //cout << "f_n_rows = " << f_n_rows << endl; max@0: max@0: max@0: for(uword row=0; row < f_n_rows; ++row) max@0: { max@0: for(uword col=0; col < f_n_cols; ++col) max@0: { max@0: x.at(row,col) = eT(tmp[i]); max@0: ++i; max@0: } max@0: } max@0: max@0: } max@0: else max@0: { max@0: const uword n_elem = f_n_cols*f_n_rows; max@0: podarray tmp(n_elem); max@0: max@0: f.read( reinterpret_cast(tmp.memptr()), std::streamsize(n_elem*2) ); max@0: max@0: uword i = 0; max@0: max@0: for(uword row=0; row < f_n_rows; ++row) max@0: { max@0: for(uword col=0; col < f_n_cols; ++col) max@0: { max@0: x.at(row,col) = eT(tmp[i]); max@0: ++i; max@0: } max@0: } max@0: max@0: } max@0: max@0: } max@0: else max@0: { max@0: load_okay = false; max@0: err_msg = "currently no code available to handle loading "; max@0: } max@0: max@0: if(f.good() == false) max@0: { max@0: load_okay = false; max@0: } max@0: } max@0: else max@0: { max@0: load_okay = false; max@0: err_msg = "unsupported header in "; max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: //! Load a PGM greyscale image as a matrix max@0: template max@0: inline max@0: bool max@0: diskio::load_pgm_binary(Mat< std::complex >& x, const std::string& name, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: uchar_mat tmp; max@0: const bool load_okay = diskio::load_pgm_binary(tmp, name, err_msg); max@0: max@0: x = conv_to< Mat< std::complex > >::from(tmp); max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: //! Load a PGM greyscale image as a matrix max@0: template max@0: inline max@0: bool max@0: diskio::load_pgm_binary(Mat< std::complex >& x, std::istream& is, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: uchar_mat tmp; max@0: const bool load_okay = diskio::load_pgm_binary(tmp, is, err_msg); max@0: max@0: x = conv_to< Mat< std::complex > >::from(tmp); max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: //! Try to load a matrix by automatically determining its type max@0: template max@0: inline max@0: bool max@0: diskio::load_auto_detect(Mat& x, const std::string& name, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: std::fstream f; max@0: f.open(name.c_str(), std::fstream::in | std::fstream::binary); max@0: max@0: bool load_okay = f.is_open(); max@0: max@0: if(load_okay == true) max@0: { max@0: load_okay = diskio::load_auto_detect(x, f, err_msg); max@0: f.close(); max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: //! Try to load a matrix by automatically determining its type max@0: template max@0: inline max@0: bool max@0: diskio::load_auto_detect(Mat& x, std::istream& f, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: static const std::string ARMA_MAT_TXT = "ARMA_MAT_TXT"; max@0: static const std::string ARMA_MAT_BIN = "ARMA_MAT_BIN"; max@0: static const std::string P5 = "P5"; max@0: max@0: podarray raw_header(ARMA_MAT_TXT.length() + 1); max@0: max@0: std::streampos pos = f.tellg(); max@0: max@0: f.read( raw_header.memptr(), std::streamsize(ARMA_MAT_TXT.length()) ); max@0: raw_header[ARMA_MAT_TXT.length()] = '\0'; max@0: max@0: f.clear(); max@0: f.seekg(pos); max@0: max@0: const std::string header = raw_header.mem; max@0: max@0: if(ARMA_MAT_TXT == header.substr(0,ARMA_MAT_TXT.length())) max@0: { max@0: return load_arma_ascii(x, f, err_msg); max@0: } max@0: else max@0: if(ARMA_MAT_BIN == header.substr(0,ARMA_MAT_BIN.length())) max@0: { max@0: return load_arma_binary(x, f, err_msg); max@0: } max@0: else max@0: if(P5 == header.substr(0,P5.length())) max@0: { max@0: return load_pgm_binary(x, f, err_msg); max@0: } max@0: else max@0: { max@0: const file_type ft = guess_file_type(f); max@0: max@0: switch(ft) max@0: { max@0: case csv_ascii: max@0: return load_csv_ascii(x, f, err_msg); max@0: break; max@0: max@0: case raw_binary: max@0: return load_raw_binary(x, f, err_msg); max@0: break; max@0: max@0: case raw_ascii: max@0: return load_raw_ascii(x, f, err_msg); max@0: break; max@0: max@0: default: max@0: err_msg = "unknown data in "; max@0: return false; max@0: } max@0: } max@0: max@0: return false; max@0: } max@0: max@0: max@0: max@0: // cubes max@0: max@0: max@0: max@0: //! Save a cube as raw text (no header, human readable). max@0: template max@0: inline max@0: bool max@0: diskio::save_raw_ascii(const Cube& x, const std::string& final_name) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: const std::string tmp_name = diskio::gen_tmp_name(final_name); max@0: max@0: std::fstream f(tmp_name.c_str(), std::fstream::out); max@0: max@0: bool save_okay = f.is_open(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = save_raw_ascii(x, f); max@0: max@0: f.flush(); max@0: f.close(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::safe_rename(tmp_name, final_name); max@0: } max@0: } max@0: max@0: return save_okay; max@0: } max@0: max@0: max@0: max@0: //! Save a cube as raw text (no header, human readable). max@0: template max@0: inline max@0: bool max@0: diskio::save_raw_ascii(const Cube& x, std::ostream& f) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: uword cell_width; max@0: max@0: // TODO: need sane values for complex numbers max@0: max@0: if( (is_float::value == true) || (is_double::value == true) ) max@0: { max@0: f.setf(ios::scientific); max@0: f.precision(10); max@0: cell_width = 18; max@0: } max@0: max@0: for(uword slice=0; slice < x.n_slices; ++slice) max@0: { max@0: for(uword row=0; row < x.n_rows; ++row) max@0: { max@0: for(uword col=0; col < x.n_cols; ++col) max@0: { max@0: f.put(' '); max@0: max@0: if( (is_float::value == true) || (is_double::value == true) ) max@0: { max@0: f.width(cell_width); max@0: } max@0: max@0: f << x.at(row,col,slice); max@0: } max@0: max@0: f.put('\n'); max@0: } max@0: } max@0: max@0: return f.good(); max@0: } max@0: max@0: max@0: max@0: //! Save a cube as raw binary (no header) max@0: template max@0: inline max@0: bool max@0: diskio::save_raw_binary(const Cube& x, const std::string& final_name) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: const std::string tmp_name = diskio::gen_tmp_name(final_name); max@0: max@0: std::ofstream f(tmp_name.c_str(), std::fstream::binary); max@0: max@0: bool save_okay = f.is_open(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::save_raw_binary(x, f); max@0: max@0: f.flush(); max@0: f.close(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::safe_rename(tmp_name, final_name); max@0: } max@0: } max@0: max@0: return save_okay; max@0: } max@0: max@0: max@0: max@0: template max@0: inline max@0: bool max@0: diskio::save_raw_binary(const Cube& x, std::ostream& f) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: f.write( reinterpret_cast(x.mem), std::streamsize(x.n_elem*sizeof(eT)) ); max@0: max@0: return f.good(); max@0: } max@0: max@0: max@0: max@0: //! Save a cube in text format (human readable), max@0: //! with a header that indicates the cube type as well as its dimensions max@0: template max@0: inline max@0: bool max@0: diskio::save_arma_ascii(const Cube& x, const std::string& final_name) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: const std::string tmp_name = diskio::gen_tmp_name(final_name); max@0: max@0: std::ofstream f(tmp_name.c_str()); max@0: max@0: bool save_okay = f.is_open(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::save_arma_ascii(x, f); max@0: max@0: f.flush(); max@0: f.close(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::safe_rename(tmp_name, final_name); max@0: } max@0: } max@0: max@0: return save_okay; max@0: } max@0: max@0: max@0: max@0: //! Save a cube in text format (human readable), max@0: //! with a header that indicates the cube type as well as its dimensions max@0: template max@0: inline max@0: bool max@0: diskio::save_arma_ascii(const Cube& x, std::ostream& f) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: const ios::fmtflags orig_flags = f.flags(); max@0: max@0: f << diskio::gen_txt_header(x) << '\n'; max@0: f << x.n_rows << ' ' << x.n_cols << ' ' << x.n_slices << '\n'; max@0: max@0: uword cell_width; max@0: max@0: // TODO: need sane values for complex numbers max@0: max@0: if( (is_float::value == true) || (is_double::value == true) ) max@0: { max@0: f.setf(ios::scientific); max@0: f.precision(10); max@0: cell_width = 18; max@0: } max@0: max@0: for(uword slice=0; slice < x.n_slices; ++slice) max@0: { max@0: for(uword row=0; row < x.n_rows; ++row) max@0: { max@0: for(uword col=0; col < x.n_cols; ++col) max@0: { max@0: f.put(' '); max@0: max@0: if( (is_float::value == true) || (is_double::value == true) ) max@0: { max@0: f.width(cell_width); max@0: } max@0: max@0: f << x.at(row,col,slice); max@0: } max@0: max@0: f.put('\n'); max@0: } max@0: } max@0: max@0: const bool save_okay = f.good(); max@0: max@0: f.flags(orig_flags); max@0: max@0: return save_okay; max@0: } max@0: max@0: max@0: max@0: //! Save a cube in binary format, max@0: //! with a header that stores the cube type as well as its dimensions max@0: template max@0: inline max@0: bool max@0: diskio::save_arma_binary(const Cube& x, const std::string& final_name) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: const std::string tmp_name = diskio::gen_tmp_name(final_name); max@0: max@0: std::ofstream f(tmp_name.c_str(), std::fstream::binary); max@0: max@0: bool save_okay = f.is_open(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::save_arma_binary(x, f); max@0: max@0: f.flush(); max@0: f.close(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::safe_rename(tmp_name, final_name); max@0: } max@0: } max@0: max@0: return save_okay; max@0: } max@0: max@0: max@0: max@0: //! Save a cube in binary format, max@0: //! with a header that stores the cube type as well as its dimensions max@0: template max@0: inline max@0: bool max@0: diskio::save_arma_binary(const Cube& x, std::ostream& f) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: f << diskio::gen_bin_header(x) << '\n'; max@0: f << x.n_rows << ' ' << x.n_cols << ' ' << x.n_slices << '\n'; max@0: max@0: f.write( reinterpret_cast(x.mem), std::streamsize(x.n_elem*sizeof(eT)) ); max@0: max@0: return f.good(); max@0: } max@0: max@0: max@0: max@0: //! Load a cube as raw text (no header, human readable). max@0: //! NOTE: this is much slower than reading a file with a header. max@0: template max@0: inline max@0: bool max@0: diskio::load_raw_ascii(Cube& x, const std::string& name, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: Mat tmp; max@0: const bool load_okay = diskio::load_raw_ascii(tmp, name, err_msg); max@0: max@0: if(load_okay == true) max@0: { max@0: if(tmp.is_empty() == false) max@0: { max@0: x.set_size(tmp.n_rows, tmp.n_cols, 1); max@0: max@0: x.slice(0) = tmp; max@0: } max@0: else max@0: { max@0: x.reset(); max@0: } max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: //! Load a cube as raw text (no header, human readable). max@0: //! NOTE: this is much slower than reading a file with a header. max@0: template max@0: inline max@0: bool max@0: diskio::load_raw_ascii(Cube& x, std::istream& f, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: Mat tmp; max@0: const bool load_okay = diskio::load_raw_ascii(tmp, f, err_msg); max@0: max@0: if(load_okay == true) max@0: { max@0: if(tmp.is_empty() == false) max@0: { max@0: x.set_size(tmp.n_rows, tmp.n_cols, 1); max@0: max@0: x.slice(0) = tmp; max@0: } max@0: else max@0: { max@0: x.reset(); max@0: } max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: //! Load a cube in binary format (no header); max@0: //! the cube is assumed to have one slice with one column max@0: template max@0: inline max@0: bool max@0: diskio::load_raw_binary(Cube& x, const std::string& name, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: std::ifstream f; max@0: f.open(name.c_str(), std::fstream::binary); max@0: max@0: bool load_okay = f.is_open(); max@0: max@0: if(load_okay == true) max@0: { max@0: load_okay = diskio::load_raw_binary(x, f, err_msg); max@0: f.close(); max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: template max@0: inline max@0: bool max@0: diskio::load_raw_binary(Cube& x, std::istream& f, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: arma_ignore(err_msg); max@0: max@0: f.clear(); max@0: const std::streampos pos1 = f.tellg(); max@0: max@0: f.clear(); max@0: f.seekg(0, ios::end); max@0: max@0: f.clear(); max@0: const std::streampos pos2 = f.tellg(); max@0: max@0: const uword N = ( (pos1 >= 0) && (pos2 >= 0) ) ? uword(pos2 - pos1) : 0; max@0: max@0: f.clear(); max@0: //f.seekg(0, ios::beg); max@0: f.seekg(pos1); max@0: max@0: x.set_size(N / sizeof(eT), 1, 1); max@0: max@0: f.clear(); max@0: f.read( reinterpret_cast(x.memptr()), std::streamsize(N) ); max@0: max@0: return f.good(); max@0: } max@0: max@0: max@0: max@0: //! Load a cube in text format (human readable), max@0: //! with a header that indicates the cube type as well as its dimensions max@0: template max@0: inline max@0: bool max@0: diskio::load_arma_ascii(Cube& x, const std::string& name, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: std::ifstream f(name.c_str()); max@0: max@0: bool load_okay = f.is_open(); max@0: max@0: if(load_okay == true) max@0: { max@0: load_okay = diskio::load_arma_ascii(x, f, err_msg); max@0: f.close(); max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: //! Load a cube in text format (human readable), max@0: //! with a header that indicates the cube type as well as its dimensions max@0: template max@0: inline max@0: bool max@0: diskio::load_arma_ascii(Cube& x, std::istream& f, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: bool load_okay = true; max@0: max@0: std::string f_header; max@0: uword f_n_rows; max@0: uword f_n_cols; max@0: uword f_n_slices; max@0: max@0: f >> f_header; max@0: f >> f_n_rows; max@0: f >> f_n_cols; max@0: f >> f_n_slices; max@0: max@0: if(f_header == diskio::gen_txt_header(x)) max@0: { max@0: x.set_size(f_n_rows, f_n_cols, f_n_slices); max@0: max@0: for(uword slice=0; slice < x.n_slices; ++slice) max@0: { max@0: for(uword row=0; row < x.n_rows; ++row) max@0: { max@0: for(uword col=0; col < x.n_cols; ++col) max@0: { max@0: f >> x.at(row,col,slice); max@0: } max@0: } max@0: } max@0: max@0: load_okay = f.good(); max@0: } max@0: else max@0: { max@0: load_okay = false; max@0: err_msg = "incorrect header in "; max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: //! Load a cube in binary format, max@0: //! with a header that indicates the cube type as well as its dimensions max@0: template max@0: inline max@0: bool max@0: diskio::load_arma_binary(Cube& x, const std::string& name, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: std::ifstream f; max@0: f.open(name.c_str(), std::fstream::binary); max@0: max@0: bool load_okay = f.is_open(); max@0: max@0: if(load_okay == true) max@0: { max@0: load_okay = diskio::load_arma_binary(x, f, err_msg); max@0: f.close(); max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: template max@0: inline max@0: bool max@0: diskio::load_arma_binary(Cube& x, std::istream& f, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: bool load_okay = true; max@0: max@0: std::string f_header; max@0: uword f_n_rows; max@0: uword f_n_cols; max@0: uword f_n_slices; max@0: max@0: f >> f_header; max@0: f >> f_n_rows; max@0: f >> f_n_cols; max@0: f >> f_n_slices; max@0: max@0: if(f_header == diskio::gen_bin_header(x)) max@0: { max@0: //f.seekg(1, ios::cur); // NOTE: this may not be portable, as on a Windows machine a newline could be two characters max@0: f.get(); max@0: max@0: x.set_size(f_n_rows, f_n_cols, f_n_slices); max@0: f.read( reinterpret_cast(x.memptr()), std::streamsize(x.n_elem*sizeof(eT)) ); max@0: max@0: load_okay = f.good(); max@0: } max@0: else max@0: { max@0: load_okay = false; max@0: err_msg = "incorrect header in "; max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: //! Try to load a cube by automatically determining its type max@0: template max@0: inline max@0: bool max@0: diskio::load_auto_detect(Cube& x, const std::string& name, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: std::fstream f; max@0: f.open(name.c_str(), std::fstream::in | std::fstream::binary); max@0: max@0: bool load_okay = f.is_open(); max@0: max@0: if(load_okay == true) max@0: { max@0: load_okay = diskio::load_auto_detect(x, f, err_msg); max@0: f.close(); max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: //! Try to load a cube by automatically determining its type max@0: template max@0: inline max@0: bool max@0: diskio::load_auto_detect(Cube& x, std::istream& f, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: static const std::string ARMA_CUB_TXT = "ARMA_CUB_TXT"; max@0: static const std::string ARMA_CUB_BIN = "ARMA_CUB_BIN"; max@0: static const std::string P6 = "P6"; max@0: max@0: podarray raw_header(ARMA_CUB_TXT.length() + 1); max@0: max@0: std::streampos pos = f.tellg(); max@0: max@0: f.read( raw_header.memptr(), std::streamsize(ARMA_CUB_TXT.length()) ); max@0: raw_header[ARMA_CUB_TXT.length()] = '\0'; max@0: max@0: f.clear(); max@0: f.seekg(pos); max@0: max@0: const std::string header = raw_header.mem; max@0: max@0: if(ARMA_CUB_TXT == header.substr(0, ARMA_CUB_TXT.length())) max@0: { max@0: return load_arma_ascii(x, f, err_msg); max@0: } max@0: else max@0: if(ARMA_CUB_BIN == header.substr(0, ARMA_CUB_BIN.length())) max@0: { max@0: return load_arma_binary(x, f, err_msg); max@0: } max@0: else max@0: if(P6 == header.substr(0, P6.length())) max@0: { max@0: return load_ppm_binary(x, f, err_msg); max@0: } max@0: else max@0: { max@0: const file_type ft = guess_file_type(f); max@0: max@0: switch(ft) max@0: { max@0: // case csv_ascii: max@0: // return load_csv_ascii(x, f, err_msg); max@0: // break; max@0: max@0: case raw_binary: max@0: return load_raw_binary(x, f, err_msg); max@0: break; max@0: max@0: case raw_ascii: max@0: return load_raw_ascii(x, f, err_msg); max@0: break; max@0: max@0: default: max@0: err_msg = "unknown data in "; max@0: return false; max@0: } max@0: } max@0: max@0: return false; max@0: } max@0: max@0: max@0: max@0: max@0: max@0: // fields max@0: max@0: max@0: max@0: template max@0: inline max@0: bool max@0: diskio::save_arma_binary(const field& x, const std::string& final_name) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: const std::string tmp_name = diskio::gen_tmp_name(final_name); max@0: max@0: std::ofstream f( tmp_name.c_str(), std::fstream::binary ); max@0: max@0: bool save_okay = f.is_open(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::save_arma_binary(x, f); max@0: max@0: f.flush(); max@0: f.close(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::safe_rename(tmp_name, final_name); max@0: } max@0: } max@0: max@0: return save_okay; max@0: } max@0: max@0: max@0: max@0: template max@0: inline max@0: bool max@0: diskio::save_arma_binary(const field& x, std::ostream& f) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: arma_type_check(( (is_Mat::value == false) && (is_Cube::value == false) )); max@0: max@0: f << "ARMA_FLD_BIN" << '\n'; max@0: f << x.n_rows << '\n'; max@0: f << x.n_cols << '\n'; max@0: max@0: bool save_okay = true; max@0: max@0: for(uword i=0; i max@0: inline max@0: bool max@0: diskio::load_arma_binary(field& x, const std::string& name, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: std::ifstream f( name.c_str(), std::fstream::binary ); max@0: max@0: bool load_okay = f.is_open(); max@0: max@0: if(load_okay == true) max@0: { max@0: load_okay = diskio::load_arma_binary(x, f, err_msg); max@0: f.close(); max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: template max@0: inline max@0: bool max@0: diskio::load_arma_binary(field& x, std::istream& f, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: arma_type_check(( (is_Mat::value == false) && (is_Cube::value == false) )); max@0: max@0: bool load_okay = true; max@0: max@0: std::string f_type; max@0: f >> f_type; max@0: max@0: if(f_type != "ARMA_FLD_BIN") max@0: { max@0: load_okay = false; max@0: err_msg = "unsupported field type in "; max@0: } max@0: else max@0: { max@0: uword f_n_rows; max@0: uword f_n_cols; max@0: max@0: f >> f_n_rows; max@0: f >> f_n_cols; max@0: max@0: x.set_size(f_n_rows, f_n_cols); max@0: max@0: f.get(); max@0: max@0: for(uword i=0; i& x, const std::string& final_name) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: const std::string tmp_name = diskio::gen_tmp_name(final_name); max@0: max@0: std::ofstream f( tmp_name.c_str(), std::fstream::binary ); max@0: max@0: bool save_okay = f.is_open(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::save_std_string(x, f); max@0: max@0: f.flush(); max@0: f.close(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::safe_rename(tmp_name, final_name); max@0: } max@0: } max@0: max@0: return save_okay; max@0: } max@0: max@0: max@0: max@0: inline max@0: bool max@0: diskio::save_std_string(const field& x, std::ostream& f) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: for(uword row=0; row& x, const std::string& name, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: std::ifstream f( name.c_str() ); max@0: max@0: bool load_okay = f.is_open(); max@0: max@0: if(load_okay == true) max@0: { max@0: load_okay = diskio::load_std_string(x, f, err_msg); max@0: f.close(); max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: inline max@0: bool max@0: diskio::load_std_string(field& x, std::istream& f, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: bool load_okay = true; max@0: max@0: // max@0: // work out the size max@0: max@0: uword f_n_rows = 0; max@0: uword f_n_cols = 0; max@0: max@0: bool f_n_cols_found = false; max@0: max@0: std::string line_string; max@0: std::string token; max@0: max@0: while( (f.good() == true) && (load_okay == true) ) max@0: { max@0: std::getline(f, line_string); max@0: if(line_string.size() == 0) max@0: break; max@0: max@0: std::stringstream line_stream(line_string); max@0: max@0: uword line_n_cols = 0; max@0: while (line_stream >> token) max@0: line_n_cols++; max@0: max@0: if(f_n_cols_found == false) max@0: { max@0: f_n_cols = line_n_cols; max@0: f_n_cols_found = true; max@0: } max@0: else max@0: { max@0: if(line_n_cols != f_n_cols) max@0: { max@0: load_okay = false; max@0: err_msg = "inconsistent number of columns in "; max@0: } max@0: } max@0: max@0: ++f_n_rows; max@0: } max@0: max@0: if(load_okay == true) max@0: { max@0: f.clear(); max@0: f.seekg(0, ios::beg); max@0: //f.seekg(start); max@0: max@0: x.set_size(f_n_rows, f_n_cols); max@0: max@0: for(uword row=0; row < x.n_rows; ++row) max@0: { max@0: for(uword col=0; col < x.n_cols; ++col) max@0: { max@0: f >> x.at(row,col); max@0: } max@0: } max@0: } max@0: max@0: if(f.good() == false) max@0: { max@0: load_okay = false; max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: //! Try to load a field by automatically determining its type max@0: template max@0: inline max@0: bool max@0: diskio::load_auto_detect(field& x, const std::string& name, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: std::fstream f; max@0: f.open(name.c_str(), std::fstream::in | std::fstream::binary); max@0: max@0: bool load_okay = f.is_open(); max@0: max@0: if(load_okay == true) max@0: { max@0: load_okay = diskio::load_auto_detect(x, f, err_msg); max@0: f.close(); max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: //! Try to load a field by automatically determining its type max@0: template max@0: inline max@0: bool max@0: diskio::load_auto_detect(field& x, std::istream& f, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: arma_type_check(( is_Mat::value == false )); max@0: max@0: static const std::string ARMA_FLD_BIN = "ARMA_FLD_BIN"; max@0: static const std::string P6 = "P6"; max@0: max@0: podarray raw_header(ARMA_FLD_BIN.length() + 1); max@0: max@0: std::streampos pos = f.tellg(); max@0: max@0: f.read( raw_header.memptr(), std::streamsize(ARMA_FLD_BIN.length()) ); max@0: max@0: f.clear(); max@0: f.seekg(pos); max@0: max@0: raw_header[ARMA_FLD_BIN.length()] = '\0'; max@0: max@0: const std::string header = raw_header.mem; max@0: max@0: if(ARMA_FLD_BIN == header.substr(0, ARMA_FLD_BIN.length())) max@0: { max@0: return load_arma_binary(x, f, err_msg); max@0: } max@0: else max@0: if(P6 == header.substr(0, P6.length())) max@0: { max@0: return load_ppm_binary(x, f, err_msg); max@0: } max@0: else max@0: { max@0: err_msg = "unsupported header in "; max@0: return false; max@0: } max@0: } max@0: max@0: max@0: max@0: // max@0: // handling of PPM images by cubes max@0: max@0: max@0: template max@0: inline max@0: bool max@0: diskio::load_ppm_binary(Cube& x, const std::string& name, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: std::fstream f; max@0: f.open(name.c_str(), std::fstream::in | std::fstream::binary); max@0: max@0: bool load_okay = f.is_open(); max@0: max@0: if(load_okay == true) max@0: { max@0: load_okay = diskio::load_ppm_binary(x, f, err_msg); max@0: f.close(); max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: template max@0: inline max@0: bool max@0: diskio::load_ppm_binary(Cube& x, std::istream& f, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: bool load_okay = true; max@0: max@0: std::string f_header; max@0: f >> f_header; max@0: max@0: if(f_header == "P6") max@0: { max@0: uword f_n_rows = 0; max@0: uword f_n_cols = 0; max@0: int f_maxval = 0; max@0: max@0: diskio::pnm_skip_comments(f); max@0: max@0: f >> f_n_cols; max@0: diskio::pnm_skip_comments(f); max@0: max@0: f >> f_n_rows; max@0: diskio::pnm_skip_comments(f); max@0: max@0: f >> f_maxval; max@0: f.get(); max@0: max@0: if( (f_maxval > 0) || (f_maxval <= 65535) ) max@0: { max@0: x.set_size(f_n_rows, f_n_cols, 3); max@0: max@0: if(f_maxval <= 255) max@0: { max@0: const uword n_elem = 3*f_n_cols*f_n_rows; max@0: podarray tmp(n_elem); max@0: max@0: f.read( reinterpret_cast(tmp.memptr()), std::streamsize(n_elem) ); max@0: max@0: uword i = 0; max@0: max@0: //cout << "f_n_cols = " << f_n_cols << endl; max@0: //cout << "f_n_rows = " << f_n_rows << endl; max@0: max@0: max@0: for(uword row=0; row < f_n_rows; ++row) max@0: { max@0: for(uword col=0; col < f_n_cols; ++col) max@0: { max@0: x.at(row,col,0) = eT(tmp[i+0]); max@0: x.at(row,col,1) = eT(tmp[i+1]); max@0: x.at(row,col,2) = eT(tmp[i+2]); max@0: i+=3; max@0: } max@0: max@0: } max@0: } max@0: else max@0: { max@0: const uword n_elem = 3*f_n_cols*f_n_rows; max@0: podarray tmp(n_elem); max@0: max@0: f.read( reinterpret_cast(tmp.memptr()), std::streamsize(2*n_elem) ); max@0: max@0: uword i = 0; max@0: max@0: for(uword row=0; row < f_n_rows; ++row) max@0: { max@0: for(uword col=0; col < f_n_cols; ++col) max@0: { max@0: x.at(row,col,0) = eT(tmp[i+0]); max@0: x.at(row,col,1) = eT(tmp[i+1]); max@0: x.at(row,col,2) = eT(tmp[i+2]); max@0: i+=3; max@0: } max@0: max@0: } max@0: max@0: } max@0: max@0: } max@0: else max@0: { max@0: load_okay = false; max@0: err_msg = "currently no code available to handle loading "; max@0: } max@0: max@0: if(f.good() == false) max@0: { max@0: load_okay = false; max@0: } max@0: max@0: } max@0: else max@0: { max@0: load_okay = false; max@0: err_msg = "unsupported header in "; max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: template max@0: inline max@0: bool max@0: diskio::save_ppm_binary(const Cube& x, const std::string& final_name) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: const std::string tmp_name = diskio::gen_tmp_name(final_name); max@0: max@0: std::ofstream f( tmp_name.c_str(), std::fstream::binary ); max@0: max@0: bool save_okay = f.is_open(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::save_ppm_binary(x, f); max@0: max@0: f.flush(); max@0: f.close(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::safe_rename(tmp_name, final_name); max@0: } max@0: } max@0: max@0: return save_okay; max@0: } max@0: max@0: max@0: max@0: template max@0: inline max@0: bool max@0: diskio::save_ppm_binary(const Cube& x, std::ostream& f) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: arma_debug_check( (x.n_slices != 3), "diskio::save_ppm_binary(): given cube must have exactly 3 slices" ); max@0: max@0: const uword n_elem = 3 * x.n_rows * x.n_cols; max@0: podarray tmp(n_elem); max@0: max@0: uword i = 0; max@0: for(uword row=0; row < x.n_rows; ++row) max@0: { max@0: for(uword col=0; col < x.n_cols; ++col) max@0: { max@0: tmp[i+0] = u8( access::tmp_real( x.at(row,col,0) ) ); max@0: tmp[i+1] = u8( access::tmp_real( x.at(row,col,1) ) ); max@0: tmp[i+2] = u8( access::tmp_real( x.at(row,col,2) ) ); max@0: max@0: i+=3; max@0: } max@0: } max@0: max@0: f << "P6" << '\n'; max@0: f << x.n_cols << '\n'; max@0: f << x.n_rows << '\n'; max@0: f << 255 << '\n'; max@0: max@0: f.write( reinterpret_cast(tmp.mem), std::streamsize(n_elem) ); max@0: max@0: return f.good(); max@0: } max@0: max@0: max@0: max@0: // max@0: // handling of PPM images by fields max@0: max@0: max@0: max@0: template max@0: inline max@0: bool max@0: diskio::load_ppm_binary(field& x, const std::string& name, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: std::fstream f; max@0: f.open(name.c_str(), std::fstream::in | std::fstream::binary); max@0: max@0: bool load_okay = f.is_open(); max@0: max@0: if(load_okay == true) max@0: { max@0: load_okay = diskio::load_ppm_binary(x, f, err_msg); max@0: f.close(); max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: template max@0: inline max@0: bool max@0: diskio::load_ppm_binary(field& x, std::istream& f, std::string& err_msg) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: arma_type_check(( is_Mat::value == false )); max@0: typedef typename T1::elem_type eT; max@0: max@0: bool load_okay = true; max@0: max@0: std::string f_header; max@0: f >> f_header; max@0: max@0: if(f_header == "P6") max@0: { max@0: uword f_n_rows = 0; max@0: uword f_n_cols = 0; max@0: int f_maxval = 0; max@0: max@0: diskio::pnm_skip_comments(f); max@0: max@0: f >> f_n_cols; max@0: diskio::pnm_skip_comments(f); max@0: max@0: f >> f_n_rows; max@0: diskio::pnm_skip_comments(f); max@0: max@0: f >> f_maxval; max@0: f.get(); max@0: max@0: if( (f_maxval > 0) || (f_maxval <= 65535) ) max@0: { max@0: x.set_size(3); max@0: Mat& R = x(0); max@0: Mat& G = x(1); max@0: Mat& B = x(2); max@0: max@0: R.set_size(f_n_rows,f_n_cols); max@0: G.set_size(f_n_rows,f_n_cols); max@0: B.set_size(f_n_rows,f_n_cols); max@0: max@0: if(f_maxval <= 255) max@0: { max@0: const uword n_elem = 3*f_n_cols*f_n_rows; max@0: podarray tmp(n_elem); max@0: max@0: f.read( reinterpret_cast(tmp.memptr()), std::streamsize(n_elem) ); max@0: max@0: uword i = 0; max@0: max@0: //cout << "f_n_cols = " << f_n_cols << endl; max@0: //cout << "f_n_rows = " << f_n_rows << endl; max@0: max@0: max@0: for(uword row=0; row < f_n_rows; ++row) max@0: { max@0: for(uword col=0; col < f_n_cols; ++col) max@0: { max@0: R.at(row,col) = eT(tmp[i+0]); max@0: G.at(row,col) = eT(tmp[i+1]); max@0: B.at(row,col) = eT(tmp[i+2]); max@0: i+=3; max@0: } max@0: max@0: } max@0: } max@0: else max@0: { max@0: const uword n_elem = 3*f_n_cols*f_n_rows; max@0: podarray tmp(n_elem); max@0: max@0: f.read( reinterpret_cast(tmp.memptr()), std::streamsize(2*n_elem) ); max@0: max@0: uword i = 0; max@0: max@0: for(uword row=0; row < f_n_rows; ++row) max@0: { max@0: for(uword col=0; col < f_n_cols; ++col) max@0: { max@0: R.at(row,col) = eT(tmp[i+0]); max@0: G.at(row,col) = eT(tmp[i+1]); max@0: B.at(row,col) = eT(tmp[i+2]); max@0: i+=3; max@0: } max@0: max@0: } max@0: max@0: } max@0: max@0: } max@0: else max@0: { max@0: load_okay = false; max@0: err_msg = "currently no code available to handle loading "; max@0: } max@0: max@0: if(f.good() == false) max@0: { max@0: load_okay = false; max@0: } max@0: max@0: } max@0: else max@0: { max@0: load_okay = false; max@0: err_msg = "unsupported header in "; max@0: } max@0: max@0: return load_okay; max@0: } max@0: max@0: max@0: max@0: template max@0: inline max@0: bool max@0: diskio::save_ppm_binary(const field& x, const std::string& final_name) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: const std::string tmp_name = diskio::gen_tmp_name(final_name); max@0: std::ofstream f( tmp_name.c_str(), std::fstream::binary ); max@0: max@0: bool save_okay = f.is_open(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::save_ppm_binary(x, f); max@0: max@0: f.flush(); max@0: f.close(); max@0: max@0: if(save_okay == true) max@0: { max@0: save_okay = diskio::safe_rename(tmp_name, final_name); max@0: } max@0: } max@0: max@0: return save_okay; max@0: } max@0: max@0: max@0: max@0: template max@0: inline max@0: bool max@0: diskio::save_ppm_binary(const field& x, std::ostream& f) max@0: { max@0: arma_extra_debug_sigprint(); max@0: max@0: arma_type_check(( is_Mat::value == false )); max@0: max@0: typedef typename T1::elem_type eT; max@0: max@0: arma_debug_check( (x.n_elem != 3), "diskio::save_ppm_binary(): given field must have exactly 3 matrices of equal size" ); max@0: max@0: bool same_size = true; max@0: for(uword i=1; i<3; ++i) max@0: { max@0: if( (x(0).n_rows != x(i).n_rows) || (x(0).n_cols != x(i).n_cols) ) max@0: { max@0: same_size = false; max@0: break; max@0: } max@0: } max@0: max@0: arma_debug_check( (same_size != true), "diskio::save_ppm_binary(): given field must have exactly 3 matrices of equal size" ); max@0: max@0: const Mat& R = x(0); max@0: const Mat& G = x(1); max@0: const Mat& B = x(2); max@0: max@0: f << "P6" << '\n'; max@0: f << R.n_cols << '\n'; max@0: f << R.n_rows << '\n'; max@0: f << 255 << '\n'; max@0: max@0: const uword n_elem = 3 * R.n_rows * R.n_cols; max@0: podarray tmp(n_elem); max@0: max@0: uword i = 0; max@0: for(uword row=0; row < R.n_rows; ++row) max@0: { max@0: for(uword col=0; col < R.n_cols; ++col) max@0: { max@0: tmp[i+0] = u8( access::tmp_real( R.at(row,col) ) ); max@0: tmp[i+1] = u8( access::tmp_real( G.at(row,col) ) ); max@0: tmp[i+2] = u8( access::tmp_real( B.at(row,col) ) ); max@0: max@0: i+=3; max@0: } max@0: } max@0: max@0: f.write( reinterpret_cast(tmp.mem), std::streamsize(n_elem) ); max@0: max@0: return f.good(); max@0: } max@0: max@0: max@0: max@0: //! @} max@0: