diff --git a/stim/envi/bil.h b/stim/envi/bil.h index cdae1af..0d7412a 100644 --- a/stim/envi/bil.h +++ b/stim/envi/bil.h @@ -1127,6 +1127,54 @@ public: free(line); } + /// Combine two BSQ images along the Y axis + + /// @param outfile is the combined file to be output + /// @param infile is the input file stream for the image to combine with this one + /// @param Sx is the size of the second image along X + /// @param Sy is the size of the second image along Y + /// @param offset is a shift (negative or positive) in the combined image to the left or right + void combine(std::string outfile, bil* C, long long xp, long long yp, bool PROGRESS = false){ + std::ofstream out(outfile.c_str(), std::ios::binary); //open the output file for writing + file.seekg(0, std::ios::beg); //move to the beginning of both files + C->file.seekg(0, std::ios::beg); + + size_t S[2]; //size of the output band image + size_t p0[2]; //position of the current image in the output + size_t p1[2]; //position of the source image in the output + + hsi::calc_combined_size(xp, yp, C->X(), C->Y(), S[0], S[1], p0[0], p0[1], p1[0], p1[1]); //calculate the image placement parameters + + size_t line_bytes = X() * sizeof(T); + size_t band_bytes = X() * Y() * sizeof(T); + T* cur = (T*)malloc(line_bytes); //allocate space for a band of the current image + + size_t line_src_bytes = C->X() * sizeof(T); + size_t band_src_bytes = C->X() * C->Y() * sizeof(T); + T* src = (T*)malloc(line_src_bytes); //allocate space for a band of the source image + + size_t line_dst_bytes = S[0] * sizeof(T); + size_t band_dst_bytes = S[0] * S[1] * sizeof(T); + T* dst = (T*)malloc(line_dst_bytes); //allocate space for a band of the destination image + + for(size_t y = 0; y < S[1]; y++){ //for each line in the destination file + memset(dst, 0, line_dst_bytes); //set all values to zero (0) in the destination image + for(size_t b = 0; b < Z(); b++){ //for each band in both images + if(y >= p0[1] && y < p0[1] + Y()){ //if the current image crosses this line + file.read((char*)cur, line_bytes); //read a line from the current image + memcpy(&dst[p0[0]], cur, line_bytes); //copy the current line to the correct spot in the destination line + } + if(y >= p1[1] && y < p1[1] + C->Y()){ //if the source image crosses this line + C->file.read((char*)src, line_src_bytes); //read a line from the source image + memcpy(&dst[p1[0]], src, line_src_bytes); //copy the source line into the correct spot in the destination line + } + out.write((char*)dst, line_dst_bytes); + if(PROGRESS) progress = (double)((y + 1)*Z() + b + 1) / (double) (Z() * S[1]) * 100; + } + } + } + + /// Close the file. bool close(){ diff --git a/stim/envi/bip.h b/stim/envi/bip.h index bd2d264..dbf01a4 100644 --- a/stim/envi/bip.h +++ b/stim/envi/bip.h @@ -1215,6 +1215,41 @@ public: free(dst); } + /// Combine two BIP images along the Y axis + + /// @param outfile is the combined file to be output + /// @param infile is the input file stream for the image to combine with this one + /// @param Sx is the size of the second image along X + /// @param Sy is the size of the second image along Y + /// @param offset is a shift (negative or positive) in the combined image to the left or right + void combine(std::string outfile, bip* C, long long xp, long long yp, bool PROGRESS = false){ + std::ofstream out(outfile.c_str(), std::ios::binary); //open the output file for writing + file.seekg(0, std::ios::beg); //move to the beginning of both files + C->file.seekg(0, std::ios::beg); + + size_t S[2]; //size of the output band image + size_t p0[2]; //position of the current image in the output + size_t p1[2]; //position of the source image in the output + + hsi::calc_combined_size(xp, yp, C->X(), C->Y(), S[0], S[1], p0[0], p0[1], p1[0], p1[1]); //calculate the image placement parameters + + size_t spec_bytes = Z() * sizeof(T); //calculate the number of bytes in a spectrum + T* spec = (T*)malloc(spec_bytes); //allocate space for a spectrum + + for(size_t y = 0; y < S[1]; y++){ //for each pixel in the destination image + for(size_t x = 0; x < S[0]; x++){ + if(x >= p0[0] && x < p0[0] + X() && y >= p0[1] && y < p0[1] + Y()) //if this pixel is in the current image + file.read((char*)spec, spec_bytes); + else if(x >= p1[0] && x < p1[0] + C->X() && y >= p1[1] && y < p1[1] + C->Y()) //if this pixel is in the source image + C->file.read((char*)spec, spec_bytes); + else + memset(spec, 0, spec_bytes); + out.write((char*)spec, spec_bytes); //write to the output file + } + if(PROGRESS) progress = (double)( (y+1) * S[0] + 1) / (double) (S[0] * S[1]) * 100; + } + } + /// Close the file. diff --git a/stim/envi/bsq.h b/stim/envi/bsq.h index 272b33a..82a6d6c 100644 --- a/stim/envi/bsq.h +++ b/stim/envi/bsq.h @@ -32,15 +32,6 @@ protected: using binary::R; - /*unsigned long long X(){ - return R[0]; - } - unsigned long long Y(){ - return R[1]; - } - unsigned long long Z(){ - return R[2]; - }*/ using hsi::w; //use the wavelength array in stim::hsi using hsi::nnz; using binary::progress; @@ -1025,6 +1016,51 @@ public: free(temp); //free the scratch space for the band } + /// Combine two BSQ images along the Y axis + + /// @param outfile is the combined file to be output + /// @param infile is the input file stream for the image to combine with this one + /// @param Sx is the size of the second image along X + /// @param Sy is the size of the second image along Y + /// @param offset is a shift (negative or positive) in the combined image to the left or right + void combine(std::string outfile, bsq* C, long long xp, long long yp, bool PROGRESS = false){ + std::ofstream out(outfile.c_str(), std::ios::binary); //open the output file for writing + file.seekg(0, std::ios::beg); //move to the beginning of both files + C->file.seekg(0, std::ios::beg); + + size_t S[2]; //size of the output band image + size_t p0[2]; //position of the current image in the output + size_t p1[2]; //position of the source image in the output + + hsi::calc_combined_size(xp, yp, C->X(), C->Y(), S[0], S[1], p0[0], p0[1], p1[0], p1[1]); //calculate the image placement parameters + + size_t line_bytes = X() * sizeof(T); + size_t band_bytes = X() * Y() * sizeof(T); + T* cur = (T*)malloc(X() * Y() * sizeof(T)); //allocate space for a band of the current image + + size_t line_src_bytes = C->X() * sizeof(T); + size_t band_src_bytes = C->X() * C->Y() * sizeof(T); + T* src = (T*)malloc(C->X() * C->Y() * sizeof(T)); //allocate space for a band of the source image + + size_t line_dst_bytes = S[0] * sizeof(T); + size_t band_dst_bytes = S[0] * S[1] * sizeof(T); + T* dst = (T*)malloc(band_dst_bytes); //allocate space for a band of the destination image + memset(dst, 0, band_dst_bytes); //set all values to zero (0) in the destination image + + for(size_t b = 0; b < Z(); b++){ //for each band in both images + file.read((char*)cur, band_bytes); //read a band from the current image + C->file.read((char*)src, band_src_bytes); //read a band from the source image + for(size_t y = 0; y < Y(); y++) + memcpy( &dst[ (p0[1]+y) * S[0] + p0[0] ], &cur[ y * X() ], line_bytes); //copy the line from the current to the destination image + //memset( &dst[ (p0[1]+y) * S[0] + p0[0] ], 0, line_dst_bytes); + for(size_t y = 0; y < C->Y(); y++) + memcpy( &dst[ (p1[1]+y) * S[0] + p1[0] ], &src[ y * C->X() ], line_src_bytes); //copy the line from the source to the destination image + out.write((char*)dst, band_dst_bytes); //write the combined image to an output file + if(PROGRESS) progress = (double)(b + 1) / (double) Z() * 100; + } + + } + /// Close the file. bool close(){ diff --git a/stim/envi/envi.h b/stim/envi/envi.h index e2f7602..f2add36 100644 --- a/stim/envi/envi.h +++ b/stim/envi/envi.h @@ -1293,6 +1293,54 @@ public: } + /// Combine two ENVI images along the Y axis + + /// @param outfile is the combined file to be output + /// @param C is the ENVI object for the image to be combined + void combine(std::string outfile, envi C, long long x, long long y, bool PROGRESS = false){ + envi_header h = header; + + long long left = std::min(0, x); //calculate the left edge of the final image + long long right = std::max((long long)header.samples, C.header.samples + x); //calculate the right edge of the final image + long long top = std::min(0, y); //calculate the top edge of the final image + long long bottom = std::max((long long)header.lines, C.header.lines + y); //calculate the bottom edge of the final image + + h.samples = right - left; + h.lines = bottom - top; + + h.save(outfile + ".hdr"); + + if (header.interleave == envi_header::BSQ){ + if (header.data_type == envi_header::float32) + ((bsq*)file)->combine(outfile, (bsq*)C.file, x, y, PROGRESS); + else if (header.data_type == envi_header::float64) + ((bsq*)file)->combine(outfile, (bsq*)C.file, x, y, PROGRESS); + else{ + std::cout << "ERROR: unidentified data type" << std::endl; + exit(1); + } + } + else if (header.interleave == envi_header::BIL){ + if (header.data_type == envi_header::float32) + ((bil*)file)->combine(outfile, (bil*)C.file, x, y, PROGRESS); + else if (header.data_type == envi_header::float64) + ((bil*)file)->combine(outfile, (bil*)C.file, x, y, PROGRESS); + else{ + std::cout << "ERROR: unidentified data type" << std::endl; + exit(1); + } + } + else if (header.interleave == envi_header::BIP){ + if (header.data_type == envi_header::float32) + ((bip*)file)->combine(outfile, (bip*)C.file, x, y, PROGRESS); + else if (header.data_type == envi_header::float64) + ((bip*)file)->combine(outfile, (bip*)C.file, x, y, PROGRESS); + else{ + std::cout << "ERROR: unidentified data type" << std::endl; + exit(1); + } + } + } }; } //end namespace rts diff --git a/stim/envi/hsi.h b/stim/envi/hsi.h index 26f6bf1..4a09290 100644 --- a/stim/envi/hsi.h +++ b/stim/envi/hsi.h @@ -159,6 +159,46 @@ public: } } + void calc_combined_size(long long xp, long long yp, long long Sx, long long Sy, + size_t& Sfx, size_t& Sfy){ + long long left = std::min(0, xp); //calculate the left edge of the final image + long long right = std::max((long long)X(), Sx + xp); //calculate the right edge of the final image + long long top = std::min(0, yp); //calculate the top edge of the final image + long long bottom = std::max((long long)Y(), Sy + yp); //calculate the bottom edge of the final image + + Sfx = right - left; + Sfy = bottom - top; //calculate the size of the final image + } + + /// Calculates the necessary image size required to combine two images given the specified offset (position) of the second image + void calc_combined_size(long long xp, long long yp, long long Sx, long long Sy, + size_t& Sfx, size_t& Sfy, + size_t& p0_x, size_t& p0_y, + size_t& p1_x, size_t& p1_y){ + + calc_combined_size(xp, yp, Sx, Sy, Sfx, Sfy); + + p0_x = p0_y = p1_x = p1_y = 0; //initialize all boundary positions to zero + + if(xp < 0) p0_x = -xp; //set the left positions of the current and source image + else p1_x = xp; + if(yp < 0) p0_y = -yp; + else p1_y = yp; + } + + /// Inserts an image of a band into a larger image + void pad_band(T* padded, T* src, size_t x0, size_t x1, size_t y0, size_t y1){ + + size_t w = X(); //calculate the number of pixels in a line + size_t wb = w * sizeof(T); //calculate the number of bytes in a line + pw = (X() + x0 + x1); //calculate the width of the padded image + pwb = pw * sizeof(T); //calculate the number of bytes in a line of the padded image + + for(size_t y = 0; y < Y(); y++){ //for each line in the real image + memcpy( &padded[ (y + y0) * pw + x0 ], &src[y * w], wb ); //use memcpy to copy the line to the appropriate place in the padded image + } + } + }; } //end namespace STIM -- libgit2 0.21.4