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