Blame view

tira/grids/image_stack.h 6.83 KB
ce6381d7   David Mayerich   updating to TIRA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
  #ifndef STIM_IMAGE_STACK_H
  #define STIM_IMAGE_STACK_H
  
  #include <stim/parser/wildcards.h>
  #include <stim/parser/filename.h>
  #include <stim/grids/grid.h>
  #include <stim/image/image.h>
  #include <stim/math/vec3.h>
  
  namespace stim{
  
  ///This class is used to load 3D grid data from stacks of images
  //	The class uses a 4D grid object, where the first dimension is a color value.
  template<typename T, typename F = float>
  class image_stack : public virtual stim::grid<T, 4, F>{
  
  	enum image_type {stimAuto, stimMono, stimRGB, stimRGBA};
  
  protected:
  	//using stim::grid<T, 4>::S;
  	using stim::grid<T, 4, F>::R;
  	using stim::grid<T, 4, F>::ptr;
  	using stim::grid<T, 4, F>::S;
  
  public:
  	//default constructor
  	image_stack() : grid<T, 4, F>() {
  
  	}
  
  	/// Overloads grid::samples() to return the number of samples associated with a given spatial dimension
  	///		this is necessary because R[0] stores the color
  	size_t samples(size_t d){
  		return grid<T, 4, F>::samples(d + 1);
  	}
  
  	size_t samples(){
  		return R[1] * R[2] * R[3];						//return the number of spatial samples
  	}
  
  	// get the number of pixels in each dimension
  	size_t nc() {
  		return R[0];
  	}
  	size_t nx() {
  		return R[1];
  	}
  	size_t ny() {
  		return R[2];
  	}
  	size_t nz() {
  		return R[3];
  	}
  
  	/// Returns the number of color channels
  	size_t channels(){
  		return R[0];
  	}
  
  	/// Overloads grid::size() to return the size of the grid associated with a given spatial dimension
  	F size(size_t d){
  		return grid<T, 4, F>::size(d + 1);
  	}
  
  	/// Sets the spacing between samples in the image stack
  	void spacing(F sx, F sy, F sz){
  		grid<T, 4, F>::S[1] = sx;			//set the sample spacing for the appropriate spatial dimension
  		grid<T, 4, F>::S[2] = sy;
  		grid<T, 4, F>::S[3] = sz;
  	}
  
  	F spacing(size_t d){
  		return grid<T, 4, F>::spacing(d + 1);
  	}
  
  	/// Overloads the spacing parameter to set the size of the grid associated with a given spatial dimension
  	//void spacing(F sx, F sy = 1.0f, F sz = 1.0f){
  	//	grid<T, 4, F>::spacing((F)1.0, sx, sy, sz);
  	//}
  
  	/// Load all of the images specified by a list of strings
  	/// @param string_list is a list of file names specifying images
  	void load_images(std::vector<std::string> string_list){
  
  		//if there are no matching files, exit
  		if(string_list.size() == 0){
  			std::cout<<"STIM ERROR (image_stack): No matching files for loading a stack."<<std::endl;
  			exit(1);
  		}
  
  		stim::image<T> I(string_list[0]);		//load the first image and set all of the image_stack proparties
  
  		R[0] = I.channels();				//set the number of color channels
  		R[1] = I.width();				//set the stack height and width based on the image size
  		R[2] = I.height();
  		R[3] = string_list.size();			//set the stack z-resolution based on the number of images
  
  		ptr = (T*)malloc(grid<T, 4, F>::bytes());	//allocate storage space
  
  		//load and copy each image into the grid
  		for(unsigned int i = 0; i<R[3]; i++){				//for each image in the list			
  			stim::image<T> I(string_list[i]);			//load the image			
  			I.get_interleaved_rgb(&ptr[ i * R[0] * R[1] * R[2] ]);	//retrieve the interlaced data from the image - store it in the grid			
  		}
  	}
  
  	/// Load a stack of images based on a file mask. Images are loaded in alphanumeric order
  	/// @param file_mask is the mask describing the images to be loaded
  	void load_images(std::string file_mask){
  		stim::filename file_path(file_mask);				//get the path for the images
  		std::vector<stim::filename> file_list = file_path.get_list();	//get the list of files
  		std::vector<std::string> string_list(file_list.size());		//allocate space for an array of strings
  		for(size_t f = 0; f < file_list.size(); f++){			//for each file name in the list
  			string_list[f] = file_list[f].str();			//convert the file name to a string
  		}
  		load_images(string_list);					//load all of the images in the list
  	}
  
  	///Inserts image I into slot i.
  	/// @param stim::image<T> I; image to insert.
  	/// @int I, where to place the image.
  	void insert_image(stim::image<T> I, int i){
  		I.get_interleaved_rgb(&ptr[i *R[0] *R[1] *R[2] ]);
  	}
  
  	///Saves a single page to an image file
  	/// @param file_name is the name of the image file to be created
  	/// @param i is the page to be saved
  	void save_image(std::string file_name, unsigned int i){		
  		stim::image<T> I;											//create an image		
  		I.set_interleaved(&ptr[ i * R[0] * R[1] * R[2] ], R[1], R[2], R[0]);	//retrieve the interlaced data from the image - store it in the grid
  //		I.set_interleaved_rgb(&ptr[ i * R[0] * R[1] * R[2] ], R[1], R[2], R[0]);	//retrieve the interlaced data from the image - store it in the grid
  		I.save(file_name);
  	}
  
  	///Sets the dimensions of the image in each direction
  	///Voxel-size.
  	/// @param x size in the x direction
  	/// @param y size in the y direction
  	/// @param z size in the z direction
  	void
  	set_dim(float x, float y, float z)
  	{
  		grid<T, 4, F>::S[0] = 1;
  		grid<T, 4, F>::S[1] = x;
  		grid<T, 4, F>::S[2] = y;
  		grid<T, 4, F>::S[3] = z;
  	}
  
  	///set dimensions of the grid.
  	/// @param channels, number of channels in each image.
  	/// @param width,  number of pixels in width each image.
  	/// @param height, number of pixels in height.
  	/// @param depth,  number of pixels in depth.
  	void init(int channels, int width, int height, int depth)
  	{
  		//R.resize(4);
  		R[0] = channels;
  		R[1] = width;
  		R[2] = height;
  		R[3] = depth;
  
  		ptr = (T*)malloc(sizeof(T) * samples());
  		memset(ptr, 0, sizeof(T) * samples());
  	}
  
  	///Saves the entire stack to a set of images
  	/// @param file_mask is the mask describing how the file names will be saved (ex. image????.bmp)
  	void save_images(std::string file_mask){
  
  		stim::filename file_path(file_mask);
  		//stim::filename abs_file_path = file_pat
  
  		//create a list of file names
  		std::vector<std::string> file_list = stim::wildcards::increment(file_path.str(), 0, R[3]-1, 1);
  		for (int i = 0; i < R[3]; i++) {
  			save_image(file_list[i], i);
  		}
  	}
  
  	/// Returns the pixel at the specified point
  	T get(unsigned int x, unsigned int y, unsigned int z, unsigned int c = 0){
  		return ptr[z * R[0] * R[1] * R[2] + y * R[0] * R[1] + x * R[0] + c];
  	}
  
  	/// Returns the world-space position at an index point (i, j, k)
  	vec3<F> p(size_t i, size_t j, size_t k){
  		vec3<F> result;
  		result[0] = (F)i * S[1];
  		result[1] = (F)j * S[2];
  		result[2] = (F)k * S[3];
  		return result;
  	}
  
  	// set the pixel at the specified point
  	void set(size_t i, size_t j, size_t k, T value, size_t c = 0){
  		ptr[k * R[0] * R[1] * R[2] + j * R[0] * R[1] + i * R[0] + c] = value;
  	}
  	void set(T* Ptr, size_t k) {
  		
  		for (unsigned i = 0; i < R[0] * R[1] * R[2]; i++)
  			ptr[i + k * R[0] * R[1] * R[2]] = Ptr[i];
  	}
  	void copy(T* Ptr) {
  		ptr = Ptr;
  	}
  
  
  	/* This was causing compiler errors. I don't think this function call exists anywhere:
  
  	void read(std::string file, unsigned int X, unsigned int Y, unsigned int Z, unsigned int C = 1, unsigned int header = 0){
  		read(file, stim::vec<unsigned long>(C, X, Y, Z), header);
  	}
  	*/
  
  	T* data(){
  		return ptr;
  	}
  
  };
  
  
  }
  
  #endif