您的位置:首页 > 数据库

WIN10 VS2019下编译GDAL3.0+PROJ6+SQLite

2019-07-04 10:38 531 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/weixin_42141589/article/details/94357199

WIN10 VS2019下编译GDAL3.0+PROJ6+SQLite

  • 编译和安装
  • 测试程序
  • 准备

    • GDAL3.0编译要求PROJ6投影库,而PROJ6又要求SQLite3环境,所以在编译GDAL之前我们需要先编译好SQLite和PROJ6.

    下载

    1. 下载库
      GDAL官方下载地址为https://gdal.org/download.html,我下载的版本是
      gdal-3.0.0
      ;PROJ6的官方下载地址为https://proj.org/download.html,我现在的版本为
      6.1.0
      版本;SQLite3的官方下载地址为https://www.sqlite.org/download.html,下载Source Code下的
      sqlite-amalgamation-3280000.zip
      ,和Precompiled Binaries for Windows下的
      sqlite-dll-win32-x86-3280000.zip
      sqlite-tools-win32-x86-3280000.zip
      为了方便编译,我将下载的三个文件分别解压在F盘的根目录GDALPROJSQLite文件夹内,以备后用。
    2. 工具下载
      cmake官方下载地址为https://cmake.org/download/,下载
      cmake-3.15.0-rc3-win64-x64.msi
      文件直接载windows上安装,之后添加环境变量,以便在cmd命令行中使用。详细方法
    3. 懒人包
      我编译好的版本静态库debug版静态库release版动态库debug版动态库release版

    编译和安装

    1. 静态编译SQLite库

    可以按照文章的步骤进行编译。我在此重复一遍。

    1. 解压
      将下载好的两个文件
      sqlite-amalgamation-3280000.zip
      、和
      sqlite-dll-win32-x86-3280000.zip
      解压到SQLite文件夹内,如下所示:
    F:.
    ├─sqlite-amalgamation-3280000
    │      shell.c
    │      sqlite3.c
    │      sqlite3.h
    │      sqlite3ext.h
    │
    └─sqlite-dll-win64-x64-3280000
    sqlite3.def
    sqlite3.dll
    1. 创建静态库工程
    • 在SQLite目录下创建一个新工程

    • 选好工程创建位置之后,将
      sqlite3.c
      sqlite3.h
      sqlite3ext.h
      sqlite3.def
      四个文件添加到工程中,如下图所示:
    • C/C++ --> 预处理器 --> 预处理器定义:设置预定义处理
      _USRDLL

      SQLITE_ENABLE_RTREE

      SQLITE_ENABLE_COLUMN_METADATA

      SQLITE_ENABLE_FTS5

      SQLITE_ENABLE_UNLOCK_NOTIFY

    • 设置模块定义文件,链接器 --> 输入 --> 模块定义文件:
      sqlite3.def

    • 修改模块定义文件:在最后追加sqlite3_unlock_notify
    • 配置类型改为静态库lib
    • 最后生成解决方案(需要生成debug版时,选择debug,这里一release版为例),在
      F:\SQLite\SQLite3\x64\Release
      文件夹可以看到SQLite3.lib静态库和SQLite3.exe(debug版在
      F:\SQLite\SQLite3\x64\Release
      文件夹中)。
      在SQLite目录中分别创建
      include
      lib
      bin
      文件夹,将刚才生成的.lib文件放入
      lib
      文件夹中,将
      sqlite3.h
      sqlite3ext.h
      放入
      include
      中,将
      sqlite-tools-win32-x86-3280000.zip
      中的sqlite3.exe放在
      bin
      文件夹中以备后用。

    2. 编译PROJ6

    1. 解压
      将下载好的
      proj-6.1.0
      解压到PROJ文件夹内。
    2. 编译PROJ6
    • 进入库文件夹中,在源码目录中创建
      build
      文件夹,打开cmake
    • 点击Configure,编译64位,vs2019
    • 会出现一些错误,如图
    • 这时找到
      Name
      EXE_SQLITE3
      SQLITE3_INCLUDE_DIR
      SQLITE3_LIBRARY
      三个属性,可以看到现在它们的
      Value
      值都为NOTFOUND的状态,我们将
      SQLite3.exe
      include
      SQLite3.lib
      的路径分别赋给它们。
      并设置文件生成目录,我设置的是c:/OSGeo4W。
    • 重新点击Configure,提示Configuring done。点击Generate,这时可以看到
      build
      文件夹里有PROJ4.sln。打开
      x64 Native Tools Command Prompt for VS 2019
      (一般在开始菜单安装VS2019的文件夹里就能看到),进入build文件夹,
    • 然后输入命令
    msbuild ALL_BUILD.vcxproj /p:Configuration="Release"
    msbuild INSTALL.vcxproj /p:Configuration="Release"
    • 开启编译(编译debug版是将引号里面的Release改为Debug)。
    • 这时可以在设置的文件生成目录中找到生成的文件

      bin
      中有各种
      *.exe
      文件、
      include
      中放有头文件、
      lib
      中是静态库文件、
      share
      放有一些数据文件。到此PROJ编译完成。

    3. 编译GDAL

    1. 解压
      将下载好的
      GDAL3.0.0
      解压到
      GDAL
      文件夹内。
    2. 编译GDAL
      首先简单了解一下
      nmake.opt
      文件中变量的意义(链接):
    项目 Value
    MSVC_VER 编译器版本
    WIN64 是否编译64位版本
    GDAL_HOME 生成文件的目录
    DLLBUILD 是否动态编译

    进入库文件夹中,找到

    nmake.opt
    文件,用VS2019打开。

    • 第41行左右,找到
      MSVC_VER=
      设置为
      1921
      (VS2019版本应该为1920及以上,视自己编译器而定)。
    • 第57行左右找到
      GDAL_HOME =
      将生成文件的路径设置成你想要的位置,我这里设置成
      "F:\warmerda_release"
    • 第194行左右找到
      WIN64=YES
      ,如果生成64位版本取消注释本行。
    • 第218行左右找到
      DLLBUILD=
      设置为
      1
      启动动态编译、
      0
      为静态编译。我这里进行静态编译设置
      DLLBUILD=0
    • 第238行左右,找到
      PROJ_INCLUDE
      PROJ_LIBRARY
      ,分别设置成你刚才生成PROJ时的
      include
      lib
      文件夹(其中
      PROJ_INCLUDE
      -I
      后为地址),并将.lib的名称改对。
    • 第509行左右,找到
      SQLITE_INC
      SQLITE_LIB
      ,路径设置同上。
      至此设置完成,保存文件。
      打开
      x64 Native Tools Command Prompt for VS 2019
      进入库文件夹,输入命令:
    nmake /f makefile.vc
    nmake /f makefile.vc devinstall

    debug版输入

    nmake /f makefile.vc DEBUG=1
    nmake /f makefile.vc devinstall

    进行编译和安装,完毕后可以在生成文件夹找到5个文件夹

    完成!

    测试程序

    下面几个程序来源于网络,可以作为测试程序验证库是否可用。
    库的引用设置可以参考博客

    #include "gdal_priv.h"
    #include<iostream>
    using namespace std;
    int main()
    {
    const char* pszFile;
    GDALAllRegister();
    pszFile = "F://2.jpg";
    GDALDataset *poDataset = (GDALDataset*)GDALOpen(pszFile, GA_ReadOnly);
    GDALRasterBand *poBand = poDataset->GetRasterBand(1);
    int xsize = poBand->GetXSize();
    int ysize = poBand->GetYSize();
    cout << xsize << endl;
    cout << ysize << endl;
    
    return 0;
    }

    上述程序输出加载图片的行列数,具体数值由你加载的图片决定:

    #include <iostream>
    #include <iomanip>
    #include "gdal_priv.h"
    
    using std::cout;
    
    /*
    @brief 计算图像行列号在给定坐标系下对应的地理坐标
    @param x                行号
    @param y                列号
    @param coords           返回的地理坐标
    @param transform        变换的六参数
    */
    void toGeoCoord(int x, int y, double* coords, double* transform)
    {
    coords[0] = transform[0] + x * transform[1] + y * transform[2];
    coords[1] = transform[3] + x * transform[4] + y * transform[5];
    }
    
    /*
    @brief 读取数据并输出元数据信息
    @param fileName 数据文件路径
    @return 数据读取失败返回1,读取成功返回0
    */
    int readGeoRaster(const char* fileName)
    {
    GDALAllRegister();  // 注册所有支持的数据格式驱动
    GDALDataset* dataset = static_cast<GDALDataset*>(GDALOpen(fileName, GA_ReadOnly));  // 以只读模式打开给定的数据文件
    if (!dataset)
    {
    cout << "影像读取失败:(" << fileName << ")!" << '\n';
    return EXIT_FAILURE;
    }
    
    int nSizeX = dataset->GetRasterXSize(); // 影像的宽度(像元数目)
    int nSizeY = dataset->GetRasterYSize(); // 影像的高度(像元数目)
    int nBandCount = dataset->GetRasterCount(); // 影像波段数
    
    cout << "图像大小:(" << nSizeX << ", " << nSizeY << ")\n";
    cout << "波段数:" << nBandCount << "\n";
    
    double adfGeoTransform[6];  //  存储图像的六参数信息
    dataset->GetGeoTransform(adfGeoTransform);  // 获取数据的六参数信息
    
    double adfULCoord[2];   // 图像左上角坐标
    double adfLRCoord[2];   // 图像右下角坐标
    // 获取左上角和右下角的地理坐标
    toGeoCoord(0, 0, adfULCoord, adfGeoTransform);
    toGeoCoord(nSizeX - 1, nSizeY - 1, adfLRCoord, adfGeoTransform);
    
    cout << std::fixed; // 对于double类型的数据可以使其正常输入,阻止默认的科学计数法输出,
    cout << "左上角坐标:(" << adfULCoord[0] << ", " << adfULCoord[1] << ")\n";
    cout << "右下角坐标:(" << adfLRCoord[0] << ", " << adfLRCoord[1] << ")\n";
    
    const char* pszProj = dataset->GetProjectionRef(); // 获得WKT形式的投影信息
    cout << "投影信息:" << pszProj << '\n';
    
    GDALClose(dataset); // 关闭数据集
    
    return EXIT_SUCCESS;
    }
    
    int main()
    {
    const char* pszFileName = R"(E:\1_MASK.tif)";
    return readGeoRaster(pszFileName);
    }

    上述程序的结果为:

    有可能提示ERROR:找不到pro.db。解决方法是设置一个环境变量PROJ_LIB,将其路径设定到你share文件夹下proj文件夹中,因为在那里面有pro.db文件。

    #include "gdal_priv.h"
    #include "cpl_conv.h" //for CPLMalloc()
    
    // int main()
    int main(int argc, char* argv[])
    {
    //注册文件格式
    GDALAllRegister();
    
    const char* pszFile = "F:\\2.jpg";//"C:\\Test.img";  //1.jpg
    // const char* pszFile = argv[1];
    GDALDataset *poDataset;
    //使用只读方式打开图像
    poDataset = (GDALDataset*) GDALOpen( pszFile,GA_ReadOnly );
    if( poDataset == NULL )
    {
    printf( "File: %s不能打开!\n",pszFile);
    return 0;
    }
    
    //输出图像的格式信息
    printf( "Driver:%s/%s\n",
    poDataset->GetDriver()->GetDescription(),
    poDataset->GetDriver()->GetMetadataItem( GDAL_DMD_LONGNAME) );
    
    //输出图像的大小和波段个数
    printf( "Size is%dx%dx%d\n",
    poDataset->GetRasterXSize(),poDataset->GetRasterYSize(),
    poDataset->GetRasterCount());
    
    //输出图像的投影信息
    if( poDataset->GetProjectionRef() != NULL )
    printf( "Projectionis `%s'\n", poDataset->GetProjectionRef() );
    
    //输出图像的坐标和分辨率信息
    double adfGeoTransform[6];
    if( poDataset->GetGeoTransform( adfGeoTransform) == CE_None )
    {
    printf( "Origin =(%.6f,%.6f)\n",
    adfGeoTransform[0], adfGeoTransform[3]);
    
    printf( "PixelSize = (%.6f,%.6f)\n",
    adfGeoTransform[1], adfGeoTransform[5]);
    }
    
    GDALRasterBand *poBand;
    int            nBlockXSize, nBlockYSize;
    int            bGotMin, bGotMax;
    double         adfMinMax[2];
    
    //读取第一个波段
    poBand = poDataset->GetRasterBand( 1 );
    
    //获取图像的块大小并输出
    poBand->GetBlockSize(&nBlockXSize, &nBlockYSize );
    printf( "Block=%dx%dType=%s, ColorInterp=%s\n",
    nBlockXSize, nBlockYSize,
    GDALGetDataTypeName(poBand->GetRasterDataType()),
    GDALGetColorInterpretationName(
    poBand->GetColorInterpretation()));
    
    //获取该波段的最大值最小值,如果获取失败,则进行统计
    adfMinMax[0] = poBand->GetMinimum( &bGotMin);
    adfMinMax[1] = poBand->GetMaximum( &bGotMax);
    
    if( ! (bGotMin&& bGotMax) )
    GDALComputeRasterMinMax((GDALRasterBandH)poBand, TRUE, adfMinMax);
    
    printf( "Min=%.3fd,Max=%.3f\n", adfMinMax[0], adfMinMax[1] );
    
    //输出图像的金字塔信息
    if( poBand->GetOverviewCount() > 0 )
    printf( "Band has%d overviews.\n", poBand->GetOverviewCount() );
    
    //输出图像的颜色表信息
    if( poBand->GetColorTable() != NULL)
    printf( "Band hasa color table with %d entries.\n",
    poBand->GetColorTable()->GetColorEntryCount() );
    
    float *pafScanline;
    int   nXSize = poBand->GetXSize();
    
    //读取图像的第一行数据
    pafScanline = (float*) CPLMalloc(sizeof(float)*nXSize);
    poBand->RasterIO(GF_Read, 0, 0, nXSize,1,
    pafScanline, nXSize,1, GDT_Float32, 0, 0 );
    
    CPLFree(pafScanline);
    //关闭文件
    GDALClose((GDALDatasetH)poDataset);
    }

    上述程序的输出结果为(具体信息由加载图片决定)

    #include "ogrsf_frmts.h"
    int main()
    {
    GDALAllRegister();
    GDALDataset* poDS;
    poDS = (GDALDataset*)GDALOpenEx("F:\\point.shp", GDAL_OF_VECTOR, NULL, NULL, NULL);
    if (poDS == NULL)
    {
    printf("Open failed.\n");
    exit(1);
    }
    
    OGRLayer* poLayer;
    poLayer = poDS->GetLayerByName("point");
    
    //中间读取Feature、FeatureDefn和Geometry等接口没有任何变化
    
    //关闭数据
    GDALClose(poDS);
    }

    上述程序不报

    Open failed
    ,基本就为成功。

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: