#include "stdafx.h"
#include "ImageOperatorBase.h"
#include "BaseTool.h"
#include "GeoOperator.h"
#include <Eigen/Core>
#include <Eigen/Dense>
#include <omp.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <gdal.h>
#include <gdal_utils.h>
#include <gdal_priv.h>
#include <gdalwarper.h>
#include <proj.h>
#include <string.h>
#include <memory>
#include <iostream>
#include "FileOperator.h"
#include <opencv2/opencv.hpp>
#include <QMessageBox>
#include <QDir>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <QProgressDialog>
#include <gdal_priv.h>
#include <ogr_spatialref.h>  // OGRSpatialReference ÓÃÓÚ¿Õ¼ä²Î¿¼×ª»»
#include <gdal_alg.h>        // ÓÃÓÚ GDALWarp ²Ù×÷





gdalImage::gdalImage()
{
	this->height = 0;
	this->width = 0;
	this->data_band_ids = 1;
	this->start_row = 0;
	this->start_col = 0;
}

/// <summary>
/// ½ï¿½Í¼½È¡Ó°ï¿½ï¿?1ï¿?7
/// </summary>
/// <param name="dem_path"></param>
gdalImage::gdalImage(const QString& raster_path)
{
	omp_lock_t lock;
	omp_init_lock(&lock); // ï¿½ï¿½Ê¼½ï¿½½ï¿½
	omp_set_lock(&lock);  // ï¿½ï¿½Ã»½ï¿½ï¿?1ï¿?7
	this->img_path = raster_path;

	GDALAllRegister();
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); // ×¢½Ê½ï¿½½ï¿½ï¿?1ï¿?7
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
	// ï¿½ï¿½DEMÓ°ï¿½ï¿½
	GDALDataset* rasterDataset = (GDALDataset*)(GDALOpen(raster_path.toUtf8().constData(), GA_ReadOnly));
	if (nullptr == rasterDataset || NULL == rasterDataset) {
		QMessageBox::warning(nullptr, u8"¾¯¸æ", QString(u8"ÎÄ¼þÎÞ·¨´ò¿ª£º") + QString(raster_path));
		exit(1);
	}
	this->width = rasterDataset->GetRasterXSize();
	this->height = rasterDataset->GetRasterYSize();
	this->band_num = rasterDataset->GetRasterCount();

	double* gt = new double[6];
	// ï¿½ï¿½Ã·½ï¿½ï¿½ï¿½
	rasterDataset->GetGeoTransform(gt);
	this->gt = Eigen::MatrixXd(2, 3);
	this->gt << gt[0], gt[1], gt[2], gt[3], gt[4], gt[5];

	this->projection = rasterDataset->GetProjectionRef();
	// ½ï¿½½ï¿½
	// double* inv_gt = new double[6];;
	// GDALInvGeoTransform(gt, inv_gt); // ½ï¿½½ï¿½
	// ½ï¿½Í¶Ó°
	GDALFlushCache((GDALDatasetH)rasterDataset);
	GDALClose((GDALDatasetH)rasterDataset);
	rasterDataset = NULL; // Ö¸½Ã¿ï¿½
	this->InitInv_gt();
	delete[] gt;
	GDALDestroy(); // or, DllMain at DLL_PROCESS_DETACH
	omp_unset_lock(&lock);	 // ï¿½Í·Å»ï¿½½ï¿½
	omp_destroy_lock(&lock); // ½Ù»ï¿½½ï¿½
}

gdalImage::~gdalImage() {}

void gdalImage::setHeight(int height)
{
	this->height = height;
}

void gdalImage::setWidth(int width)
{
	this->width = width;
}

void gdalImage::setTranslationMatrix(Eigen::MatrixXd gt)
{
	this->gt = gt;
}

void gdalImage::setData(Eigen::MatrixXd, int data_band_ids)
{
	this->data = data;
	this->data_band_ids = data_band_ids;
}

Eigen::MatrixXd gdalImage::getData(int start_row, int start_col, int rows_count, int cols_count,
	int band_ids = 1)
{
	omp_lock_t lock;
	omp_init_lock(&lock);
	omp_set_lock(&lock);
	GDALAllRegister();
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
	GDALDataset* rasterDataset = (GDALDataset*)(GDALOpen(
		this->img_path.toUtf8().constData(), GA_ReadOnly)); // ï¿½ï¿½Ö»½ï¿½Ê½ï¿½ï¿½È¡½ï¿½Ó°ï¿½ï¿½

	GDALDataType	gdal_datatype = rasterDataset->GetRasterBand(1)->GetRasterDataType();
	GDALRasterBand* demBand = rasterDataset->GetRasterBand(band_ids);

	rows_count = start_row + rows_count <= this->height ? rows_count : this->height - start_row;
	cols_count = start_col + cols_count <= this->width ? cols_count : this->width - start_col;

	Eigen::MatrixXd datamatrix(rows_count, cols_count);

	if (gdal_datatype == GDT_Byte) {
		char* temp = new char[rows_count * cols_count];
		demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
			rows_count, gdal_datatype, 0, 0);
		for (int i = 0; i < rows_count; i++) {
			for (int j = 0; j < cols_count; j++) {
				datamatrix(i, j) = long(temp[i * cols_count + j]) * 1.0;
			}
		}
		delete[] temp;
	}
	else if (gdal_datatype == GDT_UInt16) {
		unsigned short* temp = new unsigned short[rows_count * cols_count];
		demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
			rows_count, gdal_datatype, 0, 0);
		for (int i = 0; i < rows_count; i++) {
			for (int j = 0; j < cols_count; j++) {
				datamatrix(i, j) = long(temp[i * cols_count + j]) * 1.0;
			}
		}
		delete[] temp;
	}
	else if (gdal_datatype == GDT_Int16) {
		short* temp = new short[rows_count * cols_count];
		demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
			rows_count, gdal_datatype, 0, 0);
		for (int i = 0; i < rows_count; i++) {
			for (int j = 0; j < cols_count; j++) {
				datamatrix(i, j) = long(temp[i * cols_count + j]) * 1.0;
			}
		}
		delete[] temp;
	}
	else if (gdal_datatype == GDT_UInt32) {
		unsigned int* temp = new unsigned int[rows_count * cols_count];
		demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
			rows_count, gdal_datatype, 0, 0);
		for (int i = 0; i < rows_count; i++) {
			for (int j = 0; j < cols_count; j++) {
				datamatrix(i, j) = temp[i * cols_count + j];
			}
		}
		delete[] temp;
	}
	else if (gdal_datatype == GDT_Int32) {
		int* temp = new int[rows_count * cols_count];
		demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
			rows_count, gdal_datatype, 0, 0);
		for (int i = 0; i < rows_count; i++) {
			for (int j = 0; j < cols_count; j++) {
				datamatrix(i, j) = long(temp[i * cols_count + j]) * 1.0;
			}
		}
		delete[] temp;
	}
	//else if (gdal_datatype == GDT_UInt64) {
	//	unsigned long* temp = new unsigned long[rows_count * cols_count];
	//	demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
	//		rows_count, gdal_datatype, 0, 0); 	for (int i = 0; i < rows_count; i++) {
	//		for (int j = 0; j <
	//			cols_count; j++) {
	//			datamatrix(i, j) = temp[i * cols_count + j];
	//		}
	//	}
	//	delete[] temp;
	//}
	//else if (gdal_datatype == GDT_Int64) {
	//	long* temp = new long[rows_count * cols_count];
	//	demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
	//		rows_count, gdal_datatype, 0, 0); 	for (int i = 0; i < rows_count; i++) {
	//		for (int j = 0; j <
	//			cols_count; j++) {
	//			datamatrix(i, j) = temp[i * cols_count + j];
	//		}
	//	}
	//	delete[] temp;
	//}
	else if (gdal_datatype == GDT_Float32) {
		float* temp = new float[rows_count * cols_count];
		demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
			rows_count, gdal_datatype, 0, 0);

		for (int i = 0; i < rows_count; i++) {
			for (int j = 0; j < cols_count; j++) {
				datamatrix(i, j) = temp[i * cols_count + j];
			}
		}
		delete[] temp;
	}
	else if (gdal_datatype == GDT_Float64) {
		double* temp = new double[rows_count * cols_count];
		demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
			rows_count, gdal_datatype, 0, 0);

		for (int i = 0; i < rows_count; i++) {
			for (int j = 0; j < cols_count; j++) {
				datamatrix(i, j) = temp[i * cols_count + j];
			}
		}
		delete[] temp;
	}
	else {
	}
	GDALClose((GDALDatasetH)rasterDataset);
	omp_unset_lock(&lock);	 // ï¿½Í·Å»ï¿½½ï¿½
	omp_destroy_lock(&lock); // ½Ù»ï¿½½ï¿½
	GDALDestroy(); // or, DllMain at DLL_PROCESS_DETACH
	return datamatrix;
}

Eigen::MatrixXf gdalImage::getDataf(int start_row, int start_col, int rows_count, int cols_count,
	int band_ids = 1)
{
	omp_lock_t lock;
	omp_init_lock(&lock);
	omp_set_lock(&lock);
	GDALAllRegister();
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
	GDALDataset* rasterDataset = (GDALDataset*)(GDALOpen(
		this->img_path.toUtf8().constData(), GA_ReadOnly)); // ï¿½ï¿½Ö»½ï¿½Ê½ï¿½ï¿½È¡½ï¿½Ó°ï¿½ï¿½

	GDALDataType	gdal_datatype = rasterDataset->GetRasterBand(1)->GetRasterDataType();
	GDALRasterBand* demBand = rasterDataset->GetRasterBand(band_ids);

	rows_count = start_row + rows_count <= this->height ? rows_count : this->height - start_row;
	cols_count = start_col + cols_count <= this->width ? cols_count : this->width - start_col;

	Eigen::MatrixXf datamatrix(rows_count, cols_count);

	if (gdal_datatype == GDT_Byte) {
		char* temp = new char[rows_count * cols_count];
		demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
			rows_count, gdal_datatype, 0, 0);
		for (int i = 0; i < rows_count; i++) {
			for (int j = 0; j < cols_count; j++) {
				datamatrix(i, j) = temp[i * cols_count + j];
			}
		}
		delete[] temp;
	}
	else if (gdal_datatype == GDT_UInt16) {
		unsigned short* temp = new unsigned short[rows_count * cols_count];
		demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
			rows_count, gdal_datatype, 0, 0);
		for (int i = 0; i < rows_count; i++) {
			for (int j = 0; j < cols_count; j++) {
				datamatrix(i, j) = temp[i * cols_count + j];
			}
		}
		delete[] temp;
	}
	else if (gdal_datatype == GDT_Int16) {
		short* temp = new short[rows_count * cols_count];
		demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
			rows_count, gdal_datatype, 0, 0);
		for (int i = 0; i < rows_count; i++) {
			for (int j = 0; j < cols_count; j++) {
				datamatrix(i, j) = temp[i * cols_count + j];
			}
		}
		delete[] temp;
	}
	else if (gdal_datatype == GDT_UInt32) {
		unsigned int* temp = new unsigned int[rows_count * cols_count];
		demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
			rows_count, gdal_datatype, 0, 0);
		for (int i = 0; i < rows_count; i++) {
			for (int j = 0; j < cols_count; j++) {
				datamatrix(i, j) = temp[i * cols_count + j];
			}
		}
		delete[] temp;
	}
	else if (gdal_datatype == GDT_Int32) {
		int* temp = new int[rows_count * cols_count];
		demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
			rows_count, gdal_datatype, 0, 0);
		for (int i = 0; i < rows_count; i++) {
			for (int j = 0; j < cols_count; j++) {
				datamatrix(i, j) = temp[i * cols_count + j];
			}
		}
		delete[] temp;
	}
	//else if (gdal_datatype == GDT_UInt64) {
	//	unsigned long* temp = new unsigned long[rows_count * cols_count];
	//	demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
	//		rows_count, gdal_datatype, 0, 0); 	for (int i = 0; i < rows_count; i++) {
	//		for (int j = 0; j <
	//			cols_count; j++) {
	//			datamatrix(i, j) = temp[i * cols_count + j];
	//		}
	//	}
	//	delete[] temp;
	//}
	//else if (gdal_datatype == GDT_Int64) {
	//	long* temp = new long[rows_count * cols_count];
	//	demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
	//		rows_count, gdal_datatype, 0, 0); 	for (int i = 0; i < rows_count; i++) {
	//		for (int j = 0; j <
	//			cols_count; j++) {
	//			datamatrix(i, j) = temp[i * cols_count + j];
	//		}
	//	}
	//	delete[] temp;
	//}
	else if (gdal_datatype == GDT_Float32) {
		float* temp = new float[rows_count * cols_count];
		demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
			rows_count, gdal_datatype, 0, 0);

		for (int i = 0; i < rows_count; i++) {
			for (int j = 0; j < cols_count; j++) {
				datamatrix(i, j) = temp[i * cols_count + j];
			}
		}
		delete[] temp;
	}
	else if (gdal_datatype == GDT_Float64) {
		double* temp = new double[rows_count * cols_count];
		demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
			rows_count, gdal_datatype, 0, 0);

		for (int i = 0; i < rows_count; i++) {
			for (int j = 0; j < cols_count; j++) {
				datamatrix(i, j) = temp[i * cols_count + j];
			}
		}
		delete[] temp;
	}
	else {
	}
	GDALClose((GDALDatasetH)rasterDataset);
	omp_unset_lock(&lock);	 // ï¿½Í·Å»ï¿½½ï¿½
	omp_destroy_lock(&lock); // ½Ù»ï¿½½ï¿½
	GDALDestroy(); // or, DllMain at DLL_PROCESS_DETACH
	return datamatrix;
}



Eigen::MatrixXi gdalImage::getDatai(int start_row, int start_col, int rows_count, int cols_count, int band_ids)
{
	omp_lock_t lock;
	omp_init_lock(&lock);
	omp_set_lock(&lock);
	GDALAllRegister();
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
	GDALDataset* rasterDataset = (GDALDataset*)(GDALOpen(
		this->img_path.toUtf8().constData(), GA_ReadOnly)); // ï¿½ï¿½Ö»½ï¿½Ê½ï¿½ï¿½È¡½ï¿½Ó°ï¿½ï¿½

	GDALDataType	gdal_datatype = rasterDataset->GetRasterBand(1)->GetRasterDataType();
	GDALRasterBand* demBand = rasterDataset->GetRasterBand(band_ids);

	rows_count = start_row + rows_count <= this->height ? rows_count : this->height - start_row;
	cols_count = start_col + cols_count <= this->width ? cols_count : this->width - start_col;

	Eigen::MatrixXi datamatrix(rows_count, cols_count);

	if (gdal_datatype == GDT_Byte) {
		char* temp = new char[rows_count * cols_count];
		demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
			rows_count, gdal_datatype, 0, 0);
		for (int i = 0; i < rows_count; i++) {
			for (int j = 0; j < cols_count; j++) {
				datamatrix(i, j) = temp[i * cols_count + j];
			}
		}
		delete[] temp;
	}
	else if (gdal_datatype == GDT_UInt16) {
		unsigned short* temp = new unsigned short[rows_count * cols_count];
		demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
			rows_count, gdal_datatype, 0, 0);
		for (int i = 0; i < rows_count; i++) {
			for (int j = 0; j < cols_count; j++) {
				datamatrix(i, j) = temp[i * cols_count + j];
			}
		}
		delete[] temp;
	}
	else if (gdal_datatype == GDT_Int16) {
		short* temp = new short[rows_count * cols_count];
		demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
			rows_count, gdal_datatype, 0, 0);
		for (int i = 0; i < rows_count; i++) {
			for (int j = 0; j < cols_count; j++) {
				datamatrix(i, j) = temp[i * cols_count + j];
			}
		}
		delete[] temp;
	}
	else if (gdal_datatype == GDT_UInt32) {
		unsigned int* temp = new unsigned int[rows_count * cols_count];
		demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
			rows_count, gdal_datatype, 0, 0);
		for (int i = 0; i < rows_count; i++) {
			for (int j = 0; j < cols_count; j++) {
				datamatrix(i, j) = temp[i * cols_count + j];
			}
		}
		delete[] temp;
	}
	else if (gdal_datatype == GDT_Int32) {
		int* temp = new int[rows_count * cols_count];
		demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
			rows_count, gdal_datatype, 0, 0);
		for (int i = 0; i < rows_count; i++) {
			for (int j = 0; j < cols_count; j++) {
				datamatrix(i, j) = temp[i * cols_count + j];
			}
		}
		delete[] temp;
	}
	//else if (gdal_datatype == GDT_UInt64) {
	//	unsigned long* temp = new unsigned long[rows_count * cols_count];
	//	demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
	//		rows_count, gdal_datatype, 0, 0); 	for (int i = 0; i < rows_count; i++) {
	//		for (int j = 0; j <
	//			cols_count; j++) {
	//			datamatrix(i, j) = temp[i * cols_count + j];
	//		}
	//	}
	//	delete[] temp;
	//}
	//else if (gdal_datatype == GDT_Int64) {
	//	long* temp = new long[rows_count * cols_count];
	//	demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,	rows_count, gdal_datatype, 0, 0); 
	//	for (int i = 0; i < rows_count; i++) {
	//		for (int j = 0; j <	cols_count; j++) {
	//			datamatrix(i, j) = temp[i * cols_count + j];
	//		}
	//	}
	//	delete[] temp;
	//}
	else if (gdal_datatype == GDT_Float32) {
		float* temp = new float[rows_count * cols_count];
		demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
			rows_count, gdal_datatype, 0, 0);

		for (int i = 0; i < rows_count; i++) {
			for (int j = 0; j < cols_count; j++) {
				datamatrix(i, j) = temp[i * cols_count + j];
			}
		}
		delete[] temp;
	}
	else if (gdal_datatype == GDT_Float64) {
		double* temp = new double[rows_count * cols_count];
		demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count,
			rows_count, gdal_datatype, 0, 0);

		for (int i = 0; i < rows_count; i++) {
			for (int j = 0; j < cols_count; j++) {
				datamatrix(i, j) = temp[i * cols_count + j];
			}
		}
		delete[] temp;
	}
	else {
	}
	GDALClose((GDALDatasetH)rasterDataset);
	omp_unset_lock(&lock);	 // ï¿½Í·Å»ï¿½½ï¿½
	omp_destroy_lock(&lock); // ½Ù»ï¿½½ï¿½
	GDALDestroy(); // or, DllMain at DLL_PROCESS_DETACH
	return datamatrix;
}

ErrorCode gdalImage::getData(double* data, int start_row, int start_col, int rows_count, int cols_count, int band_ids)
{
	ErrorCode state = ErrorCode::SUCCESS;
	omp_lock_t lock;
	omp_init_lock(&lock);
	omp_set_lock(&lock);
	GDALAllRegister();
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
	GDALDataset* rasterDataset = (GDALDataset*)(GDALOpen(this->img_path.toUtf8().constData(), GA_ReadOnly)); // ï¿½ï¿½Ö»½ï¿½Ê½ï¿½ï¿½È¡½ï¿½Ó°ï¿½ï¿½

	GDALDataType	gdal_datatype = rasterDataset->GetRasterBand(1)->GetRasterDataType();
	GDALRasterBand* demBand = rasterDataset->GetRasterBand(band_ids);

	rows_count = start_row + rows_count <= this->height ? rows_count : this->height - start_row;
	cols_count = start_col + cols_count <= this->width ? cols_count : this->width - start_col;



	if (gdal_datatype == GDT_Float64) {
		demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, data, cols_count, rows_count, gdal_datatype, 0, 0);
	}
	else {
		state = ErrorCode::FAIL;
	}
	GDALClose((GDALDatasetH)rasterDataset);
	omp_unset_lock(&lock);	 // ï¿½Í·Å»ï¿½½ï¿½
	omp_destroy_lock(&lock); // ½Ù»ï¿½½ï¿½
	return state;
}

ErrorCode gdalImage::getData(long* data, int start_row, int start_col, int rows_count, int cols_count, int band_ids)
{
	ErrorCode state = ErrorCode::SUCCESS;
	omp_lock_t lock;
	omp_init_lock(&lock);
	omp_set_lock(&lock);
	GDALAllRegister();
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
	GDALDataset* rasterDataset = (GDALDataset*)(GDALOpen(this->img_path.toUtf8().constData(), GA_ReadOnly)); // ï¿½ï¿½Ö»½ï¿½Ê½ï¿½ï¿½È¡½ï¿½Ó°ï¿½ï¿½

	GDALDataType	gdal_datatype = rasterDataset->GetRasterBand(1)->GetRasterDataType();
	GDALRasterBand* demBand = rasterDataset->GetRasterBand(band_ids);

	rows_count = start_row + rows_count <= this->height ? rows_count : this->height - start_row;
	cols_count = start_col + cols_count <= this->width ? cols_count : this->width - start_col;

	if (gdal_datatype == GDT_Int32) {
		demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, data, cols_count, rows_count, gdal_datatype, 0, 0);
	}
	else {
		state = ErrorCode::FAIL;
	}
	GDALClose((GDALDatasetH)rasterDataset);
	omp_unset_lock(&lock);	 // ï¿½Í·Å»ï¿½½ï¿½
	omp_destroy_lock(&lock); // ½Ù»ï¿½½ï¿½
	return state;
}

Eigen::MatrixXd gdalImage::getGeoTranslation()
{
	return this->gt;
}

GDALDataType gdalImage::getDataType()
{
	GDALDataset* rasterDataset =
		(GDALDataset*)(GDALOpen(this->img_path.toUtf8().constData(), GA_ReadOnly));
	GDALDataType gdal_datatype = rasterDataset->GetRasterBand(1)->GetRasterDataType();
	return gdal_datatype;
}

/// <summary>
/// 
/// </summary>
/// <param name="data"></param>
/// <param name="start_row"></param>
/// <param name="start_col"></param>
/// <param name="band_ids"></param>
void gdalImage::saveImage(Eigen::MatrixXd data, int start_row = 0, int start_col = 0,
	int band_ids = 1)
{
	GDALDataType datetype = this->getDataType();
	omp_lock_t lock;
	omp_init_lock(&lock);
	omp_set_lock(&lock);
	if (start_row + data.rows() > this->height || start_col + data.cols() > this->width) {
		QString tip = u8"file path: " + this->img_path + " image size :(  " + QString::number(this->height) + " , " + QString::number(this->width) + " ) " + " input size (" + QString::number(start_row + data.rows()) + ", " + QString::number(start_col + data.cols()) + ") ";
		qDebug() << tip;
		throw std::exception(tip.toUtf8().constData());
	}
	GDALAllRegister();
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");

	QString filesuffer = getFileExtension(this->img_path).toLower();
	bool isTiff = filesuffer.contains("tif");
	GDALDriver* poDriver = isTiff ? GetGDALDriverManager()->GetDriverByName("GTiff") : GetGDALDriverManager()->GetDriverByName("ENVI");
	GDALDataset* poDstDS = nullptr;
	if (exists_test(this->img_path)) {
		poDstDS = (GDALDataset*)(GDALOpen(this->img_path.toUtf8().constData(), GA_Update));
	}
	else {
		poDstDS = poDriver->Create(this->img_path.toUtf8().constData(), this->width, this->height,
			this->band_num, datetype, NULL); // ½ï¿½ï¿½ï¿½

		if (nullptr == poDstDS) {
			QString tip = u8"file path: " + this->img_path + " image size :(  " + QString::number(this->height) + " , " + QString::number(this->width) + " ) " + " input size (" + QString::number(start_row + data.rows()) + ", " + QString::number(start_col + data.cols()) + ") ";
			qDebug() << tip;
			throw std::exception(tip.toUtf8().constData());
			return;
		}

		poDstDS->SetProjection(this->projection.toUtf8().constData());

		double gt_ptr[6];
		for (int i = 0; i < this->gt.rows(); i++) {
			for (int j = 0; j < this->gt.cols(); j++) {
				gt_ptr[i * 3 + j] = this->gt(i, j);
			}
		}
		poDstDS->SetGeoTransform(gt_ptr);
		//delete gt_ptr;
	}


	int	   datarows = data.rows();
	int	   datacols = data.cols();
	void* databuffer = nullptr;
	if (datetype == GDT_Float32) {
		databuffer = new float[datarows * datacols];
		for (int i = 0; i < datarows; i++) {
			for (int j = 0; j < datacols; j++) {
				((float*)databuffer)[i * datacols + j] = float(data(i, j));
			}
		}

		poDstDS->GetRasterBand(band_ids)->RasterIO(GF_Write, start_col, start_row, datacols, datarows,
			databuffer, datacols, datarows, datetype, 0, 0);
	}
	else if (datetype == GDT_Float64) {
		databuffer = new double[datarows * datacols];
		for (int i = 0; i < datarows; i++) {
			for (int j = 0; j < datacols; j++) {
				((double*)databuffer)[i * datacols + j] = double(data(i, j));
			}
		}

		poDstDS->GetRasterBand(band_ids)->RasterIO(GF_Write, start_col, start_row, datacols, datarows,
			databuffer, datacols, datarows, datetype, 0, 0);
	}
	else {

	}
	GDALFlushCache(poDstDS);
	GDALClose((GDALDatasetH)poDstDS);
	GDALDestroy(); // or, DllMain at DLL_PROCESS_DETACH
	delete[] databuffer;
	omp_unset_lock(&lock);	 // ï¿½Í·Å»ï¿½½ï¿½
	omp_destroy_lock(&lock); // ½Ù»ï¿½½ï¿½
}

void gdalImage::saveImage(Eigen::MatrixXf data, int start_row = 0, int start_col = 0,
	int band_ids = 1)
{
	GDALDataType datetype = this->getDataType();
	omp_lock_t lock;
	omp_init_lock(&lock);
	omp_set_lock(&lock);
	if (start_row + data.rows() > this->height || start_col + data.cols() > this->width) {
		QString tip = u8"file path: " + this->img_path + " image size :(  " + QString::number(this->height) + " , " + QString::number(this->width) + " ) " + " input size (" + QString::number(start_row + data.rows()) + ", " + QString::number(start_col + data.cols()) + ") ";
		qDebug() << tip;
		throw std::exception(tip.toUtf8().constData());
	}
	GDALAllRegister();
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
	QString filesuffer = getFileExtension(this->img_path).toLower();
	bool isTiff = filesuffer.contains("tif");
	GDALDriver* poDriver = isTiff ? GetGDALDriverManager()->GetDriverByName("GTiff") : GetGDALDriverManager()->GetDriverByName("ENVI");
	GDALDataset* poDstDS = nullptr;
	if (exists_test(this->img_path)) {
		poDstDS = (GDALDataset*)(GDALOpen(this->img_path.toUtf8().constData(), GA_Update));
	}
	else {
		poDstDS = poDriver->Create(this->img_path.toUtf8().constData(), this->width, this->height,
			this->band_num, datetype, NULL); // ½ï¿½ï¿½ï¿½

		if (nullptr == poDstDS) {
			QString tip = u8"file path: " + this->img_path + " image size :(  " + QString::number(this->height) + " , " + QString::number(this->width) + " ) " + " input size (" + QString::number(start_row + data.rows()) + ", " + QString::number(start_col + data.cols()) + ") ";
			qDebug() << tip;
			throw std::exception(tip.toUtf8().constData());
			return;
		}

		poDstDS->SetProjection(this->projection.toUtf8().constData());

		double gt_ptr[6];
		for (int i = 0; i < this->gt.rows(); i++) {
			for (int j = 0; j < this->gt.cols(); j++) {
				gt_ptr[i * 3 + j] = this->gt(i, j);
			}
		}
		poDstDS->SetGeoTransform(gt_ptr);
		//delete gt_ptr;
	}


	int	   datarows = data.rows();
	int	   datacols = data.cols();
	void* databuffer = nullptr;
	if (datetype == GDT_Float32) {
		databuffer = new float[datarows * datacols];
		for (int i = 0; i < datarows; i++) {
			for (int j = 0; j < datacols; j++) {
				((float*)databuffer)[i * datacols + j] = float(data(i, j));
			}
		}

		poDstDS->GetRasterBand(band_ids)->RasterIO(GF_Write, start_col, start_row, datacols, datarows,
			databuffer, datacols, datarows, datetype, 0, 0);
	}
	else if (datetype == GDT_Float64) {
		databuffer = new double[datarows * datacols];
		for (int i = 0; i < datarows; i++) {
			for (int j = 0; j < datacols; j++) {
				((double*)databuffer)[i * datacols + j] = double(data(i, j));
			}
		}

		poDstDS->GetRasterBand(band_ids)->RasterIO(GF_Write, start_col, start_row, datacols, datarows,
			databuffer, datacols, datarows, datetype, 0, 0);
	}
	else {

	}
	GDALFlushCache(poDstDS);
	GDALClose((GDALDatasetH)poDstDS);
	GDALDestroy(); // or, DllMain at DLL_PROCESS_DETACH
	delete[] databuffer;
	omp_unset_lock(&lock);	 // ï¿½Í·Å»ï¿½½ï¿½
	omp_destroy_lock(&lock); // ½Ù»ï¿½½ï¿½
}


void gdalImage::saveImage(Eigen::MatrixXi data, int start_row, int start_col, int band_ids)
{
	GDALDataType datetype = this->getDataType();
	omp_lock_t lock;
	omp_init_lock(&lock);
	omp_set_lock(&lock);
	if (start_row + data.rows() > this->height || start_col + data.cols() > this->width) {
		QString tip = u8"file path: " + this->img_path + " image size :(  " + QString::number(this->height) + " , " + QString::number(this->width) + " ) " + " input size (" + QString::number(start_row + data.rows()) + ", " + QString::number(start_col + data.cols()) + ") ";
		qDebug() << tip;
		throw std::exception(tip.toUtf8().constData());
	}
	GDALAllRegister();
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
	QString filesuffer = getFileExtension(this->img_path).toLower();
	bool isTiff = filesuffer.contains("tif");
	GDALDriver* poDriver = isTiff ? GetGDALDriverManager()->GetDriverByName("GTiff") : GetGDALDriverManager()->GetDriverByName("ENVI");
	GDALDataset* poDstDS = nullptr;
	if (exists_test(this->img_path)) {
		poDstDS = (GDALDataset*)(GDALOpen(this->img_path.toUtf8().constData(), GA_Update));
	}
	else {
		poDstDS = poDriver->Create(this->img_path.toUtf8().constData(), this->width, this->height,
			this->band_num, GDT_Float32, NULL); // ½ï¿½ï¿½ï¿½
		poDstDS->SetProjection(this->projection.toUtf8().constData());

		double gt_ptr[6];
		for (int i = 0; i < this->gt.rows(); i++) {
			for (int j = 0; j < this->gt.cols(); j++) {
				gt_ptr[i * 3 + j] = this->gt(i, j);
			}
		}
		poDstDS->SetGeoTransform(gt_ptr);
		//delete gt_ptr;
	}

	long	   datarows = data.rows();
	long	   datacols = data.cols();

	long* databuffer = new long[datarows * datacols]; // (float*)malloc(datarows * datacols * sizeof(float));

	for (long i = 0; i < datarows; i++) {
		for (long j = 0; j < datacols; j++) {
			databuffer[i * datacols + j] = data(i, j);
		}
	}
	// poDstDS->RasterIO(GF_Write,start_col, start_row, datacols, datarows, databuffer, datacols,
	// datarows, GDT_Float32,band_ids, num,0,0,0);
	poDstDS->GetRasterBand(band_ids)->RasterIO(GF_Write, start_col, start_row, datacols, datarows,
		databuffer, datacols, datarows, datetype, 0, 0);

	GDALFlushCache(poDstDS);
	GDALClose((GDALDatasetH)poDstDS);
	GDALDestroy(); // or, DllMain at DLL_PROCESS_DETACH
	delete[] databuffer;
	omp_unset_lock(&lock);	 // ï¿½Í·Å»ï¿½½ï¿½
	omp_destroy_lock(&lock); // ½Ù»ï¿½½ï¿½
}

void gdalImage::saveImage(std::shared_ptr<double> data, int start_row, int start_col, int rowcount, int colcount, int band_ids)
{
	GDALDataType datetype = this->getDataType();
	omp_lock_t lock;
	omp_init_lock(&lock);
	omp_set_lock(&lock);
	if (start_row + rowcount > this->height || start_col + colcount > this->width) {
		QString tip = u8"file path: " + this->img_path + " image size :(  " + QString::number(this->height) + " , " + QString::number(this->width) + " ) " + " input size (" + QString::number(start_row + rowcount) + ", " + QString::number(start_col + colcount) + ") ";
		qDebug() << tip;
		throw std::exception(tip.toUtf8().constData());
	}
	GDALAllRegister();
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
	QString filesuffer = getFileExtension(this->img_path).toLower();
	bool isTiff = filesuffer.contains("tif");
	GDALDriver* poDriver = isTiff ? GetGDALDriverManager()->GetDriverByName("GTiff") : GetGDALDriverManager()->GetDriverByName("ENVI");
	GDALDataset* poDstDS = nullptr;
	if (exists_test(this->img_path)) {
		poDstDS = (GDALDataset*)(GDALOpen(this->img_path.toUtf8().constData(), GA_Update));
	}
	else {
		poDstDS = poDriver->Create(this->img_path.toUtf8().constData(), this->width, this->height,
			this->band_num, GDT_Float64, NULL); // ½ï¿½ï¿½ï¿½
		poDstDS->SetProjection(this->projection.toUtf8().constData());

		double gt_ptr[6];
		for (int i = 0; i < this->gt.rows(); i++) {
			for (int j = 0; j < this->gt.cols(); j++) {
				gt_ptr[i * 3 + j] = this->gt(i, j);
			}
		}
		poDstDS->SetGeoTransform(gt_ptr);
	}

	long datarows = rowcount;
	long datacols = colcount;
	double* databuffer = new double[datarows * datacols];
	if (datetype == GDT_Float64) {
		memcpy(databuffer, data.get(), sizeof(double) * datarows * datacols);
	}
	else {
		for (long i = 0; i < datarows; i++) {
			for (long j = 0; j < datacols; j++) {
				databuffer[i * datacols + j] = data.get()[i * datacols + j];
			}
		}
	}

	// poDstDS->RasterIO(GF_Write,start_col, start_row, datacols, datarows, databuffer, datacols,
	// datarows, GDT_Float32,band_ids, num,0,0,0);
	poDstDS->GetRasterBand(band_ids)->RasterIO(GF_Write, start_col, start_row, datacols, datarows,
		databuffer, datacols, datarows, datetype, 0, 0);

	GDALFlushCache(poDstDS);
	GDALClose((GDALDatasetH)poDstDS);
	GDALDestroy(); // or, DllMain at DLL_PROCESS_DETACH
	delete[] databuffer;
	omp_unset_lock(&lock);	 // ï¿½Í·Å»ï¿½½ï¿½
	omp_destroy_lock(&lock); // ½Ù»ï¿½½ï¿½
}

void gdalImage::saveImage(std::shared_ptr<float> data, int start_row, int start_col, int rowcount, int colcount, int band_ids)
{
	GDALDataType datetype = this->getDataType();
	omp_lock_t lock;
	omp_init_lock(&lock);
	omp_set_lock(&lock);
	if (start_row + rowcount > this->height || start_col + colcount > this->width) {
		QString tip = u8"file path: " + this->img_path + " image size :(  " + QString::number(this->height) + " , " + QString::number(this->width) + " ) " + " input size (" + QString::number(start_row + rowcount) + ", " + QString::number(start_col + colcount) + ") ";
		qDebug() << tip;
		throw std::exception(tip.toUtf8().constData());
	}
	GDALAllRegister();
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
	QString filesuffer = getFileExtension(this->img_path).toLower();
	bool isTiff = filesuffer.contains("tif");
	GDALDriver* poDriver = isTiff ? GetGDALDriverManager()->GetDriverByName("GTiff") : GetGDALDriverManager()->GetDriverByName("ENVI");
	GDALDataset* poDstDS = nullptr;
	if (exists_test(this->img_path)) {
		poDstDS = (GDALDataset*)(GDALOpen(this->img_path.toUtf8().constData(), GA_Update));
	}
	else {
		poDstDS = poDriver->Create(this->img_path.toUtf8().constData(), this->width, this->height,
			this->band_num, GDT_Float32, NULL); // ½ï¿½ï¿½ï¿½
		poDstDS->SetProjection(this->projection.toUtf8().constData());

		double gt_ptr[6];
		for (int i = 0; i < this->gt.rows(); i++) {
			for (int j = 0; j < this->gt.cols(); j++) {
				gt_ptr[i * 3 + j] = this->gt(i, j);
			}
		}
		poDstDS->SetGeoTransform(gt_ptr);
	}

	long datarows = rowcount;
	long datacols = colcount;
	float* databuffer = new float[datarows * datacols];
	if (datetype == GDT_Float32) {
		memcpy(databuffer, data.get(), sizeof(float) * datarows * datacols);
	}
	else {
		for (long i = 0; i < datarows; i++) {
			for (long j = 0; j < datacols; j++) {
				databuffer[i * datacols + j] = data.get()[i * datacols + j];
			}
		}
	}

	// poDstDS->RasterIO(GF_Write,start_col, start_row, datacols, datarows, databuffer, datacols,
	// datarows, GDT_Float32,band_ids, num,0,0,0);
	poDstDS->GetRasterBand(band_ids)->RasterIO(GF_Write, start_col, start_row, datacols, datarows,
		databuffer, datacols, datarows, datetype, 0, 0);

	GDALFlushCache(poDstDS);
	GDALClose((GDALDatasetH)poDstDS);
	//delete poDstDS;
	//poDstDS = nullptr;
	GDALDestroy(); // or, DllMain at DLL_PROCESS_DETACH
	delete[] databuffer;
	omp_unset_lock(&lock);	 // ï¿½Í·Å»ï¿½½ï¿½
	omp_destroy_lock(&lock); // ½Ù»ï¿½½ï¿½
}


void gdalImage::saveImage(std::shared_ptr<int> data, int start_row, int start_col, int rowcount, int colcount, int band_ids)
{
	GDALDataType datetype = this->getDataType();
	omp_lock_t lock;
	omp_init_lock(&lock);
	omp_set_lock(&lock);
	if (start_row + rowcount > this->height || start_col + colcount > this->width) {
		QString tip = u8"file path: " + this->img_path + " image size :(  " + QString::number(this->height) + " , " + QString::number(this->width) + " ) " + " input size (" + QString::number(start_row + rowcount) + ", " + QString::number(start_col + colcount) + ") ";
		qDebug() << tip;
		throw std::exception(tip.toUtf8().constData());
	}
	GDALAllRegister();
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
	QString filesuffer = getFileExtension(this->img_path).toLower();
	bool isTiff = filesuffer.contains("tif");
	GDALDriver* poDriver = isTiff ? GetGDALDriverManager()->GetDriverByName("GTiff") : GetGDALDriverManager()->GetDriverByName("ENVI");
	GDALDataset* poDstDS = nullptr;
	if (exists_test(this->img_path)) {
		poDstDS = (GDALDataset*)(GDALOpen(this->img_path.toUtf8().constData(), GA_Update));
	}
	else {
		poDstDS = poDriver->Create(this->img_path.toUtf8().constData(), this->width, this->height,
			this->band_num, GDT_Float32, NULL); // ½ï¿½ï¿½ï¿½
		poDstDS->SetProjection(this->projection.toUtf8().constData());

		double gt_ptr[6];
		for (int i = 0; i < this->gt.rows(); i++) {
			for (int j = 0; j < this->gt.cols(); j++) {
				gt_ptr[i * 3 + j] = this->gt(i, j);
			}
		}
		poDstDS->SetGeoTransform(gt_ptr);
	}

	long datarows = rowcount;
	long datacols = colcount;
	int* databuffer = new int[datarows * datacols];
	if (datetype == GDT_Int32) {
		memcpy(databuffer, data.get(), sizeof(int) * datarows * datacols);
	}
	else {
		for (long i = 0; i < datarows; i++) {
			for (long j = 0; j < datacols; j++) {
				databuffer[i * datacols + j] = data.get()[i * datacols + j];
			}
		}
	}

	// poDstDS->RasterIO(GF_Write,start_col, start_row, datacols, datarows, databuffer, datacols,
	// datarows, GDT_Float32,band_ids, num,0,0,0);
	poDstDS->GetRasterBand(band_ids)->RasterIO(GF_Write, start_col, start_row, datacols, datarows,
		databuffer, datacols, datarows, datetype, 0, 0);

	GDALFlushCache(poDstDS);
	GDALClose((GDALDatasetH)poDstDS);
	GDALDestroy(); // or, DllMain at DLL_PROCESS_DETACH
	delete[] databuffer;
	omp_unset_lock(&lock);	 // ï¿½Í·Å»ï¿½½ï¿½
	omp_destroy_lock(&lock); // ½Ù»ï¿½½ï¿½
}


void gdalImage::saveImage()
{
	this->saveImage(this->data, this->start_row, this->start_col, this->data_band_ids);
}




void gdalImage::setNoDataValue(double nodatavalue = -9999, int band_ids = 1)
{
	GDALAllRegister();
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); // ×¢½Ê½ï¿½½ï¿½ï¿?1ï¿?7
	// GDALDriver* poDriver = GetGDALDriverManager()->GetDriverByName("GTiff");
	GDALDataset* poDstDS = (GDALDataset*)(GDALOpen(img_path.toUtf8().constData(), GA_Update));
	poDstDS->GetRasterBand(band_ids)->SetNoDataValue(nodatavalue);
	GDALFlushCache((GDALDatasetH)poDstDS);
	GDALClose((GDALDatasetH)poDstDS);
}

void gdalImage::setNoDataValuei(int nodatavalue, int band_ids)
{
	GDALAllRegister();
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); // ×¢½Ê½ï¿½½ï¿½ï¿?1ï¿?7
	// GDALDriver* poDriver = GetGDALDriverManager()->GetDriverByName("GTiff");
	GDALDataset* poDstDS = (GDALDataset*)(GDALOpen(img_path.toUtf8().constData(), GA_Update));
	poDstDS->GetRasterBand(band_ids)->SetNoDataValue(nodatavalue);
	GDALFlushCache((GDALDatasetH)poDstDS);
	GDALClose((GDALDatasetH)poDstDS);
}

double gdalImage::getNoDataValue(int band_ids)
{
	GDALAllRegister();
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); // ×¢½Ê½ï¿½½ï¿½ï¿?1ï¿?7
	// GDALDriver* poDriver = GetGDALDriverManager()->GetDriverByName("GTiff");
	GDALDataset* poDstDS = (GDALDataset*)(GDALOpen(img_path.toUtf8().constData(), GA_Update));
	double v = poDstDS->GetRasterBand(band_ids)->GetNoDataValue();
	GDALFlushCache((GDALDatasetH)poDstDS);
	GDALClose((GDALDatasetH)poDstDS);
	return v;
}

int gdalImage::getNoDataValuei(int band_ids)
{
	GDALAllRegister();
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); // ×¢½Ê½ï¿½½ï¿½ï¿?1ï¿?7
	// GDALDriver* poDriver = GetGDALDriverManager()->GetDriverByName("GTiff");
	GDALDataset* poDstDS = (GDALDataset*)(GDALOpen(img_path.toUtf8().constData(), GA_Update));
	int v = poDstDS->GetRasterBand(band_ids)->GetNoDataValue();
	GDALFlushCache((GDALDatasetH)poDstDS);
	GDALClose((GDALDatasetH)poDstDS);
	return v;
}


int gdalImage::InitInv_gt()
{
	// 1 lon lat = x
	// 1 lon lat = y
	Eigen::MatrixXd temp = Eigen::MatrixXd::Zero(2, 3);
	this->inv_gt = temp;
	double a = this->gt(0, 0);
	double b = this->gt(0, 1);
	double c = this->gt(0, 2);
	double d = this->gt(1, 0);
	double e = this->gt(1, 1);
	double f = this->gt(1, 2);
	double g = 1;
	double det_gt = b * f - c * e;
	if (det_gt == 0) {
		return 0;
	}
	this->inv_gt(0, 0) = (c * d - a * f) / det_gt; // 2
	this->inv_gt(0, 1) = f / det_gt;			   // lon
	this->inv_gt(0, 2) = -c / det_gt;			   // lat
	this->inv_gt(1, 0) = (a * e - b * d) / det_gt; // 1
	this->inv_gt(1, 1) = -e / det_gt;			   // lon
	this->inv_gt(1, 2) = b / det_gt;			   // lat
	return 1;
}

Landpoint gdalImage::getRow_Col(double lon, double lat)
{
	Landpoint p{ 0, 0, 0 };
	p.lon = this->inv_gt(0, 0) + lon * this->inv_gt(0, 1) + lat * this->inv_gt(0, 2); // x
	p.lat = this->inv_gt(1, 0) + lon * this->inv_gt(1, 1) + lat * this->inv_gt(1, 2); // y
	return p;
}

Landpoint gdalImage::getLandPoint(double row, double col, double ati = 0)
{
	Landpoint p{ 0, 0, 0 };
	p.lon = this->gt(0, 0) + col * this->gt(0, 1) + row * this->gt(0, 2); // x
	p.lat = this->gt(1, 0) + col * this->gt(1, 1) + row * this->gt(1, 2); // y
	p.ati = ati;
	return p;
}

void gdalImage::getLandPoint(double  row, double  col, double  ati, Landpoint& Lp)
{
	Lp.lon = this->gt(0, 0) + col * this->gt(0, 1) + row * this->gt(0, 2); // x
	Lp.lat = this->gt(1, 0) + col * this->gt(1, 1) + row * this->gt(1, 2); // y
	Lp.ati = ati;

}






double gdalImage::mean(int bandids)
{
	double mean_value = 0;
	double count = this->height * this->width;
	int	   line_invert = 100;
	int	   start_ids = 0;
	do {
		Eigen::MatrixXd sar_a = this->getData(start_ids, 0, line_invert, this->width, bandids);
		mean_value = mean_value + sar_a.sum() / count;
		start_ids = start_ids + line_invert;
	} while (start_ids < this->height);
	return mean_value;
}

double gdalImage::BandmaxValue(int bandids)
{
	double max_value = 0;
	bool   state_max = true;
	int	   line_invert = 100;
	int	   start_ids = 0;
	double temp_max = 0;
	do {
		Eigen::MatrixXd sar_a = this->getData(start_ids, 0, line_invert, this->width, bandids);
		if (state_max) {
			state_max = false;
			max_value = sar_a.maxCoeff();
		}
		else {
			temp_max = sar_a.maxCoeff();
			if (max_value < temp_max) {
				max_value = temp_max;
			}
		}
		start_ids = start_ids + line_invert;
	} while (start_ids < this->height);
	return max_value;
}

double gdalImage::BandminValue(int bandids)
{
	double min_value = 0;
	bool   state_min = true;
	int	   line_invert = 100;
	int	   start_ids = 0;
	double temp_min = 0;
	do {
		Eigen::MatrixXd sar_a = this->getData(start_ids, 0, line_invert, this->width, bandids);
		if (state_min) {
			state_min = false;
			min_value = sar_a.minCoeff();
		}
		else {
			temp_min = sar_a.minCoeff();
			if (min_value < temp_min) {
				min_value = temp_min;
			}
		}
		start_ids = start_ids + line_invert;
	} while (start_ids < this->height);
	return min_value;
}

GDALRPCInfo gdalImage::getRPC()
{
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");
	CPLSetConfigOption("GDAL_DATA", "./data");
	GDALAllRegister();
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); // ×¢½ï¿½ï¿½ï¿½
	// ½ï¿½ï¿½ï¿½
	GDALDataset* pDS = (GDALDataset*)GDALOpen(this->img_path.toUtf8().constData(), GA_ReadOnly);
	// ï¿½ï¿½Ôª½ï¿½ï¿½Ð»ï¿½È¡RPCï¿½ï¿½Ï¢
	char** papszRPC = pDS->GetMetadata("RPC");

	// ½ï¿½È¡ï¿½ï¿½RPCï¿½ï¿½Ï¢½ï¿½É½á¹¹ï¿½ï¿?1ï¿?7
	GDALRPCInfo	 oInfo;
	GDALExtractRPCInfo(papszRPC, &oInfo);

	GDALClose((GDALDatasetH)pDS);

	return oInfo;
}

Eigen::MatrixXd gdalImage::getLandPoint(Eigen::MatrixXd points)
{
	if (points.cols() != 3) {
		throw new std::exception("the size of points is equit 3!!!");
	}

	Eigen::MatrixXd result(points.rows(), 3);
	result.col(2) = points.col(2); // ï¿½ß³ï¿½
	points.col(2) = points.col(2).array() * 0 + 1;
	points.col(0).swap(points.col(2)); // ½ï¿½
	Eigen::MatrixXd gts(3, 2);
	gts.col(0) = this->gt.row(0);
	gts.col(1) = this->gt.row(1);

	result.block(0, 0, points.rows(), 2) = points * gts;
	return result;
}

Eigen::MatrixXd gdalImage::getHist(int bandids)
{
	GDALAllRegister();
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); // ×¢½Ê½ï¿½½ï¿½ï¿?1ï¿?7
	// ï¿½ï¿½DEMÓ°ï¿½ï¿½
	GDALDataset* rasterDataset = (GDALDataset*)(GDALOpen(
		this->img_path.toUtf8().constData(), GA_ReadOnly)); // ï¿½ï¿½Ö»½ï¿½Ê½ï¿½ï¿½È¡½ï¿½Ó°ï¿½ï¿½

	GDALDataType	gdal_datatype = rasterDataset->GetRasterBand(1)->GetRasterDataType();
	GDALRasterBand* xBand = rasterDataset->GetRasterBand(bandids);

	double			dfMin = this->BandminValue(bandids);
	double			dfMax = this->BandmaxValue(bandids);
	int				count = int((dfMax - dfMin) / 0.01);
	count = count > 255 ? count : 255;
	GUIntBig* panHistogram = new GUIntBig[count];
	xBand->GetHistogram(dfMin, dfMax, count, panHistogram, TRUE, FALSE, NULL, NULL);
	Eigen::MatrixXd result(count, 2);
	double			delta = (dfMax - dfMin) / count;
	for (int i = 0; i < count; i++) {
		result(i, 0) = dfMin + i * delta;
		result(i, 1) = double(panHistogram[i]);
	}
	delete[] panHistogram;
	GDALClose((GDALDatasetH)rasterDataset);
	return result;
}

RasterExtend gdalImage::getExtend()
{
	RasterExtend extend{ 0,0,0,0 };
	double x1 = this->gt(0, 0);
	double y1 = this->gt(1, 0);

	double x2 = this->gt(0, 0) + (this->width - 1) * gt(0, 1) + (0) * gt(0, 2); // ¾­
	double y2 = this->gt(1, 0) + (this->width - 1) * gt(1, 1) + (0) * gt(1, 2); // Î³

	double x3 = this->gt(0, 0) + (0) * gt(0, 1) + (this->height - 1) * gt(0, 2);
	double y3 = this->gt(1, 0) + (0) * gt(1, 1) + (this->height - 1) * gt(1, 2);

	double x4 = this->gt(0, 0) + (this->width - 1) * gt(0, 1) + (this->height - 1) * gt(0, 2);
	double y4 = this->gt(1, 0) + (this->width - 1) * gt(1, 1) + (this->height - 1) * gt(1, 2);


	extend.min_x = x1 < x2 ? x1 : x2;
	extend.max_x = x1 < x2 ? x2 : x1;
	extend.min_y = y1 < y2 ? y1 : y2;
	extend.max_y = y1 < y2 ? y2 : y1;


	extend.min_x = extend.min_x < x3 ? extend.min_x : x3;
	extend.max_x = extend.max_x > x3 ? extend.max_x : x3;
	extend.min_y = extend.min_y < y3 ? extend.min_y : y3;
	extend.max_y = extend.max_y > y3 ? extend.max_y : y3;


	extend.min_x = extend.min_x < x4 ? extend.min_x : x4;
	extend.max_x = extend.max_x > x4 ? extend.max_x : x4;
	extend.min_y = extend.min_y < y4 ? extend.min_y : y4;
	extend.max_y = extend.max_y > y4 ? extend.max_y : y4;

	return extend;
}






gdalImage  CreategdalImageDouble(QString& img_path, int height, int width, int band_num, bool overwrite, bool isEnvi)
{

	if (exists_test(img_path.toUtf8().constData())) {
		if (overwrite) {
			gdalImage result_img(img_path);
			return result_img;
		}
		else {
			throw "file has exist!!!";
			exit(1);
		}
	}
	GDALAllRegister();
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); // ×¢ï¿½ï¿½ï¿½Ê½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿?1ï¿?7
	GDALDriver* poDriver = nullptr;
	if (isEnvi) {
		poDriver = GetGDALDriverManager()->GetDriverByName("ENVI");
	}
	else {
		poDriver = GetGDALDriverManager()->GetDriverByName("GTiff");
	}


	GDALDataset* poDstDS = poDriver->Create(img_path.toUtf8().constData(), width, height, band_num, GDT_Float64, NULL); // ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½
	GDALFlushCache((GDALDatasetH)poDstDS);
	GDALClose((GDALDatasetH)poDstDS);
	GDALDestroy(); // or, DllMain at DLL_PROCESS_DETACH
	gdalImage result_img(img_path);
	return result_img;

}

gdalImage  CreategdalImageFloat(QString& img_path, int height, int width, int band_num, bool overwrite, bool isEnvi)
{

	if (exists_test(img_path.toUtf8().constData())) {
		if (overwrite) {
			gdalImage result_img(img_path);
			return result_img;
		}
		else {
			throw "file has exist!!!";
			exit(1);
		}
	}
	GDALAllRegister();
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); // ×¢ï¿½ï¿½ï¿½Ê½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿?1ï¿?7
	GDALDriver* poDriver = nullptr;
	if (isEnvi) {
		poDriver = GetGDALDriverManager()->GetDriverByName("ENVI");
	}
	else {
		poDriver = GetGDALDriverManager()->GetDriverByName("GTiff");
	}


	GDALDataset* poDstDS = poDriver->Create(img_path.toUtf8().constData(), width, height, band_num, GDT_Float32, NULL); // ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½
	GDALFlushCache((GDALDatasetH)poDstDS);
	GDALClose((GDALDatasetH)poDstDS);
	GDALDestroy(); // or, DllMain at DLL_PROCESS_DETACH
	gdalImage result_img(img_path);
	return result_img;
}

gdalImage CreategdalImageDouble(const QString& img_path, int height, int width, int band_num, Eigen::MatrixXd gt, QString projection, bool need_gt, bool overwrite, bool isEnvi)
{
	if (exists_test(img_path.toUtf8().constData())) {
		if (overwrite) {
			gdalImage result_img(img_path);
			return result_img;
		}
		else {
			throw "file has exist!!!";
			exit(1);
		}
	}
	GDALAllRegister();
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); // ×¢ï¿½ï¿½ï¿½Ê½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿?1ï¿?7
	GDALDriver* poDriver = nullptr;
	if (isEnvi) {
		poDriver = GetGDALDriverManager()->GetDriverByName("ENVI");
	}
	else {
		poDriver = GetGDALDriverManager()->GetDriverByName("GTiff");
	}


	GDALDataset* poDstDS = poDriver->Create(img_path.toUtf8().constData(), width, height, band_num,
		GDT_Float64, NULL); // ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½
	if (need_gt) {
		if (!projection.isEmpty()) {
			poDstDS->SetProjection(projection.toUtf8().constData());
		}
		double gt_ptr[6] = { 0 };
		for (int i = 0; i < gt.rows(); i++) {
			for (int j = 0; j < gt.cols(); j++) {
				gt_ptr[i * 3 + j] = gt(i, j);
			}
		}
		poDstDS->SetGeoTransform(gt_ptr);
	}
	for (int i = 1; i <= band_num; i++) {
		poDstDS->GetRasterBand(i)->SetNoDataValue(-9999);
	}
	GDALFlushCache((GDALDatasetH)poDstDS);
	GDALClose((GDALDatasetH)poDstDS);
	GDALDestroy(); // or, DllMain at DLL_PROCESS_DETACH
	gdalImage result_img(img_path);
	return result_img;
}

gdalImage CreategdalImage(const QString& img_path, int height, int width, int band_num,
	Eigen::MatrixXd gt, QString projection, bool need_gt, bool overwrite, bool isEnvi, GDALDataType datetype)
{
	if (exists_test(img_path.toUtf8().constData())) {
		if (overwrite) {
			gdalImage result_img(img_path);
			return result_img;
		}
		else {
			throw "file has exist!!!";
			exit(1);
		}
	}
	GDALAllRegister();
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); // ×¢ï¿½ï¿½ï¿½Ê½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿?1ï¿?7
	GDALDriver* poDriver = nullptr;
	if (isEnvi) {
		poDriver = GetGDALDriverManager()->GetDriverByName("ENVI");
	}
	else {
		poDriver = GetGDALDriverManager()->GetDriverByName("GTiff");
	}


	GDALDataset* poDstDS = poDriver->Create(img_path.toUtf8().constData(), width, height, band_num,
		datetype, NULL); // ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½

	if (NULL == poDstDS)
	{
		qDebug() << "Create image failed!";
		throw "Create image failed!";
		exit(1);
	}


	if (need_gt) {
		if (!projection.isEmpty()) {
			poDstDS->SetProjection(projection.toUtf8().constData());
		}
		double gt_ptr[6] = { 0 };
		for (int i = 0; i < gt.rows(); i++) {
			for (int j = 0; j < gt.cols(); j++) {
				gt_ptr[i * 3 + j] = gt(i, j);
			}
		}
		poDstDS->SetGeoTransform(gt_ptr);
	}
	for (int i = 1; i <= band_num; i++) {
		poDstDS->GetRasterBand(i)->SetNoDataValue(-9999);
	}
	GDALFlushCache((GDALDatasetH)poDstDS);
	GDALClose((GDALDatasetH)poDstDS);
	GDALDestroy(); // or, DllMain at DLL_PROCESS_DETACH
	gdalImage result_img(img_path);
	return result_img;
}

gdalImage CreategdalImage(const QString& img_path, int height, int width, int band_num, Eigen::MatrixXd gt, long epsgCode, GDALDataType eType, bool need_gt, bool overwrite, bool isENVI)
{
	if (exists_test(img_path.toUtf8().constData())) {
		if (overwrite) {
			gdalImage result_img(img_path);
			return result_img;
		}
		else {
			throw "file has exist!!!";
			exit(1);
		}
	}
	GDALAllRegister();
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); // ×¢ï¿½ï¿½ï¿½Ê½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿?1ï¿?7
	GDALDriver* poDriver = isENVI ? GetGDALDriverManager()->GetDriverByName("ENVI") : GetGDALDriverManager()->GetDriverByName("GTiff");
	GDALDataset* poDstDS = poDriver->Create(img_path.toUtf8().constData(), width, height, band_num, eType, NULL); // ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½
	if (need_gt) {
		OGRSpatialReference oSRS;

		if (oSRS.importFromEPSG(epsgCode) != OGRERR_NONE) {
			qDebug() << "Failed to import EPSG code " << epsgCode;
			throw "Failed to import EPSG code ";
			exit(1);
		}
		char* pszWKT = NULL;
		oSRS.exportToWkt(&pszWKT);
		qDebug() << "WKT of EPSG:" << epsgCode << " :\n" << pszWKT;
		poDstDS->SetProjection(pszWKT);
		double gt_ptr[6] = { 0 };
		for (int i = 0; i < gt.rows(); i++) {
			for (int j = 0; j < gt.cols(); j++) {
				gt_ptr[i * 3 + j] = gt(i, j);
			}
		}
		poDstDS->SetGeoTransform(gt_ptr);
	}
	for (int i = 1; i <= band_num; i++) {
		poDstDS->GetRasterBand(i)->SetNoDataValue(-9999);
	}
	GDALFlushCache((GDALDatasetH)poDstDS);
	GDALClose((GDALDatasetH)poDstDS);
	GDALDestroy(); // or, DllMain at DLL_PROCESS_DETACH
	gdalImage result_img(img_path);
	return result_img;
}


bool  CopyProjectTransformMatrixFromRasterAToRasterB(QString RasterAPath, QString  RasterBPath) {
	// ×¢²áËùÓÐGDALÇý¶¯
	GDALAllRegister();

	// ´ò¿ªÓ°ÏñA£¨Ö»¶ÁÄ£Ê½£©
	GDALDataset* ds_a = (GDALDataset*)GDALOpen(RasterAPath.toUtf8().constData(), GA_ReadOnly);
	if (ds_a == nullptr) {
		std::cerr << "ÎÞ·¨´ò¿ªÓ°ÏñA" << std::endl;
		return false;
	}

	// »ñÈ¡AµÄ·ÂÉä¾ØÕóºÍÍ¶Ó°ÐÅÏ¢
	double geotransform[6];
	ds_a->GetGeoTransform(geotransform); // °üº¬Áù²ÎÊý·ÂÉä±ä»»
	const char* projection = ds_a->GetProjectionRef(); // WKT¸ñÊ½Í¶Ó°

	// ´ò¿ªÓ°ÏñB£¨¸üÐÂÄ£Ê½£©
	GDALDataset* ds_b = (GDALDataset*)GDALOpen(RasterBPath.toUtf8().constData(), GA_Update);
	if (ds_b == nullptr) {
		std::cerr << "ÎÞ·¨´ò¿ªÓ°ÏñB" << std::endl;
		GDALClose(ds_a);
		return false;
	}

	// ÉèÖÃ·ÂÉä¾ØÕó
	if (ds_b->SetGeoTransform(geotransform) != CE_None) {
		std::cerr << "ÉèÖÃ·ÂÉä¾ØÕóÊ§°Ü" << std::endl;
	}

	// ÉèÖÃÍ¶Ó°×ø±êÏµ
	if (ds_b->SetProjection(projection) != CE_None) {
		std::cerr << "ÉèÖÃÍ¶Ó°Ê§°Ü" << std::endl;
	}

	// ÊÍ·Å×ÊÔ´
	GDALClose(ds_a);
	GDALClose(ds_b);

	return true;





}




