Commit 8b7be6708fa4da77ce9ea10b31a75c39c84ba466
1 parent
8157c392
implemented saving and loading of image stacks
Showing
4 changed files
with
145 additions
and
24 deletions
Show diff stats
grids/grid_data.h
@@ -4,6 +4,7 @@ | @@ -4,6 +4,7 @@ | ||
4 | #include <vector> | 4 | #include <vector> |
5 | #include <string> | 5 | #include <string> |
6 | #include <sstream> | 6 | #include <sstream> |
7 | +#include <fstream> | ||
7 | 8 | ||
8 | #include "../cuda/threads.h" | 9 | #include "../cuda/threads.h" |
9 | #include "../cuda/error.h" | 10 | #include "../cuda/error.h" |
@@ -14,7 +15,6 @@ | @@ -14,7 +15,6 @@ | ||
14 | namespace stim{ | 15 | namespace stim{ |
15 | 16 | ||
16 | //This object describes a generic D-dimensional grid containing data of type T | 17 | //This object describes a generic D-dimensional grid containing data of type T |
17 | - // data can be stored on the GPU or CPU (and transferred between the two) | ||
18 | // data can be loaded in the form of images | 18 | // data can be loaded in the form of images |
19 | // data can be saved in the form of binary files | 19 | // data can be saved in the form of binary files |
20 | template<typename T, unsigned int D = 1> | 20 | template<typename T, unsigned int D = 1> |
@@ -22,9 +22,8 @@ class grid_data{ | @@ -22,9 +22,8 @@ class grid_data{ | ||
22 | 22 | ||
23 | protected: | 23 | protected: |
24 | 24 | ||
25 | - stim::vector<unsigned long, D> R; //elements in each dimension | 25 | + stim::vec<unsigned long, D> R; //elements in each dimension |
26 | T* ptr; //pointer to the data (on the GPU or CPU) | 26 | T* ptr; //pointer to the data (on the GPU or CPU) |
27 | - bool gpu; //true if the data is on the GPU | ||
28 | 27 | ||
29 | //return the total number of values in the binary file | 28 | //return the total number of values in the binary file |
30 | unsigned long samples(){ | 29 | unsigned long samples(){ |
@@ -42,19 +41,23 @@ public: | @@ -42,19 +41,23 @@ public: | ||
42 | //write data to disk | 41 | //write data to disk |
43 | void write(std::string filename){ | 42 | void write(std::string filename){ |
44 | 43 | ||
44 | + std::fstream file; | ||
45 | + | ||
45 | //open the file as binary for reading | 46 | //open the file as binary for reading |
46 | file.open(filename.c_str(), std::ios::out | std::ios::binary); | 47 | file.open(filename.c_str(), std::ios::out | std::ios::binary); |
47 | 48 | ||
48 | //write file to disk | 49 | //write file to disk |
49 | - file.write((char *)p, samples() * sizeof(T)); | 50 | + file.write((char *)ptr, samples() * sizeof(T)); |
50 | } | 51 | } |
51 | 52 | ||
52 | //load a binary file from disk | 53 | //load a binary file from disk |
53 | // header size is in bytes | 54 | // header size is in bytes |
54 | - void read(std::string filename, stim::vector<unsigned long, D> S, unsigned long header = 0){ | 55 | + void read(std::string filename, stim::vec<unsigned long, D> S, unsigned long header = 0){ |
55 | 56 | ||
56 | R = S; //set the sample resolution | 57 | R = S; //set the sample resolution |
57 | 58 | ||
59 | + std::fstream file; | ||
60 | + | ||
58 | //open the file as binary for writing | 61 | //open the file as binary for writing |
59 | file.open(filename.c_str(), std::ios::in | std::ios::binary); | 62 | file.open(filename.c_str(), std::ios::in | std::ios::binary); |
60 | 63 | ||
@@ -62,7 +65,7 @@ public: | @@ -62,7 +65,7 @@ public: | ||
62 | file.seekg(header, std::ios::beg); | 65 | file.seekg(header, std::ios::beg); |
63 | 66 | ||
64 | //read the data | 67 | //read the data |
65 | - file.read((char *)p, samples() * sizeof(T)); | 68 | + file.read((char *)ptr, samples() * sizeof(T)); |
66 | } | 69 | } |
67 | 70 | ||
68 | 71 | ||
@@ -72,4 +75,4 @@ public: | @@ -72,4 +75,4 @@ public: | ||
72 | } | 75 | } |
73 | 76 | ||
74 | 77 | ||
75 | -#endif | ||
76 | \ No newline at end of file | 78 | \ No newline at end of file |
79 | +#endif |
grids/image_stack.h
1 | #ifndef STIM_IMAGE_STACK_H | 1 | #ifndef STIM_IMAGE_STACK_H |
2 | #define STIM_IMAGE_STACK_H | 2 | #define STIM_IMAGE_STACK_H |
3 | 3 | ||
4 | +#include "../parser/wildcards.h" | ||
5 | +#include "../parser/filename.h" | ||
6 | +#include "../grids/grid_data.h" | ||
7 | +#include "../image/image.h" | ||
4 | 8 | ||
5 | namespace stim{ | 9 | namespace stim{ |
6 | 10 | ||
7 | //this creates a class that can be used to load 3D grid data from stacks of images | 11 | //this creates a class that can be used to load 3D grid data from stacks of images |
12 | +// The class uses a 4D grid_data object, where the first dimension is color | ||
8 | template<typename T> | 13 | template<typename T> |
9 | -class image_stack : public virtual grid_data<T, 3>{ | 14 | +class image_stack : public virtual grid_data<T, 4>{ |
15 | + | ||
16 | + enum image_type {stimAuto, stimMono, stimRGB, stimRGBA}; | ||
17 | + | ||
18 | +protected: | ||
19 | + using grid_data<T, 4>::R; | ||
20 | + using grid_data<T, 4>::ptr; | ||
21 | + using grid_data<T, 4>::samples; | ||
10 | 22 | ||
11 | public: | 23 | public: |
12 | 24 | ||
13 | - void load(std::string wild_name){ | 25 | + void load_images(std::string file_mask){ |
26 | + | ||
27 | + stim::filename file_path(file_mask); | ||
28 | + | ||
29 | + //if the file path is relative, update it with the current working directory | ||
30 | + if(file_path.is_relative()){ | ||
31 | + stim::filename wd = stim::filename::cwd(); | ||
32 | + file_path = wd.get_relative(file_mask); | ||
33 | + } | ||
34 | + | ||
35 | + //get the list of files | ||
36 | + std::vector<stim::filename> file_list = file_path.get_list(); | ||
37 | + | ||
38 | + //load the first image and set all of the image_stack properties | ||
39 | + stim::image<T> I(file_list[0].str()); | ||
40 | + | ||
41 | + //set the image resolution and number of channels | ||
42 | + R[0] = I.channels(); | ||
43 | + R[1] = I.width(); | ||
44 | + R[2] = I.height(); | ||
45 | + R[3] = file_list.size(); | ||
46 | + | ||
47 | + //allocate storage space | ||
48 | + ptr = (T*)malloc(sizeof(T) * samples()); | ||
49 | + | ||
50 | + //load and copy each image into the grid | ||
51 | + for(unsigned int i = 0; i<R[3]; i++){ | ||
52 | + | ||
53 | + //load the image | ||
54 | + stim::image<T> I(file_list[i].str()); | ||
55 | + | ||
56 | + //retrieve the interlaced data from the image - store it in the grid | ||
57 | + I.data_interleaved(&ptr[ i * R[0] * R[1] * R[2] ]); | ||
58 | + } | ||
59 | + } | ||
60 | + | ||
61 | + void save_images(std::string file_mask){ | ||
62 | + | ||
63 | + stim::filename file_path(file_mask); | ||
64 | + | ||
65 | + //if the file path is relative, update it with the current working directory | ||
66 | + if(file_path.is_relative()){ | ||
67 | + stim::filename wd = stim::filename::cwd(); | ||
68 | + file_path = wd.get_relative(file_mask); | ||
69 | + } | ||
70 | + | ||
71 | + //create a list of file names | ||
72 | + std::vector<std::string> file_list = stim::wildcards::increment(file_path.str(), 0, R[3]-1, 1); | ||
73 | + | ||
74 | + for(int i=0; i<R[3]; i++){ | ||
75 | + | ||
76 | + //create an image | ||
77 | + stim::image<T> I; | ||
78 | + | ||
79 | + //retrieve the interlaced data from the image - store it in the grid | ||
80 | + I.set_interleaved(&ptr[ i * R[0] * R[1] * R[2] ], R[1], R[2], R[0]); | ||
81 | + | ||
82 | + I.save(file_list[i]); | ||
83 | + | ||
84 | + | ||
85 | + std::cout<<file_list[i]<<std::endl; | ||
86 | + } | ||
87 | + | ||
14 | 88 | ||
15 | } | 89 | } |
16 | 90 | ||
@@ -21,4 +95,4 @@ public: | @@ -21,4 +95,4 @@ public: | ||
21 | 95 | ||
22 | } | 96 | } |
23 | 97 | ||
24 | -#endif | ||
25 | \ No newline at end of file | 98 | \ No newline at end of file |
99 | +#endif |
image/image.h
@@ -37,7 +37,7 @@ public: | @@ -37,7 +37,7 @@ public: | ||
37 | img.save(filename.c_str()); | 37 | img.save(filename.c_str()); |
38 | } | 38 | } |
39 | 39 | ||
40 | - //create an image from an interlaced buffer | 40 | + //create an image from an interleaved buffer |
41 | void set_interleaved(T* buffer, unsigned int width, unsigned int height, unsigned int channels = 1){ | 41 | void set_interleaved(T* buffer, unsigned int width, unsigned int height, unsigned int channels = 1){ |
42 | 42 | ||
43 | unsigned char* non_interleaved = (unsigned char*)malloc(width * height * 3); | 43 | unsigned char* non_interleaved = (unsigned char*)malloc(width * height * 3); |
@@ -53,8 +53,34 @@ public: | @@ -53,8 +53,34 @@ public: | ||
53 | } | 53 | } |
54 | 54 | ||
55 | //returns a pointer to the first pixel of the image data | 55 | //returns a pointer to the first pixel of the image data |
56 | - T* data(){ | ||
57 | - return img.data(); | 56 | + void data_noninterleaved(T* data){ |
57 | + memcpy(data, img.data(), sizeof(T) * size()); | ||
58 | + } | ||
59 | + | ||
60 | + void data_interleaved(T* data){ | ||
61 | + | ||
62 | + unsigned int C = channels(); | ||
63 | + unsigned int X = size(); | ||
64 | + | ||
65 | + T* ptr = img.data(); | ||
66 | + | ||
67 | + //for each channel | ||
68 | + for(unsigned int c = 0; c < C; c++) | ||
69 | + //convert each pixel | ||
70 | + for(unsigned int x = 0; x < X; x++) | ||
71 | + data[x * C + c] = ptr[c * X + x]; | ||
72 | + } | ||
73 | + | ||
74 | + unsigned int channels(){ | ||
75 | + return (unsigned int)img.spectrum(); | ||
76 | + } | ||
77 | + | ||
78 | + unsigned int width(){ | ||
79 | + return img.width(); | ||
80 | + } | ||
81 | + | ||
82 | + unsigned int height(){ | ||
83 | + return img.height(); | ||
58 | } | 84 | } |
59 | 85 | ||
60 | //returns the size (number of values) of the image | 86 | //returns the size (number of values) of the image |
parser/filename.h
@@ -31,6 +31,7 @@ class filename{ | @@ -31,6 +31,7 @@ class filename{ | ||
31 | private: | 31 | private: |
32 | void init(){ | 32 | void init(){ |
33 | 33 | ||
34 | + absolute = false; | ||
34 | 35 | ||
35 | } | 36 | } |
36 | 37 | ||
@@ -41,6 +42,8 @@ protected: | @@ -41,6 +42,8 @@ protected: | ||
41 | std::string prefix; //file prefix (without extension) | 42 | std::string prefix; //file prefix (without extension) |
42 | std::string ext; //file extension | 43 | std::string ext; //file extension |
43 | 44 | ||
45 | + bool absolute; //filename is an absolute path | ||
46 | + | ||
44 | //replace any incorrect dividers with the appropriate version for the OS | 47 | //replace any incorrect dividers with the appropriate version for the OS |
45 | std::string parse_div(std::string s) { | 48 | std::string parse_div(std::string s) { |
46 | #ifdef _WIN32 | 49 | #ifdef _WIN32 |
@@ -73,15 +76,17 @@ protected: | @@ -73,15 +76,17 @@ protected: | ||
73 | #ifdef _WIN32 | 76 | #ifdef _WIN32 |
74 | //if the second character is a colon, the character right before it is the drive | 77 | //if the second character is a colon, the character right before it is the drive |
75 | if(loc[1] == ':'){ | 78 | if(loc[1] == ':'){ |
79 | + absolute = true; //this is an absolute path | ||
76 | drive = loc[0]; //copy the drive letter | 80 | drive = loc[0]; //copy the drive letter |
77 | - loc = loc.substr(2); //remove the drive information from the locator string | 81 | + loc = loc.substr(3); //remove the drive information from the locator string |
82 | + } | ||
83 | + #else | ||
84 | + if(loc[0] == STIM_FILENAME_DIV){ | ||
85 | + absolute = true; | ||
86 | + loc = loc.substr(1); | ||
78 | } | 87 | } |
79 | #endif | 88 | #endif |
80 | 89 | ||
81 | - //remove the initial divider | ||
82 | - if(loc[0] == STIM_FILENAME_DIV) | ||
83 | - loc = loc.substr(1); | ||
84 | - | ||
85 | //determine the file name | 90 | //determine the file name |
86 | std::string fname = loc.substr( loc.find_last_of(STIM_FILENAME_DIV) + 1 ); //find the file name (including extension) | 91 | std::string fname = loc.substr( loc.find_last_of(STIM_FILENAME_DIV) + 1 ); //find the file name (including extension) |
87 | 92 | ||
@@ -124,11 +129,14 @@ public: | @@ -124,11 +129,14 @@ public: | ||
124 | std::string dir(){ | 129 | std::string dir(){ |
125 | std::stringstream ss; | 130 | std::stringstream ss; |
126 | 131 | ||
127 | - //output the drive letter if in Windows | ||
128 | - #ifdef _WIN32 | ||
129 | - ss<<drive<<":"; | ||
130 | - #endif | ||
131 | - ss<<STIM_FILENAME_DIV; | 132 | + //if the path is absolute |
133 | + if(absolute){ | ||
134 | + //output the drive letter if in Windows | ||
135 | + #ifdef _WIN32 | ||
136 | + ss<<drive<<":"; | ||
137 | + #endif | ||
138 | + ss<<STIM_FILENAME_DIV; | ||
139 | + } | ||
132 | 140 | ||
133 | //output the directory | 141 | //output the directory |
134 | for(unsigned int d = 0; d < path.size(); d++) | 142 | for(unsigned int d = 0; d < path.size(); d++) |
@@ -197,6 +205,7 @@ public: | @@ -197,6 +205,7 @@ public: | ||
197 | exit(1); | 205 | exit(1); |
198 | } | 206 | } |
199 | 207 | ||
208 | + std::cout<<cCurrentPath<<std::endl; | ||
200 | return stim::filename(std::string(cCurrentPath) + STIM_FILENAME_DIV); | 209 | return stim::filename(std::string(cCurrentPath) + STIM_FILENAME_DIV); |
201 | } | 210 | } |
202 | 211 | ||
@@ -231,13 +240,22 @@ public: | @@ -231,13 +240,22 @@ public: | ||
231 | std::vector<std::string> result_path(begin, end); | 240 | std::vector<std::string> result_path(begin, end); |
232 | 241 | ||
233 | //create a new path to be returned | 242 | //create a new path to be returned |
234 | - stim::filename result; | 243 | + stim::filename result = *this; |
235 | result.path = result_path; | 244 | result.path = result_path; |
236 | result.set_name(rel_path.back()); | 245 | result.set_name(rel_path.back()); |
237 | 246 | ||
238 | return result; | 247 | return result; |
239 | } | 248 | } |
240 | 249 | ||
250 | + bool is_relative(){ | ||
251 | + return !absolute; | ||
252 | + } | ||
253 | + | ||
254 | + bool is_absolute(){ | ||
255 | + return absolute; | ||
256 | + } | ||
257 | + | ||
258 | + | ||
241 | 259 | ||
242 | 260 | ||
243 | 261 |