#include "stdafx.h" #include using namespace cv; #include "GeoTIFFEdit.h" // tif 图像 #include #include #include #include // 几何校正 #include "SysGeoCorrect.h" // 保存情报数据为tiff文件 bool SaveQBDataToGeoTIFF(QBStru *qbData, string savePath) { try { if (qbData == NULL || savePath == "") { return false; } // 图像数据有效性验证 if (qbData->image.bValid == false) { return false; } else { if ( false == SaveImgStruToGeoTIFF(&qbData->image.geoImg, savePath)) { if (true == SysGeoCorrectImg(qbData, false)) // 几何校正 { return SaveImgStruToGeoTIFF(&qbData->image.geoImg, savePath); } else { return false; } } } } catch(cv::Exception &e) { string str = e.msg; return false; } catch(...) { return false; } return true; } //功能:保存图像结构体至本地文件(GeoTiff格式) //输入: 1. qbData 通用图像数据结构体 // 2. savePath Tiff文件保存路径 //输出: 1. 返回值:保存成功返回true,失败返回false bool SaveImgStruToGeoTIFF(const ImgStru *Img, string savePath) { try { if (Img == NULL || savePath == "") { return false; } // 判断路径后缀的有效性 string postfix = savePath.substr(savePath.rfind('.') + 1, savePath.length()); if ("tif" != postfix) { return false; } // 图像数据有效性验证 if (Img->ImgWidth <= 0 || Img->ImgHeight <= 0 || Img->bitcount <= 0 || Img->buff == NULL) { return false; } // 经纬度边界有效性验证 double NorthLat = Img->BoundingBox.NorthLat; double SouthLat = Img->BoundingBox.SouthLat; double WestLon = Img->BoundingBox.WestLon; double EastLon = Img->BoundingBox.EastLon; // 纬度验证 if (NorthLat > 90 || NorthLat < -90 || SouthLat > 90 || SouthLat < -90 || NorthLat - SouthLat <= 0) { return false; } // 经度验证 if (WestLon > 180 || WestLon < -180 || EastLon > 180 || EastLon < -180 || EastLon - WestLon <= 0) { return false; } // 数据有效,执行下属操作 int ImgWidth = Img->ImgWidth; int ImgHeight = Img->ImgHeight; int Imgchannels = Img->bitcount / 8; if (Img->bitcount != 8 && Img->bitcount != 24) { return false; } // 创建临时图像 cv::Mat geoImg; if (Img->bitcount == 8) { geoImg = cv::Mat(ImgHeight, ImgWidth, CV_8UC1); } else { geoImg = cv::Mat(ImgHeight, ImgWidth, CV_8UC3); } // 创建失败,直接返回 if (geoImg.empty() == true) { return false; } else { // 复制数据 int lineByte = ImgWidth * Img->bitcount / 8; unsigned int imgBufSize = static_cast(ImgHeight * lineByte); memcpy(geoImg.data, Img->buff, imgBufSize); } // 经纬度 分辨率 double Lon_resolution = (EastLon - WestLon) / ImgWidth; double Lat_resolution = (SouthLat - NorthLat) / ImgHeight; // 注册 GDALAllRegister(); CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO"); //创建数据集 GDALDataset* poDstDS = NULL; char** papszOptions = NULL; string fomat; fomat = "GTiff"; GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName( fomat.c_str()); double adfGeoTransform[6]; adfGeoTransform[0] = WestLon; /* top left x */ adfGeoTransform[1] = Lon_resolution;/* w-e pixel resolution */ adfGeoTransform[2] = 0; /* rotation, 0 if image is "north up" */ adfGeoTransform[3] = NorthLat; /* top left y */ adfGeoTransform[4] = 0; /* rotation, 0 if image is "north up" */ adfGeoTransform[5] = Lat_resolution;/* n-s pixel resolution */ if (Imgchannels == 1) { // 创建图像 poDstDS = poDriver->Create( savePath.c_str(), ImgWidth, ImgHeight, 1, GDT_Byte, papszOptions ); //设置椭球体信息 poDstDS->SetGeoTransform( adfGeoTransform ); OGRSpatialReference oSRS; char* pszWKT = NULL; oSRS.SetWellKnownGeogCS( "WGS84" ); oSRS.exportToWkt( &pszWKT ); poDstDS->SetProjection( pszWKT ); //遥感的一个波段 GDALRasterBand *poBand = poDstDS->GetRasterBand( 1 ); //分波段输出数据到tiff文件 poBand->RasterIO( GF_Write, 0, 0, ImgWidth, ImgHeight, geoImg.data, ImgWidth, ImgHeight, GDT_Byte, 0, 0 ); GDALFlushCache( poDstDS ); GDALClose( poDstDS ); GetGDALDriverManager()->DeregisterDriver(poDriver); GDALDestroyDriverManager(); poDstDS = NULL; poDriver = NULL; } else { // 创建图像 poDstDS = poDriver->Create( savePath.c_str(), ImgWidth, ImgHeight, 3, GDT_Byte, papszOptions ); //设置椭球体信息 poDstDS->SetGeoTransform( adfGeoTransform ); OGRSpatialReference oSRS; char* pszWKT = NULL; oSRS.SetWellKnownGeogCS( "WGS84" ); oSRS.exportToWkt( &pszWKT ); poDstDS->SetProjection( pszWKT ); //遥感的一个波段 GDALRasterBand *poBand1 = poDstDS->GetRasterBand( 1 ); GDALRasterBand *poBand2 = poDstDS->GetRasterBand( 2 ); GDALRasterBand *poBand3 = poDstDS->GetRasterBand( 3 ); std::vector planes; cv::split(geoImg, planes); //分波段输出数据到tiff文件 poBand1->RasterIO( GF_Write, 0, 0, ImgWidth, ImgHeight, planes[2].data, ImgWidth, ImgHeight, GDT_Byte, 0, 0 ); poBand2->RasterIO( GF_Write, 0, 0, ImgWidth, ImgHeight, planes[1].data, ImgWidth, ImgHeight, GDT_Byte, 0, 0 ); poBand3->RasterIO( GF_Write, 0, 0, ImgWidth, ImgHeight, planes[0].data, ImgWidth, ImgHeight, GDT_Byte, 0, 0 ); GDALFlushCache( poDstDS ); GDALClose( poDstDS ); GetGDALDriverManager()->DeregisterDriver(poDriver); GDALDestroyDriverManager(); poDstDS = NULL; poDriver = NULL; } return true; } catch(cv::Exception &e) { string str = e.msg; return false; } catch(...) { return false; } } //功能:保存图像数据至本地文件(GeoTiff格式) //输入: 1. Img OpenCV图像 // 2. LBbox 经纬度边界 // 3. savePath Tiff文件保存路径 //输出: 1. 返回值:保存成功返回true,失败返回false bool SaveImgStruToGeoTIFF(cv::Mat& img, GeoBoundingBox& LBbox, string savePath) { try { // 图像有效性验证 if (img.empty() == true || savePath == "") { return false; } if (img.type() != CV_8UC1 && img.type() != CV_8UC3) { return false; } // 经纬度边界有效性验证 double NorthLat = LBbox.NorthLat; double SouthLat = LBbox.SouthLat; double WestLon = LBbox.WestLon; double EastLon = LBbox.EastLon; // 纬度验证 if (NorthLat > 90 || NorthLat < -90 || SouthLat > 90 || SouthLat < -90 || NorthLat - SouthLat <= 0) { return false; } // 经度验证 if (WestLon > 180 || WestLon < -180 || EastLon > 180 || EastLon < -180 || EastLon - WestLon <= 0) { return false; } // 经纬度 分辨率 double Lon_resolution = (EastLon - WestLon) / img.cols; double Lat_resolution = (SouthLat - NorthLat) / img.rows; // 判断路径后缀的有效性 if ("tif" != savePath.substr(savePath.find_first_of('.'), savePath.length())) { return false; } // 注册 GDALAllRegister(); CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO"); //创建数据集 GDALDataset* poDstDS = NULL; char** papszOptions = NULL; string fomat; fomat = "GTiff"; GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName( fomat.c_str()); double adfGeoTransform[6]; adfGeoTransform[0] = WestLon; /* top left x */ adfGeoTransform[1] = Lon_resolution;/* w-e pixel resolution */ adfGeoTransform[2] = 0; /* rotation, 0 if image is "north up" */ adfGeoTransform[3] = NorthLat; /* top left y */ adfGeoTransform[4] = 0; /* rotation, 0 if image is "north up" */ adfGeoTransform[5] = Lat_resolution;/* n-s pixel resolution */ if (img.type() == 0) { // 创建图像 poDstDS = poDriver->Create( savePath.c_str(), img.cols, img.rows, 1, GDT_Byte, papszOptions ); //设置椭球体信息 poDstDS->SetGeoTransform( adfGeoTransform ); OGRSpatialReference oSRS; char* pszWKT = NULL; oSRS.SetWellKnownGeogCS( "WGS84" ); oSRS.exportToWkt( &pszWKT ); poDstDS->SetProjection( pszWKT ); //遥感的一个波段 GDALRasterBand *poBand = poDstDS->GetRasterBand( 1 ); //分波段输出数据到tiff文件 poBand->RasterIO( GF_Write, 0, 0, img.cols, img.rows, img.data, img.cols, img.rows, GDT_Byte, 0, 0 ); GDALFlushCache( poDstDS ); GDALClose( poDstDS ); GetGDALDriverManager()->DeregisterDriver(poDriver); GDALDestroyDriverManager(); poDstDS = NULL; poDriver = NULL; } else { // 创建图像 poDstDS = poDriver->Create( savePath.c_str(), img.cols, img.rows, 3, GDT_Byte, papszOptions ); //设置椭球体信息 poDstDS->SetGeoTransform( adfGeoTransform ); OGRSpatialReference oSRS; char* pszWKT = NULL; oSRS.SetWellKnownGeogCS( "WGS84" ); oSRS.exportToWkt( &pszWKT ); poDstDS->SetProjection( pszWKT ); //遥感的一个波段 GDALRasterBand *poBand1 = poDstDS->GetRasterBand( 1 ); GDALRasterBand *poBand2 = poDstDS->GetRasterBand( 2 ); GDALRasterBand *poBand3 = poDstDS->GetRasterBand( 3 ); std::vector planes; cv::split(img, planes); //分波段输出数据到tiff文件 poBand1->RasterIO( GF_Write, 0, 0, img.cols, img.rows, planes[2].data, img.cols, img.rows, GDT_Byte, 0, 0 ); poBand2->RasterIO( GF_Write, 0, 0, img.cols, img.rows, planes[1].data, img.cols, img.rows, GDT_Byte, 0, 0 ); poBand3->RasterIO( GF_Write, 0, 0, img.cols, img.rows, planes[0].data, img.cols, img.rows, GDT_Byte, 0, 0 ); GDALFlushCache( poDstDS ); GDALClose( poDstDS ); GetGDALDriverManager()->DeregisterDriver(poDriver); GDALDestroyDriverManager(); poDstDS = NULL; poDriver = NULL; } return true; } catch(cv::Exception &e) { string str = e.msg; return false; } catch(...) { return false; } }