gdal 读取tif文件,与opencv操作图像的思路不一样,不能照搬,切不可逐个像素的调用 RasterIO 函数,操作非常耗时,最简单的方式就是全部读取,再逐个赋值。
以下是经过反复测试后的代码,可以供大家借鉴:
GDALAllRegister(); // 注册数据集 GDALDataset *poDataset; // 创建数据集 poDataset = (GDALDataset *)GDALOpen(orthoFile, GA_ReadOnly); // 打开影像 if (poDataset == NULL) { emit sendMsg(tr("Error: Can‘t open photo!\t") + orthoFile); continue; } int orthoWidth = poDataset->GetRasterXSize(); // 获取影像宽度和高度 int orthoHeight = poDataset->GetRasterYSize(); double adfGeoTransform[6]; poDataset->GetGeoTransform(adfGeoTransform); // 获取影像坐标信息 if (fabs(adfGeoTransform[0]) < 1 || fabs(adfGeoTransform[3]) < 1) // 如果影像中未记录坐标系,则查找tfw文件,如果也不存在,终止程序 { QString tfwFileName = QFileInfo(orthoList[j]).baseName() + ".tfw"; if (!QFileInfo(tfwFileName).exists()) { return 1; } FILE *fp; fopen_s(&fp, tfwFileName.toLocal8Bit().data(), "r"); if (!fp) { return 1; } int n = 0; double tfwData[6]; while (!feof(fp)) { char line[128]; if (!fgets(line, 128, fp)) { break; } sscanf(line, "%lf", &tfwData[n++]); if (n >= 6) { break; } } adfGeoTransform[0] = tfwData[4]; adfGeoTransform[1] = tfwData[0]; adfGeoTransform[2] = tfwData[1]; adfGeoTransform[3] = tfwData[5]; adfGeoTransform[4] = tfwData[2]; adfGeoTransform[5] = tfwData[3]; fclose(fp); } int bandCount = poDataset->GetRasterCount(); // 获取波段数 GDALRasterBand *band = poDataset->GetRasterBand(1); // 获取第一个波段数据:目的是用来获取数据类型及数据宽度 GDALDataType datatype = band->GetRasterDataType(); // 获取数据类型 if (datatype == 0 || datatype == 12 || bandCount < 3) // 如类型未定义及波段数据小于3则退出 { emit sendMsg(tr("Error: The file is error!") + orthoList[j]); return 1; } int nXBuffSize = orthoWidth; // 读取缓存的宽度和高度,可根据需要对影像进行缩放 int nYBuffSize = orthoHeight; int depth = GDALGetDataTypeSize(band->GetRasterDataType()); // 获取数据宽度 int nchar = depth / 8; // 数据类型的字节数 size_t imgBufNum = (size_t)nXBuffSize * nYBuffSize * bandCount; // 计算缓存空间大小 MEMORYSTATUS ms; ::GlobalMemoryStatus(&ms); // 获取系统内存使用情况 if (imgBufNum * 32 > ms.dwAvailPhys * 0.8) // 如果内存不够,则退出 { emit sendMsg(tr("Error: Insufficient remaining memory, please check!")); return 1; } int bandMap[3] = { 1, 2, 3 }; // 读取波段的次序,可设定,比如:RGB BGR 等 float *imgBuf = new float[imgBufNum]; // 开辟缓存空间,此处定义位float,以兼容 byte short ushort int uint poDataset->RasterIO(GF_Read, 0, 0, orthoWidth, orthoHeight, // 获取的图像区域大小 起始坐标(x,y),宽度、高度(width,height imgBuf, nXBuffSize, nYBuffSize, // 缓存地址,缓存的宽度和高度 GDT_Float32, // 缓存的数据类型,不是影像的数据类型,gdal会自动把影像的数据类型转为指定的数据类型 3, // 要获取的波段数,此处设为3 bandMap, // 获取的波段次序,此处设为 RGB 次序 3 * 4, // 缓存中相邻波段间隔,比如 RGB RGB,第一个R与第二个R相隔三个float,也就是 3 * 4(字节) nXBuffSize * 3 * 4, // 缓存中相邻行的间距 4); // 缓存中两个波段的间距,R与G相邻,间隔是一个float,也就是 4(字节)
原文:https://www.cnblogs.com/xingzhensun/p/11921737.html