Commit 26da82c8bdc9c3289d5dfae45b2629acd99edda6

Authored by David Mayerich
1 parent 983b730b

finalized stim::gl_texture edits for Windows

stim/gl/gl_texture.h
@@ -5,8 +5,11 @@ @@ -5,8 +5,11 @@
5 #include <iostream> 5 #include <iostream>
6 #include <vector> 6 #include <vector>
7 #include "../grids/image_stack.h" 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 #include <stim/gl/error.h> 13 #include <stim/gl/error.h>
11 namespace stim{ 14 namespace stim{
12 15
@@ -15,21 +18,21 @@ class gl_texture @@ -15,21 +18,21 @@ class gl_texture
15 Uses image_stack class in order to create a texture object. 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 protected: 24 protected:
22 //std::string path; 25 //std::string path;
23 GLuint texID; //OpenGL object 26 GLuint texID; //OpenGL object
24 GLenum texture_type; //1D, 2D, 3D 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 using image_stack<T>::R; 33 using image_stack<T>::R;
30 - using image_stack<T>::S; 34 + //using image_stack<T>::S;
31 using image_stack<T>::ptr; 35 using image_stack<T>::ptr;
32 - using image_stack<T>::samples;  
33 36
34 /// Sets the internal texture_type, based on the data dimensions 37 /// Sets the internal texture_type, based on the data dimensions
35 void setTextureType(){ 38 void setTextureType(){
@@ -44,22 +47,186 @@ class gl_texture : public virtual image_stack&lt;T&gt; @@ -44,22 +47,186 @@ class gl_texture : public virtual image_stack&lt;T&gt;
44 //initializes important variables 47 //initializes important variables
45 void init() { 48 void init() {
46 texID = 0; //initialize texture ID to zero, default if OpenGL returns an error 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 public: 196 public:
51 197
52 ///default constructor 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 ///@param string path to the directory with the image files. 207 ///@param string path to the directory with the image files.
58 ///Creates an instance of the gl_texture object with a path to the data. 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 ///returns the dimentions of the data in the x, y, z directions. 232 ///returns the dimentions of the data in the x, y, z directions.
@@ -72,21 +239,6 @@ class gl_texture : public virtual image_stack&lt;T&gt; @@ -72,21 +239,6 @@ class gl_texture : public virtual image_stack&lt;T&gt;
72 x = R[0]; y = R[1]; z = R[2]; 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 ///@param x size of the voxel in x direction 242 ///@param x size of the voxel in x direction
91 ///@param y size of the voxel in y direction 243 ///@param y size of the voxel in y direction
92 ///@param z size of the voxel in z direction 244 ///@param z size of the voxel in z direction
@@ -106,15 +258,12 @@ class gl_texture : public virtual image_stack&lt;T&gt; @@ -106,15 +258,12 @@ class gl_texture : public virtual image_stack&lt;T&gt;
106 ///@param file_mask specifies the file(s) to be loaded 258 ///@param file_mask specifies the file(s) to be loaded
107 /// Sets the path and calls the loader on that path. 259 /// Sets the path and calls the loader on that path.
108 void load(std::string file_mask){ 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 /// Returns the GLuint id of the texture created by/associated with the 268 /// Returns the GLuint id of the texture created by/associated with the
120 /// instance of the gl_texture class. 269 /// instance of the gl_texture class.
@@ -122,39 +271,8 @@ class gl_texture : public virtual image_stack&lt;T&gt; @@ -122,39 +271,8 @@ class gl_texture : public virtual image_stack&lt;T&gt;
122 return texID; 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 return ptr; 276 return ptr;
159 } 277 }
160 278
@@ -24,27 +24,26 @@ protected: @@ -24,27 +24,26 @@ protected:
24 F S[D]; //spacing between element samples 24 F S[D]; //spacing between element samples
25 T* ptr; //pointer to the data (on the GPU or CPU) 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 ///Initializes a grid by allocating the necessary memory and setting all values to zero 29 ///Initializes a grid by allocating the necessary memory and setting all values to zero
36 void init(){ 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 public: 42 public:
42 43
43 ///Default constructor doesn't do anything 44 ///Default constructor doesn't do anything
44 grid(){ 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 ///Constructor used to specify the grid size as a vector 49 ///Constructor used to specify the grid size as a vector
@@ -56,6 +55,19 @@ public: @@ -56,6 +55,19 @@ public:
56 init(); 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 void 71 void
60 setDim(stim::vec<float> s){ 72 setDim(stim::vec<float> s){
61 for(size_t d = 0; d < D; d++) 73 for(size_t d = 0; d < D; d++)
@@ -64,7 +76,7 @@ public: @@ -64,7 +76,7 @@ public:
64 76
65 ///Constructor used to specify the grid size as a set of parameters 77 ///Constructor used to specify the grid size as a set of parameters
66 /// @param X0... is a list of values describing the grid size along each dimension 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 R[0] = X0; //set the grid size of the first dimension 80 R[0] = X0; //set the grid size of the first dimension
69 va_list ap; //get a variable list 81 va_list ap; //get a variable list
70 va_start(ap, X0); //start the variable list at the first element 82 va_start(ap, X0); //start the variable list at the first element
@@ -72,18 +84,35 @@ public: @@ -72,18 +84,35 @@ public:
72 R[d] = va_arg(ap, size_t); //read the value from the variable list as a size_t 84 R[d] = va_arg(ap, size_t); //read the value from the variable list as a size_t
73 va_end(ap); 85 va_end(ap);
74 init(); //initialize the grid 86 init(); //initialize the grid
75 - } 87 + }*/
76 88
77 ///Set the spacing between grid sample points 89 ///Set the spacing between grid sample points
78 /// @param X0... is a list of values describing the grid sample spacing 90 /// @param X0... is a list of values describing the grid sample spacing
79 - void spacing(F X0, ...) { 91 + /*void spacing(F X0, ...) {
80 S[0] = X0; //set the grid size of the first dimension 92 S[0] = X0; //set the grid size of the first dimension
81 va_list ap; //get a variable list 93 va_list ap; //get a variable list
82 va_start(ap, X0); //start the variable list at the first element 94 va_start(ap, X0); //start the variable list at the first element
83 for (size_t d = 1; d<D; d++) //for each additional element 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 va_end(ap); 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 /// Get the sample spacing for the given dimension 118 /// Get the sample spacing for the given dimension
@@ -91,6 +120,16 @@ public: @@ -91,6 +120,16 @@ public:
91 return S[d]; 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 ///Writes the binary data to disk 133 ///Writes the binary data to disk
95 134
96 /// @param filename is the name of the binary file to be written 135 /// @param filename is the name of the binary file to be written
@@ -118,7 +157,7 @@ public: @@ -118,7 +157,7 @@ public:
118 157
119 ///Gets a single value from the grid given a set of coordinates 158 ///Gets a single value from the grid given a set of coordinates
120 /// @param x0... is a list of coordinates specifying the desired value 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 va_list ap; //create a variable list 162 va_list ap; //create a variable list
124 163
@@ -133,13 +172,13 @@ public: @@ -133,13 +172,13 @@ public:
133 va_end(ap); 172 va_end(ap);
134 173
135 return ptr[idx]; //access the appropriate element and return the value 174 return ptr[idx]; //access the appropriate element and return the value
136 - } 175 + }*/
137 176
138 ///Sets a value in the grid 177 ///Sets a value in the grid
139 178
140 /// @param value is the grid point value 179 /// @param value is the grid point value
141 /// @x0... is the coordinate of the value to be set 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 va_list ap; //create a variable list 182 va_list ap; //create a variable list
144 unsigned long F = 1; //initialize the dimension counter to 1 183 unsigned long F = 1; //initialize the dimension counter to 1
145 unsigned long idx = x0; //initialize the index to the first variable 184 unsigned long idx = x0; //initialize the index to the first variable
@@ -151,7 +190,7 @@ public: @@ -151,7 +190,7 @@ public:
151 } 190 }
152 va_end(ap); 191 va_end(ap);
153 ptr[idx] = value; //set the value at the indexed location 192 ptr[idx] = value; //set the value at the indexed location
154 - } 193 + }*/
155 194
156 195
157 ///Outputs grid data as a string 196 ///Outputs grid data as a string
stim/grids/image_stack.h
@@ -10,16 +10,15 @@ namespace stim{ @@ -10,16 +10,15 @@ namespace stim{
10 10
11 ///This class is used to load 3D grid data from stacks of images 11 ///This class is used to load 3D grid data from stacks of images
12 // The class uses a 4D grid object, where the first dimension is a color value. 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 enum image_type {stimAuto, stimMono, stimRGB, stimRGBA}; 16 enum image_type {stimAuto, stimMono, stimRGB, stimRGBA};
17 17
18 protected: 18 protected:
19 - using stim::grid<T, 4>::S; 19 + //using stim::grid<T, 4>::S;
20 using stim::grid<T, 4>::R; 20 using stim::grid<T, 4>::R;
21 using stim::grid<T, 4>::ptr; 21 using stim::grid<T, 4>::ptr;
22 - using stim::grid<T, 4>::samples;  
23 using stim::grid<T, 4>::read; 22 using stim::grid<T, 4>::read;
24 23
25 public: 24 public:
@@ -28,6 +27,42 @@ 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 ///Load an image stack based on a file mask. Images are loaded in alphanumeric order 66 ///Load an image stack based on a file mask. Images are loaded in alphanumeric order
32 /// @param file_mask is the mask describing images to be loaded 67 /// @param file_mask is the mask describing images to be loaded
33 void load_images(std::string file_mask){ 68 void load_images(std::string file_mask){
@@ -42,17 +77,15 @@ public: @@ -42,17 +77,15 @@ public:
42 std::cout<<"STIM ERROR (image_stack): No matching files for loading a stack."<<std::endl; 77 std::cout<<"STIM ERROR (image_stack): No matching files for loading a stack."<<std::endl;
43 exit(1); 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 //load the first image and set all of the image_stack properties 81 //load the first image and set all of the image_stack properties
49 stim::image<T> I(file_list[0].str()); 82 stim::image<T> I(file_list[0].str());
50 83
51 //set the image resolution and number of channels 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 //allocate storage space 90 //allocate storage space
58 ptr = (T*)malloc(sizeof(T) * samples()); 91 ptr = (T*)malloc(sizeof(T) * samples());
stim/image/image.h
@@ -159,7 +159,10 @@ public: @@ -159,7 +159,10 @@ public:
159 std::cout<<"ERROR stim::image::load() - unable to find image "<<filename<<std::endl; 159 std::cout<<"ERROR stim::image::load() - unable to find image "<<filename<<std::endl;
160 exit(1); 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 unsigned char* cv_ptr = (unsigned char*)cvImage.data; 166 unsigned char* cv_ptr = (unsigned char*)cvImage.data;
164 if(C() == 1) //if this is a single-color image, just copy the data 167 if(C() == 1) //if this is a single-color image, just copy the data
165 memcpy(img, cv_ptr, bytes()); 168 memcpy(img, cv_ptr, bytes());