//make sure that this header file is only loaded once #ifndef RTS_BINARY_H #define RTS_BINARY_H #include "../envi/envi_header.h" #include "../math/vector.h" #include #include namespace stim{ /** This class manages the streaming of large multidimensional binary files. * Generally these are hyperspectral files with 2 spatial and 1 spectral dimension. However, this class supports * other dimensions via the template parameter D. * * @param T is the data type used to store data to disk (generally float or double) * @param D is the dimension of the data (default 3) */ template< typename T, unsigned int D = 3 > class binary{ protected: std::fstream file; //file stream used for reading and writing std::string name; //file name unsigned long long R[D]; //resolution unsigned long long header; //header size (in bytes) unsigned char* mask; //pointer to a character array: 0 = background, 1 = foreground (or valid data) double progress; //stores the progress on the current operation (accessible using a thread) /// Private initialization function used to set default parameters in the data structure. void init(){ memset(R, 0, sizeof(unsigned long long) * D); //initialize the resolution to zero header = 0; //initialize the header size to zero mask = NULL; progress = 0; } /// Private helper function that returns the size of the file on disk using system functions. long long int get_file_size(){ #ifdef _WIN32 struct _stat64 results; if(_stat64(name.c_str(), &results) == 0) return results.st_size; #else struct stat results; if(stat(name.c_str(), &results) == 0) return results.st_size; #endif else return 0; } /// Private helper function that tests to make sure that the calculated data size specified by the structure is the same as the data size on disk. bool test_file_size(){ long long int npts = 1; //initialize the number of data points to 1 for(unsigned int i = 0; i r, unsigned long long h = 0){ for(unsigned long long i = 0; i < D; i++) //set the dimensions of the binary file object R[i] = r[i]; header = h; //save the header size if(!open_file(filename)) return false; //open the binary file //reset(); return test_file_size(); } /// Creates a new binary file for streaming /// @param filename is the name of the binary file to be created /// @param r is a STIM vector specifying the size of the file along each dimension /// @offset specifies how many bytes to offset the file (used to leave room for a header) bool create(std::string filename, vec r, unsigned long long offset = 0){ std::ofstream target(filename.c_str(), std::ios::binary); //initialize binary file T p = 0; for(unsigned long long i =0; i < r[0] * r[1] * r[2]; i++){ target.write((char*)(&p), sizeof(T)); } for(unsigned long long i = 0; i < D; i++) //set the dimensions of the binary file object R[i] = r[i]; header = offset; //save the header size if(!open_file(filename)) return false; //open the binary file return test_file_size(); } /// Writes a single page of data to disk. A page consists of a sequence of data of size R[0] * R[1] * ... * R[D-1]. /// @param p is a pointer to the data to be written /// @param page is the page number (index of the highest-numbered dimension) bool write_page( T * p, unsigned long long page){ if(p == NULL){ std::cout<<"ERROR: unable to write into file, empty pointer"<= R[2]){ //make sure the bank number is right std::cout<<"ERROR: page out of range"<= R[0] || y >= R[1]){ //make sure the sample and line number is right std::cout<<"ERROR: sample or line out of range"<= R[1] || z >= R[2] ){ std::cout<<"ERROR: sample or line out of range"<= R[0] || z >= R[2] ){ std::cout<<"ERROR: sample or line out of range"<= R[0]){ //make sure the number is within the possible range std::cout<<"ERROR read_plane_0: page out of range"<= R[1]){ //make sure the bank number is right std::cout<<"ERROR read_plane_1: page out of range"<= R[0] * R[1] * R[2]){ std::cout<<"ERROR read_pixel: n is out of range"<= R[0] || y < 0 || y >= R[1] || z < 0 || z > R[2]){ std::cout<<"ERROR read_pixel: (x,y,z) is out of range"<