C++使用GDAL库完成tiff图像的合并

全色图

完整代码:

#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;
}


 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在three.js中显示tiff文件,您需要使用gdal将其加载为图像数据,然后将其转换为three.js支持的格式。以下是一些步骤: 1. 安装gdal 使用以下命令安装gdal: ``` pip install gdal ``` 2. 使用gdal加载tiff文件 使用以下代码加载tiff文件: ```python from osgeo import gdal # 打开tiff文件 ds = gdal.Open('path/to/tiff/file') # 读取tiff文件中的图像数据 data = ds.ReadAsArray() # 获取图像数据的相关信息 width = ds.RasterXSize height = ds.RasterYSize channels = ds.RasterCount # 关闭tiff文件 ds = None ``` 3. 转换图像数据为three.js支持的格式 使用以下代码将图像数据转换为three.js支持的格式: ```javascript // 将图像数据转换为three.js支持的格式 var texture = new THREE.DataTexture(data, width, height, channels, THREE.RGBAFormat); // 设置纹理属性 texture.magFilter = THREE.LinearFilter; texture.minFilter = THREE.LinearFilter; texture.wrapS = THREE.ClampToEdgeWrapping; texture.wrapT = THREE.ClampToEdgeWrapping; // 创建材质 var material = new THREE.MeshBasicMaterial({ map: texture }); // 创建网格 var geometry = new THREE.PlaneGeometry(width, height); var mesh = new THREE.Mesh(geometry, material); // 添加网格到场景中 scene.add(mesh); ``` 这些代码将创建一个平面网格,其中纹理使用tiff文件加载的图像数据。您可以根据需要调整平面网格的大小和位置。 请注意,由于gdal是用C++编写的,因此在使用Python时可能会遇到一些性能问题。如果您需要更高的性能,请考虑使用其他,例如OpenCV。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值