Blame view

stim/envi/binary.h 6.72 KB
1f2ca8ec   David Mayerich   added files for b...
1
2
  
  //make sure that this header file is only loaded once
180d7f3a   David Mayerich   added binary file...
3
4
5
  #ifndef RTS_BINARY_H
  #define RTS_BINARY_H
  
e8eb202f   David Mayerich   added a new ENVI ...
6
  #include "../envi/envi_header.h"
4dcc9392   heziqi   Ziqi's first chan...
7
  #include "../math/vector.h"
180d7f3a   David Mayerich   added binary file...
8
9
10
  #include <fstream>
  #include <sys/stat.h>
  
8a86bd56   David Mayerich   changed rts names...
11
  namespace stim{
180d7f3a   David Mayerich   added binary file...
12
  
33d7d3cf   David Mayerich   documentation for...
13
14
15
16
17
18
19
  /** 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)
   */
180d7f3a   David Mayerich   added binary file...
20
21
22
23
  template< typename T, unsigned int D = 3 >
  class binary{
  
  protected:
180d7f3a   David Mayerich   added binary file...
24
25
26
  	std::fstream file;		//file stream used for reading and writing
  	std::string name;		//file name
  
193ff00e   David Mayerich   dealth with preci...
27
  	unsigned long long int R[D];		//resolution
180d7f3a   David Mayerich   added binary file...
28
  	unsigned int header;	//header size (in bytes)
f4c5d71b   David Mayerich   started working w...
29
  	unsigned char* mask;	//pointer to a character array: 0 = background, 1 = foreground (or valid data)
180d7f3a   David Mayerich   added binary file...
30
31
  
  
ee4dea28   David Mayerich   fixed errors in c...
32
33
  
  
33d7d3cf   David Mayerich   documentation for...
34
  	/// Private initialization function used to set default parameters in the data structure.
180d7f3a   David Mayerich   added binary file...
35
36
37
  	void init(){
  		memset(R, 0, sizeof(unsigned int) * D);		//initialize the resolution to zero
  		header = 0;									//initialize the header size to zero
f4c5d71b   David Mayerich   started working w...
38
  		mask = NULL;
180d7f3a   David Mayerich   added binary file...
39
40
  	}
  
33d7d3cf   David Mayerich   documentation for...
41
  	/// Private helper function that returns the size of the file on disk using system functions.
b0fee590   heziqi   convert long int ...
42
  	long long int get_file_size(){
193ff00e   David Mayerich   dealth with preci...
43
  #ifdef _WIN32
b0fee590   heziqi   convert long int ...
44
45
  		struct _stat64 results;
  		if(_stat64(name.c_str(), &results) == 0)
180d7f3a   David Mayerich   added binary file...
46
  			return results.st_size;
193ff00e   David Mayerich   dealth with preci...
47
48
49
50
51
  #else
  		struct stat results;
  		if(stat(name.c_str(), &results) == 0)
  			return results.st_size;
  #endif
180d7f3a   David Mayerich   added binary file...
52
53
54
  		else return 0;
  	}
  
33d7d3cf   David Mayerich   documentation for...
55
  	/// 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.
180d7f3a   David Mayerich   added binary file...
56
  	bool test_file_size(){
b0fee590   heziqi   convert long int ...
57
  		long long int npts = 1;				//initialize the number of data points to 1
87da9adc   David Mayerich   fixed issues with...
58
59
  		for(unsigned int i = 0; i<D; i++)	//iterate over each dimension
  			npts *= R[i];					//compute the total number of data points in the file
b0fee590   heziqi   convert long int ...
60
  		long long int datasize = npts * sizeof(T);//multiply the sum by the size of the template parameter
87da9adc   David Mayerich   fixed issues with...
61
62
  
  		if(datasize + header == get_file_size()) return true;	//if the byte size matches the file size, we're golden
180d7f3a   David Mayerich   added binary file...
63
64
65
66
  		else return false;					//otherwise return an error
  
  	}
  
33d7d3cf   David Mayerich   documentation for...
67
68
69
  	/// Private helper file that opens a specified binary file.
  
  	/// @param filename is the name of the binary file to stream
180d7f3a   David Mayerich   added binary file...
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
  	bool open_file(std::string filename){
  		//open the file as binary for reading and writing
  		file.open(filename.c_str(), std::ios::in | std::ios::out | std::ios::binary);
  
  		//if the file is successful
  		if(file){
  			name = filename;		//set the name
  			if(test_file_size())	//test the file size
  				return true;
  		}
  		
  		return false;
  	}
  
  public:
  
33d7d3cf   David Mayerich   documentation for...
86
87
88
89
90
  	/// Open a binary file for streaming.
  
  	/// @param filename is the name of the binary file
  	/// @param r is a STIM vector specifying the size of the binary file along each dimension
  	/// @param h is the length (in bytes) of any header file (default zero)
180d7f3a   David Mayerich   added binary file...
91
  	bool open(std::string filename, vec<unsigned int, D> r, unsigned int h = 0){
180d7f3a   David Mayerich   added binary file...
92
  
87da9adc   David Mayerich   fixed issues with...
93
  		for(unsigned int i = 0; i < D; i++)		//set the dimensions of the binary file object
180d7f3a   David Mayerich   added binary file...
94
95
  			R[i] = r[i];
  
87da9adc   David Mayerich   fixed issues with...
96
97
98
  		header = h;				//save the header size
  
  		if(!open_file(filename)) return false;	//open the binary file
180d7f3a   David Mayerich   added binary file...
99
100
101
102
  
  		return test_file_size();
  	}
  
33d7d3cf   David Mayerich   documentation for...
103
104
105
106
107
  	/// 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)
f47168a2   heziqi   Ziqi added create...
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
  	bool create(std::string filename, vec<unsigned int, D> r, unsigned int offset = 0){
  
  		std::ofstream target(filename.c_str(), std::ios::binary);
  
  		//initialize binary file
  		T p = 0;
  		for(unsigned int i =0; i < r[0] * r[1] * r[2]; i++){
  			target.write((char*)(&p), sizeof(T));
  		}
  
  		for(unsigned int 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();
  	}
  
33d7d3cf   David Mayerich   documentation for...
128
129
130
131
  	/// 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)
8157c392   David Mayerich   added parser and ...
132
  	bool write_page( T * p, unsigned int page){
f47168a2   heziqi   Ziqi added create...
133
134
135
136
137
138
  
  		if(p == NULL){
  			std::cout<<"ERROR: unable to write into file, empty pointer"<<std::endl;
  			exit(1);
  		}
  
8157c392   David Mayerich   added parser and ...
139
140
  		file.seekg(R[1] * R[0] * page * sizeof(T), std::ios::beg);   //seek to the desired location on disk
  		file.write((char *)p, R[0] * R[1] * sizeof(T));				 //write binary data
f47168a2   heziqi   Ziqi added create...
141
142
143
144
  
  		return true;
  	}
  
33d7d3cf   David Mayerich   documentation for...
145
146
147
148
  	/// Reads a page from disk. A page consists of a sequence of data of size R[0] * R[1] * ... * R[D-1].
  
  	/// @param p is a pointer to pre-allocated memory equal to the page size
  	/// @param page is the index of the page
8157c392   David Mayerich   added parser and ...
149
  	bool read_page( T * p, unsigned int page){
c7da85e3   heziqi   he,ziqi add metho...
150
  
5d5ce39a   heziqi   Ziqi convert the ...
151
  		if (page >= R[2]){										//make sure the bank number is right
2ad0ce4f   David Mayerich   syntactic edits b...
152
  			std::cout<<"ERROR: page out of range"<<std::endl;
5d5ce39a   heziqi   Ziqi convert the ...
153
  			return false;
c7da85e3   heziqi   he,ziqi add metho...
154
155
  		}
  
3b972fb3   David Mayerich   wrote a general f...
156
  		file.seekg(R[1] * R[0] * page * sizeof(T), std::ios::beg);   //write into memory from the binary file
2ad0ce4f   David Mayerich   syntactic edits b...
157
  		file.read((char *)p, R[0] * R[1] * sizeof(T));
c7da85e3   heziqi   he,ziqi add metho...
158
  
5d5ce39a   heziqi   Ziqi convert the ...
159
  		return true;
c7da85e3   heziqi   he,ziqi add metho...
160
161
  	}
  
3b972fb3   David Mayerich   wrote a general f...
162
  	//saves a hyperplane orthogonal to dimension d at intersection n
8157c392   David Mayerich   added parser and ...
163
  	bool read_plane(T * dest, unsigned int d, unsigned int n){
3b972fb3   David Mayerich   wrote a general f...
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
  
  		//reset the file pointer back to the beginning of the file
  		file.seekg(0, std::ios::beg);
  
  		//compute the contiguous size C for each readable block
  		unsigned int C = 1;
  		for(unsigned int i = 0; i < d; i++)		//for each dimension less than d
  			C *= R[i];							//compute the product
  
  		//compute the non-contiguous size NC for each readable block
  		unsigned int NC = 1;
  		for(unsigned int i = d + 1; i < D; i++)
  			NC *= R[i];
  
  		//for all noncontiguous blocks, read each contiguous block that makes up the hyper-plane
  		for(unsigned int nc = 0; nc < NC; nc++){
  			file.seekg(n * C * sizeof(T), std::ios::cur);	//skip n contiguous blocks
  			file.read( (char*)&dest[nc * C], C * sizeof(T));	//read one contiguous block
  			file.seekg( (R[d] - n - 1) * C * sizeof(T), std::ios::cur);	//skip R[d] - n contiguous blocks
  		}
  
  		return true;
  
  	}
  
5d5ce39a   heziqi   Ziqi convert the ...
189
  	//save one pixel of the file into the memory, and return the pointer
8157c392   David Mayerich   added parser and ...
190
  	bool read_spectrum(T * p, unsigned x, unsigned y){
c7da85e3   heziqi   he,ziqi add metho...
191
  
c7da85e3   heziqi   he,ziqi add metho...
192
193
  		unsigned int i;
  
5d5ce39a   heziqi   Ziqi convert the ...
194
195
196
  		if ( x >= R[0] || y >= R[1]){							//make sure the sample and line number is right
  			std::cout<<"ERROR: sample or line out of range"<<std::endl;
  			return false;
51f94485   heziqi   Ziqi added saveZ,...
197
198
  		}
  
3b972fb3   David Mayerich   wrote a general f...
199
  		file.seekg((x + y * R[0]) * sizeof(T), std::ios::beg);           //point to the certain sample and line
5d5ce39a   heziqi   Ziqi convert the ...
200
  		for (i = 0; i < R[2]; i++)
c7da85e3   heziqi   he,ziqi add metho...
201
  		{
5d5ce39a   heziqi   Ziqi convert the ...
202
  			file.read((char *)(p + i), sizeof(T));
3b972fb3   David Mayerich   wrote a general f...
203
  			file.seekg((R[1] * R[0] - 1) * sizeof(T), std::ios::cur);    //go to the next band
c7da85e3   heziqi   he,ziqi add metho...
204
205
  		}
  
5d5ce39a   heziqi   Ziqi convert the ...
206
  		return true;	
c7da85e3   heziqi   he,ziqi add metho...
207
208
  	}
  
180d7f3a   David Mayerich   added binary file...
209
210
211
212
213
214
  
  };
  
  }
  
  #endif