Commit 8b7be6708fa4da77ce9ea10b31a75c39c84ba466

Authored by David Mayerich
1 parent 8157c392

implemented saving and loading of image stacks

@@ -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
@@ -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
@@ -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