Commit 26da82c8bdc9c3289d5dfae45b2629acd99edda6
1 parent
983b730b
finalized stim::gl_texture edits for Windows
Showing
4 changed files
with
296 additions
and
103 deletions
Show diff stats
stim/gl/gl_texture.h
... | ... | @@ -5,8 +5,11 @@ |
5 | 5 | #include <iostream> |
6 | 6 | #include <vector> |
7 | 7 | #include "../grids/image_stack.h" |
8 | -#include <GL/glut.h> | |
9 | -#include <GL/glext.h> | |
8 | +//Visual Studio requires GLEW | |
9 | +#ifdef _WIN32 | |
10 | + #include <GL/glew.h> | |
11 | +#endif | |
12 | +//#include <GL/glut.h> | |
10 | 13 | #include <stim/gl/error.h> |
11 | 14 | namespace stim{ |
12 | 15 | |
... | ... | @@ -15,21 +18,21 @@ class gl_texture |
15 | 18 | Uses image_stack class in order to create a texture object. |
16 | 19 | */ |
17 | 20 | |
18 | -template<typename T> | |
19 | -class gl_texture : public virtual image_stack<T> | |
21 | +template<typename T, typename F = float> | |
22 | +class gl_texture : public virtual image_stack<T, F> | |
20 | 23 | { |
21 | 24 | protected: |
22 | 25 | //std::string path; |
23 | 26 | GLuint texID; //OpenGL object |
24 | 27 | GLenum texture_type; //1D, 2D, 3D |
25 | - GLint interpType; | |
26 | - GLint texWrap; | |
27 | - GLenum type; | |
28 | - GLenum format; | |
28 | + GLint interpolation; | |
29 | + GLint wrap; | |
30 | + GLenum cpu_type; | |
31 | + GLenum gpu_type; | |
32 | + GLenum format; //format for the texture (GL_RGBA, GL_LUMINANCE, etc.) | |
29 | 33 | using image_stack<T>::R; |
30 | - using image_stack<T>::S; | |
34 | + //using image_stack<T>::S; | |
31 | 35 | using image_stack<T>::ptr; |
32 | - using image_stack<T>::samples; | |
33 | 36 | |
34 | 37 | /// Sets the internal texture_type, based on the data dimensions |
35 | 38 | void setTextureType(){ |
... | ... | @@ -44,22 +47,186 @@ class gl_texture : public virtual image_stack<T> |
44 | 47 | //initializes important variables |
45 | 48 | void init() { |
46 | 49 | texID = 0; //initialize texture ID to zero, default if OpenGL returns an error |
47 | - memset(R, 0, sizeof) | |
50 | + memset(R, 0, sizeof(size_t)); | |
51 | + memset(S, 0, sizeof(F)); | |
52 | + } | |
53 | + | |
54 | + //guesses the color format of the texture | |
55 | + GLenum guess_format(){ | |
56 | + size_t channels = R[0]; | |
57 | + switch(channels){ | |
58 | + case 1: | |
59 | + return GL_LUMINANCE; | |
60 | + case 2: | |
61 | + return GL_RG; | |
62 | + case 3: | |
63 | + return GL_RGB; | |
64 | + case 4: | |
65 | + return GL_RGBA; | |
66 | + default: | |
67 | + std::cout<<"Error in stim::gl_texture - unable to guess texture format based on number of channels ("<<R[4]<<")"<<std::endl; | |
68 | + exit(1); | |
69 | + } | |
70 | + } | |
71 | + | |
72 | + //guesses the OpenGL CPU data type based on T | |
73 | + GLenum guess_cpu_type(){ | |
74 | + // The following is C++ 11 code, but causes problems on some compilers (ex. nvcc). Below is my best approximation to a solution | |
75 | + | |
76 | + //if(std::is_same<T, unsigned char>::value) return CV_MAKETYPE(CV_8U, (int)C()); | |
77 | + //if(std::is_same<T, char>::value) return CV_MAKETYPE(CV_8S, (int)C()); | |
78 | + //if(std::is_same<T, unsigned short>::value) return CV_MAKETYPE(CV_16U, (int)C()); | |
79 | + //if(std::is_same<T, short>::value) return CV_MAKETYPE(CV_16S, (int)C()); | |
80 | + //if(std::is_same<T, int>::value) return CV_MAKETYPE(CV_32S, (int)C()); | |
81 | + //if(std::is_same<T, float>::value) return CV_MAKETYPE(CV_32F, (int)C()); | |
82 | + //if(std::is_same<T, double>::value) return CV_MAKETYPE(CV_64F, (int)C()); | |
83 | + | |
84 | + if(typeid(T) == typeid(unsigned char)) return GL_UNSIGNED_BYTE; | |
85 | + if(typeid(T) == typeid(char)) return GL_BYTE; | |
86 | + if(typeid(T) == typeid(unsigned short)) return GL_UNSIGNED_SHORT; | |
87 | + if(typeid(T) == typeid(short)) return GL_SHORT; | |
88 | + if(typeid(T) == typeid(unsigned int)) return GL_UNSIGNED_INT; | |
89 | + if(typeid(T) == typeid(int)) return GL_INT; | |
90 | + if(typeid(T) == typeid(float)) return GL_FLOAT; | |
91 | + | |
92 | + std::cout<<"ERROR in stim::gl_texture - no valid data type found"<<std::endl; | |
93 | + exit(1); | |
94 | + } | |
95 | + | |
96 | + //Guesses the "internal format" of the texture to closely approximate the original format | |
97 | + GLint guess_gpu_type(){ | |
98 | + switch(format){ | |
99 | + case GL_LUMINANCE: | |
100 | + switch(cpu_type){ | |
101 | + case GL_BYTE: | |
102 | + case GL_UNSIGNED_BYTE: | |
103 | + return GL_LUMINANCE8; | |
104 | + case GL_SHORT: | |
105 | + case GL_UNSIGNED_SHORT: | |
106 | + return GL_LUMINANCE16; | |
107 | + case GL_INT: | |
108 | + case GL_UNSIGNED_INT: | |
109 | + return GL_LUMINANCE32I_EXT; | |
110 | + case GL_FLOAT: | |
111 | + return GL_LUMINANCE32F_ARB; | |
112 | + default: | |
113 | + std::cout<<"error in stim::gl_texture - unable to guess GPU internal format"<<std::endl; | |
114 | + exit(1); | |
115 | + } | |
116 | + case GL_RGB: | |
117 | + switch(cpu_type){ | |
118 | + case GL_BYTE: | |
119 | + case GL_UNSIGNED_BYTE: | |
120 | + return GL_RGB8; | |
121 | + case GL_SHORT: | |
122 | + case GL_UNSIGNED_SHORT: | |
123 | + return GL_RGB16; | |
124 | + case GL_INT: | |
125 | + case GL_UNSIGNED_INT: | |
126 | + return GL_RGB32I; | |
127 | + case GL_FLOAT: | |
128 | + return GL_RGB32F; | |
129 | + default: | |
130 | + std::cout<<"error in stim::gl_texture - unable to guess GPU internal format"<<std::endl; | |
131 | + exit(1); | |
132 | + } | |
133 | + case GL_RGBA: | |
134 | + switch(cpu_type){ | |
135 | + case GL_BYTE: | |
136 | + case GL_UNSIGNED_BYTE: | |
137 | + return GL_RGBA8; | |
138 | + case GL_SHORT: | |
139 | + case GL_UNSIGNED_SHORT: | |
140 | + return GL_RGBA16; | |
141 | + case GL_INT: | |
142 | + case GL_UNSIGNED_INT: | |
143 | + return GL_RGBA32I; | |
144 | + case GL_FLOAT: | |
145 | + return GL_RGBA32F; | |
146 | + default: | |
147 | + std::cout<<"error in stim::gl_texture - unable to guess GPU internal format"<<std::endl; | |
148 | + exit(1); | |
149 | + } | |
150 | + default: | |
151 | + std::cout<<"error in stim::gl_texture - unable to guess GPU internal format"<<std::endl; | |
152 | + exit(1); | |
153 | + } | |
154 | + } | |
155 | + /// creates this texture in the current OpenGL context | |
156 | + void generate_texture(){ | |
157 | + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | |
158 | + CHECK_OPENGL_ERROR | |
159 | + glGenTextures(1, &texID); | |
160 | + CHECK_OPENGL_ERROR | |
161 | + glBindTexture(texture_type, texID); | |
162 | + CHECK_OPENGL_ERROR | |
163 | + glTexParameteri(texture_type, GL_TEXTURE_MIN_FILTER, interpolation); | |
164 | + CHECK_OPENGL_ERROR | |
165 | + glTexParameteri(texture_type, GL_TEXTURE_MAG_FILTER, interpolation); | |
166 | + CHECK_OPENGL_ERROR | |
167 | + switch(texture_type){ | |
168 | + case GL_TEXTURE_3D: | |
169 | + glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, wrap); | |
170 | + glTexParameteri(texture_type, GL_TEXTURE_WRAP_T, wrap); | |
171 | + glTexParameteri(texture_type, GL_TEXTURE_WRAP_R, wrap); | |
172 | + glTexImage3D(texture_type, 0, gpu_type, (GLsizei)R[1], (GLsizei)R[2], (GLsizei)R[3], 0, format, cpu_type, ptr); | |
173 | + break; | |
174 | + case GL_TEXTURE_2D: | |
175 | + glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, wrap); | |
176 | + CHECK_OPENGL_ERROR | |
177 | + glTexParameteri(texture_type, GL_TEXTURE_WRAP_T, wrap); | |
178 | + CHECK_OPENGL_ERROR | |
179 | + glTexImage2D(texture_type, 0, gpu_type, (GLsizei)R[1], (GLsizei)R[2], 0, format, cpu_type, ptr); | |
180 | + CHECK_OPENGL_ERROR | |
181 | + break; | |
182 | + case GL_TEXTURE_1D: | |
183 | + glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, wrap); | |
184 | + CHECK_OPENGL_ERROR | |
185 | + glTexImage1D(texture_type, 0, gpu_type, (GLsizei)R[1], 0, format, cpu_type, ptr); | |
186 | + CHECK_OPENGL_ERROR | |
187 | + break; | |
188 | + default: | |
189 | + std::cout<<"Error in stim::gl_texture - unrecognized texture target when generating texture"<<std::endl; | |
190 | + exit(1); | |
191 | + break; | |
192 | + } | |
193 | + CHECK_OPENGL_ERROR | |
48 | 194 | } |
49 | 195 | |
50 | 196 | public: |
51 | 197 | |
52 | 198 | ///default constructor |
53 | - gl_texture() : image_stack<T>() { | |
54 | - | |
199 | + gl_texture( GLint interp = GL_LINEAR, //default to linear interpolation | |
200 | + GLint twrap = GL_REPEAT) //default repeating the texture at the edges | |
201 | + : image_stack<T>() { | |
202 | + init(); //initialize the texture with NULL values | |
203 | + interpolation = interp; //store the interpolation type | |
204 | + wrap = twrap; //store the wrap type | |
55 | 205 | } |
56 | 206 | |
57 | 207 | ///@param string path to the directory with the image files. |
58 | 208 | ///Creates an instance of the gl_texture object with a path to the data. |
59 | 209 | |
60 | - gl_texture(std::string file_mask){ | |
61 | - image_stack<T>::load_images(file_mask); | |
62 | - setTextureType(); | |
210 | + gl_texture(std::string file_mask, GLint interp = GL_LINEAR, GLint twrap = GL_REPEAT){ | |
211 | + init(); | |
212 | + interpolation = interp; //store interpolation type | |
213 | + wrap = twrap; //store wrap type | |
214 | + load(file_mask); | |
215 | + } | |
216 | + | |
217 | + ///Attaches the texture to the current OpenGL context and makes it ready to render | |
218 | + void attach(){ | |
219 | + if(texID == 0) generate_texture(); //generate the texture if it doesn't already exist | |
220 | + else{ | |
221 | + std::cout<<"Texture has already been attached to a context."<<std::endl; | |
222 | + exit(1); | |
223 | + } | |
224 | + } | |
225 | + | |
226 | + //binds a texture to be the current render source | |
227 | + void bind(){ | |
228 | + glBindTexture(texture_type, texID); //bind the texture to the appropriate texture target | |
229 | + CHECK_OPENGL_ERROR | |
63 | 230 | } |
64 | 231 | |
65 | 232 | ///returns the dimentions of the data in the x, y, z directions. |
... | ... | @@ -72,21 +239,6 @@ class gl_texture : public virtual image_stack<T> |
72 | 239 | x = R[0]; y = R[1]; z = R[2]; |
73 | 240 | } |
74 | 241 | |
75 | - ///@param GLint interp --GL_LINEAR, GL_NEAREST... | |
76 | - ///@param GLint twrap --GL_REPEAR, GL_CLAMP_TO_EDGE... | |
77 | - ///@param GLenum dataType --GL_UNSIGNED_BYTE, GL_FLOAT16... | |
78 | - ///@param GLenum dataFormat--GL_LUMINANCE, GL_RGB... | |
79 | - /// Texture paramenters. | |
80 | - void setTexParam(GLint interp = GL_LINEAR, | |
81 | - GLint twrap = GL_CLAMP_TO_EDGE, | |
82 | - GLenum dataType = GL_UNSIGNED_BYTE, | |
83 | - GLenum dataFormat = GL_LUMINANCE){ | |
84 | - interpType = interp; | |
85 | - texWrap = twrap; | |
86 | - type = dataType; | |
87 | - format = dataFormat; | |
88 | - } | |
89 | - | |
90 | 242 | ///@param x size of the voxel in x direction |
91 | 243 | ///@param y size of the voxel in y direction |
92 | 244 | ///@param z size of the voxel in z direction |
... | ... | @@ -106,15 +258,12 @@ class gl_texture : public virtual image_stack<T> |
106 | 258 | ///@param file_mask specifies the file(s) to be loaded |
107 | 259 | /// Sets the path and calls the loader on that path. |
108 | 260 | void load(std::string file_mask){ |
109 | - image_stack<T>::load_images(file_mask); | |
110 | - setTextureType(); | |
261 | + image_stack<T>::load_images(file_mask); //load images | |
262 | + setTextureType(); //set the texture type: 1D, 2D, 3D | |
263 | + format = guess_format(); //guess the texture format based on the number of image channels | |
264 | + cpu_type = guess_cpu_type(); //guess the CPU type based on the template | |
265 | + gpu_type = guess_gpu_type(); //guess the GPU type based on the format and template | |
111 | 266 | } |
112 | - | |
113 | - /// Returns an std::string path associated with an instance of the gl_texture class. | |
114 | - //std::string getPath() | |
115 | - //{ | |
116 | - // return path; | |
117 | - //} | |
118 | 267 | |
119 | 268 | /// Returns the GLuint id of the texture created by/associated with the |
120 | 269 | /// instance of the gl_texture class. |
... | ... | @@ -122,39 +271,8 @@ class gl_texture : public virtual image_stack<T> |
122 | 271 | return texID; |
123 | 272 | } |
124 | 273 | |
125 | - /// Creates a texture and from the loaded data and | |
126 | - /// assigns that texture to texID | |
127 | - //TO DO :::: 1D textures | |
128 | - //TO DO:::add methods for handling the cases of T | |
129 | - // and convert them to GL equivalent. | |
130 | - // i.e. an overloaded function that handles paramenter conversion. | |
131 | - void createTexture(){ | |
132 | - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | |
133 | - glGenTextures(1, &texID); | |
134 | - glBindTexture(texture_type, texID); | |
135 | - glTexParameteri(texture_type, GL_TEXTURE_MIN_FILTER, interpType); | |
136 | - glTexParameteri(texture_type, GL_TEXTURE_MAG_FILTER, interpType); | |
137 | - switch(texture_type){ | |
138 | - case GL_TEXTURE_3D: | |
139 | - glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, texWrap); | |
140 | - glTexParameteri(texture_type, GL_TEXTURE_WRAP_T, texWrap); | |
141 | - glTexParameteri(texture_type, GL_TEXTURE_WRAP_R, texWrap); | |
142 | - glTexImage3D(texture_type, 0, 1, R[1], R[2], R[3], 0, format, type, ptr); | |
143 | - glPixelStorei(GL_PACK_ALIGNMENT,1); | |
144 | - break; | |
145 | - case GL_TEXTURE_2D: | |
146 | - glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, texWrap); | |
147 | - glTexParameteri(texture_type, GL_TEXTURE_WRAP_T, texWrap); | |
148 | - glTexImage2D(texture_type, 0, 1, R[1], R[2], 0, format, type, ptr); | |
149 | - break; | |
150 | - } | |
151 | - } | |
152 | - ///Temporary methods for debugging and testing are below. | |
153 | - ///Self-explanatory. | |
154 | 274 | |
155 | - T* | |
156 | - getData() | |
157 | - { | |
275 | + T* getData(){ | |
158 | 276 | return ptr; |
159 | 277 | } |
160 | 278 | ... | ... |
stim/grids/grid.h
... | ... | @@ -24,27 +24,26 @@ protected: |
24 | 24 | F S[D]; //spacing between element samples |
25 | 25 | T* ptr; //pointer to the data (on the GPU or CPU) |
26 | 26 | |
27 | - ///Return the total number of values in the binary file | |
28 | - size_t samples(){ | |
29 | - size_t s = 1; | |
30 | - for(size_t d = 0; d < D; d++) | |
31 | - s *= R[d]; | |
32 | - return s; | |
33 | - } | |
27 | + | |
34 | 28 | |
35 | 29 | ///Initializes a grid by allocating the necessary memory and setting all values to zero |
36 | 30 | void init(){ |
37 | - size_t N = samples(); //calculate the total number of values | |
38 | - ptr = (T*)calloc(sizeof(T) * N); //allocate memory to store the grid | |
31 | + ptr = NULL; //initialize the data pointer to NULL | |
32 | + memset(R, 0, sizeof(size_t) * D); //set the resolution to zero | |
33 | + for(size_t d = 0; d < D; d++) S[d] = (F)1.0; //initialize the spacing to unity | |
34 | + } | |
35 | + | |
36 | + void alloc(){ | |
37 | + if(ptr != NULL) free(ptr); //if memory has already been allocated, free it | |
38 | + size_t N = samples(); //calculate the total number of values | |
39 | + ptr = (T*)calloc(sizeof(T), N); //allocate memory to store the grid | |
39 | 40 | } |
40 | 41 | |
41 | 42 | public: |
42 | 43 | |
43 | 44 | ///Default constructor doesn't do anything |
44 | 45 | grid(){ |
45 | - memset(R, 0, sizeof(size_t) * D); //initialize the grid dimensions to zero | |
46 | - memset(S, 0, sizeof(F) * D); //initialize the grid size to zero | |
47 | - ptr = NULL; //set the data pointer to NULL | |
46 | + init(); | |
48 | 47 | } |
49 | 48 | |
50 | 49 | ///Constructor used to specify the grid size as a vector |
... | ... | @@ -56,6 +55,19 @@ public: |
56 | 55 | init(); |
57 | 56 | } |
58 | 57 | |
58 | + ///Return the total number of values in the binary file | |
59 | + size_t samples(){ | |
60 | + size_t s = 1; | |
61 | + for(size_t d = 0; d < D; d++) | |
62 | + s *= R[d]; | |
63 | + return s; | |
64 | + } | |
65 | + | |
66 | + ///Return the number of bytes in the binary file | |
67 | + size_t bytes(){ | |
68 | + return samples() * sizeof(T); | |
69 | + } | |
70 | + | |
59 | 71 | void |
60 | 72 | setDim(stim::vec<float> s){ |
61 | 73 | for(size_t d = 0; d < D; d++) |
... | ... | @@ -64,7 +76,7 @@ public: |
64 | 76 | |
65 | 77 | ///Constructor used to specify the grid size as a set of parameters |
66 | 78 | /// @param X0... is a list of values describing the grid size along each dimension |
67 | - grid( size_t X0, ...){ | |
79 | + /*grid( size_t X0, ...){ | |
68 | 80 | R[0] = X0; //set the grid size of the first dimension |
69 | 81 | va_list ap; //get a variable list |
70 | 82 | va_start(ap, X0); //start the variable list at the first element |
... | ... | @@ -72,18 +84,35 @@ public: |
72 | 84 | R[d] = va_arg(ap, size_t); //read the value from the variable list as a size_t |
73 | 85 | va_end(ap); |
74 | 86 | init(); //initialize the grid |
75 | - } | |
87 | + }*/ | |
76 | 88 | |
77 | 89 | ///Set the spacing between grid sample points |
78 | 90 | /// @param X0... is a list of values describing the grid sample spacing |
79 | - void spacing(F X0, ...) { | |
91 | + /*void spacing(F X0, ...) { | |
80 | 92 | S[0] = X0; //set the grid size of the first dimension |
81 | 93 | va_list ap; //get a variable list |
82 | 94 | va_start(ap, X0); //start the variable list at the first element |
83 | 95 | for (size_t d = 1; d<D; d++) //for each additional element |
84 | - S[d] = va_arg(ap, size_t); //read the value from the variable list as a size_t | |
96 | + S[d] = va_arg(ap, F); //read the value from the variable list as a size_t | |
85 | 97 | va_end(ap); |
86 | - init(); //initialize the grid | |
98 | + }*/ | |
99 | + | |
100 | + /// Set the spacing between grid sample points for the specified dimension | |
101 | + void spacing(size_t d, F sp){ | |
102 | + if(d < D) S[d] = sp; | |
103 | + else{ | |
104 | + std::cout<<"error in stim::grid::spacing() - insufficient dimensions"<<std::endl; | |
105 | + exit(1); | |
106 | + } | |
107 | + } | |
108 | + | |
109 | + /// Return the spacing for a given dimension | |
110 | + F spacing(size_t d){ | |
111 | + if(d < D) return S[d]; | |
112 | + else{ | |
113 | + std::cout<<"error in stim::grid::spacing() - insufficient dimensions"<<std::endl; | |
114 | + exit(1); | |
115 | + } | |
87 | 116 | } |
88 | 117 | |
89 | 118 | /// Get the sample spacing for the given dimension |
... | ... | @@ -91,6 +120,16 @@ public: |
91 | 120 | return S[d]; |
92 | 121 | } |
93 | 122 | |
123 | + /// Get the size of the grid along the specified dimension | |
124 | + F size(size_t d){ | |
125 | + return (F)R[d] * S[d]; | |
126 | + } | |
127 | + | |
128 | + /// Return the number of samples | |
129 | + size_t samples(size_t d){ | |
130 | + return R[d]; | |
131 | + } | |
132 | + | |
94 | 133 | ///Writes the binary data to disk |
95 | 134 | |
96 | 135 | /// @param filename is the name of the binary file to be written |
... | ... | @@ -118,7 +157,7 @@ public: |
118 | 157 | |
119 | 158 | ///Gets a single value from the grid given a set of coordinates |
120 | 159 | /// @param x0... is a list of coordinates specifying the desired value |
121 | - T get(unsigned long x0, ...){ | |
160 | + /*T get(unsigned long x0, ...){ | |
122 | 161 | |
123 | 162 | va_list ap; //create a variable list |
124 | 163 | |
... | ... | @@ -133,13 +172,13 @@ public: |
133 | 172 | va_end(ap); |
134 | 173 | |
135 | 174 | return ptr[idx]; //access the appropriate element and return the value |
136 | - } | |
175 | + }*/ | |
137 | 176 | |
138 | 177 | ///Sets a value in the grid |
139 | 178 | |
140 | 179 | /// @param value is the grid point value |
141 | 180 | /// @x0... is the coordinate of the value to be set |
142 | - void set(T value, unsigned long x0, ...){ | |
181 | + /*void set(T value, unsigned long x0, ...){ | |
143 | 182 | va_list ap; //create a variable list |
144 | 183 | unsigned long F = 1; //initialize the dimension counter to 1 |
145 | 184 | unsigned long idx = x0; //initialize the index to the first variable |
... | ... | @@ -151,7 +190,7 @@ public: |
151 | 190 | } |
152 | 191 | va_end(ap); |
153 | 192 | ptr[idx] = value; //set the value at the indexed location |
154 | - } | |
193 | + }*/ | |
155 | 194 | |
156 | 195 | |
157 | 196 | ///Outputs grid data as a string | ... | ... |
stim/grids/image_stack.h
... | ... | @@ -10,16 +10,15 @@ namespace stim{ |
10 | 10 | |
11 | 11 | ///This class is used to load 3D grid data from stacks of images |
12 | 12 | // The class uses a 4D grid object, where the first dimension is a color value. |
13 | -template<typename T> | |
14 | -class image_stack : public virtual stim::grid<T, 4>{ | |
13 | +template<typename T, typename F = float> | |
14 | +class image_stack : public virtual stim::grid<T, 4, F>{ | |
15 | 15 | |
16 | 16 | enum image_type {stimAuto, stimMono, stimRGB, stimRGBA}; |
17 | 17 | |
18 | 18 | protected: |
19 | - using stim::grid<T, 4>::S; | |
19 | + //using stim::grid<T, 4>::S; | |
20 | 20 | using stim::grid<T, 4>::R; |
21 | 21 | using stim::grid<T, 4>::ptr; |
22 | - using stim::grid<T, 4>::samples; | |
23 | 22 | using stim::grid<T, 4>::read; |
24 | 23 | |
25 | 24 | public: |
... | ... | @@ -28,6 +27,42 @@ public: |
28 | 27 | |
29 | 28 | } |
30 | 29 | |
30 | + /// Overloads grid::samples() to return the number of samples associated with a given spatial dimension | |
31 | + /// this is necessary because R[0] stores the color | |
32 | + size_t samples(size_t d){ | |
33 | + return grid<T, 4, F>::samples(d + 1); | |
34 | + } | |
35 | + | |
36 | + size_t samples(){ | |
37 | + return R[1] * R[2] * R[3]; //return the number of spatial samples | |
38 | + } | |
39 | + | |
40 | + /// Returns the number of color channels | |
41 | + size_t channels(){ | |
42 | + return R[0]; | |
43 | + } | |
44 | + | |
45 | + /// Overloads grid::size() to return the size of the grid associated with a given spatial dimension | |
46 | + F size(size_t d){ | |
47 | + return grid<T, 4, F>::size(d + 1); | |
48 | + } | |
49 | + | |
50 | + /// Sets the spacing between samples in the image stack | |
51 | + void spacing(F sx, F sy, F sz){ | |
52 | + grid<T, 4, F>::S[1] = sx; //set the sample spacing for the appropriate spatial dimension | |
53 | + grid<T, 4, F>::S[2] = sy; | |
54 | + grid<T, 4, F>::S[3] = sz; | |
55 | + } | |
56 | + | |
57 | + F spacing(size_t d){ | |
58 | + return grid<T, 4, F>::spacing(d + 1); | |
59 | + } | |
60 | + | |
61 | + /// Overloads the spacing parameter to set the size of the grid associated with a given spatial dimension | |
62 | + //void spacing(F sx, F sy = 1.0f, F sz = 1.0f){ | |
63 | + // grid<T, 4, F>::spacing((F)1.0, sx, sy, sz); | |
64 | + //} | |
65 | + | |
31 | 66 | ///Load an image stack based on a file mask. Images are loaded in alphanumeric order |
32 | 67 | /// @param file_mask is the mask describing images to be loaded |
33 | 68 | void load_images(std::string file_mask){ |
... | ... | @@ -42,17 +77,15 @@ public: |
42 | 77 | std::cout<<"STIM ERROR (image_stack): No matching files for loading a stack."<<std::endl; |
43 | 78 | exit(1); |
44 | 79 | } |
45 | - for(int i = 0; i < file_list.size(); i++) | |
46 | - std::cout << file_list[i].str() << std::endl; | |
47 | 80 | |
48 | 81 | //load the first image and set all of the image_stack properties |
49 | 82 | stim::image<T> I(file_list[0].str()); |
50 | 83 | |
51 | 84 | //set the image resolution and number of channels |
52 | - R.push(I.channels()); | |
53 | - R.push(I.width()); | |
54 | - R.push(I.height()); | |
55 | - R.push(file_list.size()); | |
85 | + R[0] = I.channels(); | |
86 | + R[1] = I.width(); | |
87 | + R[2] = I.height(); | |
88 | + R[3] = file_list.size(); | |
56 | 89 | |
57 | 90 | //allocate storage space |
58 | 91 | ptr = (T*)malloc(sizeof(T) * samples()); | ... | ... |
stim/image/image.h
... | ... | @@ -159,7 +159,10 @@ public: |
159 | 159 | std::cout<<"ERROR stim::image::load() - unable to find image "<<filename<<std::endl; |
160 | 160 | exit(1); |
161 | 161 | } |
162 | - allocate(cvImage.cols, cvImage.rows, cvImage.channels()); //allocate space for the image | |
162 | + int cols = cvImage.cols; | |
163 | + int rows = cvImage.rows; | |
164 | + int channels = cvImage.channels(); | |
165 | + allocate(cols, rows, channels); //allocate space for the image | |
163 | 166 | unsigned char* cv_ptr = (unsigned char*)cvImage.data; |
164 | 167 | if(C() == 1) //if this is a single-color image, just copy the data |
165 | 168 | memcpy(img, cv_ptr, bytes()); | ... | ... |