Commit 2ce6954b27ac5f17bff82a432b3ec70b65fc20f9
1 parent
dc8eb8aa
added the ability to combine images
Showing
5 changed files
with
216 additions
and
9 deletions
Show diff stats
stim/envi/bil.h
@@ -1127,6 +1127,54 @@ public: | @@ -1127,6 +1127,54 @@ public: | ||
1127 | free(line); | 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 | /// Close the file. | 1179 | /// Close the file. |
1132 | bool close(){ | 1180 | bool close(){ |
stim/envi/bip.h
@@ -1215,6 +1215,41 @@ public: | @@ -1215,6 +1215,41 @@ public: | ||
1215 | free(dst); | 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 | /// Close the file. | 1255 | /// Close the file. |
stim/envi/bsq.h
@@ -32,15 +32,6 @@ protected: | @@ -32,15 +32,6 @@ protected: | ||
32 | 32 | ||
33 | using binary<T>::R; | 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 | using hsi<T>::w; //use the wavelength array in stim::hsi | 35 | using hsi<T>::w; //use the wavelength array in stim::hsi |
45 | using hsi<T>::nnz; | 36 | using hsi<T>::nnz; |
46 | using binary<T>::progress; | 37 | using binary<T>::progress; |
@@ -1025,6 +1016,51 @@ public: | @@ -1025,6 +1016,51 @@ public: | ||
1025 | free(temp); //free the scratch space for the band | 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 | /// Close the file. | 1065 | /// Close the file. |
1030 | bool close(){ | 1066 | bool close(){ |
stim/envi/envi.h
@@ -1293,6 +1293,54 @@ public: | @@ -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 | } //end namespace rts | 1346 | } //end namespace rts |
stim/envi/hsi.h
@@ -159,6 +159,46 @@ public: | @@ -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 | } //end namespace STIM | 204 | } //end namespace STIM |