diff --git a/stim/grids/grid3.h b/stim/grids/grid3.h new file mode 100644 index 0000000..2a9c923 --- /dev/null +++ b/stim/grids/grid3.h @@ -0,0 +1,32 @@ +#ifndef STIM_GRID3_H +#define STIM_GRID3_H + +namespace stim{ + +template +class grid : public stim::grid{ + +public: + + /// Convert grid coordinates (integers) into world coordinates (F) based on the pixel spacing + void grid2volume(size_t xi, size_t yi, size_t zi, F& x, F& y, F&z){ + + } + + /// Use linear interpolation to get a value from the grid at (x, y, z) in VOLUME space (based on voxel size) + T lerp(F x, F y, F z){ + + } + /// Create a resampled grid with isotropic voxel sizes + grid3 resample_iso(){ + + //find the smallest spacing + //create a new grid of the appropriate size + //use linear interpolation to resample the old grid into the new grid + } + + +}; +} //end namespace stim + +#endif \ No newline at end of file diff --git a/stim/image/bmp.h b/stim/image/bmp.h new file mode 100644 index 0000000..2c66e1d --- /dev/null +++ b/stim/image/bmp.h @@ -0,0 +1,263 @@ +#pragma once + +namespace stim { +#pragma pack(1) + typedef unsigned int DWORD; + typedef unsigned short WORD; + typedef signed int LONG; + typedef struct tagBITMAPFILEHEADER { + WORD bfType; + DWORD bfSize; + WORD bfReserved1; + WORD bfReserved2; + DWORD bfOffBits; + } BITMAPFILEHEADER, *PBITMAPFILEHEADER; + + const unsigned int DIB_BITMAPCOREHEADER = 12; + const unsigned int DIB_OS21XBITMAPHEADER = 16; + const unsigned int DIB_BITMAPINFOHEADER = 40; + const unsigned int DIB_BITMAPV2INFOHEADER = 52; + const unsigned int DIB_BITMAPV3INFOHEADER = 56; + const unsigned int DIB_OS22XBITMAPHEADER = 64; + const unsigned int DIB_BITMAPV4HEADER = 108; + const unsigned int DIB_BITMAPV5HEADER = 124; + + typedef struct tagBITMAPCOREHEADER { + DWORD bcSize; + WORD bcWidth; + WORD bcHeight; + WORD bcPlanes; + WORD bcBitCount; + } BITMAPCOREHEADER, *PBITMAPCOREHEADER; + + typedef struct tagBITMAPINFOHEADER { + DWORD biSize; //40 bytes + LONG biWidth; + LONG biHeight; + WORD biPlanes; + WORD biBitCount; + DWORD biCompression; + DWORD biSizeImage; + LONG biXPelsPerMeter; + LONG biYPelsPerMeter; + DWORD biClrUsed; + DWORD biClrImportant; + } BITMAPINFOHEADER, *PBITMAPINFOHEADER; + + // From FileFormat.info + typedef struct { + DWORD Size; /* Size of this header in bytes */ + LONG Width; /* Image width in pixels */ + LONG Height; /* Image height in pixels */ + WORD Planes; /* Number of color planes */ + WORD BitsPerPixel; /* Number of bits per pixel */ + DWORD Compression; /* Compression methods used */ + DWORD SizeOfBitmap; /* Size of bitmap in bytes */ + LONG HorzResolution; /* Horizontal resolution in pixels per meter */ + LONG VertResolution; /* Vertical resolution in pixels per meter */ + DWORD ColorsUsed; /* Number of colors in the image */ + DWORD ColorsImportant; /* Minimum number of important colors */ + /* Fields added for Windows 4.x follow this line */ + + DWORD RedMask; /* Mask identifying bits of red component */ + DWORD GreenMask; /* Mask identifying bits of green component */ + DWORD BlueMask; /* Mask identifying bits of blue component */ + DWORD AlphaMask; /* Mask identifying bits of alpha component */ + DWORD CSType; /* Color space type */ + LONG RedX; /* X coordinate of red endpoint */ + LONG RedY; /* Y coordinate of red endpoint */ + LONG RedZ; /* Z coordinate of red endpoint */ + LONG GreenX; /* X coordinate of green endpoint */ + LONG GreenY; /* Y coordinate of green endpoint */ + LONG GreenZ; /* Z coordinate of green endpoint */ + LONG BlueX; /* X coordinate of blue endpoint */ + LONG BlueY; /* Y coordinate of blue endpoint */ + LONG BlueZ; /* Z coordinate of blue endpoint */ + DWORD GammaRed; /* Gamma red coordinate scale value */ + DWORD GammaGreen; /* Gamma green coordinate scale value */ + DWORD GammaBlue; /* Gamma blue coordinate scale value */ + } WIN4XBITMAPHEADER; + + typedef struct { + DWORD bV5Size; + LONG bV5Width; + LONG bV5Height; + WORD bV5Planes; + WORD bV5BitCount; + DWORD bV5Compression; + DWORD bV5SizeImage; + LONG bV5XPelsPerMeter; + LONG bV5YPelsPerMeter; + DWORD bV5ClrUsed; + DWORD bV5ClrImportant; + DWORD bV5RedMask; + DWORD bV5GreenMask; + DWORD bV5BlueMask; + DWORD bV5AlphaMask; + DWORD bV5CSType; + LONG RedX; /* X coordinate of red endpoint */ + LONG RedY; /* Y coordinate of red endpoint */ + LONG RedZ; /* Z coordinate of red endpoint */ + LONG GreenX; /* X coordinate of green endpoint */ + LONG GreenY; /* Y coordinate of green endpoint */ + LONG GreenZ; /* Z coordinate of green endpoint */ + LONG BlueX; /* X coordinate of blue endpoint */ + LONG BlueY; /* Y coordinate of blue endpoint */ + LONG BlueZ; /* Z coordinate of blue endpoint */ + DWORD bV5GammaRed; + DWORD bV5GammaGreen; + DWORD bV5GammaBlue; + DWORD bV5Intent; + DWORD bV5ProfileData; + DWORD bV5ProfileSize; + DWORD bV5Reserved; + } BITMAPV5HEADER, *PBITMAPV5HEADER; + + + //compression methods + const unsigned int BI_RGB = 0; + const unsigned int BI_BITFIELDS = 3; + + class bmp { + std::ifstream file; + public: + unsigned int dib_header_size; + size_t bit_pos; // start position (relative to the beginning of the file) of the bitmap bits + size_t total_size; //total size of the bitmap file (in bytes) + size_t width; + size_t height; + int channels; + int bits_per_pixel; + unsigned int compression; + + size_t bytes() { + return width * height * bits_per_pixel / 8; + } + void read_bmpFileHeader() { + BITMAPFILEHEADER file_header; + file.read((char*)&file_header, sizeof(BITMAPFILEHEADER)); + bit_pos = file_header.bfOffBits; + total_size = file_header.bfSize; + } + void read_bmpCoreHeader() { + tagBITMAPCOREHEADER header; + file.read((char*)&header, sizeof(tagBITMAPCOREHEADER)); + width = header.bcWidth; + height = header.bcHeight; + bits_per_pixel = header.bcBitCount; + compression = 0; + } + void read_bmpInfoHeader() { + tagBITMAPINFOHEADER info_header; + file.read((char*)&info_header, sizeof(tagBITMAPINFOHEADER)); + width = info_header.biWidth; + height = info_header.biHeight; + bits_per_pixel = info_header.biBitCount; + compression = info_header.biCompression; + } + void read_bmpV4Header() { + WIN4XBITMAPHEADER header; + file.read((char*)&header, sizeof(WIN4XBITMAPHEADER)); + width = header.Width; + height = header.Height; + bits_per_pixel = header.BitsPerPixel; + compression = header.Compression; + } + void read_bmpV5Header() { + BITMAPV5HEADER header; + file.read((char*)&header, sizeof(BITMAPV5HEADER)); + width = header.bV5Width; + height = header.bV5Height; + bits_per_pixel = header.bV5BitCount; + compression = header.bV5Compression; + } + void read_dib() { //read the bitmap DIB information header + int header_pos = file.tellg(); + file.read((char*)&dib_header_size, sizeof(unsigned int)); + file.seekg(header_pos); + switch (dib_header_size) { + case DIB_BITMAPCOREHEADER: read_bmpCoreHeader(); break; + case DIB_BITMAPINFOHEADER: read_bmpInfoHeader(); break; + case DIB_BITMAPV4HEADER: read_bmpV4Header(); break; + case DIB_BITMAPV5HEADER: read_bmpV5Header(); break; + default: + std::cout << "stim::bmp ERROR: this bitmap header format isn't supported" << std::endl; + exit(1); + } + } + + bool open(std::string filename) { //open the bitmap file and read the header data + file.open(filename, std::ifstream::binary); + if (!file) { + std::cout << "stim::bmp ERROR: error opening file: " << filename.c_str() << std::endl; + return false; + } + read_bmpFileHeader(); //read the file header + read_dib(); + if (compression != BI_RGB) { //check for compression + std::cout << "stim::bmp ERROR: this file is compressed, and compression is not supported" << std::endl; + return false; + } + return true; + } + void close() { + file.close(); + } + + /// Copy the bitmap data into a pre-allocated array + bool read(char* dst){ + file.seekg(bit_pos); //seek to the beginning of the data array + size_t row_bytes = width * bits_per_pixel / 8; //number of bytes in each row + size_t padding = row_bytes % 4; //calculate the padding on disk for each row (rows must be multiples of 4) + + if(file){ + for (size_t h = 0; h < height; h++) { //for each row in the image + file.read(dst + (height - h - 1) * row_bytes, row_bytes); //read the row of image data + file.seekg(padding, std::ios::cur); //seek to the end of the row on disk + if (file.eof()) std::cout << "stim::bmp ERROR: array size incorrect, end of file reached while reading bitmap." << std::endl; + else if (file.fail()) std::cout << "stim::bmp ERROR: reading bitmap array failed." << std::endl; + else if (file.bad()) std::cout << "stim::bmp ERROR: stream integrity failed while reading bitmap array" << std::endl; + } + return true; + } + else{ + std::cout<<"stim::bmp ERROR: could not read array from file."< #include +#include +#include + namespace stim{ /// This static class provides the STIM interface for loading, saving, and storing 2D images. /// Data is stored in an interleaved (BIP) format (default for saving and loading is RGB). @@ -130,6 +133,17 @@ public: return *this; } + void load_bmp(std::string filename) { + stim::bmp bitmap; + bitmap.open(filename); //load the bitmap and read the headers + resize(bitmap.width, bitmap.height, 3); //resize the current image to match the bitmap + if (!bitmap.read((char*)img)) { //read the bits from file + std::cout << "stim::image ERROR: problem loading bitmap image." << std::endl; + exit(1); + } + bitmap.close(); //close the bitmap file + } + //save a Netpbm file void load_netpbm(std::string filename) { std::ifstream infile(filename.c_str(), std::ios::in | std::ios::binary); //open an output file @@ -226,7 +240,11 @@ public: if(C() == 3) //if this is a 3-color image, OpenCV uses BGR interleaving from_opencv(cv_ptr, X(), Y()); #else - load_netpbm(filename); + stim::filename file(filename); + if (file.extension() == "ppm") + load_netpbm(filename); + else if (file.extension() == "bmp") + load_bmp(filename); #endif } @@ -258,6 +276,10 @@ public: outfile.close(); } + void save_bmp(std::string filename) { + stim::save_bmp(filename, (char*)img, width(), height()); + } + //save a file void save(std::string filename){ #ifdef USING_OPENCV @@ -272,7 +294,15 @@ public: cv::imwrite(filename, cvImage); free(buffer); #else - save_netpbm(filename); + stim::filename file(filename); + if (file.extension() == "ppm") + save_netpbm(filename); + else if (file.extension() == "bmp") + save_bmp(filename); + else { + std::cout << "stim::image ERROR: File type not supported without OpenCV. Make sure to link OpenCV and define USING_OPENCV" << std::endl; + exit(1); + } #endif } @@ -399,8 +429,8 @@ public: image result = *this; //create a new image for output size_t N = size(); //get the number of values in the image - double range = maxval - minval; //calculate the current range of the image - double desired_range = high - low; //calculate the desired range of the image + T range = maxval - minval; //calculate the current range of the image + T desired_range = high - low; //calculate the desired range of the image for (size_t n = 0; n < N; n++) { //for each element in the image result.data()[n] = desired_range * (img[n] - minval) / range + low; } -- libgit2 0.21.4