220 std::map<
int, std::vector<double>>
breaks,
222 std::string filename,
225 std::string tempFolder,
226 std::map<std::string, std::string> driverOptions)
233 std::string projection = std::string(p_raster->
getDataset()->GetProjectionRef());
235 GDALDataset *p_dataset =
nullptr;
237 size_t bandCount =
breaks.size();
238 std::vector<std::vector<double>> bandBreaks;
239 std::vector<std::string> bandNames = p_raster->
getBands();
241 std::vector<helper::RasterBandMetaData> dataBands(bandCount);
242 std::vector<helper::RasterBandMetaData> stratBands(bandCount +
map);
243 std::vector<helper::VRTBandDatasetInfo> VRTBandInfo;
245 bool isMEMDataset = !largeRaster && filename ==
"";
246 bool isVRTDataset = largeRaster && filename ==
"";
248 std::mutex dataBandMutex;
249 std::mutex stratBandMutex;
251 std::vector<std::mutex> stratBandMutexes(isVRTDataset * (bandCount +
map));
254 if (isMEMDataset || isVRTDataset) {
255 driver = isMEMDataset ?
"MEM" :
"VRT";
259 std::filesystem::path filepath = filename;
260 std::string extension = filepath.extension().string();
262 if (extension ==
".tif") {
266 throw std::runtime_error(
"sgs only supports .tif files right now");
271 GDALDataType stratPixelType = GDT_Int8;
272 size_t stratPixelSize = 1;
274 for (
auto const& [key, val] :
breaks) {
280 p_dataBand->
p_band = p_band;
284 p_dataBand->
nan = p_band->GetNoDataValue();
285 p_dataBand->
p_mutex = &dataBandMutex;
289 std::vector<double> valCopy = val;
290 std::sort(valCopy.begin(), valCopy.end());
291 bandBreaks.push_back(valCopy);
294 size_t maxStrata = val.size() + 1;
296 p_stratBand->
name =
"strat_" + bandNames[key];
299 p_stratBand->
p_mutex = &stratBandMutex;
305 else if (isVRTDataset) {
307 p_stratBand->
p_mutex = &stratBandMutexes[band];
310 if (stratPixelSize < p_stratBand->size) {
311 stratPixelSize = p_stratBand->
size;
312 stratPixelType = p_stratBand->
type;
320 std::vector<size_t> multipliers(
breaks.size(), 1);
323 for (
size_t i = 0; i < bandCount - 1; i++) {
324 multipliers[i + 1] = multipliers[i] * (bandBreaks[i].size() + 1);
329 size_t maxStrata = multipliers.back() * (bandBreaks.back().size() + 1);
331 p_stratBand->
name =
"strat_map";
332 p_stratBand->
xBlockSize = dataBands[0].xBlockSize;
333 p_stratBand->
yBlockSize = dataBands[0].yBlockSize;
334 p_stratBand->
p_mutex = &stratBandMutex;
340 else if (isVRTDataset) {
349 p_stratBand->
p_mutex = &stratBandMutexes.back();
352 if (stratPixelSize < p_stratBand->size) {
353 stratPixelSize = p_stratBand->
size;
354 stratPixelType = p_stratBand->
type;
360 if (!isMEMDataset && !isVRTDataset) {
361 bool useTiles = stratBands[0].xBlockSize != width &&
362 stratBands[0].yBlockSize != height;
364 for (
size_t band = 0; band < stratBands.size(); band++) {
365 stratBands[band].size = stratPixelSize;
366 stratBands[band].type = stratPixelType;
367 stratBands[band].p_buffer = !largeRaster ? VSIMalloc3(height, width, stratPixelSize) :
nullptr;
386 pybind11::gil_scoped_acquire acquire;
387 boost::asio::thread_pool pool(threads);
391 int xBlockSize = dataBands[0].xBlockSize;
392 int yBlockSize = dataBands[0].yBlockSize;
394 int xBlocks = (p_raster->
getWidth() + xBlockSize - 1) / xBlockSize;
395 int yBlocks = (p_raster->
getHeight() + yBlockSize - 1) / yBlockSize;
396 int chunkSize = yBlocks / threads;
398 for (
int yBlockStart = 0; yBlockStart < yBlocks; yBlockStart += chunkSize) {
399 int yBlockEnd = std::min(yBlockStart + chunkSize, yBlocks);
401 boost::asio::post(pool, [
413 std::vector<void *> dataBuffers(dataBands.size());
414 std::vector<void *> stratBuffers(stratBands.size());
415 for (
size_t band = 0; band < dataBuffers.size(); band++) {
416 dataBuffers[band] = VSIMalloc3(xBlockSize, yBlockSize, dataBands[band].size);
417 stratBuffers[band] = VSIMalloc3(xBlockSize, yBlockSize, stratBands[band].size);
419 stratBuffers.back() = VSIMalloc3(xBlockSize, yBlockSize, stratBands.back().size);
421 for (
int yBlock = yBlockStart; yBlock < yBlockEnd; yBlock++) {
422 for (
int xBlock = 0; xBlock < xBlocks; xBlock++) {
424 dataBands[0].p_mutex->lock();
425 dataBands[0].p_band->GetActualBlockSize(xBlock, yBlock, &xValid, &yValid);
426 dataBands[0].p_mutex->unlock();
429 for (
size_t band = 0; band < bandCount; band++) {
444 for (
int y = 0; y < yValid; y++) {
445 size_t index =
static_cast<size_t>(y * xBlockSize);
446 for (
int x = 0; x < xValid; x++) {
450 for (
size_t band = 0; band < bandCount; band++) {
465 stratBands.back().type,
477 for (
size_t band = 0; band <= bandCount; band++) {
493 for (
size_t band = 0; band < dataBuffers.size(); band++) {
494 VSIFree(dataBuffers[band]);
495 VSIFree(stratBuffers[band]);
497 VSIFree(stratBuffers.back());
502 for (
size_t band = 0; band < bandCount; band++) {
509 int xBlocks = (p_raster->
getWidth() + xBlockSize - 1) / xBlockSize;
510 int yBlocks = (p_raster->
getHeight() + yBlockSize - 1) / yBlockSize;
511 int chunkSize = yBlocks / threads;
513 for (
int yBlockStart = 0; yBlockStart < yBlocks; yBlockStart += chunkSize) {
514 int yBlockEnd = std::min(yBlocks, yBlockStart + chunkSize);
515 std::vector<double> *p_breaks = &bandBreaks[band];
517 boost::asio::post(pool, [
527 void *p_data = VSIMalloc3(xBlockSize, yBlockSize, p_dataBand->
size);
528 void *p_strat = VSIMalloc3(xBlockSize, yBlockSize, p_stratBand->
size);
531 for (
int yBlock = yBlockStart; yBlock < yBlockEnd; yBlock++) {
532 for (
int xBlock = 0; xBlock < xBlocks; xBlock++) {
534 p_dataBand->
p_band->GetActualBlockSize(xBlock, yBlock, &xValid, &yValid);
551 for (
int y = 0; y < yValid; y++) {
552 size_t index =
static_cast<size_t>(y * xBlockSize);
553 for (
int x = 0; x < xValid; x++) {
554 processPixel(index, p_data, p_dataBand, p_strat, p_stratBand, *p_breaks);
580 pybind11::gil_scoped_release release;
583 size_t pixelCount =
static_cast<size_t>(p_raster->
getWidth()) *
static_cast<size_t>(p_raster->
getHeight());
585 for (
size_t index = 0; index < pixelCount; index++) {
589 for (
size_t band = 0; band < bandCount; band++) {
593 dataBands[band].p_buffer,
595 stratBands[band].p_buffer,
604 stratBands.back().type,
605 stratBands.back().p_buffer,
613 for (
size_t band = 0; band < bandCount; band++) {
614 for (
size_t i = 0; i < pixelCount; i++) {
617 dataBands[band].p_buffer,
619 stratBands[band].p_buffer,
628 if (!isVRTDataset && !isMEMDataset) {
630 for (
size_t band = 0; band < stratBands.size(); band++) {
631 err = stratBands[band].p_band->RasterIO(
637 stratBands[band].p_buffer,
640 stratBands[band].type,
645 throw std::runtime_error(
"error writing band to file.");
653 for (
size_t band = 0; band < VRTBandInfo.size(); band++) {
654 GDALClose(VRTBandInfo[band].p_dataset);
660 std::vector<void *> buffers(stratBands.size());
662 for (
size_t band = 0; band < stratBands.size(); band++) {
663 buffers[band] = stratBands[band].p_buffer;