GDALDataset类中的RasterIO函数能够对图像任意指定区域、任意波段的数据按指定数据类型、指定排列方式读入内存和写入文件中,因此可以实现对大影像的分块读、写运算操作。针对特大的影像图像,有时为了减少内存消耗,对图像进行分块读取很有必要。在以下的测试代码中,给出了3种方式,每种方式的最终结果都是完全相同的,从内存占用情况来看:第一种大于第二种,第二种大于第三种。第三种消耗内存最小。

测试代码如下:

int test_gdal_GDALDataset()
{
	const char* image_name = "E:/GitCode/GDAL_Test/test_images/3.jpg";

	GDALAllRegister();

	GDALDataset* poDataset = (GDALDataset*)GDALOpen(image_name, GA_ReadOnly);
	if (poDataset == nullptr) {
		std::cout << "input image error" << std::endl;
		return -1;
	}

	int width = poDataset->GetRasterXSize();
	int height = poDataset->GetRasterYSize();
	int band_count = poDataset->GetRasterCount();
	size_t length = width * height * band_count;

	GDALDataType gdal_data_type = poDataset->GetRasterBand(1)->GetRasterDataType();
	int depth = GDALGetDataTypeSize((GDALDataType)gdal_data_type);
	//fprintf(stderr, "depth: %d\n", depth);
	assert(depth == 8 || depth == 16);
	int size_byte = 1;
	if (depth == 16) size_byte = 2;

	void* data1 = nullptr;
	void* data2 = nullptr;
	void* data3 = nullptr;

	if (depth == 8) {
		data1 = new unsigned char[length];
		memset(data1, 0, length);
		data2 = new unsigned char[length];
		memset(data2, 0, length);
		data3 = new unsigned char[length];
		memset(data3, 0, length);
	} else {
		data1 = new unsigned short[length];
		memset(data1, 0, length * 2);
		data2 = new unsigned short[length];
		memset(data2, 0, length * 2);
		data3 = new unsigned short[length];
		memset(data3, 0, length * 2);
	}

	GDALClose((GDALDatasetH)poDataset);

	{ // mode1
		GDALDataset* poDataset = (GDALDataset*)GDALOpen(image_name, GA_ReadOnly);
		int band_count = poDataset->GetRasterCount();
		fprintf(stderr, "mode=1: band_count = %d\n", band_count);
		int* pBandMap = new int[band_count];
		for (int i = 0; i < band_count; i++) {
			pBandMap[i] = i + 1;
		}
		GDALDataType gdal_data_type = poDataset->GetRasterBand(1)->GetRasterDataType();
		int depth = GDALGetDataTypeSize((GDALDataType)gdal_data_type);
		void* poSrcData = nullptr;
		if (depth == 8)
			poSrcData = new unsigned char[width * height * band_count];
		else
			poSrcData = new unsigned short[width * height * band_count];

		poDataset->RasterIO(GF_Read, 0, 0, width, height,
			poSrcData, width, height, gdal_data_type, band_count, pBandMap, 0, 0, 0);

		if (depth == 8) {
			unsigned char* p1 = (unsigned char*)poSrcData;

			for (int y = 0; y < height; y++) {
				unsigned char* p2 = (unsigned char*)data1 + width * band_count * y;
				for (int x = 0; x < width; x++) {
					for (int band = 0; band < band_count; band++) {
						p2[x * band_count + band] = p1[band * width * height + y * width + x];;
					}
				}
			}
		} else {
			unsigned short* p1 = (unsigned short*)poSrcData;

			for (int y = 0; y < height; y++) {
				unsigned short* p2 = (unsigned short*)data1 + width * band_count * y;
				for (int x = 0; x < width; x++) {
					for (int band = 0; band < band_count; band++) {
						p2[x * band_count + band] = p1[band * width * height + y * width + x];;
					}
				}
			}
		}

		GDALClose((GDALDatasetH)poDataset);
		delete[] pBandMap;
		delete[] poSrcData;
	}

	{ // mode2
		GDALDataset* poDataset = (GDALDataset*)GDALOpen(image_name, GA_ReadOnly);

		int crop_width = 200;
		int crop_height = 200;
		int loops_y = height / crop_height;
		int loops_x = width / crop_width;

		for (int y = 0; y < loops_y; y++) {
			for (int x = 0; x < loops_x; x++) {
				int band_count = poDataset->GetRasterCount();
				fprintf(stderr, "mode=2: band_count = %d\n", band_count);
				int* pBandMap = new int[band_count];
				for (int i = 0; i < band_count; i++) {
					pBandMap[i] = i + 1;
				}
				GDALDataType gdal_data_type = poDataset->GetRasterBand(1)->GetRasterDataType();
				int depth = GDALGetDataTypeSize((GDALDataType)gdal_data_type);
				void* poSrcData = nullptr;
				if (depth == 8)
					poSrcData = new unsigned char[crop_width * crop_height * band_count];
				else
					poSrcData = new unsigned short[crop_width * crop_height * band_count];

				int xOff = crop_width * x;
				int yOff = crop_height * y;

				poDataset->RasterIO(GF_Read, xOff, yOff, crop_width, crop_height,
					poSrcData, crop_width, crop_height, gdal_data_type, band_count, pBandMap, 0, 0, 0);

				if (depth == 8) {
					unsigned char* p1 = (unsigned char*)poSrcData;
					unsigned char* p2 = (unsigned char*)data2 + width * band_count * y * crop_height;

					for (int m = 0; m < crop_height; m++) {
						unsigned char* p3 = p2 + width * band_count * m + x * crop_width * band_count;
						for (int n = 0; n < crop_width; n++) {
							for (int band = 0; band < band_count; band++) {
								p3[n * band_count + band] = p1[band * crop_width * crop_height + m * crop_width + n];
							}
						}
					}

				}
				else {
					unsigned short* p1 = (unsigned short*)poSrcData;
					unsigned short* p2 = (unsigned short*)data2 + width * band_count * y * crop_height;

					for (int m = 0; m < crop_height; m++) {
						unsigned short* p3 = p2 + width * band_count * m + x * crop_width * band_count;
						for (int n = 0; n < crop_width; n++) {
							for (int band = 0; band < band_count; band++) {
								p3[n * band_count + band] = p1[band * crop_width * crop_height + m * crop_width + n];
							}
						}
					}
				}

				delete[] pBandMap;
				delete[] poSrcData;
			}
		}

		GDALClose((GDALDatasetH)poDataset);
	}

	{ // mode3
		int crop_width = 200;
		int crop_height = 200;
		int loops_y = height / crop_height;
		int loops_x = width / crop_width;

		for (int y = 0; y < loops_y; y++) {
			for (int x = 0; x < loops_x; x++) {
				GDALDataset* poDataset = (GDALDataset*)GDALOpen(image_name, GA_ReadOnly);
				int band_count = poDataset->GetRasterCount();
				fprintf(stderr, "mode=3: band_count = %d\n", band_count);
				int* pBandMap = new int[band_count];
				for (int i = 0; i < band_count; i++) {
					pBandMap[i] = i + 1;
				}
				GDALDataType gdal_data_type = poDataset->GetRasterBand(1)->GetRasterDataType();
				int depth = GDALGetDataTypeSize((GDALDataType)gdal_data_type);
				void* poSrcData = nullptr;
				if (depth == 8)
					poSrcData = new unsigned char[crop_width * crop_height * band_count];
				else
					poSrcData = new unsigned short[crop_width * crop_height * band_count];

				int xOff = crop_width * x;
				int yOff = crop_height * y;

				poDataset->RasterIO(GF_Read, xOff, yOff, crop_width, crop_height,
					poSrcData, crop_width, crop_height, gdal_data_type, band_count, pBandMap, 0, 0, 0);

				if (depth == 8) {
					unsigned char* p1 = (unsigned char*)poSrcData;
					unsigned char* p2 = (unsigned char*)data3 + width * band_count * y * crop_height;

					for (int m = 0; m < crop_height; m++) {
						unsigned char* p3 = p2 + width * band_count * m + x * crop_width * band_count;
						for (int n = 0; n < crop_width; n++) {
							for (int band = 0; band < band_count; band++) {
								p3[n * band_count + band] = p1[band * crop_width * crop_height + m * crop_width + n];
							}
						}
					}

				} else {
					unsigned short* p1 = (unsigned short*)poSrcData;
					unsigned short* p2 = (unsigned short*)data3 + width * band_count * y * crop_height;

					for (int m = 0; m < crop_height; m++) {
						unsigned short* p3 = p2 + width * band_count * m + x * crop_width * band_count;
						for (int n = 0; n < crop_width; n++) {
							for (int band = 0; band < band_count; band++) {
								p3[n * band_count + band] = p1[band * crop_width * crop_height + m * crop_width + n];
							}
						}
					}
				}

				GDALClose((GDALDatasetH)poDataset);
				delete[] pBandMap;
				delete[] poSrcData;
			}
		}
	}

	for (int i = 0; i < length * size_byte; i++) {
		unsigned char* p1 = (unsigned char*)data1;
		unsigned char* p2 = (unsigned char*)data2;
		unsigned char* p3 = (unsigned char*)data3;

		if (p1[i] != p2[i] || p1[i] != p3[i]) {
			fprintf(stderr, "error: data1 != data2 or data1 != data3\n");
			return -1;
		}
	}

	delete[] data1;
	delete[] data2;
	delete[] data3;

	return 0;
}

GitHub:https://github.com/fengbingchun/GDAL_Test

GDAL中GDALDataset::RasterIO分块读取的实现的更多相关文章

  1. GDAL中通过GDALDriver类的Create函数实现图像的保存

    GDAL中除了读取各种类型的图像外,也可以实现对各种图像的保存操作,具体实现测试代码如下: int test_gadl_GDALDataset_write() { const char* image_ ...

  2. 分块读取Blob字段数据(Oracle)

    试过了MSSQL的分块读取Blob字段,又尝试在Oracle下完成,发现还是可行的. 首先建立一个存储过程: create or replace procedure PRO_GET_BLOB(     ...

  3. 分块读取Blob字段数据(MSSQL)

    MSSQL中提供了一个功能,能够分块读取Blob字段中的数据,写了一个存储过程代码如下: CREATE PROCEDURE PRO_GET_FILE_DATA     @PKG_ID INT,     ...

  4. 此操作只能由 SQL Server 中拥有配置数据库读取权限的用户在已加入到某个服务器场的计算机上执行

    错误提示:此操作只能由 SQL Server 中拥有配置数据库读取权限的用户在已加入到某个服务器场的计算机上执行.若要将此服务器连接到服务器场,请使用 SharePoint 产品配置向导,该向导可从 ...

  5. Delphi中使用python脚本读取Excel数据

    Delphi中使用python脚本读取Excel数据2007-10-18 17:28:22标签:Delphi Excel python原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 . ...

  6. MySQL中游标使用以及读取文本数据

    原文:MySQL中游标使用以及读取文本数据 前言 之前一直没有接触数据库的学习,只是本科时候修了一本数据库基本知识的课.当时只对C++感兴趣,天真的认为其它的课都没有用,数据库也是半懂不懂,胡乱就考试 ...

  7. 解决SpringMVC拦截器中Request数据只能读取一次的问题

    解决SpringMVC拦截器中Request数据只能读取一次的问题 开发项目中,经常会直接在request中取数据,如Json数据,也经常用到@RequestBody注解,也可以直接通过request ...

  8. GDAL中GDALDataType中值与其在C++中数据类型对应

    GDAL中的GDALDataType是一个枚举型,其中的值为: GDT_Unknown : 未知数据类型 GDT_Byte : 8bit正整型 (C++中对应unsigned char) GDT_UI ...

  9. java中Properties类及读取properties中属性值

    本文为博主原创,未经允许不得转载: 在项目的应用中,经常将一些配置放入properties文件中,在代码应用中读取properties文件,就需要专门的类Properties类,通过这个类可以进行读取 ...

随机推荐

  1. 简单封装的ajax请求

    简单封装了一个ajax请求,做一下统一处理,少写重复代码,只是一个初步的代码,没有经过优化. $.extend({ myAjax: function (option, rollBack) { var ...

  2. 理解Underscore中的restArgs函数

    虽然Underscore并没有在API手册中提及到restArgs函数,我们仍然可以通过_.restArgs接口使用restArgs函数.如果不去阅读源码,我们很难发现Underscore中还有这样的 ...

  3. 使用combineReducers注意事项

    一.从‘redux’包中引入combineReducers方法: import { combineReducers } from 'redux'; 二.针对state的不同属性写不同的reducer, ...

  4. Yii 集成 PHPExcel读取Excel文件

    PHPexcel官方下载以后,放入Yii的protected\extensions\phpexcel下面 try { spl_autoload_unregister(array('YiiBase', ...

  5. 【[ZJOI2006]物流运输】

    一直不会做,觉得这是一道神题 于是万般无奈下去借鉴抄了一下题解 发现这就是一道套路题 我们用\(dp[i]\)表示前\(i\)天的最小总花费,于是我们就可以用一个常规的老套路来做了 那就是枚举断点 我 ...

  6. PHP-------MySQLi 的函数

    MySQLi 的函数 在数据库中找到一张是自增长的科目表表就可以, Code主键值是自增长的,name是varchar类型的. 如果想往科目表里添加一条数据,是自增长列的表中添加数据,添加完之后,取添 ...

  7. 1.springboot:入门项目

    简介: Springboot 来简化spring应用开发,约定大于配置,去繁从简,just run 就可以创建一个独立的,产品应用 背景: J2EE笨重开发,繁多的配置,低下的开发效率,复杂的部署流程 ...

  8. vue中图片返回404时,显示默认的图片

    图片返回404时候的处理 <img :src="userMsg.portrait" ref="img" alt=""> _thi ...

  9. CPP-基础:信号量

    windows api 多线程---信号量 信号量(Semaphore)和互斥量一样,属于内核对象.它自动执行可用资源查询的测试,如果有可用资源,则可用资源的计数减少1,从而避免其它线程请求资源.当该 ...

  10. zipfile 解压文件名乱码

    zipfile 中文文件名 解压乱码 上传文件功能模块需求及BUG现象: 环境 mac django 1.11.13 python 3.6 功能需求: 上传一个.zip格式的压缩文件 解压该test. ...