全色图
完整代码:
#include "gdal_priv.h"
#include "cpl_string.h"
#include <vector>
#include <algorithm>
#include <iostream>
#include <filesystem>
using namespace std;
namespace fs = std::filesystem;
vector<pair<int, int>> imageDims; // 存储每个图像的宽和高
vector<string> fileNames;
void concatenateImages(const string& folderPath, const string& outputFilePath) {
GDALAllRegister();//注册驱动
CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");//支持中文路径
GDALDataType dataType{};
// 遍历文件夹获取图像
for (const auto& entry : fs::directory_iterator(folderPath)) {
if (entry.is_regular_file() && entry.path().extension() == ".tiff") {
fileNames.push_back(entry.path().string());
GDALDataset* ds = (GDALDataset*)GDALOpen(entry.path().string().c_str(), GA_ReadOnly);
if (ds) {
imageDims.push_back({ ds->GetRasterXSize(), ds->GetRasterYSize() });
GDALClose(ds);
// 获取第一个波段的数据类型
GDALRasterBand* band = ds->GetRasterBand(1);
dataType = band->GetRasterDataType();
}
else {
cerr << "无法打开文件: " << entry.path() << endl;
}
}
}
// 计算新图像的尺寸
int totalWidth = 0;
int maxHeight = 0;
for (const auto& dim : imageDims) {
totalWidth += dim.first;
maxHeight = max(maxHeight, dim.second);
}
// 创建输出图像
GDALDriver* driver = GetGDALDriverManager()->GetDriverByName("GTiff");
GDALDataset* outDataset = driver->Create(outputFilePath.c_str(), totalWidth, maxHeight, 1, dataType, nullptr);
if (outDataset == nullptr) {
cerr << "创建输出文件失败." << endl;
return;
}
GDALRasterBand* outBand = outDataset->GetRasterBand(1);
outBand->Fill(0); // 填充黑色背景
// 拼接图像
int xOff = 0;
vector<unsigned short> buffer; // 缓冲区
for (size_t i = 0; i < fileNames.size(); ++i) {
GDALDataset* dataset = (GDALDataset*)GDALOpen(fileNames[i].c_str(), GA_ReadOnly);
if (dataset) {
GDALRasterBand* inBand = dataset->GetRasterBand(1);
int width = imageDims[i].first; // 当前处理图像的宽度
int height = imageDims[i].second;
// 动态调整缓冲区大小,适应当前图像宽度
buffer.resize(width);
// 从输入波段读取数据到缓冲区
for (int j = 0; j < height; ++j) {
CPLErr err = GDALRasterIO(inBand, GF_Read, 0, j, width, 1,
&buffer[0], width, 1, dataType, 0, 0);
if (err != CE_None) {
cerr << "从输入波段读取数据时出错." << endl;
break;
}
// 再从缓冲区写入到输出波段
err = GDALRasterIO(outBand, GF_Write, xOff, j, width, 1,
&buffer[0], width, 1, dataType, 0, 0);
if (err != CE_None) {
cerr << "将数据写入输出波段时出错." << endl;
break;
}
}
GDALClose(dataset);
xOff += width; // 更新x偏移量,准备拼接下一幅图像
}
}
// 写入并关闭输出文件
outDataset->FlushCache();
GDALClose(outDataset);
}
int main() {
string folderPath = "C:\\Users\\WHU\\Desktop\\PAN"; // 文件夹路径
string outputFilePath = "C:\\Users\\WHU\\Desktop\\PAN\\image.tiff"; // 输出文件路径
concatenateImages(folderPath, outputFilePath);
return 0;
}
多光谱:
完整代码:
#include "gdal_priv.h"
#include <vector>
#include <algorithm>//计算图像宽度和高度
#include <filesystem>//读文件
#include <numeric> //数值操作
#include <iostream>
#include <memory>//智能指针
using namespace std;
// 初始化GDAL
void InitializeGDAL()
{
GDALAllRegister();
CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");//支持中文路径
}
// 获取图像的宽度、高度和波段数
bool GetImageSizeAndBands(const string& filePath, int& width, int& height, int& bands)
{
GDALDataset* dataset = (GDALDataset*)GDALOpen(filePath.c_str(), GA_ReadOnly);
if (!dataset)
{
printf("打开失败 %s\n", filePath.c_str());
return false;
}
width = dataset->GetRasterXSize();
height = dataset->GetRasterYSize();
bands = dataset->GetRasterCount();
GDALClose(dataset);
return true;
}
// 拼接多波段图像
void StitchMultiBandImages(const vector<string>& fileNames, const string& outputFilePath)
{
InitializeGDAL();
vector<int> widths, heights, bandCounts;
for (const auto& fileName : fileNames)
{
int width, height, bands;
if (GetImageSizeAndBands(fileName, width, height, bands))
{
widths.push_back(width);
heights.push_back(height);
bandCounts.push_back(bands);
}
else
{
printf("获取失败 %s\n", fileName.c_str());
}
}
int totalWidth = accumulate(widths.begin(), widths.end(), 0);
int maxHeight = *max_element(heights.begin(), heights.end());
int maxBands = *max_element(bandCounts.begin(), bandCounts.end());
GDALDriver* driver = GetGDALDriverManager()->GetDriverByName("GTiff");
char** options = nullptr;
//创建输出图像
GDALDataset* dstDataset = driver->Create(outputFilePath.c_str(), totalWidth, maxHeight, maxBands, GDT_UInt16, options);
for (int band = 1; band <= maxBands; ++band)
{
// 初始化输出波段为黑色
GDALRasterBand* dstBand = dstDataset->GetRasterBand(band);
//智能管理缓冲区内存
unique_ptr<float[]> buffer(new float[totalWidth * maxHeight]);
fill_n(buffer.get(), totalWidth * maxHeight, 0); // 填充黑色
dstBand->RasterIO(GF_Write, 0, 0, totalWidth, maxHeight, buffer.get(), totalWidth, maxHeight, GDT_UInt16, 0, 0);
}
// 逐个读取并写入图像数据
int xOffset = 0;
for (size_t i = 0; i < fileNames.size(); ++i)
{
GDALDataset* srcDataset = (GDALDataset*)GDALOpen(fileNames[i].c_str(), GA_ReadOnly);
if (srcDataset)
{
for (int band = 1; band <= bandCounts[i]; ++band)
{
GDALRasterBand* srcBand = srcDataset->GetRasterBand(band);
GDALRasterBand* dstBand = dstDataset->GetRasterBand(band);
unique_ptr<float[]> buffer(new float[widths[i] * heights[i]]);
CPLErr readErr = srcBand->RasterIO(GF_Read, 0, 0, widths[i], heights[i], buffer.get(), widths[i], heights[i], GDT_UInt16, 0, 0);
if (readErr == CE_None)
{
dstBand->RasterIO(GF_Write, xOffset, 0, widths[i], heights[i], buffer.get(), widths[i], heights[i], GDT_UInt16, 0, 0);
}
}
GDALClose(srcDataset);
}
xOffset += widths[i];
}
GDALClose(dstDataset);
}
// 从指定目录获取所有.tiff文件路径
vector<string> GetTiffFilesFromDirectory(const string& directoryPath)
{
vector<string> tiffFiles;
for (const auto& entry : filesystem::directory_iterator(directoryPath))
{
if (entry.is_regular_file() && entry.path().extension() == ".tiff")
{
tiffFiles.push_back(entry.path().string());
}
}
return tiffFiles;
}
int main() {
string folderPath = "C:\\Users\\WHU\\Desktop\\MSS"; // 文件夹路径
string outputFilePath = "C:\\Users\\WHU\\Desktop\\MSS\\stitched_image.tiff"; // 输出文件路径
// 获取指定文件夹内的所有.tiff文件路径
vector<string> tiffFiles = GetTiffFilesFromDirectory(folderPath);
if (!tiffFiles.empty()) {
// 使用获取到的文件列表进行图像拼接
StitchMultiBandImages(tiffFiles, outputFilePath);
cout << "图像成功生成" << endl;
}
else {
cerr << "没有找到该路径: " << folderPath << endl;
}
return 0;
}