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. Micro

    Micro 架构与设计   Micro 架构与设计 翻译自 Micro architecture & design patterns for microservices 注: 原文作者即 Mi ...

  2. 为什么要使用base64编码,有哪些情景需求?

    Base64编码原理与应用 Java实现BASE64编解码 公钥证书也好,电子邮件数据也好,经常要用到Base64编码,那么为什么要作一下这样的编码呢? 我们知道在计算机中任何数据都是按ascii码存 ...

  3. 百度地图隐藏LOGO显示

    在引入地图的页面加入下列样式即可隐藏百度地图左下角的LOGO   <style type="text/css">   .anchorBL{display:none;} ...

  4. 【[POI2006]OKR-Periods of Words】

    很妙的一道题 感觉又加深了对\(KMP\)还有\(next\)数组的理解 先来看看这个鬼畜的题意,大致就是给你一个字符串,对于这个字符串的每一个前缀,要去找到这个前缀的一个最长的前缀,使得前缀成为这个 ...

  5. thinkphp 和 laravel使用sql语句操作db和源码浅析

    thinkphp 和 laravel是phper开发中用的比较多的两个框架,无所谓好坏,看个人习惯及喜爱! 前言对于一个PHP应用,可能最多的就是操作数据,以致于初学者有时只把php当做数据库增删查改 ...

  6. 2018.12.31 Failed to load JavaHL Library.错误解决

    创建项目出现下面的错误 Failed to load JavaHL Library. These are the errors that were encountered: no libsvnjava ...

  7. C++备忘知识整理

    一.设置字体颜色 C++控制台程序运行时输出框默认的文字颜色是白色,所以我常称其输出框为黑白框.但是这个文字样式不是固定不变的,是可以改变颜色的字体的.方法有两种: 1.设置输出框的框体属性.在运行时 ...

  8. C# 泛型的协变和逆变 (转载)

    1. 可变性的类型:协变性和逆变性 可变性是以一种类型安全的方式,将一个对象当做另一个对象来使用.如果不能将一个类型替换为另一个类型,那么这个类型就称之为:不变量. 协变和逆变是两个相互对立的概念: ...

  9. jquery删除当前行

    <tr><td><input type='hidden' name='annex' value="+rs+"><a href='javas ...

  10. Dokcer-ce安装脚本

    安装docker #!/bin/bash # coding: utf- # Copyright (c) set -e #返回值为0时,退出脚本 echo "1. 备份yum" { ...