GDAL建立图像金字塔

Posted by jiang yuxuan on October 6, 2022

GDAL金字塔接口

psResampling: 下采样的算法
nOverviews: 金字塔的层数
panOverviewList: int数组,从低到高存储下采样倍率
nListBands: 要创建金字塔的波段数,如果所有波段都创建该值为0
panBandList: 要创建金字塔的波段列表, 如果所有波段都创建该值为nullptr
pfnProgress: 进度回调函数, 或者为nullptr
nProgressData: 进度回调函数参数

RasterIO

在进一步理解与应用金字塔相关的知识前,需要了解RasterIO函数

该函数是用来读写图像数据的,该函数允许从dataset中读取GDALRasterBands到一个缓冲区,或者从一个缓冲区写一个数据到GDALRasterBands类中。如果buffer中的数据type和GDALRasterBands中的不同,该方法会自动转换。如果缓冲区的大小(nBufXSize x nBufYSize)与被访问区域的大小不同(nXSize x nYSize),该方法还负责图像采样或者复制。
通过设置nPixelSpace, nLineSpace 和 nBandSpace参数,可以适应不同的缓冲区。

eRWFlag: GF_Read读取一个区域的数据,GF_Write写一个区域的数据
nXOff: 在x方向上,左上点相对于0的偏置
nYOff: 在y方向上,左上点相对于0的偏置
nXSize: 被访问区域x方向上的尺寸
nYSize: 被访问区域y方向上的尺寸
pData: void类型,缓冲区。其大小至少为 nBufXSize * nBufYSize * nBandCount * eBufType的字节数
*nBufXSize:
在内存中需要读或者写的图像区域X方向上的尺寸
nBufYSize: 在内存中需要读或者写的图像区域y方向上的尺寸
eBufType: 图像的类型,int,double这种。这种类型会被自动转换为GDALRasterBand需要的类型
nBandCount: 读写图像的band数(通道数?)
panBandMap: int数组,被选择的band。band数量至少为1,也可以设为nullptr来选择第一个bind。
nPixelSpace: 表示在一个扫描行中,一个像素的字节偏移起点到下一个像素偏移起点之间的字节间隔,如果默认使用0,那么表示使用eBuffType作为实际的两个像素间的字节间隔。
nLineSpace: 表示一行数据和下一行数据之间的起始字节间的间隔,如果使用0,那么表示使用eBufTypenBufXSize来表示实际间隔。
*nBandSpace:
如果使用GDALDataset::RasterIO()函数,最后还有一个参数叫nBandSpace, 同上, 这个参数的意思就是一个波段与下一个波段之间的起始字节间的间隔,如果使用0,实际将使用eBufType * nBufXSize * nBUfYSize来表示。

GetOverview

这个函数在GDALDataset类里找不到对应的,只能先把对应的波段提出来,然后再用GetOverview获取金字塔对应层

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

int main(){
	GDALAllRegister();//注册
	GDALDataset * poBand = (GDALDataset *)GDALOpen("E:/yjs/SynologyDrive/by/data/optical.tif", GA_ReadOnly);
	if (poBand == nullptr) {
		cout << "读取图像错误" << endl;
		return 1;
	}
	//计算图像大小
	long nXSize = poBand->GetRasterXSize();
	long nYSize = poBand->GetRasterYSize();
	long nBandCount = poBand->GetRasterCount();
	//图像金字塔尺寸
	int overViewList[4] = { 2,4,8,16 };
	poBand->BuildOverviews("NEAREST",4,overViewList,0,nullptr,nullptr,nullptr);
	GDALRasterBand *poBandTmp = poBand->GetRasterBand(1);
	GDALRasterBand *poBand1 = poBandTmp->GetOverview(1);
	long overView1_0_XSize = poBand1->GetXSize();
	long overView1_0_YSize = poBand1->GetYSize();
	//保存对应的图像
	//将GDALRasterBand里的数据转到 BYTE* 数组里去
	char *grayWrite;
	grayWrite = (char*)CPLMalloc(sizeof(char)*overView1_0_XSize*overView1_0_YSize);
	poBand1->RasterIO(GF_Read, 0, 0, overView1_0_XSize, overView1_0_YSize, grayWrite, overView1_0_XSize, overView1_0_YSize, GDT_Byte, 0, 0);
	GDALDriver *poDriver;
	GDALDataset *writeDataset;
	poDriver = GetGDALDriverManager()->GetDriverByName("Gtiff");
	writeDataset = poDriver->Create("./test1.jpg", overView1_0_XSize, overView1_0_YSize, 1, GDT_Byte, nullptr);
	writeDataset->RasterIO(GF_Write,0,0,overView1_0_XSize,overView1_0_YSize,grayWrite,overView1_0_XSize,overView1_0_YSize,GDT_Byte,1,nullptr,0,0,0);
	GDALClose(writeDataset);
	return 0;
}