Commit 2ce6954b27ac5f17bff82a432b3ec70b65fc20f9

Authored by David Mayerich
1 parent dc8eb8aa

added the ability to combine images

stim/envi/bil.h
... ... @@ -1127,6 +1127,54 @@ public:
1127 1127 free(line);
1128 1128 }
1129 1129  
  1130 + /// Combine two BSQ images along the Y axis
  1131 +
  1132 + /// @param outfile is the combined file to be output
  1133 + /// @param infile is the input file stream for the image to combine with this one
  1134 + /// @param Sx is the size of the second image along X
  1135 + /// @param Sy is the size of the second image along Y
  1136 + /// @param offset is a shift (negative or positive) in the combined image to the left or right
  1137 + void combine(std::string outfile, bil<T>* C, long long xp, long long yp, bool PROGRESS = false){
  1138 + std::ofstream out(outfile.c_str(), std::ios::binary); //open the output file for writing
  1139 + file.seekg(0, std::ios::beg); //move to the beginning of both files
  1140 + C->file.seekg(0, std::ios::beg);
  1141 +
  1142 + size_t S[2]; //size of the output band image
  1143 + size_t p0[2]; //position of the current image in the output
  1144 + size_t p1[2]; //position of the source image in the output
  1145 +
  1146 + hsi<T>::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
  1147 +
  1148 + size_t line_bytes = X() * sizeof(T);
  1149 + size_t band_bytes = X() * Y() * sizeof(T);
  1150 + T* cur = (T*)malloc(line_bytes); //allocate space for a band of the current image
  1151 +
  1152 + size_t line_src_bytes = C->X() * sizeof(T);
  1153 + size_t band_src_bytes = C->X() * C->Y() * sizeof(T);
  1154 + T* src = (T*)malloc(line_src_bytes); //allocate space for a band of the source image
  1155 +
  1156 + size_t line_dst_bytes = S[0] * sizeof(T);
  1157 + size_t band_dst_bytes = S[0] * S[1] * sizeof(T);
  1158 + T* dst = (T*)malloc(line_dst_bytes); //allocate space for a band of the destination image
  1159 +
  1160 + for(size_t y = 0; y < S[1]; y++){ //for each line in the destination file
  1161 + memset(dst, 0, line_dst_bytes); //set all values to zero (0) in the destination image
  1162 + for(size_t b = 0; b < Z(); b++){ //for each band in both images
  1163 + if(y >= p0[1] && y < p0[1] + Y()){ //if the current image crosses this line
  1164 + file.read((char*)cur, line_bytes); //read a line from the current image
  1165 + memcpy(&dst[p0[0]], cur, line_bytes); //copy the current line to the correct spot in the destination line
  1166 + }
  1167 + if(y >= p1[1] && y < p1[1] + C->Y()){ //if the source image crosses this line
  1168 + C->file.read((char*)src, line_src_bytes); //read a line from the source image
  1169 + memcpy(&dst[p1[0]], src, line_src_bytes); //copy the source line into the correct spot in the destination line
  1170 + }
  1171 + out.write((char*)dst, line_dst_bytes);
  1172 + if(PROGRESS) progress = (double)((y + 1)*Z() + b + 1) / (double) (Z() * S[1]) * 100;
  1173 + }
  1174 + }
  1175 + }
  1176 +
  1177 +
1130 1178  
1131 1179 /// Close the file.
1132 1180 bool close(){
... ...
stim/envi/bip.h
... ... @@ -1215,6 +1215,41 @@ public:
1215 1215 free(dst);
1216 1216 }
1217 1217  
  1218 + /// Combine two BIP images along the Y axis
  1219 +
  1220 + /// @param outfile is the combined file to be output
  1221 + /// @param infile is the input file stream for the image to combine with this one
  1222 + /// @param Sx is the size of the second image along X
  1223 + /// @param Sy is the size of the second image along Y
  1224 + /// @param offset is a shift (negative or positive) in the combined image to the left or right
  1225 + void combine(std::string outfile, bip<T>* C, long long xp, long long yp, bool PROGRESS = false){
  1226 + std::ofstream out(outfile.c_str(), std::ios::binary); //open the output file for writing
  1227 + file.seekg(0, std::ios::beg); //move to the beginning of both files
  1228 + C->file.seekg(0, std::ios::beg);
  1229 +
  1230 + size_t S[2]; //size of the output band image
  1231 + size_t p0[2]; //position of the current image in the output
  1232 + size_t p1[2]; //position of the source image in the output
  1233 +
  1234 + hsi<T>::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
  1235 +
  1236 + size_t spec_bytes = Z() * sizeof(T); //calculate the number of bytes in a spectrum
  1237 + T* spec = (T*)malloc(spec_bytes); //allocate space for a spectrum
  1238 +
  1239 + for(size_t y = 0; y < S[1]; y++){ //for each pixel in the destination image
  1240 + for(size_t x = 0; x < S[0]; x++){
  1241 + if(x >= p0[0] && x < p0[0] + X() && y >= p0[1] && y < p0[1] + Y()) //if this pixel is in the current image
  1242 + file.read((char*)spec, spec_bytes);
  1243 + 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
  1244 + C->file.read((char*)spec, spec_bytes);
  1245 + else
  1246 + memset(spec, 0, spec_bytes);
  1247 + out.write((char*)spec, spec_bytes); //write to the output file
  1248 + }
  1249 + if(PROGRESS) progress = (double)( (y+1) * S[0] + 1) / (double) (S[0] * S[1]) * 100;
  1250 + }
  1251 + }
  1252 +
1218 1253  
1219 1254  
1220 1255 /// Close the file.
... ...
stim/envi/bsq.h
... ... @@ -32,15 +32,6 @@ protected:
32 32  
33 33 using binary<T>::R;
34 34  
35   - /*unsigned long long X(){
36   - return R[0];
37   - }
38   - unsigned long long Y(){
39   - return R[1];
40   - }
41   - unsigned long long Z(){
42   - return R[2];
43   - }*/
44 35 using hsi<T>::w; //use the wavelength array in stim::hsi
45 36 using hsi<T>::nnz;
46 37 using binary<T>::progress;
... ... @@ -1025,6 +1016,51 @@ public:
1025 1016 free(temp); //free the scratch space for the band
1026 1017 }
1027 1018  
  1019 + /// Combine two BSQ images along the Y axis
  1020 +
  1021 + /// @param outfile is the combined file to be output
  1022 + /// @param infile is the input file stream for the image to combine with this one
  1023 + /// @param Sx is the size of the second image along X
  1024 + /// @param Sy is the size of the second image along Y
  1025 + /// @param offset is a shift (negative or positive) in the combined image to the left or right
  1026 + void combine(std::string outfile, bsq<T>* C, long long xp, long long yp, bool PROGRESS = false){
  1027 + std::ofstream out(outfile.c_str(), std::ios::binary); //open the output file for writing
  1028 + file.seekg(0, std::ios::beg); //move to the beginning of both files
  1029 + C->file.seekg(0, std::ios::beg);
  1030 +
  1031 + size_t S[2]; //size of the output band image
  1032 + size_t p0[2]; //position of the current image in the output
  1033 + size_t p1[2]; //position of the source image in the output
  1034 +
  1035 + hsi<T>::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
  1036 +
  1037 + size_t line_bytes = X() * sizeof(T);
  1038 + size_t band_bytes = X() * Y() * sizeof(T);
  1039 + T* cur = (T*)malloc(X() * Y() * sizeof(T)); //allocate space for a band of the current image
  1040 +
  1041 + size_t line_src_bytes = C->X() * sizeof(T);
  1042 + size_t band_src_bytes = C->X() * C->Y() * sizeof(T);
  1043 + T* src = (T*)malloc(C->X() * C->Y() * sizeof(T)); //allocate space for a band of the source image
  1044 +
  1045 + size_t line_dst_bytes = S[0] * sizeof(T);
  1046 + size_t band_dst_bytes = S[0] * S[1] * sizeof(T);
  1047 + T* dst = (T*)malloc(band_dst_bytes); //allocate space for a band of the destination image
  1048 + memset(dst, 0, band_dst_bytes); //set all values to zero (0) in the destination image
  1049 +
  1050 + for(size_t b = 0; b < Z(); b++){ //for each band in both images
  1051 + file.read((char*)cur, band_bytes); //read a band from the current image
  1052 + C->file.read((char*)src, band_src_bytes); //read a band from the source image
  1053 + for(size_t y = 0; y < Y(); y++)
  1054 + memcpy( &dst[ (p0[1]+y) * S[0] + p0[0] ], &cur[ y * X() ], line_bytes); //copy the line from the current to the destination image
  1055 + //memset( &dst[ (p0[1]+y) * S[0] + p0[0] ], 0, line_dst_bytes);
  1056 + for(size_t y = 0; y < C->Y(); y++)
  1057 + 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
  1058 + out.write((char*)dst, band_dst_bytes); //write the combined image to an output file
  1059 + if(PROGRESS) progress = (double)(b + 1) / (double) Z() * 100;
  1060 + }
  1061 +
  1062 + }
  1063 +
1028 1064  
1029 1065 /// Close the file.
1030 1066 bool close(){
... ...
stim/envi/envi.h
... ... @@ -1293,6 +1293,54 @@ public:
1293 1293  
1294 1294 }
1295 1295  
  1296 + /// Combine two ENVI images along the Y axis
  1297 +
  1298 + /// @param outfile is the combined file to be output
  1299 + /// @param C is the ENVI object for the image to be combined
  1300 + void combine(std::string outfile, envi C, long long x, long long y, bool PROGRESS = false){
  1301 + envi_header h = header;
  1302 +
  1303 + long long left = std::min<long long>(0, x); //calculate the left edge of the final image
  1304 + long long right = std::max<long long>((long long)header.samples, C.header.samples + x); //calculate the right edge of the final image
  1305 + long long top = std::min<long long>(0, y); //calculate the top edge of the final image
  1306 + long long bottom = std::max<long long>((long long)header.lines, C.header.lines + y); //calculate the bottom edge of the final image
  1307 +
  1308 + h.samples = right - left;
  1309 + h.lines = bottom - top;
  1310 +
  1311 + h.save(outfile + ".hdr");
  1312 +
  1313 + if (header.interleave == envi_header::BSQ){
  1314 + if (header.data_type == envi_header::float32)
  1315 + ((bsq<float>*)file)->combine(outfile, (bsq<float>*)C.file, x, y, PROGRESS);
  1316 + else if (header.data_type == envi_header::float64)
  1317 + ((bsq<double>*)file)->combine(outfile, (bsq<double>*)C.file, x, y, PROGRESS);
  1318 + else{
  1319 + std::cout << "ERROR: unidentified data type" << std::endl;
  1320 + exit(1);
  1321 + }
  1322 + }
  1323 + else if (header.interleave == envi_header::BIL){
  1324 + if (header.data_type == envi_header::float32)
  1325 + ((bil<float>*)file)->combine(outfile, (bil<float>*)C.file, x, y, PROGRESS);
  1326 + else if (header.data_type == envi_header::float64)
  1327 + ((bil<double>*)file)->combine(outfile, (bil<double>*)C.file, x, y, PROGRESS);
  1328 + else{
  1329 + std::cout << "ERROR: unidentified data type" << std::endl;
  1330 + exit(1);
  1331 + }
  1332 + }
  1333 + else if (header.interleave == envi_header::BIP){
  1334 + if (header.data_type == envi_header::float32)
  1335 + ((bip<float>*)file)->combine(outfile, (bip<float>*)C.file, x, y, PROGRESS);
  1336 + else if (header.data_type == envi_header::float64)
  1337 + ((bip<double>*)file)->combine(outfile, (bip<double>*)C.file, x, y, PROGRESS);
  1338 + else{
  1339 + std::cout << "ERROR: unidentified data type" << std::endl;
  1340 + exit(1);
  1341 + }
  1342 + }
  1343 + }
1296 1344 };
1297 1345  
1298 1346 } //end namespace rts
... ...
stim/envi/hsi.h
... ... @@ -159,6 +159,46 @@ public:
159 159 }
160 160 }
161 161  
  162 + void calc_combined_size(long long xp, long long yp, long long Sx, long long Sy,
  163 + size_t& Sfx, size_t& Sfy){
  164 + long long left = std::min<long long>(0, xp); //calculate the left edge of the final image
  165 + long long right = std::max<long long>((long long)X(), Sx + xp); //calculate the right edge of the final image
  166 + long long top = std::min<long long>(0, yp); //calculate the top edge of the final image
  167 + long long bottom = std::max<long long>((long long)Y(), Sy + yp); //calculate the bottom edge of the final image
  168 +
  169 + Sfx = right - left;
  170 + Sfy = bottom - top; //calculate the size of the final image
  171 + }
  172 +
  173 + /// Calculates the necessary image size required to combine two images given the specified offset (position) of the second image
  174 + void calc_combined_size(long long xp, long long yp, long long Sx, long long Sy,
  175 + size_t& Sfx, size_t& Sfy,
  176 + size_t& p0_x, size_t& p0_y,
  177 + size_t& p1_x, size_t& p1_y){
  178 +
  179 + calc_combined_size(xp, yp, Sx, Sy, Sfx, Sfy);
  180 +
  181 + p0_x = p0_y = p1_x = p1_y = 0; //initialize all boundary positions to zero
  182 +
  183 + if(xp < 0) p0_x = -xp; //set the left positions of the current and source image
  184 + else p1_x = xp;
  185 + if(yp < 0) p0_y = -yp;
  186 + else p1_y = yp;
  187 + }
  188 +
  189 + /// Inserts an image of a band into a larger image
  190 + void pad_band(T* padded, T* src, size_t x0, size_t x1, size_t y0, size_t y1){
  191 +
  192 + size_t w = X(); //calculate the number of pixels in a line
  193 + size_t wb = w * sizeof(T); //calculate the number of bytes in a line
  194 + pw = (X() + x0 + x1); //calculate the width of the padded image
  195 + pwb = pw * sizeof(T); //calculate the number of bytes in a line of the padded image
  196 +
  197 + for(size_t y = 0; y < Y(); y++){ //for each line in the real image
  198 + memcpy( &padded[ (y + y0) * pw + x0 ], &src[y * w], wb ); //use memcpy to copy the line to the appropriate place in the padded image
  199 + }
  200 + }
  201 +
162 202 };
163 203  
164 204 } //end namespace STIM
... ...