Commit 8b7be6708fa4da77ce9ea10b31a75c39c84ba466

Authored by David Mayerich
1 parent 8157c392

implemented saving and loading of image stacks

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