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(字節)