#ifndef STIM_IMAGE_STACK_H #define STIM_IMAGE_STACK_H #include #include #include #include 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 class image_stack : public virtual stim::grid{ enum image_type {stimAuto, stimMono, stimRGB, stimRGBA}; protected: //using stim::grid::S; using stim::grid::R; using stim::grid::ptr; using stim::grid::read; public: //default constructor image_stack() : grid() { } /// 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 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 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."< 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::bytes()); //allocate storage space //load and copy each image into the grid for(unsigned int i = 0; i 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 file_list = file_path.get_list(); //get the list of files std::vector 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 I; image to insert. /// @int I, where to place the image. void insert_image(stim::image 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 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::S[0] = 1; grid::S[1] = x; grid::S[2] = y; grid::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 file_list = stim::wildcards::increment(file_path.str(), 0, R[3]-1, 1); for(int i=0; i(C, X, Y, Z), header); } T* data(){ return ptr; } }; } #endif