diff --git a/stim/gl/gl_texture.h b/stim/gl/gl_texture.h index 1e1e17c..b20123c 100644 --- a/stim/gl/gl_texture.h +++ b/stim/gl/gl_texture.h @@ -5,8 +5,11 @@ #include #include #include "../grids/image_stack.h" -#include -#include +//Visual Studio requires GLEW +#ifdef _WIN32 + #include +#endif +//#include #include namespace stim{ @@ -15,21 +18,21 @@ class gl_texture Uses image_stack class in order to create a texture object. */ -template -class gl_texture : public virtual image_stack +template +class gl_texture : public virtual image_stack { protected: //std::string path; GLuint texID; //OpenGL object GLenum texture_type; //1D, 2D, 3D - GLint interpType; - GLint texWrap; - GLenum type; - GLenum format; + GLint interpolation; + GLint wrap; + GLenum cpu_type; + GLenum gpu_type; + GLenum format; //format for the texture (GL_RGBA, GL_LUMINANCE, etc.) using image_stack::R; - using image_stack::S; + //using image_stack::S; using image_stack::ptr; - using image_stack::samples; /// Sets the internal texture_type, based on the data dimensions void setTextureType(){ @@ -44,22 +47,186 @@ class gl_texture : public virtual image_stack //initializes important variables void init() { texID = 0; //initialize texture ID to zero, default if OpenGL returns an error - memset(R, 0, sizeof) + memset(R, 0, sizeof(size_t)); + memset(S, 0, sizeof(F)); + } + + //guesses the color format of the texture + GLenum guess_format(){ + size_t channels = R[0]; + switch(channels){ + case 1: + return GL_LUMINANCE; + case 2: + return GL_RG; + case 3: + return GL_RGB; + case 4: + return GL_RGBA; + default: + std::cout<<"Error in stim::gl_texture - unable to guess texture format based on number of channels ("<::value) return CV_MAKETYPE(CV_8U, (int)C()); + //if(std::is_same::value) return CV_MAKETYPE(CV_8S, (int)C()); + //if(std::is_same::value) return CV_MAKETYPE(CV_16U, (int)C()); + //if(std::is_same::value) return CV_MAKETYPE(CV_16S, (int)C()); + //if(std::is_same::value) return CV_MAKETYPE(CV_32S, (int)C()); + //if(std::is_same::value) return CV_MAKETYPE(CV_32F, (int)C()); + //if(std::is_same::value) return CV_MAKETYPE(CV_64F, (int)C()); + + if(typeid(T) == typeid(unsigned char)) return GL_UNSIGNED_BYTE; + if(typeid(T) == typeid(char)) return GL_BYTE; + if(typeid(T) == typeid(unsigned short)) return GL_UNSIGNED_SHORT; + if(typeid(T) == typeid(short)) return GL_SHORT; + if(typeid(T) == typeid(unsigned int)) return GL_UNSIGNED_INT; + if(typeid(T) == typeid(int)) return GL_INT; + if(typeid(T) == typeid(float)) return GL_FLOAT; + + std::cout<<"ERROR in stim::gl_texture - no valid data type found"<() { - + gl_texture( GLint interp = GL_LINEAR, //default to linear interpolation + GLint twrap = GL_REPEAT) //default repeating the texture at the edges + : image_stack() { + init(); //initialize the texture with NULL values + interpolation = interp; //store the interpolation type + wrap = twrap; //store the wrap type } ///@param string path to the directory with the image files. ///Creates an instance of the gl_texture object with a path to the data. - gl_texture(std::string file_mask){ - image_stack::load_images(file_mask); - setTextureType(); + gl_texture(std::string file_mask, GLint interp = GL_LINEAR, GLint twrap = GL_REPEAT){ + init(); + interpolation = interp; //store interpolation type + wrap = twrap; //store wrap type + load(file_mask); + } + + ///Attaches the texture to the current OpenGL context and makes it ready to render + void attach(){ + if(texID == 0) generate_texture(); //generate the texture if it doesn't already exist + else{ + std::cout<<"Texture has already been attached to a context."< x = R[0]; y = R[1]; z = R[2]; } - ///@param GLint interp --GL_LINEAR, GL_NEAREST... - ///@param GLint twrap --GL_REPEAR, GL_CLAMP_TO_EDGE... - ///@param GLenum dataType --GL_UNSIGNED_BYTE, GL_FLOAT16... - ///@param GLenum dataFormat--GL_LUMINANCE, GL_RGB... - /// Texture paramenters. - void setTexParam(GLint interp = GL_LINEAR, - GLint twrap = GL_CLAMP_TO_EDGE, - GLenum dataType = GL_UNSIGNED_BYTE, - GLenum dataFormat = GL_LUMINANCE){ - interpType = interp; - texWrap = twrap; - type = dataType; - format = dataFormat; - } - ///@param x size of the voxel in x direction ///@param y size of the voxel in y direction ///@param z size of the voxel in z direction @@ -106,15 +258,12 @@ class gl_texture : public virtual image_stack ///@param file_mask specifies the file(s) to be loaded /// Sets the path and calls the loader on that path. void load(std::string file_mask){ - image_stack::load_images(file_mask); - setTextureType(); + image_stack::load_images(file_mask); //load images + setTextureType(); //set the texture type: 1D, 2D, 3D + format = guess_format(); //guess the texture format based on the number of image channels + cpu_type = guess_cpu_type(); //guess the CPU type based on the template + gpu_type = guess_gpu_type(); //guess the GPU type based on the format and template } - - /// Returns an std::string path associated with an instance of the gl_texture class. - //std::string getPath() - //{ - // return path; - //} /// Returns the GLuint id of the texture created by/associated with the /// instance of the gl_texture class. @@ -122,39 +271,8 @@ class gl_texture : public virtual image_stack return texID; } - /// Creates a texture and from the loaded data and - /// assigns that texture to texID - //TO DO :::: 1D textures - //TO DO:::add methods for handling the cases of T - // and convert them to GL equivalent. - // i.e. an overloaded function that handles paramenter conversion. - void createTexture(){ - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glGenTextures(1, &texID); - glBindTexture(texture_type, texID); - glTexParameteri(texture_type, GL_TEXTURE_MIN_FILTER, interpType); - glTexParameteri(texture_type, GL_TEXTURE_MAG_FILTER, interpType); - switch(texture_type){ - case GL_TEXTURE_3D: - glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, texWrap); - glTexParameteri(texture_type, GL_TEXTURE_WRAP_T, texWrap); - glTexParameteri(texture_type, GL_TEXTURE_WRAP_R, texWrap); - glTexImage3D(texture_type, 0, 1, R[1], R[2], R[3], 0, format, type, ptr); - glPixelStorei(GL_PACK_ALIGNMENT,1); - break; - case GL_TEXTURE_2D: - glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, texWrap); - glTexParameteri(texture_type, GL_TEXTURE_WRAP_T, texWrap); - glTexImage2D(texture_type, 0, 1, R[1], R[2], 0, format, type, ptr); - break; - } - } - ///Temporary methods for debugging and testing are below. - ///Self-explanatory. - T* - getData() - { + T* getData(){ return ptr; } diff --git a/stim/grids/grid.h b/stim/grids/grid.h index 43a0893..18aa6cc 100644 --- a/stim/grids/grid.h +++ b/stim/grids/grid.h @@ -24,27 +24,26 @@ protected: F S[D]; //spacing between element samples T* ptr; //pointer to the data (on the GPU or CPU) - ///Return the total number of values in the binary file - size_t samples(){ - size_t s = 1; - for(size_t d = 0; d < D; d++) - s *= R[d]; - return s; - } + ///Initializes a grid by allocating the necessary memory and setting all values to zero void init(){ - size_t N = samples(); //calculate the total number of values - ptr = (T*)calloc(sizeof(T) * N); //allocate memory to store the grid + ptr = NULL; //initialize the data pointer to NULL + memset(R, 0, sizeof(size_t) * D); //set the resolution to zero + for(size_t d = 0; d < D; d++) S[d] = (F)1.0; //initialize the spacing to unity + } + + void alloc(){ + if(ptr != NULL) free(ptr); //if memory has already been allocated, free it + size_t N = samples(); //calculate the total number of values + ptr = (T*)calloc(sizeof(T), N); //allocate memory to store the grid } public: ///Default constructor doesn't do anything grid(){ - memset(R, 0, sizeof(size_t) * D); //initialize the grid dimensions to zero - memset(S, 0, sizeof(F) * D); //initialize the grid size to zero - ptr = NULL; //set the data pointer to NULL + init(); } ///Constructor used to specify the grid size as a vector @@ -56,6 +55,19 @@ public: init(); } + ///Return the total number of values in the binary file + size_t samples(){ + size_t s = 1; + for(size_t d = 0; d < D; d++) + s *= R[d]; + return s; + } + + ///Return the number of bytes in the binary file + size_t bytes(){ + return samples() * sizeof(T); + } + void setDim(stim::vec s){ for(size_t d = 0; d < D; d++) @@ -64,7 +76,7 @@ public: ///Constructor used to specify the grid size as a set of parameters /// @param X0... is a list of values describing the grid size along each dimension - grid( size_t X0, ...){ + /*grid( size_t X0, ...){ R[0] = X0; //set the grid size of the first dimension va_list ap; //get a variable list va_start(ap, X0); //start the variable list at the first element @@ -72,18 +84,35 @@ public: R[d] = va_arg(ap, size_t); //read the value from the variable list as a size_t va_end(ap); init(); //initialize the grid - } + }*/ ///Set the spacing between grid sample points /// @param X0... is a list of values describing the grid sample spacing - void spacing(F X0, ...) { + /*void spacing(F X0, ...) { S[0] = X0; //set the grid size of the first dimension va_list ap; //get a variable list va_start(ap, X0); //start the variable list at the first element for (size_t d = 1; d -class image_stack : public virtual stim::grid{ +template +class image_stack : public virtual stim::grid{ enum image_type {stimAuto, stimMono, stimRGB, stimRGBA}; protected: - using stim::grid::S; + //using stim::grid::S; using stim::grid::R; using stim::grid::ptr; - using stim::grid::samples; using stim::grid::read; public: @@ -28,6 +27,42 @@ public: } + /// 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::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::size(d + 1); + } + + /// Sets the spacing between samples in the image stack + void spacing(F sx, F sy, F sz){ + grid::S[1] = sx; //set the sample spacing for the appropriate spatial dimension + grid::S[2] = sy; + grid::S[3] = sz; + } + + F spacing(size_t d){ + return grid::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::spacing((F)1.0, sx, sy, sz); + //} + ///Load an image stack based on a file mask. Images are loaded in alphanumeric order /// @param file_mask is the mask describing images to be loaded void load_images(std::string file_mask){ @@ -42,17 +77,15 @@ public: std::cout<<"STIM ERROR (image_stack): No matching files for loading a stack."< I(file_list[0].str()); //set the image resolution and number of channels - R.push(I.channels()); - R.push(I.width()); - R.push(I.height()); - R.push(file_list.size()); + R[0] = I.channels(); + R[1] = I.width(); + R[2] = I.height(); + R[3] = file_list.size(); //allocate storage space ptr = (T*)malloc(sizeof(T) * samples()); diff --git a/stim/image/image.h b/stim/image/image.h index d3f5f92..394551c 100644 --- a/stim/image/image.h +++ b/stim/image/image.h @@ -159,7 +159,10 @@ public: std::cout<<"ERROR stim::image::load() - unable to find image "<