读取多波段的tif(利用GDAL)

2023-10-30

bmp的格式是RGBRGB.....排列下来的,每个像素的三个分量靠在一起,描述完一个像素,接着描述下一个像素。

tif的格式更多样。通常的格式也是BGRBGR.....(次序与bmp相反)排列下来的,但偶尔有一些tif文件采用RRRRRR.......GGGGG.........BBBBB.....的安排。还有的tif文件内容是压缩过的。。。。这里我们只考虑三个颜色分量靠在一起的情况。

下面的例子是一个tif文件,宽896,高608,三个分量。这里直接用gdal读取tif,再写入bmp。与前面《一个tif转bmp的示例》不同,使用gdal不需要手动交换B-R的位置。
具体项目见我的资源中的"gdalTif.rar"

#include <gdal_priv.h>
#include <algorithm>
#include <iostream>
#include <fstream>

#pragma comment(lib, "gdal_i.lib")

bool bReadImageMultiBand(unsigned char * & pImgData, int & iWidth, int & iHeight, int & iChannel, char * strPath);
bool bWriteImageData(char *, unsigned char *, int, int, int, int);
void vFindImageTypeGDAL(char *, char *);

int main(void)
{
	GDALAllRegister();
	int iWidth, iHeight, iChannel;
	unsigned char * pImgData;
	if(bReadImageMultiBand(pImgData, iWidth, iHeight, iChannel, "earthRGBRGB.tif"))
	{
		bWriteImageData("earth.bmp", pImgData, iWidth, iHeight, iChannel, iChannel);
		delete [] pImgData;
	}

	return 0;
}

bool bReadImageMultiBand(unsigned char * & pImgData, int & iWidth, int & iHeight, int & iChannel, char * strPath)
{
	GDALDataset * pDataSet = nullptr;
	pDataSet = (GDALDataset *)GDALOpen(strPath, GA_ReadOnly);
	if(pDataSet == nullptr)
	{
		GDALClose(pDataSet);
		return false;
	}

	GDALDataType dt = pDataSet->GetRasterBand(1)->GetRasterDataType();
	iWidth = pDataSet->GetRasterXSize();
	iHeight = pDataSet->GetRasterYSize();
	iChannel = std::min(pDataSet->GetRasterCount(), 3);
	int arrBandMap[] = {1,2,3};
	pImgData = new unsigned char[iWidth * iHeight * iChannel];
	pDataSet->RasterIO(GF_Read, 0,0, iWidth, iHeight, pImgData, iWidth, iHeight, dt, iChannel, arrBandMap, 0,0,0);
	GDALClose(pDataSet);

	return true;
}

bool bWriteImageData(char * strDestPath, unsigned char * pData, int iWidth, int iHeight, int iSrcChannel, int iDestChannel)
{
	char arrType[1024] = {0};
	vFindImageTypeGDAL(strDestPath, arrType);

	if(arrType)
	{
		std::fstream file;
		file.open(strDestPath, std::ios_base::out);
		file.close();
		GDALDriver * pMemDriver = GetGDALDriverManager()->GetDriverByName("MEM");
		if(pMemDriver == nullptr)
			return false;

		GDALDataset * pMemDataSet = pMemDriver->Create("",iWidth,iHeight,iDestChannel,GDT_Byte,NULL);
        GDALRasterBand *pBand = NULL;
		int arrBandMap[3] = { 1, 2, 3 };
		pMemDataSet->RasterIO(GF_Write,
			0,
			0,
			iWidth,
			iHeight,
			pData,
			iWidth,
			iHeight,
			GDT_Byte,
			iDestChannel,
			arrBandMap,
			0,0,0);

        GDALDriver *pDstDriver = NULL;
        pDstDriver = (GDALDriver *)GDALGetDriverByName(arrType);
        if (pDstDriver == NULL)
        {
            GDALClose(pMemDataSet);

            return false;
        }

        GDALDataset * pDataSet = pDstDriver->CreateCopy(strDestPath,pMemDataSet,FALSE, NULL, NULL, NULL);
        if (pDataSet == NULL)
        {
            GDALClose(pMemDataSet);

            return false;
        }

        GDALClose(pDataSet);
        GDALClose(pMemDataSet);

        return true;
    }
    else
    {
        return false;
    }
}

void vFindImageTypeGDAL(char * pDstImgFileName, char * pDst)
{
	char * dstExtension = strlwr(strrchr(pDstImgFileName, '.') + 1);

	if (0 == strcmp(dstExtension, "bmp"))
		sprintf(pDst, "%s", "BMP");
	else if (0 == strcmp(dstExtension, "jpg"))
		sprintf(pDst, "%s", "JPEG");
	else if (0 == strcmp(dstExtension, "png"))
		sprintf(pDst, "%s", "PNG");
	else if (0 == strcmp(dstExtension, "tif"))
		sprintf(pDst, "%s", "GTiff");
	else if (0 == strcmp(dstExtension, "gif"))
		sprintf(pDst, "%s", "GIF");
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

读取多波段的tif(利用GDAL) 的相关文章

随机推荐

  • 解决Vue路由重复点击报错问题

    给一个元素绑定跳转路由的事件时 跳转后当我们重复点击时就会报以下错误 原因 vueRouter版本问题 解决方案1 降低VueRouter的版本 使用旧版本的VueRouter 3 0 xxx 解决方案2 跳转路径后 捕获异常 不做处理 这
  • PC 服务器故障处理方法

    计算机网络在发展的过程中 PC服务器的各项配置也在不断的升级和改善 随着人们对计算机网络流畅性需求的逐步增长 PC服务器的快速故障分析与维护处理也愈发重要 PC服务器常见的软件故障就是在开机时可能会产生的一系列软件冲突 PC服务器的硬件也可
  • 【详细深入分析OpenHarmony编译流程】

    详细深入分析OpenHarmony编译流程 前言 编译入口 源码根目录 编译命令 记录源码根目录位置 开始构建 获取python解释器 hb主程序 build模块初始化 build模块执行 build和set参数解析 参数配置文件读写 配置
  • 七牛云之微信小程序上传图片

    本节课 我讲的是微信小程序结合七牛云上传图片 仅仅讲如何上传图片并得到图片的云链接 首先 先到官网 https developer qiniu com kodo manual 1205 programming model 了解一下大致的业务
  • docker镜像和容器有什么区别?

    我这里拿大家熟知的VMware来举例 VMware安装虚拟机 gt 下载系统镜像 gt 在VMware里安装系统 gt 得到一个系统虚拟机 我们试着叫它实例 docker里也是类似 概念上 docker里的镜像 VMware里的镜像 doc
  • react实现分页-封装组件

    需求 根据后台的数据 判断是否有下一页 如果有下一页 用户上划加载更多调用接口 结合 antd mobile 的 ListView 组件实现 参数解释 dataSource 数据源 数组 currentPage 页数 initialList
  • bash: jps: 未找到命令…

    bash jps 未找到命令 sudo yum install java 1 8 0 openjdk devel x86 64
  • Linux环境基础开发工具的使用:

    创建新用户 新建用户操作 删除用户 Linux器 vim使用 1 vim的基本概念 vim的三种模式 其实有好多模式 目前掌握这3种即可 分别是命令模式 command mode 插入模式 Insert mode 和底行模式 last li
  • 爬虫:栖落的电影网站,利用requests和re模块

    这是栖落的电影网站地址 https xxx xxx 进入网页 显示 爬取目标 电影的名称 观影人数和评分 易知本网站的url url https xxx xxx 本网站会识别出headers中的python请求而拒绝访问 所以需要更改hea
  • SuperSocket教程五:配置文件启动,配置多服务器示例

    为什么要通过配置启动 1 避免硬编码 SuperSocket提供了很多有用的配置选项 可以充分利用SuperSocket提供的工具 那么怎么通过配置启动 我最开始看文档都没搞懂有些地方 然后查了一下不懂的地方 最后解决问题 这篇博客是和上一
  • pwrite写操作——原子操作,不改变当前文件操作符位置,写入位置offset是一个相对于fd起始地址的偏移量

    意外发现 pwrite 函数是一个原子操作 现测试验证如下 1 2 pwrite相当于先调用lseek接着调用write 但又不完全是这样 3 1 pwrite是原子操作 定位和写操作在一个原子操作中完成 期间不可中断 但分开的lseek和
  • 接口自动化测试实战经验分享,测试用例也能自动生成

    作为测试 你可能会对以下场景感到似曾相识 开发改好的 BUG 反复横跳 版本兼容逻辑多 修复一个 BUG 触发了更多 BUG 上线时系统监控毫无异常 过段时间用户投诉某个页面无数据 改动祖传代码时如履薄冰 心智负担极重 为此本文提出一个自动
  • Kotlin常用的高阶函数(ForEach、Map、Flatmap、Fold、Reduce......)

    一 ForEach 类型于Java的传统的写法 package net println kotlin chapter5 builtins author wangdong description Kotlin常见的高阶函数 fun main
  • LLM-项目详解-Chinese-LLaMA-AIpaca(一):LLM+LoRa微调加速技术原理及基于PEFT的动手实践:一些思考和mt0-large+lora完整案例

    如何花费较少的算力成本来进行微调训练 十分重要 当前关于LLaMA Alpaca Instruct微调 LoRa微调等多个概念大家讲的很多 最近也在学习 也看到几个有趣的话题 主要参考于 https github com ymcui Chi
  • CompletableFuture使用案例

    最近遇到一个前端接口需要批量请求接口 担心超时 所以使用批量异步的请求方式 批量构造请求 for ProductInfoParam productInfoParam list CompletableFuture
  • 实战分享:一文读懂RS-232总线

    大家好 我是阿荣 感恩遇见 本文部分图文来源于网络 并经过整合 编辑和勘误 实战分享栏目将重点介绍嵌入式的基础知识 并融合一些实战经验 持续勘误和迭代 建议关注和收藏 WX同名 RS 232概述 RS 232标准接口 又称EIARS 232
  • php的MVC模式

    php的MVC模式 model 存放向数据库请求来的数据 view 存放组件 图片 页面模板html文件 controller 获取或改变model里的数据返回给页面渲染数据 1 根目录入口php文件index php 在此定义目录常量方便
  • (三)Refactor

    在实现线程池上个版本中 提交任务需要重写Task run 方法 获取结果会被阻塞直至任务完成 使用C 异步新标准解决上述问题 提交任务期望有如下简洁格式 auto res1 pool submitTask func 1 2 可以使用C 17
  • c++ 小型公司人员管理 类的继承和派生实战

    写在前面 希望这篇文章能对大家有一点点帮助 欢迎一起交流进步 谢谢大家的阅读 一 题目 3 小型公司人员管理 某小型公司有四类人员 总经理 技术人员 销售经理 推销员 设计一个基类employee派生出 manager 总经理 techni
  • 读取多波段的tif(利用GDAL)

    bmp的格式是RGBRGB 排列下来的 每个像素的三个分量靠在一起 描述完一个像素 接着描述下一个像素 tif的格式更多样 通常的格式也是BGRBGR 次序与bmp相反 排列下来的 但偶尔有一些tif文件采用RRRRRR GGGGG BBB