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 | 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 | ... | ... |