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. CodeIgniter框架学习要点

    以下内容从兄弟连的CI教学视频中摘抄: http://codeigniter.org.cn/tutorials/ ------------------------------------------- ...

  2. IM

    一.IM技术概念 IM技术全称Instant Messaging,中文翻译"即时通讯",它是一种使人们能在网上识别在线用户并与他们实时交换消息的技术,是电子邮件发明以来迅速崛起的在 ...

  3. [转]java中的Static class

    转自:http://www.cnblogs.com/kissazi2/p/3971065.html Java中的类可以是static吗?答案是可以.在java中我们可以有静态实例变量.静态方法.静态块 ...

  4. hdu 4825 Xor Sum(trie+贪心)

    hdu 4825 Xor Sum(trie+贪心) 刚刚补了前天的CF的D题再做这题感觉轻松了许多.简直一个模子啊...跑树上异或x最大值.贪心地让某位的值与x对应位的值不同即可. #include ...

  5. java的串行化

    参考博客:Java 对象的串行化(Serialization) 1,什么是串行化 对象的寿命通常随着生成该对象的程序的终止而终止.有时候,可能需要将对象的状态保存下来,在需要时再将对象恢复.我们把对象 ...

  6. 2018 Multi-University Training Contest 4 Problem J. Let Sudoku Rotate 【DFS+剪枝+矩阵旋转】

    任意门:http://acm.hdu.edu.cn/showproblem.php?pid=6341 Problem J. Let Sudoku Rotate Time Limit: 2000/100 ...

  7. dropout总结

    1.伯努利分布:伯努利分布亦称“零一分布”.“两点分布”.称随机变量X有伯努利分布, 参数为p(0<p<1),如果它分别以概率p和1-p取1和0为值.EX= p,DX=p(1-p). 2. ...

  8. 【题解】洛谷P1311 [NOIP2011TG] 选择客栈(递推)

    题目来源:洛谷P1311 思路 纯暴力明显过不了这道题 所以我们要考虑如何优化到至多只能到nlogn 但是我们发现可以更优到O(n) 我们假设我们当前寻找的是第二个人住的客栈i 那么第一个人住的客栈肯 ...

  9. Using Lookup Tables to Accelerate Color Transformations

    转自:http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter24.html In feature-film visual-effects ...

  10. 嵌入式 Linux 学习 之路

    1. 嵌入式 Linux  (首先百度了一下) 结果没有 看到 有信息的内容.2017年2月17日10:06:51 (嵌入式Linux 英文名:embedded Linux 简称 eLinux,Git ...