美文网首页
GDAL栅格API使用

GDAL栅格API使用

作者: NullUser | 来源:发表于2023-02-23 17:54 被阅读0次

GDAL栅格API使用

读取栅格数据

void main()
{
    // 注册所有驱动
    GDALAllRegister();
    // 打开调试信息
    CPLSetConfigOption("CPL_DEBUG", "ON");

    // 准备数据源
    std::string url = u8"C:/Users/admin/Desktop/temp/123.tif";

    // 打开栅格数据
    GDALDataset *raster = (GDALDataset*)GDALOpenEx(url.c_str(), GDAL_OF_ALL, nullptr, nullptr, nullptr);
    if(nullptr == raster)
    {
        std::cout << CPLGetLastErrorMsg() << std::endl;
        return;
    }

    // 打印栅格驱动信息
    printf("Driver: %s/%s\n", raster->GetDriver()->GetDescription(),
           raster->GetDriver()->GetMetadataItem(GDAL_DMD_LONGNAME));

    // 打印栅格维度(宽、高、波段)
    printf("Size is %dx%dx%d\n", raster->GetRasterXSize(),
           raster->GetRasterYSize(),
           raster->GetRasterCount());

    // 打印坐标系信息
    if (raster->GetProjectionRef() != NULL)
        printf("Projection is `%s'\n", raster->GetProjectionRef());

    // 参考变换规则
    // Xgeo = GT(0) + Xpixel*GT(1) + Yline*GT(2)
    // Ygeo = GT(3) + Xpixel*GT(4) + Yline*GT(5)
    // In case of north up images, 
    // the GT(2) and GT(4) coefficients are zero, 
    // and the GT(1) is pixel width, and GT(5) is pixel height. 
    // The (GT(0),GT(3)) position is the top left corner of the top left pixel of the raster.
    double adfGeoTransform[6];
    if (raster->GetGeoTransform(adfGeoTransform) == CE_None)
    {
        // 打印原点信息
        printf("Origin = (%.6f,%.6f)\n",
               adfGeoTransform[0], adfGeoTransform[3]);
        // 打印像素大小
        printf("Pixel Size = (%.6f,%.6f)\n",
               adfGeoTransform[1], adfGeoTransform[5]);
    }

    //遍历波段,下标从1开始
    for(int i = 1; i <= raster->GetRasterCount(); i++)
    {
        // 得到波段,poBand属于dataset,获取后无需释放
        GDALRasterBand *poBand = raster->GetRasterBand(i);

        // 获取波段的块大小
        // 获取波段的数据类型(Byte,UInt16...)
        // 获取波段的颜色解释(灰度图、RGB图等)
        int nBlockXSize, nBlockYSize;
        poBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
        printf("Block=%dx%d Type=%s, ColorInterp=%s\n",
               nBlockXSize, nBlockYSize,
               GDALGetDataTypeName(poBand->GetRasterDataType()),
               GDALGetColorInterpretationName(
                   poBand->GetColorInterpretation()));

        // 获取波段最大最小值
        int bGotMin, bGotMax;
        double adfMinMax[2];
        adfMinMax[0] = poBand->GetMinimum(&bGotMin);
        adfMinMax[1] = poBand->GetMaximum(&bGotMax);
        if(!(bGotMin && bGotMax))
        {
            //如果获取失败,则计算
            GDALComputeRasterMinMax((GDALRasterBandH)poBand, TRUE, adfMinMax);
        }
        printf("Min=%f, Max=%f\n", adfMinMax[0], adfMinMax[1]);

        // 金字塔?
        if (poBand->GetOverviewCount() > 0)
            printf("Band has %d overviews.\n", poBand->GetOverviewCount());
        // 获取颜色表
        if (poBand->GetColorTable() != NULL)
            printf("Band has a color table with %d entries.\n",
                   poBand->GetColorTable()->GetColorEntryCount());

        /*******************************************************
         *                读取栅格数据
         *******************************************************/
        unsigned char *pafScanline;
        // 获取波段宽度 
        int nXSize = poBand->GetXSize();
        // 根据宽度开辟缓冲区
        pafScanline = (unsigned char *)CPLMalloc(sizeof(unsigned char) * nXSize);
        //
        /**
         *
         * RasterIO参数
         * CPLErr GDALRasterBand::RasterIO
         * (
         *  GDALRWFlag eRWFlag,    //读写标志位:GF_Read or GF_Write
         *  int nXOff, int nYOff, int nXSize, int nYSize,   //选定需要读/写的窗口
         *  void * pData,  // 读取/写入后的数据缓存,其类型必须是参数eBufType的类型,如GDT_Float32,GDT_Byte
         *  int nBufXSize, int nBufYSize, //缓冲的大小,如果比选定的窗口小,则是低分辨率,此时会利用OverViews做IO操作,以提高效率
         *  GDALDataType eBufType, //传入的缓冲区类型
         *  int nPixelSpace, 
         *  int nLineSpace  //nPixelSpace,nLineSpace 通常是0, 指明使用的默认值
         * )
        */
        // 读取第一行数据
        poBand->RasterIO(GF_Read,
                         0, 0, nXSize, 1,
                         pafScanline,
                         nXSize, 1, 
                         GDT_Byte, 0, 0);

        for(int i = 0; i < nXSize; i++)
        {
            CPLDebug("TEST", "%d",pafScanline[i]);
        }

        //读取的数据使用完后释放
        CPLFree(pafScanline);
    }

    //关闭数据源
    GDALClose(raster);
}

写入栅格数据

有两种方法可以创建文件:CreateCopy()和Create(),所有支持创建文件的驱动都支持CreateCopy(),但只有一部分驱动支持Create(),通过检查 DCAP_CREATE 和 DCAP_CREATECOPY 元数据来判断该驱动是否支持。

CreateCopy()赋值栅格数据

void main()
{
    // 注册所有驱动
    GDALAllRegister();
    // 打开调试信息
    CPLSetConfigOption("CPL_DEBUG", "ON");

    // 有两种方法可以创建文件:CreateCopy()和Create()
    // 所有支持创建文件的驱动都支持CreateCopy(),但只有一部分驱动支持Create()
    // 通过检查 DCAP_CREATE 和 DCAP_CREATECOPY 元数据来判断该驱动是否支持
    const char *pszFormat = "GTiff";
    GDALDriver *poDriver;
    char **papszMetadata;

    // 获取GTiff驱动
    poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);
    if (poDriver == NULL)
        exit(1);

    // 获取驱动的元数据
    papszMetadata = poDriver->GetMetadata();

    // 从元数据中检查是否支持Create()
    if (CSLFetchBoolean(papszMetadata, GDAL_DCAP_CREATE, FALSE))
        printf("Driver %s supports Create() method.\n", pszFormat);

    // 从元数据中检查是否支持CreateCopy()
    if (CSLFetchBoolean(papszMetadata, GDAL_DCAP_CREATECOPY, FALSE))
        printf("Driver %s supports CreateCopy() method.\n", pszFormat);


    /********************************************
     * Use CreateCopy()
     *********************************************/
    const char *pszSrcFilename = u8"C:/Users/admin/Desktop/temp/123.tif";
    const char *pszDstFilename = u8"C:/Users/admin/Desktop/temp/13/copywithoutoptions.tif";
    // 打开原始文件
    GDALDataset *poSrcDS =
        (GDALDataset *)GDALOpen(pszSrcFilename, GA_ReadOnly);

    // 使用默认设置赋值到新文件 
    GDALDataset *poDstDS;
    poDstDS = poDriver->CreateCopy(pszDstFilename, poSrcDS,
                                   FALSE,   //设为TRUE则表示复制必须严格相等,通常是FALSE以按需适配输出的格式
                                   NULL,    //papszOptions: 创建的设置选项
                                   NULL,    //pfnProgress:回调函数,展示复制进度
                                   NULL);   //pProgressData:传给回调函数的数据
    /* Once we're done, close properly the dataset */
    if (poDstDS != NULL)
        GDALClose((GDALDatasetH)poDstDS);
    GDALClose((GDALDatasetH)poSrcDS);
}

Create()创建栅格数据

void main()
{
    // 注册所有驱动
    GDALAllRegister();
    // 打开调试信息
    CPLSetConfigOption("CPL_DEBUG", "ON");

    const char *pszFormat = "GTiff";
    GDALDriver *poDriver;
    char **papszMetadata;

    // 获取GTiff驱动
    poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);
    if (poDriver == NULL)
        exit(1);

    // 获取驱动的元数据
    papszMetadata = poDriver->GetMetadata();

    // 从元数据中检查是否支持Create()
    if (CSLFetchBoolean(papszMetadata, GDAL_DCAP_CREATE, FALSE))
        printf("Driver %s supports Create() method.\n", pszFormat);

    // 从元数据中检查是否支持CreateCopy()
    if (CSLFetchBoolean(papszMetadata, GDAL_DCAP_CREATECOPY, FALSE))
        printf("Driver %s supports CreateCopy() method.\n", pszFormat);

    const char *pszDstFilename = u8"C:/Users/admin/Desktop/temp/13/Create.tif";
    GDALDataset *poDstDS;
    char **papszOptions = NULL;
    poDstDS = poDriver->Create(pszDstFilename,
                               10, //nXSize:宽度
                               10, //nYSize:高度
                               1,   //nBands:波段数
                               GDT_Byte, //栅格类型
                               papszOptions);
    // 参考变换规则
    // Xgeo = GT(0) + Xpixel*GT(1) + Yline*GT(2)
    // Ygeo = GT(3) + Xpixel*GT(4) + Yline*GT(5)
    // In case of north up images, 
    // the GT(2) and GT(4) coefficients are zero, 
    // and the GT(1) is pixel width, and GT(5) is pixel height. 
    // The (GT(0),GT(3)) position is the top left corner of the top left pixel of the raster.
    double adfGeoTransform[6] = {444720, 30, 0, 3751320, 0, -30};
    OGRSpatialReference oSRS;
    char *pszSRS_WKT = NULL;
    GDALRasterBand *poBand;
    GByte abyRaster[10 * 10];
    // 设置转换信息
    poDstDS->SetGeoTransform(adfGeoTransform);
    // 设置空间参考
    oSRS.SetUTM(11, TRUE);
    oSRS.SetWellKnownGeogCS("NAD27");
    oSRS.exportToWkt(&pszSRS_WKT);
    poDstDS->SetProjection(pszSRS_WKT);
    CPLFree(pszSRS_WKT);

    // 获取波段
    poBand = poDstDS->GetRasterBand(1);
    // 往波段写入信息
    for(int i = 0; i < 10*10; i++)
    {
        abyRaster[i] = rand()%(255-0)+0;
    }
    poBand->RasterIO(GF_Write,
                     0, 0, 5, 5,    //写入的窗口大小
                     abyRaster, 10, 10, //待写入的缓冲区
                     GDT_Byte,  //写入的数据类型
                     0, 0);
    /* Once we're done, close properly the dataset */
    GDALClose((GDALDatasetH)poDstDS);
}

相关文章

网友评论

      本文标题:GDAL栅格API使用

      本文链接:https://www.haomeiwen.com/subject/itktldtx.html