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 | 4 | #include <vector> |
5 | 5 | #include <string> |
6 | 6 | #include <sstream> |
7 | +#include <fstream> | |
7 | 8 | |
8 | 9 | #include "../cuda/threads.h" |
9 | 10 | #include "../cuda/error.h" |
... | ... | @@ -14,7 +15,6 @@ |
14 | 15 | namespace stim{ |
15 | 16 | |
16 | 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 | 18 | // data can be loaded in the form of images |
19 | 19 | // data can be saved in the form of binary files |
20 | 20 | template<typename T, unsigned int D = 1> |
... | ... | @@ -22,9 +22,8 @@ class grid_data{ |
22 | 22 | |
23 | 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 | 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 | 28 | //return the total number of values in the binary file |
30 | 29 | unsigned long samples(){ |
... | ... | @@ -42,19 +41,23 @@ public: |
42 | 41 | //write data to disk |
43 | 42 | void write(std::string filename){ |
44 | 43 | |
44 | + std::fstream file; | |
45 | + | |
45 | 46 | //open the file as binary for reading |
46 | 47 | file.open(filename.c_str(), std::ios::out | std::ios::binary); |
47 | 48 | |
48 | 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 | 53 | //load a binary file from disk |
53 | 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 | 57 | R = S; //set the sample resolution |
57 | 58 | |
59 | + std::fstream file; | |
60 | + | |
58 | 61 | //open the file as binary for writing |
59 | 62 | file.open(filename.c_str(), std::ios::in | std::ios::binary); |
60 | 63 | |
... | ... | @@ -62,7 +65,7 @@ public: |
62 | 65 | file.seekg(header, std::ios::beg); |
63 | 66 | |
64 | 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 | 75 | } |
73 | 76 | |
74 | 77 | |
75 | -#endif | |
76 | 78 | \ No newline at end of file |
79 | +#endif | ... | ... |
grids/image_stack.h
1 | 1 | #ifndef STIM_IMAGE_STACK_H |
2 | 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 | 9 | namespace stim{ |
6 | 10 | |
7 | 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 | 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 | 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 | 95 | |
22 | 96 | } |
23 | 97 | |
24 | -#endif | |
25 | 98 | \ No newline at end of file |
99 | +#endif | ... | ... |
image/image.h
... | ... | @@ -37,7 +37,7 @@ public: |
37 | 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 | 41 | void set_interleaved(T* buffer, unsigned int width, unsigned int height, unsigned int channels = 1){ |
42 | 42 | |
43 | 43 | unsigned char* non_interleaved = (unsigned char*)malloc(width * height * 3); |
... | ... | @@ -53,8 +53,34 @@ public: |
53 | 53 | } |
54 | 54 | |
55 | 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 | 86 | //returns the size (number of values) of the image | ... | ... |
parser/filename.h
... | ... | @@ -31,6 +31,7 @@ class filename{ |
31 | 31 | private: |
32 | 32 | void init(){ |
33 | 33 | |
34 | + absolute = false; | |
34 | 35 | |
35 | 36 | } |
36 | 37 | |
... | ... | @@ -41,6 +42,8 @@ protected: |
41 | 42 | std::string prefix; //file prefix (without extension) |
42 | 43 | std::string ext; //file extension |
43 | 44 | |
45 | + bool absolute; //filename is an absolute path | |
46 | + | |
44 | 47 | //replace any incorrect dividers with the appropriate version for the OS |
45 | 48 | std::string parse_div(std::string s) { |
46 | 49 | #ifdef _WIN32 |
... | ... | @@ -73,15 +76,17 @@ protected: |
73 | 76 | #ifdef _WIN32 |
74 | 77 | //if the second character is a colon, the character right before it is the drive |
75 | 78 | if(loc[1] == ':'){ |
79 | + absolute = true; //this is an absolute path | |
76 | 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 | 88 | #endif |
80 | 89 | |
81 | - //remove the initial divider | |
82 | - if(loc[0] == STIM_FILENAME_DIV) | |
83 | - loc = loc.substr(1); | |
84 | - | |
85 | 90 | //determine the file name |
86 | 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 | 129 | std::string dir(){ |
125 | 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 | 141 | //output the directory |
134 | 142 | for(unsigned int d = 0; d < path.size(); d++) |
... | ... | @@ -197,6 +205,7 @@ public: |
197 | 205 | exit(1); |
198 | 206 | } |
199 | 207 | |
208 | + std::cout<<cCurrentPath<<std::endl; | |
200 | 209 | return stim::filename(std::string(cCurrentPath) + STIM_FILENAME_DIV); |
201 | 210 | } |
202 | 211 | |
... | ... | @@ -231,13 +240,22 @@ public: |
231 | 240 | std::vector<std::string> result_path(begin, end); |
232 | 241 | |
233 | 242 | //create a new path to be returned |
234 | - stim::filename result; | |
243 | + stim::filename result = *this; | |
235 | 244 | result.path = result_path; |
236 | 245 | result.set_name(rel_path.back()); |
237 | 246 | |
238 | 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 | ... | ... |