Commit 735a2a247ec4aeb7655e683a35e8465062e9d16b
1 parent
c5da6290
started testing out template casting support for stim::envi, added a stim::table…
… class for reading csv files
Showing
7 changed files
with
308 additions
and
14 deletions
Show diff stats
stim/envi/bil.h
... | ... | @@ -200,6 +200,11 @@ public: |
200 | 200 | /// @param p is a pointer to pre-allocated memory at least B * sizeof(T) in size. |
201 | 201 | /// @param x is the x-coordinate (dimension 1) of the spectrum. |
202 | 202 | /// @param y is the y-coordinate (dimension 2) of the spectrum. |
203 | + bool spectrum(T* p, size_t n, bool PROGRESS = false){ | |
204 | + size_t y = n / X(); | |
205 | + size_t x = n - y * X(); | |
206 | + return binary<T>::read_line_1(p, x, y, PROGRESS); | |
207 | + } | |
203 | 208 | bool spectrum(T * p, unsigned long long x, unsigned long long y, bool PROGRESS = false){ |
204 | 209 | return binary<T>::read_line_1(p, x, y, PROGRESS); |
205 | 210 | } | ... | ... |
stim/envi/binary.h
... | ... | @@ -200,11 +200,30 @@ public: |
200 | 200 | /// @param p is a pointer to pre-allocated memory equal to the line size R[2] |
201 | 201 | /// @param x is the x coordinate |
202 | 202 | /// @param y is the y coordinate |
203 | - bool read_line_2( T * p, unsigned long long x, unsigned long long y, bool PROGRESS = false){ | |
203 | + void read_line_2( T* p, size_t n, bool PROGRESS = false){ | |
204 | 204 | unsigned long long i; |
205 | 205 | |
206 | 206 | if(PROGRESS) progress = 0; |
207 | 207 | |
208 | + if ( n > R[0] * R[1]){ //make sure the sample and line number is right | |
209 | + std::cout<<"ERROR: sample or line out of range in "<<__FILE__<<" (line "<<__LINE__<<")"<<std::endl; | |
210 | + exit(1); | |
211 | + } | |
212 | + | |
213 | + file.seekg(n * sizeof(T), std::ios::beg); //point to the certain sample and line | |
214 | + for (i = 0; i < R[2]; i++){ //for each band | |
215 | + file.read((char *)(p + i), sizeof(T)); | |
216 | + file.seekg((R[1] * R[0] - 1) * sizeof(T), std::ios::cur); //go to the next band | |
217 | + if(PROGRESS) progress = (double)i / (double)R[2] * 100; | |
218 | + } | |
219 | + if(PROGRESS) progress = 100; | |
220 | + } | |
221 | + void read_line_2( T * p, unsigned long long x, unsigned long long y, bool PROGRESS = false){ | |
222 | + read_line_2(p, y * R[0] + x, PROGRESS); | |
223 | + /*unsigned long long i; | |
224 | + | |
225 | + if(PROGRESS) progress = 0; | |
226 | + | |
208 | 227 | if ( x >= R[0] || y >= R[1]){ //make sure the sample and line number is right |
209 | 228 | std::cout<<"ERROR: sample or line out of range"<<std::endl; |
210 | 229 | return false; |
... | ... | @@ -219,7 +238,7 @@ public: |
219 | 238 | } |
220 | 239 | if(PROGRESS) progress = 100; |
221 | 240 | |
222 | - return true; | |
241 | + return true;*/ | |
223 | 242 | } |
224 | 243 | |
225 | 244 | ///Reads a line X (fastest dimension) for a given YZ value |
... | ... | @@ -230,7 +249,7 @@ public: |
230 | 249 | bool read_line_0(T * p, unsigned long long y, unsigned long long z, bool PROGRESS = false){ |
231 | 250 | //test to make sure the specified value is within range |
232 | 251 | if( y >= R[1] || z >= R[2] ){ |
233 | - std::cout<<"ERROR: sample or line out of range"<<std::endl; | |
252 | + std::cout<<"ERROR: sample ("<<y<<", "<<z<<") out of range in "<<__FILE__<<" (line "<<__LINE__<<")"<<std::endl; | |
234 | 253 | return false; |
235 | 254 | } |
236 | 255 | |
... | ... | @@ -249,7 +268,7 @@ public: |
249 | 268 | if(PROGRESS) progress = 0; |
250 | 269 | //test to make sure the specified value is within range |
251 | 270 | if( x >= R[0] || z >= R[2] ){ |
252 | - std::cout<<"ERROR: sample or line out of range"<<std::endl; | |
271 | + std::cout<<"ERROR: sample or line out of range in "<<__FILE__<<" (line "<<__LINE__<<")"<<std::endl; | |
253 | 272 | return false; |
254 | 273 | } |
255 | 274 | |
... | ... | @@ -270,7 +289,7 @@ public: |
270 | 289 | bool read_plane_0(T* p, unsigned long long n, bool PROGRESS = false){ |
271 | 290 | if(PROGRESS) progress = 0; |
272 | 291 | if (n >= R[0]){ //make sure the number is within the possible range |
273 | - std::cout<<"ERROR read_plane_0: page out of range"<<std::endl; | |
292 | + std::cout<<"ERROR: sample or line out of range in "<<__FILE__<<" (line "<<__LINE__<<")"<<std::endl; | |
274 | 293 | return false; |
275 | 294 | } |
276 | 295 | unsigned long long jump = (R[0] - 1) * sizeof(T); //number of bytes to skip between samples | ... | ... |
stim/envi/bip.h
... | ... | @@ -143,6 +143,11 @@ public: |
143 | 143 | bool spectrum(T * p, unsigned long long x, unsigned long long y, bool PROGRESS = false){ |
144 | 144 | return read_line_0(p, x, y, PROGRESS); //read a line in the binary YZ plane (dimension order for BIP is ZXY) |
145 | 145 | } |
146 | + bool spectrum(T* p, size_t n, bool PROGRESS = false){ | |
147 | + size_t y = n / X(); | |
148 | + size_t x = n - y * X(); | |
149 | + return read_line_0(p, x, y, PROGRESS); //read a line in the binary YZ plane (dimension order for BIP is ZXY) | |
150 | + } | |
146 | 151 | |
147 | 152 | /// Retrieves a band of x values from a given xz plane. |
148 | 153 | ... | ... |
stim/envi/bsq.h
... | ... | @@ -146,9 +146,13 @@ public: |
146 | 146 | /// @param p is a pointer to pre-allocated memory at least B * sizeof(T) in size. |
147 | 147 | /// @param x is the x-coordinate (dimension 1) of the spectrum. |
148 | 148 | /// @param y is the y-coordinate (dimension 2) of the spectrum. |
149 | - bool spectrum(T * p, unsigned long long x, unsigned long long y, bool PROGRESS = false){ | |
150 | - return read_line_2(p, x, y, PROGRESS); | |
149 | + void spectrum(T* p, size_t n, bool PROGRESS){ | |
150 | + read_line_2(p, n, PROGRESS); | |
151 | 151 | } |
152 | + void spectrum(T * p, unsigned long long x, unsigned long long y, bool PROGRESS = false){ | |
153 | + read_line_2(p, x, y, PROGRESS); | |
154 | + } | |
155 | + | |
152 | 156 | |
153 | 157 | /// Retrieve a single pixel and stores it in pre-allocated memory. |
154 | 158 | ... | ... |
stim/envi/envi.h
... | ... | @@ -21,10 +21,56 @@ class envi{ |
21 | 21 | void* file; //void pointer to the relevant file reader (bip, bsq, or bil - with appropriate data type) |
22 | 22 | std::string fname; //file name used for repeated opening and closing |
23 | 23 | |
24 | + //allocate sufficient space for a spectrum based on the data type and number of bands | |
25 | + void* alloc_array(size_t len){ | |
26 | + switch(header.data_type){ | |
27 | + case envi_header::int8: | |
28 | + return malloc(len); | |
29 | + case envi_header::int16: | |
30 | + case envi_header::uint16: | |
31 | + return malloc(2 * len); | |
32 | + case envi_header::int32: | |
33 | + case envi_header::uint32: | |
34 | + case envi_header::float32: | |
35 | + return malloc(4 * len); | |
36 | + case envi_header::int64: | |
37 | + case envi_header::uint64: | |
38 | + case envi_header::float64: | |
39 | + case envi_header::complex32: | |
40 | + return malloc(8 * len); | |
41 | + case envi_header::complex64: | |
42 | + return malloc(16 * len); | |
43 | + default: | |
44 | + std::cout<<"ERROR stim::envi data type not recognized for spectral allocation"<<std::endl; | |
45 | + exit(1); | |
46 | + } | |
47 | + } | |
48 | + | |
49 | + //cast a value to DEST type from SRC type | |
50 | + template<typename DST, typename SRC> | |
51 | + inline void cast(DST* dst, SRC* src){ | |
52 | + (*dst) = (DST)(*src); | |
53 | + } | |
54 | + | |
55 | + //cast an array from type SRC to type DEST | |
56 | + template<typename DST, typename SRC> | |
57 | + inline void cast(DST* dst, SRC* src, size_t len){ | |
58 | + for(size_t i = 0; i < len; i++) | |
59 | + cast(&dst[i], &src[i]); | |
60 | + } | |
61 | + | |
24 | 62 | public: |
25 | 63 | |
26 | 64 | envi_header header; |
27 | 65 | |
66 | + void* malloc_spectrum(){ | |
67 | + return alloc_array(header.bands); | |
68 | + } | |
69 | + | |
70 | + void* malloc_band(){ | |
71 | + return alloc_array(header.samples * header.lines); | |
72 | + } | |
73 | + | |
28 | 74 | /// Returns the size of the data type in bytes |
29 | 75 | unsigned int type_size(){ |
30 | 76 | if(header.data_type == envi_header::float32) return 4; |
... | ... | @@ -1060,7 +1106,7 @@ public: |
1060 | 1106 | /// @param ptr is a pointer to pre-allocated memory of size B*sizeof(T) |
1061 | 1107 | /// @param x is the x-coordinate of the spectrum |
1062 | 1108 | /// @param y is the y-coordinate of the spectrum |
1063 | - bool spectrum(void* ptr, unsigned long long x, unsigned long long y, bool PROGRESS = false){ | |
1109 | + /*bool spectrum(void* ptr, unsigned long long x, unsigned long long y, bool PROGRESS = false){ | |
1064 | 1110 | |
1065 | 1111 | if(header.interleave == envi_header::BSQ){ //if the infile is bsq file |
1066 | 1112 | if(header.data_type ==envi_header::float32) |
... | ... | @@ -1093,6 +1139,114 @@ public: |
1093 | 1139 | } |
1094 | 1140 | } |
1095 | 1141 | return false; |
1142 | + }*/ | |
1143 | + | |
1144 | + // Retrieve a spectrum at the specified 1D location | |
1145 | + | |
1146 | + /// @param ptr is a pointer to pre-allocated memory of size B*sizeof(T) | |
1147 | + /// @param x is the 1D coordinate of the spectrum | |
1148 | + template<typename T> | |
1149 | + void spectrum(T* ptr, size_t n, bool PROGRESS = false){ | |
1150 | + | |
1151 | + void* temp = alloc_array(header.bands); //allocate space for the output array | |
1152 | + | |
1153 | + if(header.interleave == envi_header::BSQ){ //if the infile is bsq file | |
1154 | + if(header.data_type ==envi_header::float32){ | |
1155 | + ((bsq<float>*)file)->spectrum((float*)temp, n, PROGRESS); | |
1156 | + cast<T, float>(ptr, (float*)temp, header.bands); | |
1157 | + } | |
1158 | + else if (header.data_type == envi_header::float64){ | |
1159 | + ((bsq<double>*)file)->spectrum((double*)temp, n, PROGRESS); | |
1160 | + cast<T, double>(ptr, (double*)temp, header.bands); | |
1161 | + } | |
1162 | + else{ | |
1163 | + std::cout << "ERROR: unidentified data type" << std::endl; | |
1164 | + exit(1); | |
1165 | + } | |
1166 | + } | |
1167 | + else if (header.interleave == envi_header::BIL){ | |
1168 | + if (header.data_type == envi_header::float32){ | |
1169 | + ((bil<float>*)file)->spectrum((float*)temp, n, PROGRESS); | |
1170 | + cast<T, float>(ptr, (float*)temp, header.bands); | |
1171 | + } | |
1172 | + else if (header.data_type == envi_header::float64){ | |
1173 | + ((bil<double>*)file)->spectrum((double*)temp, n, PROGRESS); | |
1174 | + cast<T, double>(ptr, (double*)temp, header.bands); | |
1175 | + } | |
1176 | + else{ | |
1177 | + std::cout << "ERROR: unidentified data type" << std::endl; | |
1178 | + exit(1); | |
1179 | + } | |
1180 | + } | |
1181 | + else if (header.interleave == envi_header::BIP){ | |
1182 | + if (header.data_type == envi_header::float32){ | |
1183 | + ((bip<float>*)file)->spectrum((float*)temp, n, PROGRESS); | |
1184 | + cast<T, float>(ptr, (float*)temp, header.bands); | |
1185 | + } | |
1186 | + else if (header.data_type == envi_header::float64){ | |
1187 | + ((bip<double>*)file)->spectrum((double*)temp, n, PROGRESS); | |
1188 | + cast<T, double>(ptr, (double*)temp, header.bands); | |
1189 | + } | |
1190 | + else{ | |
1191 | + std::cout << "ERROR: unidentified data type" << std::endl; | |
1192 | + exit(1); | |
1193 | + } | |
1194 | + } | |
1195 | + } | |
1196 | + | |
1197 | + /// Retrieve a spectrum from the specified (x, y) location | |
1198 | + | |
1199 | + /// @param ptr is a pointer to pre-allocated memory of size B*sizeof(T) | |
1200 | + /// @param x is the x-coordinate of the spectrum | |
1201 | + /// @param y is the y-coordinate of the spectrum | |
1202 | + template<typename T> | |
1203 | + void spectrum(T* ptr, unsigned long long x, unsigned long long y, bool PROGRESS = false){ | |
1204 | + | |
1205 | + spectrum<T>(ptr, y * header.samples + x, PROGRESS = false); | |
1206 | + /*void* temp = alloc_array<T>(header.bands); //allocate space for the output array | |
1207 | + | |
1208 | + if(header.interleave == envi_header::BSQ){ //if the infile is bsq file | |
1209 | + if(header.data_type ==envi_header::float32){ | |
1210 | + ((bsq<float>*)file)->spectrum((float*)temp, x, y, PROGRESS); | |
1211 | + cast<T, float>(ptr, temp, header.bands); | |
1212 | + } | |
1213 | + else if (header.data_type == envi_header::float64){ | |
1214 | + ((bsq<double>*)file)->spectrum((double*)temp, x, y, PROGRESS); | |
1215 | + cast<T, double>(ptr, temp, header.bands); | |
1216 | + } | |
1217 | + else{ | |
1218 | + std::cout << "ERROR: unidentified data type" << std::endl; | |
1219 | + exit(1); | |
1220 | + } | |
1221 | + } | |
1222 | + else if (header.interleave == envi_header::BIL){ | |
1223 | + if (header.data_type == envi_header::float32){ | |
1224 | + ((bil<float>*)file)->spectrum((float*)temp, x, y, PROGRESS); | |
1225 | + cast<T, float>(ptr, temp, header.bands); | |
1226 | + } | |
1227 | + else if (header.data_type == envi_header::float64){ | |
1228 | + ((bil<double>*)file)->spectrum((double*)temp, x, y, PROGRESS); | |
1229 | + cast<T, double>(ptr, temp, header.bands); | |
1230 | + } | |
1231 | + else{ | |
1232 | + std::cout << "ERROR: unidentified data type" << std::endl; | |
1233 | + exit(1); | |
1234 | + } | |
1235 | + } | |
1236 | + else if (header.interleave == envi_header::BIP){ | |
1237 | + if (header.data_type == envi_header::float32){ | |
1238 | + ((bip<float>*)file)->spectrum((float*)temp, x, y, PROGRESS); | |
1239 | + cast<T, float>(ptr, temp, header.bands); | |
1240 | + } | |
1241 | + else if (header.data_type == envi_header::float64){ | |
1242 | + ((bip<double>*)file)->spectrum((double*)temp, x, y, PROGRESS); | |
1243 | + cast<T, double>(ptr, temp, header.bands); | |
1244 | + } | |
1245 | + else{ | |
1246 | + std::cout << "ERROR: unidentified data type" << std::endl; | |
1247 | + exit(1); | |
1248 | + } | |
1249 | + }*/ | |
1096 | 1250 | } |
1097 | 1251 | |
1098 | 1252 | /// Retrieve a single band (based on index) and stores it in pre-allocated memory. | ... | ... |
stim/image/image.h
... | ... | @@ -33,8 +33,7 @@ class image{ |
33 | 33 | |
34 | 34 | void unalloc(){ //frees any resources associated with the image |
35 | 35 | if(img) free(img); //if memory has been allocated, free it |
36 | - img=NULL; | |
37 | - | |
36 | + img=NULL; | |
38 | 37 | } |
39 | 38 | |
40 | 39 | |
... | ... | @@ -92,7 +91,9 @@ class image{ |
92 | 91 | public: |
93 | 92 | |
94 | 93 | /// Default constructor - creates an empty image object |
95 | - image(){ init(); } //initialize all variables to zero, don't allocate any memory | |
94 | + image(){ | |
95 | + init(); //initialize all variables to zero, don't allocate any memory | |
96 | + } | |
96 | 97 | |
97 | 98 | /// Constructor with a filename - loads the specified file |
98 | 99 | image(std::string filename){ //constructor initialize the image with an image file |
... | ... | @@ -114,7 +115,7 @@ public: |
114 | 115 | } |
115 | 116 | |
116 | 117 | /// Copy constructor - duplicates an image object |
117 | - image(const stim::image<T>& I){ | |
118 | + image(const stim::image<T> &I){ | |
118 | 119 | init(); |
119 | 120 | allocate(I.X(), I.Y(), I.C()); |
120 | 121 | memcpy(img, I.img, bytes()); |
... | ... | @@ -125,7 +126,7 @@ public: |
125 | 126 | free(img); |
126 | 127 | } |
127 | 128 | |
128 | - stim::image<T> operator=(const stim::image<T>& I){ | |
129 | + stim::image<T>& operator=(const stim::image<T>& I){ | |
129 | 130 | if(&I == this) //handle self-assignment |
130 | 131 | return *this; |
131 | 132 | allocate(I.X(), I.Y(), I.C()); |
... | ... | @@ -138,7 +139,7 @@ public: |
138 | 139 | |
139 | 140 | cv::Mat cvImage = cv::imread(filename, CV_LOAD_IMAGE_UNCHANGED); //use OpenCV to open the image file |
140 | 141 | if(!cvImage.data){ |
141 | - std::cout<<"ERROR stim::image::load() - unable to find image "<<filename<<std::endl; | |
142 | + std::cout<<"ERROR stim::image::load() - unable to find image "<<filename<<" ["<<__FILE__<<" (line "<<__LINE__<<")]"<<std::endl; | |
142 | 143 | exit(1); |
143 | 144 | } |
144 | 145 | allocate(cvImage.cols, cvImage.rows, cvImage.channels()); //allocate space for the image | ... | ... |
1 | +#ifndef STIM_CSV_H | |
2 | +#define STIM_CSV_H | |
3 | + | |
4 | +#include <vector> | |
5 | +#include <sstream> | |
6 | +#include <fstream> | |
7 | + | |
8 | +namespace stim{ | |
9 | + | |
10 | + class table{ | |
11 | + | |
12 | + std::vector< std::vector< std::string > > TABLE; | |
13 | + | |
14 | + size_t x; //current x and y positions for adding elements to the table | |
15 | + size_t y; | |
16 | + | |
17 | + void init(){ | |
18 | + x = y = 0; | |
19 | + TABLE.resize(1); //create a single row | |
20 | + TABLE[0].clear(); //make sure that the row is empty | |
21 | + } | |
22 | + public: | |
23 | + | |
24 | + table(){ | |
25 | + init(); | |
26 | + } | |
27 | + | |
28 | + void new_column(){ | |
29 | + x = 0; //reset to the first position of the column | |
30 | + y++; //increment the current row position | |
31 | + TABLE.push_back( std::vector<std::string>() ); //push an empty row | |
32 | + } | |
33 | + | |
34 | + template<typename T> | |
35 | + T operator<<(T i){ | |
36 | + std::stringstream ss; | |
37 | + ss<<i; | |
38 | + TABLE[y].push_back(ss.str()); | |
39 | + x++; | |
40 | + return i; | |
41 | + } | |
42 | + | |
43 | + std::string str(){ | |
44 | + std::stringstream ss; | |
45 | + for(size_t yi = 0; yi < TABLE.size(); yi++){ | |
46 | + for(size_t xi = 0; xi < TABLE[yi].size(); xi++){ | |
47 | + if(xi != 0) ss<<", "; | |
48 | + ss<<TABLE[yi][xi]; | |
49 | + } | |
50 | + ss<<std::endl; | |
51 | + } | |
52 | + return ss.str(); | |
53 | + } | |
54 | + | |
55 | + void save_ascii(std::string filename, char col_delim = ',', char row_delim = '\n'){ | |
56 | + ofstream outfile(filename); | |
57 | + for(size_t yi = 0; yi < TABLE.size(); yi++){ | |
58 | + if(yi != 0 && TABLE[yi].size() > 0) outfile<<row_delim; | |
59 | + for(size_t xi = 0; xi < TABLE[yi].size(); xi++){ | |
60 | + if(xi != 0) outfile<<col_delim; | |
61 | + outfile<<TABLE[yi][xi]; | |
62 | + } | |
63 | + } | |
64 | + } | |
65 | + | |
66 | + void read_ascii(std::string filename, char col_delim = ',', char row_delim = '\n'){ | |
67 | + ifstream infile(filename); //open an ascii file for reading | |
68 | + TABLE.clear(); //empty out the table | |
69 | + | |
70 | + std::string line; | |
71 | + while(!infile.eof()){ | |
72 | + std::getline(infile, line, row_delim); //read a line from the file using the row delimiter | |
73 | + size_t pos = 0; | |
74 | + std::string token; | |
75 | + std::vector< std::string > row; | |
76 | + while ((pos = line.find(col_delim)) != std::string::npos) { | |
77 | + token = line.substr(0, pos); | |
78 | + row.push_back(token); | |
79 | + line.erase(0, pos + 1); | |
80 | + } | |
81 | + token = line.substr(0, std::string::npos); //read the last column | |
82 | + row.push_back(token); //push it into the table | |
83 | + TABLE.push_back(row); //add an empty vector to the table | |
84 | + } | |
85 | + } | |
86 | + | |
87 | + /// Returns a vector representation of the table by casting to the specified template | |
88 | + template<typename T> | |
89 | + std::vector< std::vector<T> > get_vector(){ | |
90 | + std::vector< std::vector<T> > result; | |
91 | + result.resize(TABLE.size()); //initialize the first dimension of the returned table | |
92 | + for(size_t i = 0; i < TABLE.size(); i++){ //for each row | |
93 | + result[i].resize(TABLE[i].size()); //initialize the number of columns in this row | |
94 | + for(size_t j = 0; j < TABLE[i].size(); j++){ //for each column | |
95 | + std::stringstream ss(TABLE[i][j]); | |
96 | + ss >> result[i][j]; | |
97 | + } | |
98 | + } | |
99 | + return result; //return the casted table | |
100 | + } | |
101 | + | |
102 | + }; | |
103 | +}; | |
104 | + | |
105 | + | |
106 | +#endif | |
0 | 107 | \ No newline at end of file | ... | ... |