image_stack.h
5.73 KB
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
#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>
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>::R;
using stim::grid<T, 4>::ptr;
using stim::grid<T, 4>::read;
public:
//default constructor
image_stack() : grid<T, 4>() {
}
/// 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
}
/// 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_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());
}
///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);
//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];
}
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