diff --git a/stim/envi/binary.h b/stim/envi/binary.h index b597745..7b5a730 100644 --- a/stim/envi/binary.h +++ b/stim/envi/binary.h @@ -285,7 +285,6 @@ public: if(PROGRESS) progress = (double)(i+1) / N * 100; } - if(PROGRESS) progress = 100; return true; diff --git a/stim/envi/bip.h b/stim/envi/bip.h index 1dc0925..678201d 100644 --- a/stim/envi/bip.h +++ b/stim/envi/bip.h @@ -8,8 +8,10 @@ #include //CUDA -#include -#include "cublas_v2.h" +#ifdef CUDA_FOUND + #include + #include "cublas_v2.h" +#endif namespace stim{ @@ -31,82 +33,10 @@ protected: //std::vector w; //band wavelength unsigned long long offset; //header offset - /*unsigned long long X(){ - return R[1]; - } - unsigned long long Y(){ - return R[2]; - } - unsigned long long Z(){ - return R[0]; - }*/ using hsi::w; //use the wavelength array in stim::hsi using hsi::nnz; using binary::progress; - - /// Call the binary nnz() function for the BIP orientation - //unsigned long long nnz(unsigned char* mask){ - // return binary::nnz(mask, X()*Y()); - //} - - /// Linear interpolation of a spectral value given the bounding spectral samples - /*T lerp(double w, T low_v, double low_w, T high_v, double high_w){ - if(low_w == high_w) return low_v; //if the interval is of zero length, just return one of the bounds - double alpha = (w - low_w) / (high_w - low_w); //calculate the interpolation factor - return (1.0 - alpha) * low_v + alpha * high_v; //interpolate - } - - /// Gets the two band indices surrounding a given wavelength - void band_bounds(double wavelength, unsigned long long& low, unsigned long long& high){ - unsigned long long B = Z(); - for(high = 0; high < B; high++){ - if(w[high] > wavelength) break; - } - low = 0; - if(high > 0) - low = high-1; - } - - /// Get the list of band numbers that bound a list of wavelengths - void band_bounds(std::vector wavelengths, - std::vector& low_bands, - std::vector& high_bands){ - - unsigned long long W = w.size(); //get the number of wavelengths in the list - low_bands.resize(W); //pre-allocate space for the band lists - high_bands.resize(W); - - for(unsigned long long wl = 0; wl < W; wl++){ //for each wavelength - band_bounds(wavelengths[wl], low_bands[wl], high_bands[wl]); //find the low and high bands - } - } - - /// Returns the interpolated in the given spectrum based on the given wavelength - - /// @param s is the spectrum in main memory of length Z() - /// @param wavelength is the wavelength value to interpolate out - T interp_spectrum(T* s, double wavelength){ - unsigned long long low, high; //indices for the bands surrounding wavelength - band_bounds(wavelength, low, high); //get the surrounding band indices - - if(high == w.size()) return s[w.size()-1]; //if the high band is above the wavelength range, return the highest wavelength value - - return lerp(wavelength, s[low], w[low], s[high], w[high]); - } - - /// Returns the interpolated value corresponding to the given list of wavelengths - std::vector interp_spectrum(T* s, std::vector wavelengths){ - - unsigned long long N = wavelengths.size(); //get the number of wavelength measurements - - std::vector v; //allocate space for the resulting values - v.resize(wavelengths.size()); - for(unsigned long long n = 0; n < N; n++){ //for each measurement - v[n] = interp_spectrum(s, wavelengths[n]); //interpolate the measurement - } - return v; - }*/ - + public: using binary::open; @@ -199,7 +129,6 @@ public: { band_index(p, page, PROGRESS); } - return true; } @@ -899,7 +828,7 @@ public: return true; } - bool unsift(std::string outfile, unsigned char* mask, unsigned long long samples, unsigned long long lines){ + bool unsift(std::string outfile, unsigned char* mask, unsigned long long samples, unsigned long long lines, bool PROGRESS = false){ // open an output stream std::ofstream target(outfile.c_str(), std::ios::binary); @@ -938,7 +867,7 @@ public: target.write((char *)spectrum, B * sizeof(T)); } - progress = (double)x / XY * 100; + if(PROGRESS) progress = (double)(x + 1) / XY * 100; } @@ -946,7 +875,7 @@ public: target.close(); free(spectrum); - progress = 100; + //progress = 100; return true; diff --git a/stim/envi/bsq.h b/stim/envi/bsq.h index 81f1dd3..958517c 100644 --- a/stim/envi/bsq.h +++ b/stim/envi/bsq.h @@ -765,13 +765,7 @@ public: unsigned long long L = XY * sizeof(T); //size of XY plane (in bytes) //calculate the number of pixels in the mask - unsigned long long P = 0; - if(mask == NULL) P = XY; - else{ - for(unsigned long long xy = 0; xy < XY; xy++){ - if(mask[xy] != 0) P++; - } - } + //unsigned long long P = nnz(mask); T* band_image = (T*) malloc( XY * sizeof(T)); //allocate space for a single band @@ -784,7 +778,9 @@ public: if(mask == NULL || mask[xy] != 0){ //if the pixel is valid matrix[i*Z() + b] = band_image[xy]; //copy it to the appropriate point in the values[] array i++; + //std::cout< threshold (preventing division by small numbers) bool normalize(std::string outfile, double band, unsigned char* mask = NULL, bool PROGRESS = false){ - + header.save(outfile + ".hdr"); if(header.interleave == envi_header::BSQ){ //if the infile is bsq file if(header.data_type ==envi_header::float32) return ((bsq*)file)->normalize(outfile, band, mask, PROGRESS); @@ -355,17 +355,17 @@ public: /// @param outfile is the file name for the converted output /// @param interleave is the interleave format for the destination file bool convert(std::string outfile, stim::envi_header::interleaveType interleave, bool PROGRESS = false){ - + if(header.interleave == envi_header::BSQ){ //if the infile is bsq file - if(header.data_type ==envi_header::float32){ //if the data type of infile is float + if(header.data_type ==envi_header::float32){ //ERROR if(interleave == envi_header::BSQ){ std::cout<<"ERROR: is already BSQ file"<*)file)->bil(outfile, PROGRESS); - else if(interleave == envi_header::BIP){ //if the target file is bip file + else if(interleave == envi_header::BIL) //convert BSQ -> BIL + ((bsq*)file)->bil(outfile, PROGRESS); + else if(interleave == envi_header::BIP){ //ERROR std::cout<<"ERROR: conversion from BSQ to BIP isn't practical; use BSQ->BIL->BIP instead"<*)file)->bip(outfile, PROGRESS); exit(1); @@ -373,13 +373,13 @@ public: } else if(header.data_type == envi_header::float64){ //if the data type is float - if(interleave == envi_header::BSQ){ + if(interleave == envi_header::BSQ){ //ERROR std::cout<<"ERROR: is already BSQ file"<*)file)->bil(outfile, PROGRESS); - else if(interleave == envi_header::BIP){ //if the target file is bip file + else if(interleave == envi_header::BIL) //convert BSQ -> BIL + ((bsq*)file)->bil(outfile, PROGRESS); + else if(interleave == envi_header::BIP){ //ERROR std::cout<<"ERROR: conversion from BSQ to BIP isn't practical; use BSQ->BIL->BIP instead"<*)file)->bip(outfile, PROGRESS); exit(1); @@ -394,26 +394,26 @@ public: else if(header.interleave == envi_header::BIL){ - if(header.data_type ==envi_header::float32){ //if the data type of infile is float + if(header.data_type ==envi_header::float32){ //ERROR if(interleave == envi_header::BIL){ std::cout<<"ERROR: is already BIL file"<*)file)->bsq(outfile, PROGRESS); - else if(interleave == envi_header::BIP) //if the target file is bip file - return ((bil*)file)->bip(outfile, PROGRESS); + else if(interleave == envi_header::BSQ) //BIL -> BSQ + ((bil*)file)->bsq(outfile, PROGRESS); + else if(interleave == envi_header::BIP) //BIL -> BIP + ((bil*)file)->bip(outfile, PROGRESS); } - else if(header.data_type == envi_header::float64){ //if the data type is float - if(interleave == envi_header::BIL){ + else if(header.data_type == envi_header::float64){ + if(interleave == envi_header::BIL){ //ERROR std::cout<<"ERROR: is already BIL file"<*)file)->bsq(outfile, PROGRESS); - else if(interleave == envi_header::BIP) - return ((bil*)file)->bip(outfile, PROGRESS); + else if(interleave == envi_header::BSQ) //BIL -> BSQ + ((bil*)file)->bsq(outfile, PROGRESS); + else if(interleave == envi_header::BIP) //BIL -> BIP + ((bil*)file)->bip(outfile, PROGRESS); } else{ @@ -424,28 +424,28 @@ public: else if(header.interleave == envi_header::BIP){ - if(header.data_type ==envi_header::float32){ //if the data type of infile is float - if(interleave == envi_header::BIP){ + if(header.data_type ==envi_header::float32){ + if(interleave == envi_header::BIP){ //ERROR std::cout<<"ERROR: is already BIP file"<*)file)->bil(outfile, PROGRESS); - else if(interleave == envi_header::BSQ){ //if the target file is bip file + else if(interleave == envi_header::BIL) //BIP -> BIL + ((bip*)file)->bil(outfile, PROGRESS); + else if(interleave == envi_header::BSQ){ //ERROR std::cout<<"ERROR: conversion from BIP to BSQ isn't practical; use BIP->BIL->BSQ instead"<*)file)->bip(outfile, PROGRESS); exit(1); } } - else if(header.data_type == envi_header::float64){ //if the data type is float - if(interleave == envi_header::BIP){ + else if(header.data_type == envi_header::float64){ + if(interleave == envi_header::BIP){ //ERROR std::cout<<"ERROR: is already BIP file"<*)file)->bil(outfile, PROGRESS); - else if(interleave == envi_header::BSQ){ //if the target file is bip file + else if(interleave == envi_header::BIL) //BIP -> BIL + ((bip*)file)->bil(outfile, PROGRESS); + else if(interleave == envi_header::BSQ){ //ERROR std::cout<<"ERROR: conversion from BIP to BSQ isn't practical; use BIP->BIL->BSQ instead"<*)file)->bip(outfile, PROGRESS); exit(1); @@ -462,7 +462,11 @@ public: std::cout<<"ERROR: unidentified interleave type"<*)file)->apply_mask(outfile, p); @@ -630,7 +634,7 @@ public: return false; } - bool unsift(std::string outfile, unsigned char* mask, unsigned long long samples, unsigned long long lines){ + bool unsift(std::string outfile, unsigned char* mask, unsigned long long samples, unsigned long long lines, bool PROGRESS = false){ //create a new header envi_header new_header = header; @@ -643,9 +647,9 @@ public: if (header.interleave == envi_header::BSQ){ //if the infile is bsq file if (header.data_type == envi_header::float32) - return ((bsq*)file)->unsift(outfile, mask, samples, lines); + return ((bsq*)file)->unsift(outfile, mask, samples, lines, PROGRESS); else if (header.data_type == envi_header::float64) - return ((bsq*)file)->unsift(outfile, mask, samples, lines); + return ((bsq*)file)->unsift(outfile, mask, samples, lines, PROGRESS); else std::cout << "ERROR: unidentified data type" << std::endl; } @@ -658,9 +662,9 @@ public: else if (header.interleave == envi_header::BIP){ //if the infile is bip file if (header.data_type == envi_header::float32) - return ((bip*)file)->unsift(outfile, mask, samples, lines); + return ((bip*)file)->unsift(outfile, mask, samples, lines, PROGRESS); else if (header.data_type == envi_header::float64) - return ((bip*)file)->unsift(outfile, mask, samples, lines); + return ((bip*)file)->unsift(outfile, mask, samples, lines, PROGRESS); else std::cout << "ERROR: unidentified data type" << std::endl; } diff --git a/stim/envi/envi_header.h b/stim/envi/envi_header.h index 163ee3a..436de16 100644 --- a/stim/envi/envi_header.h +++ b/stim/envi/envi_header.h @@ -411,6 +411,26 @@ struct envi_header } } + + /// Convert an interleave type to a string + static std::string interleave_str(interleaveType t){ + switch(t){ + case stim::envi_header::BSQ: + return std::string("BSQ"); + case stim::envi_header::BIL: + return std::string("BIL"); + case stim::envi_header::BIP: + return std::string("BIP"); + default: + std::cout<<"ERROR in stim::envi_header::typestr() - unrecognized type"< #include #include +#include namespace stim{ /// This static class provides the STIM interface for loading, saving, and storing 2D images. @@ -19,9 +20,9 @@ class image{ T* img; //pointer to the image data (assumes RGB for loading/saving) size_t R[3]; - size_t X(){ return R[1]; } - size_t Y(){ return R[2]; } - size_t C(){ return R[0]; } + size_t X() const { return R[1]; } + size_t Y() const { return R[2]; } + size_t C() const { return R[0]; } void init(){ //initializes all variables, assumes no memory is allocated memset(R, 0, sizeof(size_t) * 3); //set the resolution and number of channels to zero @@ -67,40 +68,87 @@ class image{ exit(1); } + /// Returns the value for "white" based on the dynamic range (assumes white is 1.0 for floating point images) + T white(){ + if(std::is_same::value) return UCHAR_MAX; + if(std::is_same::value) return SHRT_MAX; + if(std::is_same::value) return UINT_MAX; + if(std::is_same::value) return ULONG_MAX; + if(std::is_same::value) return ULLONG_MAX; + if(std::is_same::value) return 1.0f; + if(std::is_same::value) return 1.0; + + std::cout<<"ERROR in stim::image::white - no white value known for this data type"<& I){ + allocate(I.X(), I.Y(), I.C()); + //allocate(I.R[1], I.R[2], I.R[0]); + memcpy(img, I.img, bytes()); + } + + /// Destructor - clear memory + ~image(){ + free(img); + } + + stim::image operator=(const stim::image& I){ + if(&I == this) //handle self-assignment + return *this; + allocate(I.X(), I.Y(), I.C()); + memcpy(img, I.img, bytes()); + return *this; + } + /// Load an image from a file void load(std::string filename){ cv::Mat cvImage = cv::imread(filename, CV_LOAD_IMAGE_UNCHANGED); //use OpenCV to open the image file + if(!cvImage.data){ + std::cout<<"ERROR stim::image::load() - unable to find image "< channel(size_t c){ //create a new image - image r(R[0], R[1], 1); + image r(X(), Y(), 1); for(size_t x = 0; x < X(); x++){ for(size_t y = 0; y < Y(); y++){ @@ -266,6 +314,16 @@ public: return max; } + /// Invert an image by calculating I1 = alpha - I0, where alpha is the maximum image value + image invert(T white_val){ + size_t N = size(); //calculate the total number of values in the image + image r(X(), Y(), C()); //allocate space for the resulting image + for(size_t n = 0; n < N; n++) + r.img[n] = white_val - img[n]; //perform the inversion + + return r; //return the inverted image + } + image srgb2lab(){ std::cout<<"ERROR stim::image::srgb2lab - function has been broken, re-implement."< #include +#include + +#ifdef _WIN32 + #include +#endif + #ifdef __CUDACC__ #include #endif @@ -226,8 +232,13 @@ static void cpuApplyBrewer(T* cpuSource, unsigned char* cpuDest, size_t N, T min a = (cpuSource[i] - minVal) / (maxVal - minVal); else a = 0.5; - if(a < 0) a = 0; - if(a > 1) a = 1; +#ifdef _WIN32 + if(!_finite(a)) a = 1; //deal with infinite and NaN values (return maximum in all cases) +#else + if(!std::isfinite(a)) a = 1; +#endif + else if(a < 0) a = 0; + else if(a > 1) a = 1; float c = a * (float)(BREWER_CTRL_PTS-1); int ptLow = (int)c; -- libgit2 0.21.4