【问题标题】:GDAL C++ RasterIO by blocksGDAL C++ RasterIO 按块
【发布时间】:2016-08-03 23:21:13
【问题描述】:

我是 gdal 和 c++ 的新手,我正在尝试创建一个按块读取栅格的函数(使用 RasterIO 而不是 ReadBlock)对值执行某些操作并将结果写入新的栅格文件

我收到一个错误:

Test.exe 中 0x00007FFDFB517BC4 (gdal201.dll) 处未处理的异常: 0xC0000005:访问冲突写入位置 0x00000230E2593000 在 行 rasterBand->RasterIO(GDALRWFlag::GF_Read, j * readCols, i * readRows、readCols、readRows、rasterBlock、readCols、readRows、 GDALDataType::GDT_CFloat32, 0, 0)

我有一个非常相似的函数可以正常工作,但它会逐行读取像素值

感谢任何帮助

函数如下

谢谢

#include <iostream>
#include "gdal_priv.h"
using namespace std;

void SlopeBlock()
{
int readRows = 2048;
int readCols = 2048;
int nBlockXSize;
int nBlockYSize;
int rowOff = 0;
int colOff = 0;
int nRows = 0;
int nCols = 0;
double noData = -9999;

GDALAllRegister();

GDALDataset* dem = (GDALDataset*)GDALOpen("path/EUD_CP-DEMS_4500025000-AA.tif", GA_ReadOnly);

GDALDriver *gTIF = GetGDALDriverManager()->GetDriverByName(dem->GetDriverName());

double geoTransform[6];
dem->GetGeoTransform(geoTransform);

GDALRasterBand* rasterBand = dem->GetRasterBand(1);

nCols = rasterBand->GetXSize();
nRows = rasterBand->GetYSize();
noData = rasterBand->GetNoDataValue();

//rasterBand->GetBlockSize(&nBlockXSize, &nBlockYSize);

int nXBlocks = (rasterBand->GetXSize() + readCols - 1) / readCols;
int nYBlocks = (rasterBand->GetYSize() + readRows - 1) / readRows;

cout << nYBlocks << "___" << nXBlocks << "\n";


//Slope
GDALDataset *slope = gTIF->Create("path/slopeBlock.tif", nCols, nRows, 1, GDT_Float32, NULL);
slope->SetGeoTransform(geoTransform);

for (int i = 0; i < nYBlocks; i++)
{
    for (int j = 0; j < nXBlocks; j++)
    {
        float* rasterBlock = (float*)CPLMalloc(readCols*readRows*sizeof(float));
        float* rasterBlockOut = (float*)CPLMalloc(readCols*readRows*sizeof(float));

        if (rasterBand != nullptr)
            rasterBand->RasterIO(GDALRWFlag::GF_Read, j * readCols, i * readRows, readCols, readRows, rasterBlock, readCols, readRows, GDALDataType::GDT_CFloat32, 0, 0);

        //Not sure if is working
        for (int jb = 0; jb < readCols; jb++)
        {
            if (rasterBlock[jb] == noData)
            {
                rasterBlockOut[jb] = noData;
            }
            else
            {
                rasterBlockOut[jb] = rasterBlock[jb];
            }
        }

        slope->GetRasterBand(1)->RasterIO(GDALRWFlag::GF_Write, j * readCols, i * readRows, readCols, readRows, rasterBlockOut, readCols, readRows, GDALDataType::GDT_CFloat32, 0, 0);

        CPLFree(rasterBlock);
        CPLFree(rasterBlockOut);
    }
}

GDALClose(dem);
GDALClose(slope);

}

【问题讨论】:

  • GDT_CFloat32 的大小为 8,但您只分配了 4 的大小,因此一旦到达缓冲区的中间,它就会崩溃。将类型更改为 GDT_Float32 或将缓冲区大小乘以 2。此外,您的循环方法非常慢,因为您正在分配内存并在循环内释放它。最好只在循环外分配内存并重用相同的内存,然后在循环外也将其释放。我在一个缓慢旋转的磁盘上使用了上面的代码(使用我的模块),它读取了 77 MP 光栅并在几秒钟内将其写入磁盘。

标签: c++ gdal rasterio


【解决方案1】:

这可能不是导致崩溃的原因,但即使您的图像更小,您也需要 2048*2048 块。此代码仅适用于大小为 2048 倍数的图像。

你应该这样做:

nXSize = min(readCols, rasterBand->GetXSize() - j * readCols);
nYSize = min(readRows, rasterBand->GetYSize() - i * readRows);

rasterBand->RasterIO(GDALRWFlag::GF_Read, j * readCols, i * readRows, 
    nXSize, nYSize, rasterBlock, nXSize, nYSize, GDALDataType::GDT_CFloat32, 0, 0);

【讨论】:

  • 感谢您的帮助。下面的代码现在正在运行,但它比在我更改的那些上读取整个图像需要更多的时间 float* rasterBlock = (float*)CPLMalloc(nColsnRows * sizeof(GDT_CFloat32));浮动 rasterBlockOut = (float*)CPLMalloc(nCols*nRows * sizeof(GDT_CFloat32));
  • 使用块的目的不是为了加快处理速度(如果您处理整个图像),而是能够处理大量无法放入内存的数据。如果您可以在 ram 中一次加载整个图像,那肯定会更快。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-14
  • 2015-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-01
相关资源
最近更新 更多