GDAL遍历文件夹下的所有tif文件,将所有原始tif生成png缩略图
程序员文章站
2022-03-20 13:30:08
...
在进行遥感数据平台建设时,往往需要在查看原始数据时查看数据缩略图来确保数据云量是否满足要求(往往是遥感图像太大,不可以快速显示,所以拿缩略图来辅助审查),在此写了一段比较长的代码,虽然有点瑕疵,但也算是可以解决问题了,其中包括的步骤如下(如果想要每个步骤的代码,可以私信我[email protected],也可以关注我,成为我那1位粉丝中的下一位///苦笑脸):
(1)找出所有的tif图像;
(2)原始图像重采样;
(3)云检图重采样;
(4)有云的地方原始图像中改为(0,0,0,0)值;
(5)原始图像中为前三个波段有值的地方,第四个波段改为255
(6)生成PNG,使用createcopy()函数。
代码如下:
// TIFFtransPNG.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "stdlib.h"
#include "gdal_priv.h"
#include "windows.h"
#include "algorithm"
#include "cpl_vsi.h"
#include "cpl_conv.h"
#include <iostream>
#include <fstream>
#include <string>
#include "shlwapi.h"
#include "cpl_string.h"
#include "tchar.h"
#include "FindFileExt.h"
using namespace std;
#define RAM_SIZE 200
#define PNGX 1024
#define RET_ERR_1 1
#define PATH_SIZE 255
int main(int argc, char *argv[])
{
/**********************************************************找出指定路径下所有的tiff文件*****************************************************************/
GDALAllRegister();
char strExe[PATH_SIZE];
char strImg2[PATH_SIZE];
char strPNG2[PATH_SIZE];
//如果数组里有两个参数,把数组中的第一个字符串保存到创建的拥有256个参数的数组strExe中,把数组中第二个字符串保存到strImg数组中
/////////////////////////////////////////////////////////////否则的话,输出Parameters Wrong!Img_Dect.exe [*.tiff | path]by huxudong 2018/1/30表明数据有其他错误3
//外部命令写入argv[]数组中,如果外部命令有3个,第一个是exe,第二个是原始图像路径,第三个是PNG结果文件夹路径
if (argc == 3) { strcpy(strExe, argv[0]); strcpy(strImg2, argv[1]); strcpy(strPNG2, argv[2]); }
else { cout << "输入参数有误" << endl; }
char *srcimg = strImg2;
string filePath;
filePath = srcimg;
char *srcPNG1 = strPNG2;
string fileFold;
fileFold = srcPNG1;
//找出所有的tif文件存入vector容器中,然后新建一个txt文档,将所有的tif文件路劲写入txt文档中
vector<string> files;
const char * distAll = "AllFiles.txt";
//读取所有的文件,包括子文件的文件
//FindFileExt(filePath, files);
//读取所有格式为.tif的文件
string format = ".tif";
string format1 = ".tiff";
//GetAllFormatFiles(filePath, files,format);
FindFileExt(filePath, files, format);
FindFileExt(filePath, files, format1);
ofstream ofn(distAll);
int nFileNum = files.size();
cout << "共有原始影像" << nFileNum << "幅" << endl;
for (int i = 0; i < nFileNum; i++)
{
ofn << files[i] << endl; // 写入文件
}
FILE *fp1;
if ((fp1 = fopen(distAll, "r")) == NULL)
{
printf("Open Tif File list failed:\n%s\n", distAll);
}
//循环处理vector容器中的每一个文件
for (int n = 0; n < nFileNum; n++)
{
//判断文件是否为其他tif文件,如果是跳出循环,进行下一次循环,如果不是,则为原始图像,进行处理
SIZE_T idx,idx1;
string idx2 = "AOIB.tif";
string idx3 = "POS.tif";
idx = files[n].find(idx2);
idx1 = files[n].find(idx3);
if (idx != string::npos || idx1 != string::npos)//存在。
{
continue;
}
else
{
/**********************************************************重采样*****************************************************************/
GDALDataset *poDataset2;
const char *strImg = files[n].c_str();
GDALDataset *ImgBef = (GDALDataset*)GDALOpen(strImg, GA_ReadOnly);
if (ImgBef == NULL)
{
printf("Open Image Failed:\n%s\n", ImgBef);
}
int nCols = ImgBef->GetRasterXSize();
int nRows = ImgBef->GetRasterYSize();
int nBands = ImgBef->GetRasterCount();
GDALDataType type = ImgBef->GetRasterBand(1)->GetRasterDataType();
int nBits = GDALGetDataTypeSize(type);
double ratio = (double)nCols / nRows;
double dResX = (double)PNGX / nCols;
double dResY = (double)dResX / ratio;
int iDstWidth = static_cast<int>(nCols*dResX + 0.5);
int iDstHeight = static_cast<int>(nRows*dResY + 0.5);
double GeoTransform[6];
ImgBef->GetGeoTransform(GeoTransform);
GeoTransform[1] = (double)GeoTransform[1] / dResX;
GeoTransform[5] = (double)GeoTransform[5] / dResY;
const char *sProRef = ImgBef->GetProjectionRef();
int nStepSize = (RAM_SIZE * 1024 * 1024) / (nCols * nBands);
int nStepNum = nRows / nStepSize; if (nRows%nStepSize)nStepNum++;
int *pBand = new int[nBands]; for (int gi = 0; gi < nBands; gi++){ pBand[gi] = gi + 1; }
int isize = GDALGetDataTypeSize(GDT_UInt16) / 8;
int isize1 = GDALGetDataTypeSize(GDT_Byte) / 8;
GDALDriver *poDriver2;
const char *pszFormat = "Gtiff";
poDriver2 = GetGDALDriverManager()->GetDriverByName(pszFormat);
/**********************************************************原图重采样结果路劲*****************************************************************/
string imgPath33=fileFold+"\\YXMPNG.tif" ;
const char *imgPath3 = imgPath33.c_str();
poDataset2 = poDriver2->Create(imgPath3, iDstWidth, iDstHeight, nBands, GDT_Byte, NULL);
double nodata;
nodata = ImgBef->GetRasterBand(1)->GetNoDataValue();
poDataset2->GetRasterBand(1)->SetNoDataValue(nodata);
poDataset2->SetGeoTransform(GeoTransform);
poDataset2->SetProjection(sProRef);
for (int k = 0; k < nStepNum; k++)
{
int ybeg = max(0, min(nStepSize*k, nRows - 1));
int yend = max(0, min(nStepSize*(k + 1), nRows));
WORD *pbuf = new WORD[(yend - ybeg)*nCols*nBands];
memset(pbuf, 0, (yend - ybeg)*nCols*nBands*sizeof(WORD));
ImgBef->RasterIO(GF_Read, 0, ybeg, nCols, (yend - ybeg), pbuf, iDstWidth, static_cast<int>((yend - ybeg)*dResY + 1), GDT_UInt16, nBands, pBand, isize*nBands, isize*nBands*nCols, isize);
BYTE *pImg1 = new BYTE[(yend - ybeg)*nCols*nBands];
memset(pImg1, 0, (yend - ybeg)*nCols*nBands*sizeof(BYTE));
for (int i = 0; i < ((yend - ybeg)*nCols*nBands); i++)
{
pImg1[i] = int(((pbuf[i] * 1.0) / 1024) * 255);
}
poDataset2->RasterIO(GF_Write, 0, ybeg*dResY, iDstWidth, static_cast<int>((yend - ybeg)*dResY + 1), pImg1, iDstWidth, static_cast<int>((yend - ybeg)*dResY + 1), GDT_Byte, nBands, pBand, isize1*nBands, isize1*nCols*nBands, isize1);
delete[]pbuf; pbuf = NULL;
delete[]pImg1; pImg1 = NULL;
}
cout << "原图-》重采样-》8bits成功\n" << endl;
GDALClose((GDALDatasetH)ImgBef);
GDALClose((GDALDatasetH)poDataset2);
/**********************************************************云检结果重采样*****************************************************************/
GDALDataset *poDataset;
/**********************************************************云检图路径生成*****************************************************************/
int pos1 = files[n].find_last_of('.');
string strImgC = files[n];
strImgC.erase(pos1);
strImgC += "_AOIB.tif";
const char *strImgCloud = strImgC.c_str();
GDALDataset *ImgBefCloud = (GDALDataset*)GDALOpen(strImgCloud, GA_ReadOnly);
if (ImgBefCloud == NULL)
{
printf("Open Image Failed:\n%s\n", ImgBefCloud);
}
int nColsC = ImgBefCloud->GetRasterXSize();
int nRowsC = ImgBefCloud->GetRasterYSize();
int nBandsC = ImgBefCloud->GetRasterCount();
GDALDataType typeC = ImgBefCloud->GetRasterBand(1)->GetRasterDataType();
int nBitsC = GDALGetDataTypeSize(typeC);
double dResXC, dResYC;
dResXC = (double)PNGX / nColsC;
dResYC = (double)dResXC / ratio;
int iDstWidthC = static_cast<int>(nColsC*dResXC + 0.5);
int iDstHeightC = static_cast<int>(nRowsC*dResYC + 0.5);
double GeoTransformC[6];
ImgBefCloud->GetGeoTransform(GeoTransformC);
GeoTransformC[1] = (double)GeoTransformC[1] / dResXC;
GeoTransformC[5] = (double)GeoTransformC[5] / dResYC;
const char *sProRefC = ImgBefCloud->GetProjectionRef();
int nStepSizeC = (RAM_SIZE * 1024 * 1024) / (nColsC * nBandsC);
int nStepNumC = nRowsC / nStepSizeC; if (nRowsC%nStepSizeC)nStepNumC++;
int *pBandC = new int[nBandsC]; for (int gi = 0; gi < nBandsC; gi++){ pBandC[gi] = gi + 1; }
int isizeC = GDALGetDataTypeSize(GDT_Byte) / 8;
GDALDriver *poDriver2C;
poDriver2C = GetGDALDriverManager()->GetDriverByName(pszFormat);
string imgPath3CC = fileFold + "\\YXMPNGCC.tif";
const char *imgPath3C = imgPath3CC.c_str();
poDataset = poDriver2C->Create(imgPath3C, iDstWidthC, iDstHeightC, nBandsC, GDT_Byte, NULL);
double nodataC;
nodataC = ImgBefCloud->GetRasterBand(1)->GetNoDataValue();
poDataset->GetRasterBand(1)->SetNoDataValue(nodataC);
poDataset->SetGeoTransform(GeoTransformC);
poDataset->SetProjection(sProRefC);
for (int k = 0; k < nStepNumC; k++)
{
int ybeg = max(0, min(nStepSizeC*k, nRowsC - 1));
int yend = max(0, min(nStepSizeC*(k + 1), nRowsC));
BYTE *pbufC = new BYTE[(yend - ybeg)*nColsC*nBandsC];
memset(pbufC, 0, (yend - ybeg)*nColsC*nBandsC*sizeof(BYTE));
ImgBefCloud->RasterIO(GF_Read, 0, ybeg, nColsC, (yend - ybeg), pbufC, iDstWidthC, static_cast<int>((yend - ybeg)*dResYC + 1), GDT_Byte, nBandsC, pBandC, isizeC*nBandsC, isizeC*nBandsC*nColsC, isizeC);
poDataset->RasterIO(GF_Write, 0, ybeg*dResYC, iDstWidthC, static_cast<int>((yend - ybeg)*dResYC + 1), pbufC, iDstWidthC, static_cast<int>((yend - ybeg)*dResYC + 1), GDT_Byte, nBandsC, pBandC, isizeC*nBandsC, isizeC*nColsC*nBandsC, isizeC);
delete[]pbufC; pbufC = NULL;
}
cout << "云检重采样成功\n" << endl;
GDALClose((GDALDatasetH)ImgBefCloud);
GDALClose((GDALDatasetH)poDataset);
/**********************************************************读原图重采样成8bits的结果*****************************************************************/
GDALDataset*poDS = (GDALDataset*)GDALOpen(imgPath3, GA_Update);
if (poDS == nullptr)
{
printf("\n打开原图重采样8bits影像%s失败!\n", imgPath3);
}
/**********************************************************读云检图重采样结果************************************************************************/
GDALDataset*poDS1 = (GDALDataset*)GDALOpen(imgPath3C, GA_ReadOnly);
if (poDS1 == nullptr)
{
printf("\n打开云检重采样影像%s失败!\n", imgPath3C);
}
int iWidth = poDS->GetRasterXSize();
int iHeight = poDS->GetRasterYSize();
int iWidthC = poDS1->GetRasterXSize();
int iHeightC = poDS1->GetRasterYSize();
GDALRasterBand*pBand1 = poDS->GetRasterBand(1);
GDALRasterBand*pBand2 = poDS->GetRasterBand(2);
GDALRasterBand*pBand3 = poDS->GetRasterBand(3);
GDALRasterBand*pBand4 = poDS->GetRasterBand(4);
GDALRasterBand*pBand5 = poDS1->GetRasterBand(1);
for (int i = 0; i < iHeight; i++)
{
BYTE *pbuf1 = new BYTE[iWidth];
BYTE *pbuf2 = new BYTE[iWidth];
BYTE *pbuf3 = new BYTE[iWidth];
BYTE *pbuf4 = new BYTE[iWidth];
BYTE *pbuf5 = new BYTE[iWidth];
pBand1->RasterIO(GF_Read, 0, i, iWidth, 1, pbuf1, iWidth, 1, GDT_Byte, 0, 0);
pBand2->RasterIO(GF_Read, 0, i, iWidth, 1, pbuf2, iWidth, 1, GDT_Byte, 0, 0);
pBand3->RasterIO(GF_Read, 0, i, iWidth, 1, pbuf3, iWidth, 1, GDT_Byte, 0, 0);
pBand5->RasterIO(GF_Read, 0, i, iWidth, 1, pbuf5, iWidth, 1, GDT_Byte, 0, 0);
for (int j = 0; j < iWidth; j++)
{
if (pbuf1[j] != 0 && pbuf2[j] != 0 && pbuf3[j] != 0)
{
pbuf4[j] = 255;
}
if (pbuf1[j] == 0 && pbuf2[j] == 0 && pbuf3[j] == 0)
{
pbuf4[j] = 0;
}
if (pbuf5[j] == 255)
{
pbuf1[j] = 0; pbuf2[j] = 0; pbuf3[j] = 0; pbuf4[j] = 0;
}
}
pBand1->RasterIO(GF_Write, 0, i, iWidth, 1, pbuf1, iWidth, 1, GDT_Byte, 0, 0);
pBand2->RasterIO(GF_Write, 0, i, iWidth, 1, pbuf2, iWidth, 1, GDT_Byte, 0, 0);
pBand3->RasterIO(GF_Write, 0, i, iWidth, 1, pbuf3, iWidth, 1, GDT_Byte, 0, 0);
pBand4->RasterIO(GF_Write, 0, i, iWidth, 1, pbuf4, iWidth, 1, GDT_Byte, 0, 0);
delete[]pbuf1;
delete[]pbuf2;
delete[]pbuf3;
delete[]pbuf4;
delete[]pbuf5;
}
GDALClose((GDALDatasetH)poDS1);
GDALClose((GDALDatasetH)poDS);
printf("数据集更新完成\n");
/**********************************************************tiff转png格式*****************************************************************/
GDALDriver *poDriver;
const char *pszFormat1 = "PNG";
poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat1);
/**********************************************************PNG结果路径*****************************************************************/
//substr返回一个从指定位置开始,并具有指定长度的子字符串,返回最后一个具有\之后的文件名,必须赋予新值。
string strPNG = files[n];
string strPNGPATH;
int pos2= files[n].find_last_of('\\');
strPNGPATH=strPNG.substr(pos2);
int pos3 = strPNGPATH.find_last_of('.');
//erase擦除strPNG位置pos3的所有字符
strPNGPATH.erase(pos3);
strPNGPATH += "_gDosPreview.png";
strPNG = fileFold + strPNGPATH;
//cout << strImgC << endl;
const char *imgPath4 = strPNG.c_str();
GDALDataset *ImgBef1 = (GDALDataset*)GDALOpen(imgPath3, GA_ReadOnly);
if (ImgBef1 == NULL)
{
printf("Open Image Failed:\n%s\n", ImgBef1);
}
char **papszOptions = NULL;
papszOptions = CSLSetNameValue(papszOptions, "WORLDFILE", "YES");
poDriver->CreateCopy(imgPath4, ImgBef1, FALSE, papszOptions, NULL, NULL);
GDALClose((GDALDatasetH)ImgBef1);
DeleteFile(imgPath3);
DeleteFile(imgPath3C);
}
}
return 0;
}