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.csqlite3.hsqlite3ext.hsqlite3.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目录中分别创建includelibbin文件夹,将刚才生成的.lib文件放入lib文件夹中,将sqlite3.hsqlite3ext.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
    在这里插入图片描述
  • 会出现一些错误,如图
    在这里插入图片描述
  • 这时找到NameEXE_SQLITE3SQLITE3_INCLUDE_DIRSQLITE3_LIBRARY三个属性,可以看到现在它们的Value值都为NOTFOUND的状态,我们将SQLite3.exeincludeSQLite3.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时的includelib文件夹(其中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,基本就为成功。
06f79bde-8c58-42b5-add6-d089aca9c3a2

评论 55
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值