GDAL中GDALDataset::RasterIO分块读取的实现
2024-08-24 18:22:33
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
最新文章
- L1-006. 连续因子
- wireshark 导出所有filter出来的包
- 严重:Error listenerStart
- 简单的通用TreeView(WPF)
- C# Winform MD5加密学习积累
- openjudge8469特殊密码锁[贪心]
- 使用Asyncio的Coroutine来实现一个有限状态机
- IOS第一天多线程-04GCD通信
- win7 安装 memcached
- PostgreSQL Replication之第十一章 使用Skytools(2)
- 解决sencha touch显示.JSON包含中文数据时显示乱码问题
- 重定向stdin stdout stderr |
- [BZOJ1096] [ZJOI2007] 仓库建设 (斜率优化)
- 学习ASP.NET Core Razor 编程系列十二——在页面中增加校验
- OPP的三大特征之封装总结
- C++入门篇十一
- 刘志梅2017710101152.《面向对象程序设计(java)》第十一周学习总结
- order by name 注入
- MyMathLib系列(行列式计算)
- openvpn-在Linux中安装和配置OpenVPN Server的最简便方法!(转)