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
|
63fc1df8
David Mayerich
added an inverse ...
|
27
|
unsigned long long R[D]; //resolution
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
28
|
unsigned long long 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
|
|
63fc1df8
David Mayerich
added an inverse ...
|
31
|
double progress; //stores the progress on the current operation (accessible using a thread)
|
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
|
void init(){
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
36
|
memset(R, 0, sizeof(unsigned long long) * D); //initialize the resolution to zero
|
180d7f3a
David Mayerich
added binary file...
|
37
|
header = 0; //initialize the header size to zero
|
f4c5d71b
David Mayerich
started working w...
|
38
|
mask = NULL;
|
cbce396e
David Mayerich
added support for...
|
39
|
|
63fc1df8
David Mayerich
added an inverse ...
|
40
41
42
|
progress = 0;
}
|
33d7d3cf
David Mayerich
documentation for...
|
43
|
/// Private helper function that returns the size of the file on disk using system functions.
|
b0fee590
heziqi
convert long int ...
|
44
|
long long int get_file_size(){
|
193ff00e
David Mayerich
dealth with preci...
|
45
|
#ifdef _WIN32
|
b0fee590
heziqi
convert long int ...
|
46
47
|
struct _stat64 results;
if(_stat64(name.c_str(), &results) == 0)
|
180d7f3a
David Mayerich
added binary file...
|
48
|
return results.st_size;
|
193ff00e
David Mayerich
dealth with preci...
|
49
50
51
52
53
|
#else
struct stat results;
if(stat(name.c_str(), &results) == 0)
return results.st_size;
#endif
|
180d7f3a
David Mayerich
added binary file...
|
54
55
56
|
else return 0;
}
|
33d7d3cf
David Mayerich
documentation for...
|
57
|
/// 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...
|
58
|
bool test_file_size(){
|
b0fee590
heziqi
convert long int ...
|
59
|
long long int npts = 1; //initialize the number of data points to 1
|
87da9adc
David Mayerich
fixed issues with...
|
60
61
|
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 ...
|
62
|
long long int datasize = npts * sizeof(T);//multiply the sum by the size of the template parameter
|
87da9adc
David Mayerich
fixed issues with...
|
63
64
|
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...
|
65
66
67
68
|
else return false; //otherwise return an error
}
|
f92397d2
David Mayerich
fixed a Win32 bug...
|
69
70
71
72
73
74
|
/// Private helper function that resets the file pointer to the beginning of the data
void reset(){
file.seekg(header, std::ios_base::beg);
}
|
33d7d3cf
David Mayerich
documentation for...
|
75
76
77
|
/// 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...
|
78
79
80
81
|
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);
|
ba72c5b0
David Mayerich
added OBJ class
|
82
83
|
//if the file isn't open, the user may only have read access
if(!file.is_open()){
|
3d0b6243
David Mayerich
fixed hsiproc bug...
|
84
|
std::cout<<"class STIM::BINARY - failed to open file, trying for read only"<<std::endl;
|
ba72c5b0
David Mayerich
added OBJ class
|
85
86
87
88
89
90
91
|
file.open(filename.c_str(), std::ios::in | std::ios::binary);
if(!file.is_open()){
std::cout<<" still unable to load the file"<<std::endl;
return false;
}
}
|
180d7f3a
David Mayerich
added binary file...
|
92
93
94
95
96
97
|
//if the file is successful
if(file){
name = filename; //set the name
if(test_file_size()) //test the file size
return true;
}
|
f92397d2
David Mayerich
fixed a Win32 bug...
|
98
|
|
180d7f3a
David Mayerich
added binary file...
|
99
100
101
|
return false;
}
|
724ec347
David Mayerich
simplified the EN...
|
102
103
|
|
f92397d2
David Mayerich
fixed a Win32 bug...
|
104
105
|
|
180d7f3a
David Mayerich
added binary file...
|
106
107
|
public:
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
108
|
double get_progress(){
|
63fc1df8
David Mayerich
added an inverse ...
|
109
|
return progress;
|
cbce396e
David Mayerich
added support for...
|
110
111
|
}
|
63fc1df8
David Mayerich
added an inverse ...
|
112
113
|
void reset_progress(){
progress = 0;
|
cbce396e
David Mayerich
added support for...
|
114
115
|
}
|
33d7d3cf
David Mayerich
documentation for...
|
116
117
118
119
120
|
/// 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)
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
121
|
bool open(std::string filename, vec<unsigned long long> r, unsigned long long h = 0){
|
180d7f3a
David Mayerich
added binary file...
|
122
|
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
123
|
for(unsigned long long i = 0; i < D; i++) //set the dimensions of the binary file object
|
180d7f3a
David Mayerich
added binary file...
|
124
125
|
R[i] = r[i];
|
87da9adc
David Mayerich
fixed issues with...
|
126
127
128
|
header = h; //save the header size
if(!open_file(filename)) return false; //open the binary file
|
180d7f3a
David Mayerich
added binary file...
|
129
|
|
f92397d2
David Mayerich
fixed a Win32 bug...
|
130
131
|
//reset();
|
180d7f3a
David Mayerich
added binary file...
|
132
133
134
|
return test_file_size();
}
|
33d7d3cf
David Mayerich
documentation for...
|
135
136
137
138
139
|
/// 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)
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
140
|
bool create(std::string filename, vec<unsigned long long> r, unsigned long long offset = 0){
|
f47168a2
heziqi
Ziqi added create...
|
141
142
143
144
145
|
std::ofstream target(filename.c_str(), std::ios::binary);
//initialize binary file
T p = 0;
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
146
|
for(unsigned long long i =0; i < r[0] * r[1] * r[2]; i++){
|
f47168a2
heziqi
Ziqi added create...
|
147
148
149
|
target.write((char*)(&p), sizeof(T));
}
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
150
|
for(unsigned long long i = 0; i < D; i++) //set the dimensions of the binary file object
|
f47168a2
heziqi
Ziqi added create...
|
151
152
153
154
155
156
157
158
159
|
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...
|
160
161
162
163
|
/// 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)
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
164
|
bool write_page( T * p, unsigned long long page){
|
f47168a2
heziqi
Ziqi added create...
|
165
166
167
168
169
170
|
if(p == NULL){
std::cout<<"ERROR: unable to write into file, empty pointer"<<std::endl;
exit(1);
}
|
f92397d2
David Mayerich
fixed a Win32 bug...
|
171
|
file.seekg(R[1] * R[0] * page * sizeof(T) + header, std::ios::beg); //seek to the desired location on disk
|
8157c392
David Mayerich
added parser and ...
|
172
|
file.write((char *)p, R[0] * R[1] * sizeof(T)); //write binary data
|
f47168a2
heziqi
Ziqi added create...
|
173
174
175
176
|
return true;
}
|
33d7d3cf
David Mayerich
documentation for...
|
177
178
179
180
|
/// 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
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
181
|
bool read_page( T * p, unsigned long long page, bool PROGRESS = false){
|
63fc1df8
David Mayerich
added an inverse ...
|
182
183
|
if(PROGRESS) progress = 0;
|
c7da85e3
heziqi
he,ziqi add metho...
|
184
|
|
5d5ce39a
heziqi
Ziqi convert the ...
|
185
|
if (page >= R[2]){ //make sure the bank number is right
|
2ad0ce4f
David Mayerich
syntactic edits b...
|
186
|
std::cout<<"ERROR: page out of range"<<std::endl;
|
5d5ce39a
heziqi
Ziqi convert the ...
|
187
|
return false;
|
c7da85e3
heziqi
he,ziqi add metho...
|
188
189
|
}
|
f92397d2
David Mayerich
fixed a Win32 bug...
|
190
|
file.seekg(R[1] * R[0] * page * sizeof(T) + header, std::ios::beg); //write into memory from the binary file
|
2ad0ce4f
David Mayerich
syntactic edits b...
|
191
|
file.read((char *)p, R[0] * R[1] * sizeof(T));
|
63fc1df8
David Mayerich
added an inverse ...
|
192
|
if(PROGRESS) progress = 100;
|
5d5ce39a
heziqi
Ziqi convert the ...
|
193
|
return true;
|
c7da85e3
heziqi
he,ziqi add metho...
|
194
195
|
}
|
724ec347
David Mayerich
simplified the EN...
|
196
197
198
199
200
201
202
|
///Reads a line Z (slowest dimension) for a given XY value
/// @param p is a pointer to pre-allocated memory equal to the line size R[2]
/// @param x is the x coordinate
/// @param y is the y coordinate
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
203
204
|
bool read_line_2( T * p, unsigned long long x, unsigned long long y, bool PROGRESS = false){
unsigned long long i;
|
724ec347
David Mayerich
simplified the EN...
|
205
|
|
63fc1df8
David Mayerich
added an inverse ...
|
206
207
|
if(PROGRESS) progress = 0;
|
724ec347
David Mayerich
simplified the EN...
|
208
209
210
211
212
213
214
215
216
217
|
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;
}
file.seekg((x + y * R[0]) * sizeof(T), std::ios::beg); //point to the certain sample and line
for (i = 0; i < R[2]; i++)
{
file.read((char *)(p + i), sizeof(T));
file.seekg((R[1] * R[0] - 1) * sizeof(T), std::ios::cur); //go to the next band
|
63fc1df8
David Mayerich
added an inverse ...
|
218
|
if(PROGRESS) progress = (double)i / (double)R[2] * 100;
|
724ec347
David Mayerich
simplified the EN...
|
219
|
}
|
63fc1df8
David Mayerich
added an inverse ...
|
220
|
if(PROGRESS) progress = 100;
|
724ec347
David Mayerich
simplified the EN...
|
221
222
223
224
225
226
227
228
229
|
return true;
}
///Reads a line X (fastest dimension) for a given YZ value
/// @param p is a pointer to pre-allocated memory equal to the line size R[2]
/// @param x is the y coordinate
/// @param y is the z coordinate
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
230
|
bool read_line_0(T * p, unsigned long long y, unsigned long long z, bool PROGRESS = false){
|
724ec347
David Mayerich
simplified the EN...
|
231
232
233
234
235
236
237
238
|
//test to make sure the specified value is within range
if( y >= R[1] || z >= R[2] ){
std::cout<<"ERROR: sample or line out of range"<<std::endl;
return false;
}
file.seekg((z * R[0] * R[1] + y * R[0]) * sizeof(T), std::ios::beg); //seek to the start of the line
file.read((char *)p, sizeof(T) * R[0]); //read the line
|
63fc1df8
David Mayerich
added an inverse ...
|
239
|
if(PROGRESS) progress = 100;
|
724ec347
David Mayerich
simplified the EN...
|
240
241
242
243
244
245
246
247
|
return true;
}
///Reads a line Y (second fastest dimension) for a given XZ value
/// @param p is a pointer to pre-allocated memory equal to the line size R[2]
/// @param x is the y coordinate
/// @param z is the z coordinate
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
248
|
bool read_line_1(T * p, unsigned long long x, unsigned long long z, bool PROGRESS = false){
|
63fc1df8
David Mayerich
added an inverse ...
|
249
|
if(PROGRESS) progress = 0;
|
724ec347
David Mayerich
simplified the EN...
|
250
251
252
253
254
255
256
|
//test to make sure the specified value is within range
if( x >= R[0] || z >= R[2] ){
std::cout<<"ERROR: sample or line out of range"<<std::endl;
return false;
}
file.seekg((z * R[0] * R[1] + x) * sizeof(T), std::ios::beg); //seek to the start of the line
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
257
|
for (unsigned long long i = 0; i < R[1]; i++){ //for each pixel in the line
|
724ec347
David Mayerich
simplified the EN...
|
258
259
|
file.read((char *)(p + i), sizeof(T)); //read the pixel
file.seekg((R[0] - 1) * sizeof(T), std::ios::cur); //seek to the next pixel in the line
|
63fc1df8
David Mayerich
added an inverse ...
|
260
|
if(PROGRESS) progress = (double)i / (double)R[1] * 100;
|
724ec347
David Mayerich
simplified the EN...
|
261
|
}
|
63fc1df8
David Mayerich
added an inverse ...
|
262
|
if(PROGRESS) progress = 100;
|
724ec347
David Mayerich
simplified the EN...
|
263
264
265
|
return true;
}
|
27b826a8
David Mayerich
added a spherical...
|
266
267
268
269
|
/// Reads a plane given a coordinate along the 0-axis (YZ plane)
/// @param p is a pointer to pre-allocated memory of size R[1] * R[2] * sizeof(T)
/// @param n is the 0-axis coordinate used to retrieve the plane
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
270
|
bool read_plane_0(T* p, unsigned long long n, bool PROGRESS = false){
|
63fc1df8
David Mayerich
added an inverse ...
|
271
|
if(PROGRESS) progress = 0;
|
724ec347
David Mayerich
simplified the EN...
|
272
273
274
275
|
if (n >= R[0]){ //make sure the number is within the possible range
std::cout<<"ERROR read_plane_0: page out of range"<<std::endl;
return false;
}
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
276
|
unsigned long long jump = (R[0] - 1) * sizeof(T); //number of bytes to skip between samples
|
724ec347
David Mayerich
simplified the EN...
|
277
278
279
280
|
//seek to the start of the plane
file.seekg(n * sizeof(T), std::ios::beg);
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
281
282
|
unsigned long long N = R[1] * R[2];
for(unsigned long long i = 0; i<N; i++){
|
724ec347
David Mayerich
simplified the EN...
|
283
284
|
file.read((char*)(p+i), sizeof(T));
file.seekg(jump, std::ios::cur);
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
285
|
if(PROGRESS) progress = (double)(i+1) / N * 100;
|
724ec347
David Mayerich
simplified the EN...
|
286
287
|
}
|
724ec347
David Mayerich
simplified the EN...
|
288
289
290
291
292
|
return true;
}
|
27b826a8
David Mayerich
added a spherical...
|
293
294
295
296
|
/// Reads a plane given a coordinate along the 1-axis (XZ plane)
/// @param p is a pointer to pre-allocated memory of size R[0] * R[2] * sizeof(T)
/// @param n is the 1-axis coordinate used to retrieve the plane
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
297
|
bool read_plane_1(T* p, unsigned long long n, bool PROGRESS = false){
|
63fc1df8
David Mayerich
added an inverse ...
|
298
|
if(PROGRESS) progress = 0;
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
299
300
|
unsigned long long L = R[0] * sizeof(T); //caculate the number of bytes in a sample line
unsigned long long jump = R[0] * (R[1] - 1) * sizeof(T);
|
724ec347
David Mayerich
simplified the EN...
|
301
302
303
304
305
306
307
|
if (n >= R[1]){ //make sure the bank number is right
std::cout<<"ERROR read_plane_1: page out of range"<<std::endl;
return false;
}
file.seekg(R[0] * n * sizeof(T), std::ios::beg);
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
308
|
for (unsigned long long i = 0; i < R[2]; i++){
|
63fc1df8
David Mayerich
added an inverse ...
|
309
|
if(PROGRESS) progress = (double)i / R[2] * 100;
|
724ec347
David Mayerich
simplified the EN...
|
310
311
312
313
314
|
file.read((char *)(p + i * R[0]), L);
file.seekg( jump, std::ios::cur);
std::cout<<i<<" ";
}
|
63fc1df8
David Mayerich
added an inverse ...
|
315
|
if(PROGRESS) progress = 100;
|
724ec347
David Mayerich
simplified the EN...
|
316
317
318
|
return true;
}
|
27b826a8
David Mayerich
added a spherical...
|
319
320
321
322
|
/// Reads a plane given a coordinate along the 2-axis (XY plane)
/// @param p is a pointer to pre-allocated memory of size R[0] * R[1] * sizeof(T)
/// @param n is the 2-axis coordinate used to retrieve the plane
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
323
|
bool read_plane_2(T* p, unsigned long long n, bool PROGRESS = false){
|
63fc1df8
David Mayerich
added an inverse ...
|
324
|
return read_page(p, n, PROGRESS);
|
724ec347
David Mayerich
simplified the EN...
|
325
326
|
}
|
27b826a8
David Mayerich
added a spherical...
|
327
328
329
330
|
/// Reads a single pixel, treating the entire data set as a linear array
/// @param p is a pointer to pre-allocated memory of size sizeof(T)
/// @param i is the index to the pixel using linear indexing
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
331
|
bool read_pixel(T* p, unsigned long long i){
|
724ec347
David Mayerich
simplified the EN...
|
332
333
334
335
336
337
338
339
340
341
|
if(i >= R[0] * R[1] * R[2]){
std::cout<<"ERROR read_pixel: n is out of range"<<std::endl;
return false;
}
file.seekg(i * sizeof(T), std::ios::cur);
file.read((char*)p, sizeof(T));
}
|
27b826a8
David Mayerich
added a spherical...
|
342
343
344
345
346
347
|
/// Reads a single pixel, given an x, y, z coordinate
/// @param p is a pointer to pre-allocated memory of size sizeof(T)
/// @param x is the x (0) axis coordinate
/// @param y is the y (1) axis coordinate
/// @param z is the z (2) axis coordinate
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
348
|
bool read_pixel(T* p, unsigned long long x, unsigned long long y, unsigned long long z){
|
724ec347
David Mayerich
simplified the EN...
|
349
350
351
352
353
354
|
if(x < 0 || x >= R[0] || y < 0 || y >= R[1] || z < 0 || z > R[2]){
std::cout<<"ERROR read_pixel: (x,y,z) is out of range"<<std::endl;
return false;
}
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
355
|
unsigned long long i = z * R[0] * R[1] + y * R[0] + z;
|
724ec347
David Mayerich
simplified the EN...
|
356
357
358
|
return read_pixel(p, i);
}
|
180d7f3a
David Mayerich
added binary file...
|
359
360
361
362
363
|
};
}
#endif
|