// ImgShowDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "ImgShowDlg.h"
#include "GlobalFunc.h"
#include "QB_ImgProcessFun.h"
#include "CvvImage.h"
#include "Markup.h"

// tif 图像
#include <ogr_srs_api.h>
#include <ogr_spatialref.h>
#include <gdal.h>
#include <gdal_priv.h>

// 文字编辑窗口
#include "AddTextDlg.h"

#include "MapPrj.h"
/*#include "GoogleTileOperation.h"*/

#include "TgtLocCalibrateDlg.h"

// CImgShowDlg 对话框

IMPLEMENT_DYNAMIC(CImgShowDlg, CDialog)

	CImgShowDlg::CImgShowDlg(CWnd* pParent /*=NULL*/): CDialog(CImgShowDlg::IDD, pParent)
{
	m_lpSendCoordinate = NULL;
	m_lpSendPixInfoProc = NULL;
	m_lpSendFilePath = NULL;
	m_lpSendTgrLocLeadLonLat = NULL;
	m_lpSendArtilleryReviseInfo = NULL;

	m_ShowRegion = CRect(0,0,0,0);

	m_ShowRegionOnScreen.left   = 0;
	m_ShowRegionOnScreen.right  = 0;
	m_ShowRegionOnScreen.top    = 0;
	m_ShowRegionOnScreen.bottom = 0;

	m_PicCtrlWidth  = 0;  
	m_PicCtrlHeight = 0; 

	m_LButtonDownPixelCoordinate = CPoint(0,0);
	m_bStaisfyRoamImg = FALSE;
	m_LatestPlotRect = CRect(0,0,0,0);
	m_LButtonDblClkPixelCoordinate = CPoint(-1, -1);

	m_bPlotRectOnPaint = TRUE;

	m_NorthDirectionCenter.x = 0;
	m_NorthDirectionCenter.y = 0;

	m_bPlotDirectionOnPaint = TRUE;

	m_LeftButtonDown.x = 0;
	m_LeftButtonDown.y = 0;

	m_RButtonPt.x = 0;
	m_RButtonPt.y = 0;

	m_SrcFrame = NULL;
	m_ImgRatioOnScreen = 1.0F;

	m_ImgShowShift.x = 0L;
	m_ImgShowShift.y = 0L;

	m_bFirstSignal = FALSE; 
	m_bSecondSignal = FALSE;
	m_bSatisfyMove = FALSE;

	m_iLatest = 0;
	m_iPreLatest = 0;

	m_bMemPreMultiFrame = FALSE;

	m_LatestQuadrangle = CRect(0,0,0,0);

	// 像素信息
	m_imgPixel_XY_Coordinate.x = -1;
	m_imgPixel_XY_Coordinate.y = -1;
	m_imgPixel_LBH_Coordinate.x = -200.0;
	m_imgPixel_LBH_Coordinate.y = -200.0;
	m_imgPixel_LBH_Coordinate.z = -200.0;


	m_bPlotRect = FALSE;

	// 当前显示的图像序号
	m_currentImgOrder = 0;

	// 图像编辑类型
	m_iImgEditType = 0;

	m_bHaveOnPt = false;

	m_bEnhanceEdit = true; // 增强

	m_pFastLookUpDlg = NULL;

	m_sSaveCurrentImgFolder = "";  
	m_sSavePreMultiImgFolder = ""; 

	m_TargetCenter = cv::Point(-100, -100);

	m_bDrawSquareOnImg = TRUE;

	m_deltaLon = 0;
	m_deltaLat = 0;

	m_bCloseRughtBtnMenu = false;

	m_sThemeText = "";

	m_bGetTgtImgOn = false;
	m_clipImgFirstPt = CPoint(0,0);
	m_clipImgSecondPt = CPoint(0,0);
	m_haveValidFirstPt = false;

	// 图像裁剪开关 
	m_bClipImgOn = false;

	m_hMutex_ProcessData = nullptr;
}

CImgShowDlg::~CImgShowDlg()
{
	try
	{
		// 如果有图像 需要释放该图像
		if (m_SrcFrame != NULL)
		{
			cvReleaseImage(&m_SrcFrame);
			m_SrcFrame = NULL;
		}

		// 当前情报数据结构体:LatestQBData
		ReleaseQBData(&m_LatestQBData);

		
		WaitForSingleObject(m_hMutex_ProcessData, INFINITE);
		// 情报队列销毁
		if(m_QBDataDeque.size() > 0) 
		{
			for (size_t i = 0; i < m_QBDataDeque.size(); ++i)
			{
				SAFE_DELETE_ARRAY(m_QBDataDeque[i].image.srcImg.buff);
				SAFE_DELETE_ARRAY(m_QBDataDeque[i].image.dstImg.buff);
				SAFE_DELETE_ARRAY(m_QBDataDeque[i].image.geoImg.buff);
			}
			m_QBDataDeque.clear(); 
		}
		ReleaseMutex(m_hMutex_ProcessData);



		// midImg 释放
		SAFE_DELETE_ARRAY(m_midImg.buff);

		// 释放快速查找图像对话框
		if (m_pFastLookUpDlg != NULL)
		{
			delete m_pFastLookUpDlg;
			m_pFastLookUpDlg = NULL;
		}
	}
	catch(cv::Exception &e)
	{
		e.what();
		std::abort();
	}
	catch(...)
	{
		std::abort();
	}
}

void CImgShowDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(CImgShowDlg, CDialog)
	ON_WM_ERASEBKGND()
	ON_WM_PAINT()
	ON_WM_RBUTTONDOWN()
	ON_COMMAND(ID_ZOOM_IN_IMG, &CImgShowDlg::OnZoomInImg)
	ON_COMMAND(ID_ZOOM_OUT_IMG, &CImgShowDlg::OnZoomOutImg)
	ON_COMMAND(ID_ZOOM_FIT_IMG, &CImgShowDlg::OnZoomFitImg)
	ON_COMMAND(ID_CONCEL_TARGET_PLOT, &CImgShowDlg::OnConcelTargetPlot)
	ON_COMMAND(ID_SAVE_CURRENT_FRAME, &CImgShowDlg::OnSaveCurrentFrame)
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_MOUSEMOVE()
	ON_WM_MOUSEWHEEL()
	ON_COMMAND(ID_CLEAR_MEMORY, &CImgShowDlg::OnClearMemory)
	ON_COMMAND(ID_SAVE_IMG_TO_TIFF, &CImgShowDlg::OnSaveImgToTiff)
	ON_COMMAND(ID_FAST_LOOKUP_IMGS, &CImgShowDlg::OnFastLookupImgs)
	ON_COMMAND(ID_TGT_LOC_LEAD, &CImgShowDlg::OnTgtLocLead)
	ON_COMMAND(ID_GEO_CORRECT_AND_SHOW, &CImgShowDlg::OnGeoCorrectAndShow)
	ON_COMMAND(ID_DRAW_SQUARE_ON_IMG, &CImgShowDlg::OnDrawSqureOnImg)
	ON_COMMAND(ID_OPEN_ONE_IMG, &CImgShowDlg::OnOpenOneImg)
	ON_COMMAND(ID_TGTLOC_calibrate, &CImgShowDlg::OnTgtloccalibrate)
	ON_COMMAND(ID_VIEW_DELTA_LON_LAT, &CImgShowDlg::OnViewDeltaLonLat)
	ON_COMMAND(ID_GET_TARGET_IMG, &CImgShowDlg::OnGetTargetImg)
	ON_COMMAND(ID_CLIP_IMG, &CImgShowDlg::OnClipImg)
END_MESSAGE_MAP()


// 1.1 功能:设置回调函数
BOOL CImgShowDlg::SetCallBackFun(SendCoordinateProc proc)
{
	// 输入数据有效性判断
	if (proc != NULL)
	{
		m_lpSendCoordinate = proc;
		return TRUE;
	}
	return FALSE;
}


// 2 功能:设置回调函数,像素信息传递到外部CSU中
//   输入:
//       1.proc: 函数指针
//
//   输出: 设置成功返回TRUE,否则返回FALSE
BOOL CImgShowDlg::SetCallBackFun(SendPixInfoProc proc)
{
	// 输入数据有效性判断
	if (proc != NULL)
	{
		m_lpSendPixInfoProc = proc;
		return TRUE;
	}
	return FALSE;
}


// 3 功能:设置回调函数,传递保存文件路径到外部CSU中
//   输入:
//       1.proc: 函数指针
//
//   输出: 设置成功返回TRUE,否则返回FALSE
BOOL CImgShowDlg::SetCallBackFun(SendFilePath proc)
{
	// 输入数据有效性判断
	if (proc != NULL)
	{
		m_lpSendFilePath = proc;
		return TRUE;
	}
	return FALSE;
}


BOOL CImgShowDlg::SetCallBackFun(SendTgrLocLeadLonLatProc proc)
{
	// 输入数据有效性判断
	if (proc != NULL)
	{
		m_lpSendTgrLocLeadLonLat = proc;
		return TRUE;
	}
	return FALSE;
}

//   功能:设置回调函数,目标定位导引经纬度到外部CSU中
//   输入:
//       1.proc: 函数指针
//
//   输出: 设置成功返回TRUE,否则返回FALSE
BOOL CImgShowDlg::SetCallBackFun(SendArtilleryReviseInfoProc proc)
{
	// 输入数据有效性判断
	if (proc != NULL)
	{
		m_lpSendArtilleryReviseInfo = proc;
		return TRUE;
	}
	return FALSE;
}

// 1.2 功能:在对话框中显示一帧图像 
BOOL  CImgShowDlg::ShowOneImage(const BITMAPINFO* pImgInfo,
	BYTE* pImgData, 
	BOOL  isNeedClip, 
	const CRect &ShowRegion,
	BOOL  isNeedFlip,
	float StrecthRatio,
	POINT xyShift)
{
	BOOL ret = FALSE;

	try
	{
		// 数据有效性判断
		if ( (pImgInfo == NULL) || (pImgData == NULL) )
		{
			return FALSE; 
		}

		// 图像显示拉伸比例 有效性判定和修正
		if ((StrecthRatio < 0.0F) || (StrecthRatio > 1.0F))
		{
			StrecthRatio = 1.0F;
		}

		// 图像属性提取
		int imgWidth  = static_cast<int>(pImgInfo->bmiHeader.biWidth);
		int imgHeight = static_cast<int>(pImgInfo->bmiHeader.biHeight);
		int nBitCount = static_cast<int>(pImgInfo->bmiHeader.biBitCount);

		// 图像属性判断
		if ( (imgWidth <= 0) || (imgHeight <= 0) )
		{
			return FALSE;
		}

		// 步长:每行像素所占字节数,必须扩展成4的倍数 
		int lineByte = (imgWidth * nBitCount / 8 + 3) / 4 * 4;

		// 位图数据缓冲区的大小,即图像大小
		unsigned int imgBufSize = static_cast<unsigned int>(imgHeight * lineByte);

		// 将图像数据转换到 m_SrcFrame 再显示
		if (m_SrcFrame != NULL) // 如果有图像
		{
			// 情况1:如果图像属性没有变化 直接更换原始图像数据即可,即复制图像数据,不需要再去创建一幅图像
			// 情况2:如果图像属性发生了变化,需要先释放图像,再创建图像

			// 情况1
			if ((m_SrcFrame->width == imgWidth) && 
				(m_SrcFrame->height == imgHeight) &&
				(m_SrcFrame->depth * m_SrcFrame->nChannels == nBitCount) )
			{
				// 内存复制机制
				int RealLineByte = (imgWidth * nBitCount / 8);

				if (RealLineByte == lineByte)
				{
					memcpy(m_SrcFrame->imageData, pImgData, imgBufSize);     // 图像数据复制
				} 
				else
				{
					for (int i = 0; i < imgHeight; i++)
					{
						memcpy(m_SrcFrame->imageData + i * lineByte, pImgData + i * RealLineByte, RealLineByte);
					}
				}
			} 
			else  // 情况2
			{
				// 释放图像
				cvReleaseImage(&m_SrcFrame);
				m_SrcFrame = NULL;

				// 创建
				m_SrcFrame = cvCreateImage(cvSize(imgWidth, imgHeight), 8, nBitCount/8); // 创建图像

				if (m_SrcFrame != NULL) // 创建成功
				{
					// 内存复制机制
					int RealLineByte = (imgWidth * nBitCount / 8);

					if (RealLineByte == lineByte)
					{
						memcpy(m_SrcFrame->imageData, pImgData, imgBufSize);     // 图像数据复制
					} 
					else
					{
						for (int i = 0; i < imgHeight; i++)
						{
							memcpy(m_SrcFrame->imageData + i * lineByte, pImgData + i * RealLineByte, RealLineByte);
						}
					}		
				}
				else
				{
					return FALSE;
				}
			}
		}
		else // 如果没有图像 需要先创建图像
		{
			m_SrcFrame = cvCreateImage(cvSize(imgWidth, imgHeight), 8, nBitCount/8); // 创建图像

			if (m_SrcFrame != NULL)   // 创建成功
			{
				// 内存复制机制
				int RealLineByte = (imgWidth * nBitCount / 8);

				if (RealLineByte == lineByte)
				{
					memcpy(m_SrcFrame->imageData, pImgData, imgBufSize);     // 图像数据复制
				} 
				else
				{
					for (int i = 0; i < imgHeight; i++)
					{
						memcpy(m_SrcFrame->imageData + i * lineByte, pImgData + i * RealLineByte, RealLineByte);
					}
				}
			}
			else
			{
				return FALSE;
			}
		}

		// 如果需要反转 把 SrcFrame 反转 后面的函数就再也不用考虑反转的问题
		if (isNeedFlip == TRUE)
		{
			cvFlip(m_SrcFrame); // 上下反转,改变自身
		}

		// 保存图像显示属性,如果该值不合理,会在随后的重载图像显示函数中被修改
		this->m_ShowRegion = ShowRegion;

		// 设置图像显示拉伸系数
		if (StrecthRatio >= 0.0F && StrecthRatio <= 1.0F)
		{
			m_ImgRatioOnScreen = StrecthRatio;
		}
		else
		{
			m_ImgRatioOnScreen = 1.0F;
		}


		// 转到函数1.3(重载)进行图像显示
		ret = ShowOneImage(m_SrcFrame, isNeedClip, ShowRegion, m_ImgRatioOnScreen, xyShift);

		return ret;
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return FALSE;
	}
	catch(...)
	{
		return FALSE;
	}
}


// 1.3 功能:在对话框中显示一帧图像 
BOOL CImgShowDlg::ShowOneImage(const IplImage* src, 
	BOOL isNeedClip,
	const CRect &ShowRegion,
	float StrecthRatio,
	POINT xyShift)
{
	BOOL ret = FALSE; // 返回值

	try
	{
		// 图像数据有效性判断
		if (src == NULL)
		{
			return FALSE;
		}

		// 定义变量,用于标识是否显示整个图像
		// 原因:即使 isNeedClip 设置为TURE,ShowRegion不合理时,也要显示整个图像
		BOOL ShowWholeImg = TRUE;

		// 判断是否需要裁剪
		if (isNeedClip == TRUE) // 如果需要裁剪
		{
			// 判断 ShowRegion 是否合理 
			// 如果 ShowRegion 出现任何不合理,则显示整个图像		
			if ((ShowRegion.left   >= 0)  && (ShowRegion.left   < src->width)  &&
				(ShowRegion.right  >= 0)  && (ShowRegion.right  < src->width)  &&
				(ShowRegion.top    >= 0)  && (ShowRegion.top    < src->height) &&
				(ShowRegion.bottom >= 0)  && (ShowRegion.bottom < src->height) &&
				(ShowRegion.right - ShowRegion.left > 0) && (ShowRegion.bottom - ShowRegion.top > 0) )
			{
				// 特殊情况:裁剪整个图像
				if ((ShowRegion.right - ShowRegion.left + 1 == src->width) && 
					(ShowRegion.bottom - ShowRegion.top + 1 == src->height))
				{
					ShowWholeImg = TRUE;
				}
				else
				{
					ShowWholeImg = FALSE;
				}		
			}
			else
			{
				// 显示区域设置不合理,显示全部图像
				ShowWholeImg = TRUE;
			}
		}

		// 判断是否需要显示整个图像
		if (ShowWholeImg == TRUE) // 如果显示整个图像
		{
			// 显示整个图像
			ret = ShowWholeImage(src, StrecthRatio, xyShift);

			// 更新图像显示区域 m_ShowRegion
			// 目的:用于图像放大缩小等操作
			this->m_ShowRegion.left   = 0;
			this->m_ShowRegion.right  = src->width - 1;
			this->m_ShowRegion.top    = 0;
			this->m_ShowRegion.bottom = src->height - 1;
		}
		else
		{
			// 裁剪出显示区域
			IplImage* validPart = NULL;

			// 这时,ShowRegion肯定是有效的,可以直接创建图像
			validPart = cvCreateImage(cvSize(ShowRegion.Width(), ShowRegion.Height()), src->depth, src->nChannels);

			if (validPart != NULL) // 创建成功
			{
				cvZero(validPart); // 清零

				// 设置 感兴趣区
				cvSetImageROI( const_cast<IplImage*>(src), cvRect( static_cast<int>(ShowRegion.left), static_cast<int>(ShowRegion.top), ShowRegion.Width(), ShowRegion.Height()) );

				// 叠加
				cvAdd( src, validPart, validPart, NULL );

				// 释放 感兴趣区
				cvResetImageROI( const_cast<IplImage*>(src) );

				// 显示图像 validPart
				ret = ShowWholeImage(validPart, StrecthRatio, xyShift);

				// 释放 validPart
				cvReleaseImage(&validPart);
				validPart = NULL;
			}
			else
			{
				return FALSE;
			}
		}
		return ret;
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return FALSE;
	}
	catch(...)
	{
		return FALSE;
	}
}




// 1.4 功能:在对话框中显示一帧图像 
BOOL CImgShowDlg::ShowWholeImage(const IplImage* src, float StrecthRatio, POINT &shift)
{
	try
	{
		// 数据有效性判断
		if (src == NULL)
		{
			return FALSE;
		}

		// 图像显示拉伸比例 有效性判定和修正
		if ((abs(StrecthRatio) <= 0.0F) || (StrecthRatio > 1.0F))
		{
			StrecthRatio = 1.0F;
		}

		// 计算当前显示图像对话框尺寸
		CRect clientRect;
		GetClientRect(&clientRect);

		// 获得 pictrue 控件窗口的句柄
		CWnd *pWnd = NULL; 
		pWnd = GetDlgItem(IDC_IMG_SHOW_PIC_CTRL); 

		// 后面程序无需再判定
		if (pWnd == NULL)
		{
			return FALSE;
		}

		// 让图像控件填满对话框
		pWnd->MoveWindow(&clientRect);

		// 设置图像控件尺寸
		m_PicCtrlWidth  = clientRect.Width();  // 图像控件宽
		m_PicCtrlHeight = clientRect.Height(); // 图像控件高

		// 获取图像控件HDC  
		CDC *pDC = NULL; // 函数退出时需要释放 ReleaseDC(pDC);
		pDC = pWnd->GetDC(); 

		// 后面程序无需再判定
		if (pDC == NULL)
		{
			return FALSE;
		}

		HDC hdc  = NULL;
		hdc = pDC->GetSafeHdc();

		// 当前图像尺寸
		int imgWidth  = src->width;
		int imgHeight = src->height;

		// 显示图像
		IplImage* fitSizeImg = NULL;

		// 显示图像尺寸
		int fitSizeImgWidth  = 0;
		int fitSizeImgHeight = 0;

		// 图像尺寸小于窗口尺寸 
		if ((imgWidth <= m_PicCtrlWidth) && (imgHeight <= m_PicCtrlHeight))
		{
			// 拉伸图像
			double Ratio = 1.0;
			double Ratio_Width  = static_cast<double>(m_PicCtrlWidth) / static_cast<double>(imgWidth);
			double Ratio_Height = static_cast<double>(m_PicCtrlHeight) / static_cast<double>(imgHeight);

			Ratio = (Ratio_Width < Ratio_Height) ? Ratio_Width : Ratio_Height; // Ratio 大于 1

			// 拉伸比例控制
			Ratio *= StrecthRatio;

			// 显示图像尺寸
			fitSizeImgWidth  = static_cast<int>(imgWidth  * Ratio + 0.5);
			fitSizeImgHeight = static_cast<int>(imgHeight * Ratio + 0.5);
		}
		else
		{
			// 压缩图像
			double Ratio = 1.0;
			double Ratio_Img        = static_cast<double>(imgWidth) / static_cast<double>(imgHeight);
			double Ratio_ClientRect = static_cast<double>(m_PicCtrlWidth) / static_cast<double>(m_PicCtrlHeight);

			// 计算比例系数
			if ( Ratio_Img > Ratio_ClientRect )
			{
				Ratio = static_cast<double>(m_PicCtrlWidth) / static_cast<double>(imgWidth); // Ratio 小于 1
			} 
			else
			{
				Ratio = static_cast<double>(m_PicCtrlHeight) / static_cast<double>(imgHeight); // Ratio 小于 1
			}

			// 拉伸比例控制
			Ratio *= StrecthRatio;

			// 显示图像尺寸
			fitSizeImgWidth  = static_cast<int>(imgWidth  * Ratio + 0.5);
			fitSizeImgHeight = static_cast<int>(imgHeight * Ratio + 0.5);
		}

		// 最低尺寸判断,小于一个像素时直接返回
		if(min(fitSizeImgWidth, fitSizeImgHeight) <= 1)
		{
			// 释放
			ReleaseDC(pDC);
			return FALSE;
		}

		// 创建fitSizeImg
		fitSizeImg = cvCreateImage(cvSize(fitSizeImgWidth, fitSizeImgHeight), src->depth, src->nChannels);

		if (fitSizeImg == NULL)
		{
			return FALSE;
		}

		// 改变图像尺寸
		cvResize(src, fitSizeImg); 

		// 为使显示界面不闪烁 增加中间变量 边界充满黑色
		IplImage* fillblackImg = NULL;
		fillblackImg = cvCreateImage(cvSize(clientRect.Width(), clientRect.Height()), src->depth, src->nChannels);

		if (fillblackImg != NULL)
		{
			cvZero(fillblackImg); // 清零
		}
		else
		{
			// 释放缩放后图像
			cvReleaseImage(&fitSizeImg);
			fitSizeImg = NULL;

			// 释放pdc
			ReleaseDC(pDC);

			return FALSE;
		}

		// 叠加 fitSizeImg 图像 到 fillblackImg

		// 左上 起始点
		cv::Point LeftUpBefore; 
		LeftUpBefore.x = static_cast<int>((m_PicCtrlWidth  - fitSizeImgWidth)/2);
		LeftUpBefore.y = static_cast<int>((m_PicCtrlHeight - fitSizeImgHeight)/2);

		// 加上偏移量之后
		cv::Point LeftUpAfter =  LeftUpBefore;
		LeftUpBefore.x += shift.x;
		LeftUpBefore.y += shift.y;

		// 修改全局变量 设计的不好
		if (LeftUpAfter.x < 0)
		{
			LeftUpAfter.x = 0;
		}

		if (LeftUpAfter.x > m_PicCtrlWidth  - fitSizeImgWidth)
		{
			LeftUpAfter.x = m_PicCtrlWidth  - fitSizeImgWidth;
		}

		if (LeftUpAfter.y < 0)
		{
			LeftUpAfter.y = 0;
		}

		if (LeftUpAfter.y > m_PicCtrlHeight - fitSizeImgHeight)
		{
			LeftUpAfter.y = m_PicCtrlHeight - fitSizeImgHeight;
		}

		// 实际偏移量
		shift.x = LeftUpAfter.x - LeftUpBefore.x;
		shift.y = LeftUpAfter.y - LeftUpBefore.y;



		cvSetImageROI(fillblackImg, cvRect(static_cast<int>(LeftUpAfter.x), static_cast<int>(LeftUpAfter.y), fitSizeImgWidth, fitSizeImgHeight));
		cvAdd(fillblackImg, fitSizeImg, fillblackImg);
		cvResetImageROI( fillblackImg );

		// 设置 ShowRegionOnScreen : 图像显示部分在dialog中的坐标
		m_ShowRegionOnScreen.left   = LeftUpAfter.x;
		m_ShowRegionOnScreen.right  = LeftUpAfter.x + fitSizeImgWidth;
		m_ShowRegionOnScreen.top    = LeftUpAfter.y;
		m_ShowRegionOnScreen.bottom = LeftUpAfter.y + fitSizeImgHeight;


		// 在图像中写字、添加信息示例
		if (m_LatestQBData.image.bValid == true)
		{
			cv::Mat fillblackImgMat(fillblackImg, false);
			cv::Scalar color(0, 255, 0);
			if (fillblackImgMat.type() == CV_8UC1)
			{
				color = cv::Scalar(255);
			}

			// 图像显示比例
			CString scale = 0;
			scale.Format("%.1f", double(fitSizeImgWidth) / imgWidth * 100);
			scale = scale + "%";
			cv::putText(fillblackImgMat, scale.GetBuffer(0), cv::Point(10, fillblackImgMat.rows - 20), 2, 0.5, color);
		}

		// 释放 fitSizeImg
		cvReleaseImage(&fitSizeImg);
		fitSizeImg = NULL;

		// 绘图
		CvvImage img;
		img.CopyOf(fillblackImg);		
		img.Show(hdc, 0, 0, fillblackImg->width, fillblackImg->height);	

		// 释放fillblackImg
		cvReleaseImage(&fillblackImg);
		fillblackImg = NULL;

		// 释放
		ReleaseDC(pDC);

		return TRUE;
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return FALSE;
	}
	catch(...)
	{
		return FALSE;
	}
}


// 1.5 功能:设置目标点像素坐标,如果设置合理,在在显示窗口中标绘目标
BOOL CImgShowDlg::SetTargetPixelCoordinate(const CPoint &point)
{
	try
	{
		// 设置目标点
		m_LButtonDblClkPixelCoordinate = point; // 赋值给私有成员变量

		if ((point.x >= m_ShowRegion.left) && (point.x <= m_ShowRegion.right) &&
			(point.y >= m_ShowRegion.top)  && (point.y <= m_ShowRegion.bottom) ) 
		{
			// 标绘目标:当目标点未显示到屏幕时,不标绘
			DrawSquareOnScreen(GetScreenCoordinateBasedOnPixelCoordinate(m_LButtonDblClkPixelCoordinate));
		}
		else
		{
			// 先全景显示 再标绘
			OnZoomFitImg();

			// 标绘目标:当目标点未显示到屏幕时,不标绘
			DrawSquareOnScreen(GetScreenCoordinateBasedOnPixelCoordinate(m_LButtonDblClkPixelCoordinate));
		}

		return TRUE;
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return FALSE;
	}
	catch(...)
	{
		return FALSE;
	}
}

//   功能:标绘目标,其中输入为经纬度坐标 
void CImgShowDlg::SetTgtLocLeadLonLat(double lon, double lat)
{
	if (m_bFirstSignal == TRUE || m_bSecondSignal == TRUE)
	{
		return;
	}

	if (m_SrcFrame != NULL && m_SrcFrame->width > 0 && m_SrcFrame->height > 0)
	{
		if (m_boundbingBox.EastLon - m_boundbingBox.WestLon > 0 
			&& m_boundbingBox.WestLon >= -180 
			&& m_boundbingBox.WestLon <= 180 
			&& m_boundbingBox.EastLon >= -180  
			&& m_boundbingBox.EastLon <= 180 
			&& m_boundbingBox.NorthLat - m_boundbingBox.SouthLat > 0 
			&& m_boundbingBox.SouthLat >= -90 
			&& m_boundbingBox.SouthLat <= 90 
			&& m_boundbingBox.NorthLat >= -90 
			&& m_boundbingBox.NorthLat <= 90)
		{
			if (lon >= m_boundbingBox.WestLon 
				&& lon <= m_boundbingBox.EastLon
				&& lat >= m_boundbingBox.SouthLat
				&& lat <= m_boundbingBox.NorthLat)
			{
				double LonResolution = (m_boundbingBox.EastLon -  m_boundbingBox.WestLon) / m_SrcFrame->width;
				double LatResolution = (m_boundbingBox.NorthLat - m_boundbingBox.SouthLat) / m_SrcFrame->height;

				CPoint pixelCord;
				pixelCord.x = static_cast<LONG>((lon - m_boundbingBox.WestLon) / LonResolution);
				pixelCord.y = static_cast<LONG>((m_boundbingBox.NorthLat - lat) / LatResolution);

				SetTargetPixelCoordinate(pixelCord);
			}
		}
		else
		{
			::MessageBoxA(NULL, _T("目标可能不在当前图像中!"),_T("操作提示"), MB_OK);
		}
	}
}

// 绘制四个角点连成的区域
BOOL CImgShowDlg::SetQuadrangleCorners(const POINT* pts)
{
	try
	{
		if (pts != NULL)
		{
			m_corners[0] = pts[0];
			m_corners[1] = pts[1];
			m_corners[2] = pts[2];
			m_corners[3] = pts[3];

			POINT CornersOnScreen[4];
			for (int i = 0; i < 4; i++)
			{
				CornersOnScreen[i] = GetScreenCoordinateBasedOnPixelCoordinate(m_corners[i]);
			}

			if (CornersOnScreen[0].x >= 0 && CornersOnScreen[0].y >= 0 &&
				CornersOnScreen[1].x >= 0 && CornersOnScreen[1].y >= 0 &&
				CornersOnScreen[2].x >= 0 && CornersOnScreen[2].y >= 0 &&
				CornersOnScreen[3].x >= 0 && CornersOnScreen[3].y >= 0)
			{
				DrawQuadrangleOnScreen(CornersOnScreen);
			}

			return TRUE;
		}
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return FALSE;
	}
	catch(...)
	{
		return FALSE;
	}

	return FALSE;
}


// 1.6 功能:绘制指北针
// void CImgShowDlg::DrawNorthDirection(const POINT &center, double angle)
// {
// 	try
// 	{
// 		int r = 20;  // 中心点到底角的长度
// 		int R = 30;  // 中心点到顶点的长度
// 
// 		double LocalAngle = 50.0; // 控制指北针尖锐程度
// 		LocalAngle = LocalAngle/180.0 * 3.1415926535;
// 
// 		CDC* pDC = NULL;
// 		pDC = this->GetDC();
// 
// 		// 判断,若pDC为空,直接返回,后面程序也无需再判定pDC
// 		if (pDC == NULL)
// 		{
// 			return;
// 		}
// 
// 		// 创建并选择画笔
// 		CPen aPen;
// 		aPen.CreatePen(PS_SOLID, 2, RGB(0,255,0)); 
// 
// 		CPen * pOldPen = NULL;
// 		pOldPen = pDC->SelectObject(&aPen);
// 
// 		// 设置背景透明 用于写字
// 		pDC->SetBkMode(TRANSPARENT);
// 		pDC->SetTextColor(RGB(0,255,0));
// 
// 		// 绘制图形需要的五个点
// 		POINT point[5];
// 
// 		// 零度时各点相对于中心点的位置
// 		point[0].x = - static_cast<LONG>(r * cos(LocalAngle));
// 		point[0].y =   static_cast<LONG>(r * sin(LocalAngle));
// 
// 		point[1].x =   0L;
// 		point[1].y = - static_cast<LONG>(R);
// 
// 		point[2].x = static_cast<LONG>(r * cos(LocalAngle));
// 		point[2].y = static_cast<LONG>(r * sin(LocalAngle));
// 
// 		point[3].x = 0L;
// 		point[3].y = 0L;
// 
// 		point[4].x = - 4L;
// 		point[4].y = - static_cast<LONG>(R + 16);
// 
// 		// 各点旋转一定角度,并平移至以center为中心的坐标
// 		for(int i = 0; i < 5; i++)
// 		{
// 			point[i] =  RotateShiftPoint(point[i],angle,center);
// 		}
// 
// 		// 绘图
// 		pDC->MoveTo(point[0]);
// 		pDC->LineTo(point[1]);
// 		pDC->LineTo(point[2]);
// 		pDC->LineTo(point[3]);
// 		pDC->LineTo(point[0]);
// 
// 		// 画圆圈
// 		CBrush* pBrush = CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
// 		CBrush* pOldBrush = pDC->SelectObject(pBrush);
// 		R = R + 2;
// 		pDC->Ellipse(point[3].x - R, point[3].y - R, point[3].x + R, point[3].y + R);
// 		pDC->SelectObject(pOldBrush);
// 
// 		// 写字:N
// 		// 转换为【0,360】
// 		angle = (angle/360.0 - static_cast<int>(angle/360.0)) * 360.0;
// 		if (angle < 0)
// 		{
// 			angle += 360;
// 		}
// 
// 		// 判断并修正,经验值
// 		if (angle <= 45)
// 		{
// 			point[4].y -= 3;
// 		}
// 
// 		if ((angle > 45) && (angle <= 135))
// 		{
// 			point[4].x -= 8;
// 			point[4].y -= 3;
// 		}
// 
// 		if ((angle > 135) && (angle <= 225))
// 		{
// 			point[4].x -= 8;
// 			point[4].y -= 10;
// 		}
// 
// 		if ((angle > 225) && (angle <= 315))
// 		{
// 			point[4].y -= 10;
// 		}
// 
// 		if (angle > 315)
// 		{
// 			point[4].y -= 6;
// 		}
// 
// 		// 写N
// 		pDC->TextOutA(static_cast<int>(point[4].x), static_cast<int>(point[4].y), "N");
// 
// 		// 选回旧画笔
// 		pDC->SelectObject(pOldPen);
// 
// 		// 释放pDC
// 		ReleaseDC(pDC);
// 		pDC = NULL;
// 	}
// 	catch(cv::Exception &e)
// 	{
// 		e.msg;
// 		return;
// 	}
// 	catch(...)
// 	{
// 		return;
// 	}
// }
// 
// //1.7 功能:设置指北针中心
// void CImgShowDlg::SetNorthDirectionCenter(const POINT &center)
// {
// 	CRect rect;
// 	GetClientRect(&rect);
// 
// 	if ((center.x > 0) && (center.x < rect.Width()) &&
// 		(center.y > 0) && (center.y < rect.Height()))
// 	{
// 		m_NorthDirectionCenter = center;
// 	}
// }


// 1.8 功能:基于私有成员变量LatestQBData 显示图像和指北针
//   说明:当dst有效时,优先显示dst,否则显示src
void CImgShowDlg::ShowLatestQBData()
{
	try
	{
		// geoImg
		if ((m_LatestQBData.image.bValid == true) && // 图像数据有效
			(m_LatestQBData.image.geoImg.buff != nullptr) &&  // 图像有数据
			(m_LatestQBData.image.geoImg.ImgWidth > 0) && (m_LatestQBData.image.geoImg.ImgHeight > 0) && // 图像尺寸有效 
			(m_LatestQBData.image.geoImg.bitcount > 0)) // 数据位数有效
		{
			// 创建临时变量:图像头
			BITMAPINFO imgheader;
			imgheader.bmiHeader.biWidth    = static_cast<int>(m_LatestQBData.image.geoImg.ImgWidth);
			imgheader.bmiHeader.biHeight   = static_cast<int>(m_LatestQBData.image.geoImg.ImgHeight);
			imgheader.bmiHeader.biBitCount = static_cast<WORD>(m_LatestQBData.image.geoImg.bitcount);

			// 显示图像
			ShowOneImage(&imgheader, m_LatestQBData.image.geoImg.buff, FALSE, NULL, FALSE, m_ImgRatioOnScreen, m_ImgShowShift);

			if (min(m_ShowRegionOnScreen.Width(), m_ShowRegionOnScreen.Height()) <= 10)
			{
				m_ImgRatioOnScreen = m_ImgRatioOnScreen / 0.9F;
			}
		}
		// dstImg
		else if ((m_LatestQBData.image.bValid == true) && // 图像数据有效
			(m_LatestQBData.image.dstImg.buff != nullptr) &&  // 图像有数据
			(m_LatestQBData.image.dstImg.ImgWidth > 0) && (m_LatestQBData.image.dstImg.ImgHeight > 0) && // 图像尺寸有效 
			(m_LatestQBData.image.dstImg.bitcount > 0)) // 数据位数有效
		{
			// 创建临时变量:图像头
			BITMAPINFO imgheader;
			imgheader.bmiHeader.biWidth    = static_cast<int>(m_LatestQBData.image.dstImg.ImgWidth);
			imgheader.bmiHeader.biHeight   = static_cast<int>(m_LatestQBData.image.dstImg.ImgHeight);
			imgheader.bmiHeader.biBitCount = static_cast<WORD>(m_LatestQBData.image.dstImg.bitcount);

			// 显示图像
			ShowOneImage(&imgheader, m_LatestQBData.image.dstImg.buff, FALSE, NULL, FALSE, m_ImgRatioOnScreen, m_ImgShowShift);

			if (min(m_ShowRegionOnScreen.Width(), m_ShowRegionOnScreen.Height()) <= 10)
			{
				m_ImgRatioOnScreen = m_ImgRatioOnScreen / 0.9F;
			}
		}
		// srcImg
		else if ((m_LatestQBData.image.bValid == true) && // 图像数据有效
			(m_LatestQBData.image.srcImg.buff != nullptr) &&  // 图像有数据
			(m_LatestQBData.image.srcImg.ImgWidth > 0) && (m_LatestQBData.image.srcImg.ImgHeight > 0) && // 图像尺寸有效 
			(m_LatestQBData.image.srcImg.bitcount > 0)) // 数据位数有效
		{
			// 创建临时变量:图像头
			BITMAPINFO imgheader;
			imgheader.bmiHeader.biWidth    = static_cast<LONG>(m_LatestQBData.image.srcImg.ImgWidth);
			imgheader.bmiHeader.biHeight   = static_cast<LONG>(m_LatestQBData.image.srcImg.ImgHeight);
			imgheader.bmiHeader.biBitCount = static_cast<WORD>(m_LatestQBData.image.srcImg.bitcount);

			// 显示图像
			ShowOneImage(&imgheader, m_LatestQBData.image.srcImg.buff, FALSE, NULL, FALSE, m_ImgRatioOnScreen, m_ImgShowShift);

			if (min(m_ShowRegionOnScreen.Width(), m_ShowRegionOnScreen.Height()) <= 10)
			{
				m_ImgRatioOnScreen = m_ImgRatioOnScreen / 0.9F;
			}
		}
		else  // 图像数据无效
		{

			// 如果当前帧图像数据无效,则释放上一帧保存的图像
			cvReleaseImage(&m_SrcFrame);
			m_SrcFrame = NULL;

			// 重绘窗口
			CRect clientRect;
			GetClientRect(&clientRect);
			InvalidateRect(&clientRect);
			UpdateWindow();

			// 显示指北针
			if (m_LatestQBData.framePart.bValid == TRUE) // 复接数据有效
			{
				// 设置在OnPaint中不绘制指北针
				m_bPlotDirectionOnPaint = FALSE;  

				// 清除上次绘制的指北针
				CRect rect;
				rect.left  = m_NorthDirectionCenter.x - 100;
				rect.right = m_NorthDirectionCenter.x + 100;
				rect.top    = m_NorthDirectionCenter.y - 100;
				rect.bottom = m_NorthDirectionCenter.y + 100;

				InvalidateRect(&rect);
				UpdateWindow();

				// 恢复设置 OnPaint中重绘
				m_bPlotDirectionOnPaint = TRUE;
			}
		}
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}


// 1.9 功能:获取双击目标点坐标 m_LButtonDblClkPixelCoordinate
CPoint CImgShowDlg::GetTargetCoordinate()
{
	return m_LButtonDblClkPixelCoordinate;
}


// 1.10 功能:在对话框左上角显示信息
void CImgShowDlg::ShowMessageOnDialog(CString msg)
{
	try
	{
		// 获取窗口句柄
		CWnd *pWnd = GetDlgItem(IDC_IMG_SHOW_PIC_CTRL);

		CRect Rect; 
		pWnd->GetClientRect(&Rect);

		// 获得控件的 DC
		CDC *pDC=pWnd->GetDC();

		// 设置背景透明
		pDC->SetBkMode(TRANSPARENT);

		// 设置字体颜色
		pDC->SetTextColor(RGB(255,0,0));

		// 输出信息
		pDC->TextOutA(Rect.Width() - 130, Rect.Height() - 50, msg);

		ReleaseDC(pDC);	
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}

//  3.1 功能:基于当前图像显示状态 和 像素坐标(图像某点的像素坐标),求该像素坐标对应的客户区坐标
CPoint CImgShowDlg::GetScreenCoordinateBasedOnPixelCoordinate(const POINT &PixelCoordinate)
{
	// 返回值
	CPoint screenCoordinate = CPoint(-100, -100);

	try
	{
		// 如果该像素坐标显示在当前窗口中
		if ((PixelCoordinate.x >= m_ShowRegion.left) && (PixelCoordinate.x <= m_ShowRegion.right) &&
			(PixelCoordinate.y >= m_ShowRegion.top)  && (PixelCoordinate.y <= m_ShowRegion.bottom) ) 
		{
			double ratio = 1.0;

			// 计算屏幕坐标
			if(m_ShowRegionOnScreen.Width() > 0)
			{
				ratio = m_ShowRegion.Width() * 1.0 / m_ShowRegionOnScreen.Width();

				if (ratio > 0.0)
				{
					screenCoordinate.x = static_cast<LONG>((PixelCoordinate.x - m_ShowRegion.left) / ratio) + m_ShowRegionOnScreen.left;
					screenCoordinate.y = static_cast<LONG>((PixelCoordinate.y - m_ShowRegion.top)  / ratio) + m_ShowRegionOnScreen.top;
				}
			}		
		}

		return screenCoordinate;
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return screenCoordinate;
	}
	catch(...)
	{
		return screenCoordinate;
	}
}


// 3.2 功能:给定屏幕坐标,在屏幕中绘制标框, (可能)同时清除上次绘制的标框
void CImgShowDlg::DrawSquareOnScreen(const POINT &screenCoordinate, BOOL bErase)
{
	try
	{
		// 如果该点在图像显示区域中,则清除上次绘制的标框,同时标绘该点
		int X = static_cast<int>(screenCoordinate.x); // X坐标
		int Y = static_cast<int>(screenCoordinate.y); // Y坐标

		if (X > m_ShowRegionOnScreen.left && X < m_ShowRegionOnScreen.right &&
			Y > m_ShowRegionOnScreen.top && Y < m_ShowRegionOnScreen.bottom ) // 鼠标在图像上
		{
			// 绘制标框
			if (bErase == TRUE)
			{
				// 去掉上次标绘的框
				InvalidateRect(&m_LatestPlotRect, FALSE);
				UpdateWindow();
			}

			CDC* pDC = this->GetDC();
			CPen newPen; // 创建新画笔
			newPen.CreatePen(PS_SOLID, 2, RGB(0, 255, 0));

			CPen* pOldPen = NULL;
			if (pDC != NULL)
			{
				pDC->SelectObject(&newPen);

				// 绘图
				pDC->MoveTo(X - 50, Y);
				pDC->LineTo(X - 20, Y);

				pDC->MoveTo(X + 20, Y);
				pDC->LineTo(X + 50, Y);

				pDC->MoveTo(X, Y - 50);
				pDC->LineTo(X, Y - 20);

				pDC->MoveTo(X, Y + 20);
				pDC->LineTo(X, Y + 50);

				pDC->MoveTo(X + 30, Y - 15);
				pDC->LineTo(X + 30, Y - 30);
				pDC->LineTo(X + 15, Y - 30);

				pDC->MoveTo(X - 30, Y - 15);
				pDC->LineTo(X - 30, Y - 30);
				pDC->LineTo(X - 15, Y - 30);

				pDC->MoveTo(X - 30, Y + 15);
				pDC->LineTo(X - 30, Y + 30);
				pDC->LineTo(X - 15, Y + 30);

				pDC->MoveTo(X + 30, Y + 15);
				pDC->LineTo(X + 30, Y + 30);
				pDC->LineTo(X + 15, Y + 30);

				// 中心点
				pDC->MoveTo(X - 1, Y);
				pDC->LineTo(X + 1, Y);
				pDC->MoveTo(X , Y - 1);
				pDC->LineTo(X , Y + 1);

				// 回收旧画笔
				pDC->SelectObject(pOldPen);

				// 释放设备上下文指针
				ReleaseDC(pDC);
				pDC = NULL;

				// 更新latestRect
				m_LatestPlotRect.left   = X - 51;
				m_LatestPlotRect.right  = X + 50;
				m_LatestPlotRect.top    = Y - 51;
				m_LatestPlotRect.bottom = Y + 50;
			}

			// 设置为目标标绘状态
			m_bPlotRect = TRUE;
		}
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}

//  3.2 功能:给定屏幕4个坐标,在屏幕中绘制四边形, (可能)同时清除上次绘制
//      输入:
//		    1: screenCoordinate: 屏幕坐标
//      返回值:无
void CImgShowDlg::DrawQuadrangleOnScreen(const POINT screenCoordinate[4], BOOL bErase)
{
	try
	{
		// 如果该点在图像显示区域中,则清除上次绘制的标框,同时标绘该点

		// 绘制标框
		if (bErase == TRUE)
		{
			// 去掉上次标绘的框
			InvalidateRect(&m_LatestPlotRect, FALSE);
			UpdateWindow();
		}

		CDC* pDC = this->GetDC();
		CPen newPen; // 创建新画笔
		newPen.CreatePen(PS_SOLID, 2, RGB(0, 255, 0));

		CPen* pOldPen = NULL;
		if (pDC != NULL)
		{
			pDC->SelectObject(&newPen);

			// 绘图
			pDC->MoveTo(screenCoordinate[0].x, screenCoordinate[0].y);
			pDC->LineTo(screenCoordinate[1].x, screenCoordinate[1].y);
			pDC->LineTo(screenCoordinate[2].x, screenCoordinate[2].y);
			pDC->LineTo(screenCoordinate[3].x, screenCoordinate[3].y);
			pDC->LineTo(screenCoordinate[0].x, screenCoordinate[0].y);

			// 回收旧画笔
			pDC->SelectObject(pOldPen);

			// 释放设备上下文指针
			ReleaseDC(pDC);
			pDC = NULL;
		}
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}


void CImgShowDlg::DoZoomInImg()
{
	try
	{
		/************************************************************************/
		/* 设计思路:

		分两种情况:
		情况1:当前图像的全部内容已经全部显示出来
		情况2:当前只显示出部分图像

		针对情况1:也存在两种情况:
		(1.1) 全景显示: 此时 StrecthRatio = 1.0f
		(1.2) 图像已经经过缩小显示,此时,StrecthRatio <= 0.901(考虑到存储精度),这时,放大10%显示即可,即StrecthRatio /= 0.9f;

		针对情况2:只显示出部分图像,此时 StrecthRatio = 1.0f
		/************************************************************************/

		if ((m_ShowRegion.Width() == m_SrcFrame->width - 1) && (m_ShowRegion.Height() == m_SrcFrame->height - 1)) // 情况1
		{
			// 拉伸比例计算
			if (m_ImgRatioOnScreen <= 0.901F)   // (1.2) 目前图像是缩小显示
			{
				m_ImgRatioOnScreen /= 0.9F;
			}
			else                              // (1.1) 目前图像是充满显示,正好 
			{
				m_ImgRatioOnScreen = 1.0F;    // 继续放大时要求继续填满显示才符合逻辑,故设为:ImgRatioOnScreen = 1.0F

				if (max(m_ShowRegion.Width(), m_ShowRegion.Height()) >= 100)
				{
					m_ShowRegion = GetNewRegionWhenZoom(true);
				}
			}
		}
		else  // 图像尚未完整显示     情况2
		{
			m_ImgRatioOnScreen = 1.0F; // 此时,无需拉伸比例控制

			if (max(m_ShowRegion.Width(), m_ShowRegion.Height()) >= 100)
			{
				m_ShowRegion = GetNewRegionWhenZoom(true);
			}
		}

		// 显示图像
		ShowOneImage(m_SrcFrame, TRUE, m_ShowRegion, m_ImgRatioOnScreen, m_ImgShowShift);

		int a = 5;
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}


CRect CImgShowDlg::GetNewRegionWhenZoom(bool in)
{
	CRect newShowRegion = m_ShowRegion;

	try
	{
		double ratio = 0.1;   
		if (in == true)
		{
			ratio = -ratio;
		}

		// 在当前显示区域的基础上,以中心点为基准点放大
		int ShowRegionWidth = m_ShowRegion.Width() + 1;
		int ShowRegionHeight = m_ShowRegion.Height() + 1;

		newShowRegion.left   = m_ShowRegion.left   - static_cast<LONG>(ratio / 2 * ShowRegionWidth);
		newShowRegion.right  = m_ShowRegion.right  + static_cast<LONG>(ratio / 2 * ShowRegionWidth);
		newShowRegion.top    = m_ShowRegion.top    - static_cast<LONG>(ratio / 2 * ShowRegionHeight);
		newShowRegion.bottom = m_ShowRegion.bottom + static_cast<LONG>(ratio / 2 * ShowRegionHeight);

		// 在此修正,确保返回值有效
		if (newShowRegion.left < 0)
		{
			newShowRegion.left = 0;
		}

		int _Width = m_SrcFrame->width;
		int _Height = m_SrcFrame->height;

		if (newShowRegion.right > _Width - 1)
		{
			newShowRegion.right = _Width - 1;
		}

		if (newShowRegion.top < 0)
		{
			newShowRegion.top = 0;
		}

		if (newShowRegion.bottom > _Height - 1)
		{
			newShowRegion.bottom = _Height - 1;
		}

		// 若无效,返回原始值
		if (newShowRegion.right - newShowRegion.left <= 0 ||
			newShowRegion.bottom - newShowRegion.top <= 0)
		{
			return m_ShowRegion;
		}

		// 调整 newShowRegion 目的:填充图像控件
		double newShowRegion_WH_Ration = 1.0; // 当前 newShowRegion 的“宽高” 比例
		double PicCtrl_WH_Ration       = 1.0; // 当前图像控件的“宽高”比例

		double newShowRegion_HW_Ration = 1.0; // 当前 newShowRegion 的“高宽”比例
		double PicCtrl_HW_Ration       = 1.0; // 当前图像控件的“高宽”比例

		// 分母不为0判断
		if ((newShowRegion.Height() > 0) && (m_PicCtrlHeight > 0))
		{
			newShowRegion_WH_Ration = static_cast<double>(newShowRegion.Width()) / static_cast<double>(newShowRegion.Height());
			PicCtrl_WH_Ration       = static_cast<double>(m_PicCtrlWidth) / static_cast<double>(m_PicCtrlHeight);
		}
		else
		{
			return m_ShowRegion;
		}

		// 分母不为0判断
		if ((newShowRegion_WH_Ration > 0.0) && (PicCtrl_WH_Ration > 0.0))
		{
			newShowRegion_HW_Ration = 1.0 / newShowRegion_WH_Ration;
			PicCtrl_HW_Ration       = 1.0 / PicCtrl_WH_Ration;
		}
		else
		{
			return m_ShowRegion;
		}

		if (newShowRegion_WH_Ration > PicCtrl_WH_Ration)  // 宽度已经填满时
		{
			// 图像上下填充
			int newShowRegion_ideal_Height = 0; //  在现有图像显示宽度的基础上,图像显示区域的理想高度
			newShowRegion_ideal_Height = static_cast<int>(newShowRegion.Width() * PicCtrl_HW_Ration);

			// 上下补齐
			newShowRegion.top    -= static_cast<LONG>((newShowRegion_ideal_Height - newShowRegion.Height() + 1)/ 2);  // + 1 是考虑到 0.5 误差影响
			newShowRegion.bottom += static_cast<LONG>((newShowRegion_ideal_Height - newShowRegion.Height() + 1)/ 2);  // + 1 是考虑到 0.5 误差影响

			// 补齐后有可能越界 需进行修正
			if (newShowRegion.top < 0)  // 可能上边界越出图像边界
			{
				newShowRegion.bottom -= newShowRegion.top;
				newShowRegion.top = 0L;

				if (newShowRegion.bottom > static_cast<LONG>(_Height - 1))
				{
					newShowRegion.bottom = static_cast<LONG>(_Height - 1);
				}
			}

			if (newShowRegion.bottom > static_cast<LONG>(_Height - 1)) // 可能下边界越出图像边界
			{
				newShowRegion.top   -= static_cast<LONG>((newShowRegion.bottom - _Height + 1));
				newShowRegion.bottom = static_cast<LONG>(_Height - 1);

				if (newShowRegion.top < 0L)
				{
					newShowRegion.top = 0L;
				}
			}
		}
		else // 高度已经填满
		{ 
			// 图像左右填充
			int newShowRegion_ideal_Width = 0; //  在现有图像显示高度的基础上,图像显示区域的理想宽度
			newShowRegion_ideal_Width = static_cast<int>(newShowRegion.Height() * PicCtrl_WH_Ration);

			// 左右补齐
			newShowRegion.left   -= static_cast<LONG>((newShowRegion_ideal_Width - newShowRegion.Width() + 1)/ 2); // + 1 是考虑到 0.5 误差影响
			newShowRegion.right  += static_cast<LONG>((newShowRegion_ideal_Width - newShowRegion.Width() + 1)/ 2); // + 1 是考虑到 0.5 误差影响

			// 补齐后有可能越界 需进行修正

			if (newShowRegion.left < 0L)  // 可能左边界越出图像边界
			{
				newShowRegion.right -= newShowRegion.left;
				newShowRegion.left = 0L;

				if (newShowRegion.right > static_cast<LONG>(_Width - 1))
				{
					newShowRegion.right = static_cast<LONG>(_Width - 1);
				}
			}

			if (newShowRegion.right > static_cast<LONG>(_Width - 1)) // 可能右边界越出图像边界
			{
				newShowRegion.left -= static_cast<LONG>((newShowRegion.right - _Width + 1));
				newShowRegion.right = static_cast<LONG>(_Width - 1);

				if (newShowRegion.left < 0L)
				{
					newShowRegion.left = 0L;
				}
			}
		}

		// 在此修正,确保返回值有效
		if (newShowRegion.left < 0)
		{
			newShowRegion.left = 0;
		}

		if (newShowRegion.right > _Width - 1)
		{
			newShowRegion.right = _Width - 1;
		}

		if (newShowRegion.top < 0)
		{
			newShowRegion.top = 0;
		}

		if (newShowRegion.bottom > _Height - 1)
		{
			newShowRegion.bottom = _Height - 1;
		}

		return newShowRegion;
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return newShowRegion;
	}
	catch(...)
	{
		return newShowRegion;
	}
}

//  3.6 功能: 执行图像缩小操作 
void CImgShowDlg::DoZoomOutImg()
{
	try
	{
		// 计算图像显示区域,更新:ShowRegion

		/************************************************************************/
		/* 设计思路:

		分两种情况:
		情况1:当前图像的全部内容已经全部显示出来,继续拉伸比例缩小显示即可
		情况2:当前只显示出部分图像,计算新的显示区域
		/************************************************************************/

		// 是否已经显示全部图像内容
		if ((m_ShowRegion.Width() == m_SrcFrame->width - 1) && (m_ShowRegion.Height() == m_SrcFrame->height - 1))
		{
			if (max(m_ShowRegionOnScreen.Width(), m_ShowRegionOnScreen.Height()) > 10)
			{
				m_ImgRatioOnScreen *= 0.9F;
			}
		}
		else  // 图像尚未完整显示
		{
			// 自适应计算 ShowRegion 
			m_ShowRegion = GetNewRegionWhenZoom(false);

			m_ImgRatioOnScreen = 1.0F; // 此时,无需拉伸比例控制
		}

		// 显示图像
		ShowOneImage(m_SrcFrame, TRUE, m_ShowRegion, m_ImgRatioOnScreen, m_ImgShowShift);
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}

//  3.7 功能: 当漫游图像时,自适应计算新的图像显示区 
CRect CImgShowDlg::GetNewRegionWhenRoamImg(int deltaX, int deltaY)
{
	// 返回值,初始化为当前显示区域
	CRect newShowRegion = m_ShowRegion; // 新的图像显示区域

	newShowRegion.left   = m_ShowRegion.left   - deltaX;
	newShowRegion.right  = m_ShowRegion.right  - deltaX;
	newShowRegion.top    = m_ShowRegion.top    - deltaY;
	newShowRegion.bottom = m_ShowRegion.bottom - deltaY;

	int m_Width = m_SrcFrame->width;
	int m_Height = m_SrcFrame->height;

	if (newShowRegion.left < 0L)  
	{
		newShowRegion.right -= newShowRegion.left;
		newShowRegion.left = 0L;

		if (newShowRegion.right > static_cast<LONG>(m_Width - 1))
		{
			newShowRegion.right = static_cast<LONG>(m_Width - 1);
		}
	}

	if (newShowRegion.right > static_cast<LONG>(m_Width - 1)) 
	{
		newShowRegion.left -= static_cast<LONG>((newShowRegion.right - m_Width + 1));
		newShowRegion.right = static_cast<LONG>(m_Width - 1);

		if (newShowRegion.left < 0L)
		{
			newShowRegion.left = 0L;
		}
	}

	if (newShowRegion.top < 0) 
	{
		newShowRegion.bottom -= newShowRegion.top;
		newShowRegion.top = 0L;

		if (newShowRegion.bottom > static_cast<LONG>(m_Height - 1))
		{
			newShowRegion.bottom = static_cast<LONG>(m_Height - 1);
		}
	}

	if (newShowRegion.bottom > static_cast<LONG>(m_Height - 1)) 
	{
		newShowRegion.top   -= static_cast<LONG>((newShowRegion.bottom - m_Height + 1));
		newShowRegion.bottom = static_cast<LONG>(m_Height - 1);

		if (newShowRegion.top < 0L)
		{
			newShowRegion.top = 0L;
		}
	}

	// 在此修正,确保返回值有效
	if (newShowRegion.left < 0)
	{
		newShowRegion.left = 0;
	}

	if (newShowRegion.right > m_Width - 1)
	{
		newShowRegion.right = m_Width - 1;
	}

	if (newShowRegion.top < 0)
	{
		newShowRegion.top = 0;
	}

	if (newShowRegion.bottom > m_Height - 1)
	{
		newShowRegion.bottom = m_Height - 1;
	}

	return newShowRegion;
}


//  3.8 功能: 执行图像全景(全屏)操作 
void CImgShowDlg::DoZoomFitImg()
{
	try
	{
		// 保证有图像
		if (m_SrcFrame != NULL)
		{
			// 设置为整个图像显示
			m_ShowRegion.left   = 0L;
			m_ShowRegion.right  = static_cast<LONG>(m_SrcFrame->width - 1);
			m_ShowRegion.top    = 0L;
			m_ShowRegion.bottom = static_cast<LONG>(m_SrcFrame->height - 1);

			// 拉伸比例归1
			m_ImgRatioOnScreen = 1.0F; // 复位

			// 平移量归零
			m_ImgShowShift.x = 0L;
			m_ImgShowShift.y = 0L;

			// 全景显示图像
			ShowWholeImage(m_SrcFrame, m_ImgRatioOnScreen, m_ImgShowShift);
		}
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}



// CImgShowDlg 消息处理程序


BOOL CImgShowDlg::OnEraseBkgnd(CDC* pDC)
{
	// 背景色为黑色
	CRect Rect;
	GetClientRect(&Rect);
	pDC->FillSolidRect(Rect, RGB(0, 0, 0)); //设置窗口背景颜色为黑色
	return TRUE; 
}


void CImgShowDlg::OnPaint()
{
	CPaintDC dc(this); // device context for painting

	try
	{
		if (m_SrcFrame != NULL)
		{
			// 重绘图像
			ShowOneImage(m_SrcFrame, TRUE, m_ShowRegion, m_ImgRatioOnScreen, m_ImgShowShift);

			if (min(m_ShowRegionOnScreen.Width(), m_ShowRegionOnScreen.Height()) <= 10)
			{
				m_ImgRatioOnScreen = m_ImgRatioOnScreen / 0.9F;
			}

			if (m_bPlotRectOnPaint == TRUE)
			{
				// 标绘目标点 标绘窗口
				DrawSquareOnScreen(GetScreenCoordinateBasedOnPixelCoordinate(m_LButtonDblClkPixelCoordinate), FALSE);
			}

			// 视场标绘
			// SetQuadrangleCorners(m_corners);
		}
		else
		{
			if (m_sThemeText != "")
			{
				//  写字:图像窗口
				// 获取窗口句柄
				CWnd *pWnd = NULL;
				pWnd = GetDlgItem(IDC_IMG_SHOW_PIC_CTRL);

				if (pWnd == NULL)
				{
					return;
				}

				// 获得控件的 DC
				CDC *pDC = NULL;
				pDC = pWnd->GetDC();
				if (pDC == NULL)
				{
					return;
				}

				CFont font;
				font.CreatePointFont(180,"Times New Roman");

				CFont *pOldFont = pDC->SelectObject(&font);

				// 设置背景透明
				pDC->SetBkMode(TRANSPARENT);

				// 设置字体颜色
				pDC->SetTextColor(RGB(0,255,255));

				// 确定输出位置
				CRect Rect; 
				GetClientRect(&Rect);
				int x = Rect.left + 5;
				int y = Rect.bottom - 28;

				// 输出信息
				pDC->TextOutA(x, y,  m_sThemeText);

				pDC->SelectObject(pOldFont);

				ReleaseDC(pDC);	
			}
		}
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}

// 5.10 右键响应函数 
//      功能:弹出右键菜单,进行功能选择
void CImgShowDlg::OnRButtonDown(UINT nFlags, CPoint point)
{
	try
	{ 
		if (m_bCloseRughtBtnMenu == false)
		{
			// 加载菜单项
			CMenu menu;
			menu.LoadMenu(IDR_MENU_IMG_PROCESS);

			// 保留右键坐标 由于定位导引 或 右键图像放大
			m_RButtonPt = point;

			// 输入坐标为客户区坐标,也就是相对本对话框(左上角为(0,0))的坐标转换到屏幕坐标
			ClientToScreen(&point);

			// 九宫格快速浏览图像
			if (m_pFastLookUpDlg != NULL &&  m_pFastLookUpDlg->IsWindowVisible() == TRUE)
			{
				menu.GetSubMenu(0)->CheckMenuItem(ID_FAST_LOOKUP_IMGS, MF_BYCOMMAND | MF_CHECKED);
			}
			else
			{
				menu.GetSubMenu(0)->CheckMenuItem(ID_FAST_LOOKUP_IMGS, MF_BYCOMMAND | MF_UNCHECKED);
			}

			// menu.GetSubMenu(0)->EnableMenuItem(ID_FAST_LOOKUP_IMGS, MF_GRAYED); // MF_ENABLED

			// 标绘 目标 矩形
			if (m_bDrawSquareOnImg == TRUE)
			{
				menu.GetSubMenu(0)->CheckMenuItem(ID_DRAW_SQUARE_ON_IMG, MF_BYCOMMAND | MF_CHECKED);
			} 
			else
			{
				menu.GetSubMenu(0)->CheckMenuItem(ID_DRAW_SQUARE_ON_IMG, MF_BYCOMMAND | MF_UNCHECKED);
			}

			// 目标扣取
			if (m_bGetTgtImgOn == true)
			{
				menu.GetSubMenu(0)->CheckMenuItem(ID_GET_TARGET_IMG, MF_BYCOMMAND | MF_CHECKED);
			}
			else
			{
				menu.GetSubMenu(0)->CheckMenuItem(ID_GET_TARGET_IMG, MF_BYCOMMAND | MF_UNCHECKED);
			}

			if (m_bClipImgOn == TRUE)
			{
				menu.GetSubMenu(0)->CheckMenuItem(ID_CLIP_IMG, MF_BYCOMMAND | MF_CHECKED);
			}
			else
			{
				menu.GetSubMenu(0)->CheckMenuItem(ID_CLIP_IMG, MF_BYCOMMAND | MF_UNCHECKED);
			}

			// 弹出菜单
			menu.GetSubMenu(0)->TrackPopupMenu( TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON, 
				static_cast<int>(point.x), static_cast<int>(point.y), this); // 只在本窗口内作出相应
		}

		CDialog::OnRButtonDown(nFlags, point);
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}

// 功能:设置图像在屏幕中的显示比例
void CImgShowDlg::SetImgShowRationOnScreen(float ratio)
{
	if(ratio >= 1.0F || ratio <= 0.0F)
	{
		ratio = 1.0F;
	}

	// 修改全局变量 ImgRatioOnScreen
	m_ImgRatioOnScreen = ratio;
}

void CImgShowDlg::OnZoomInImg()
{
	try
	{
		// 如果有外部信号输入,操作与视频模式下相同
		if (m_bFirstSignal == TRUE || m_bSecondSignal == TRUE)
		{
			SetImgShowRationOnScreen(m_ImgRatioOnScreen / 0.9F);
			return;
		}

		// 放大显示图像
		DoZoomInImg();

		// 更新标绘窗口
		DrawSquareOnScreen(GetScreenCoordinateBasedOnPixelCoordinate(m_LButtonDblClkPixelCoordinate));

		// 设置无效,不保留上次值
		m_RButtonPt.x = -100;
		m_RButtonPt.y = -100;	
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}


void CImgShowDlg::OnZoomOutImg()
{
	try
	{
		// 如果有外部信号输入  操作与视频模式下相同
		if (m_bFirstSignal == TRUE || m_bSecondSignal == TRUE)
		{
			SetImgShowRationOnScreen(m_ImgRatioOnScreen * 0.9F);
			return;
		}

		// 缩小显示图像
		DoZoomOutImg();

		// 更新标绘窗口
		DrawSquareOnScreen(GetScreenCoordinateBasedOnPixelCoordinate(m_LButtonDblClkPixelCoordinate));
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}


void CImgShowDlg::OnZoomFitImg()
{
	try
	{
		// 如果有外部信号输入 操作与视频模式下相同
		if (m_bFirstSignal == TRUE || m_bSecondSignal == TRUE)
		{
			// 视频显示模式复位 
			m_ImgRatioOnScreen = 1.0F;
			m_ImgShowShift.x = 0L;
			m_ImgShowShift.y = 0L;

			return;
		}

		// 直接全景显示图像
		DoZoomFitImg();

		// 更新标绘窗口
		DrawSquareOnScreen(GetScreenCoordinateBasedOnPixelCoordinate(m_LButtonDblClkPixelCoordinate));
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}


void CImgShowDlg::OnConcelTargetPlot()
{
	try
	{
		// 在onPaint中不重绘
		m_bPlotRectOnPaint = FALSE;

		// 去掉上次标绘的框
		InvalidateRect(&m_LatestPlotRect, FALSE);
		UpdateWindow(); // 发送消息 立即响应

		// 设置为 小于0 的无效值
		m_LButtonDblClkPixelCoordinate.x = -1;
		m_LButtonDblClkPixelCoordinate.y = -1;

		// 结束绘制
		m_bPlotRect = FALSE;
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}


// 功能:保存当前帧图像及信息
BOOL CImgShowDlg::SaveCurrentDecodedFrame()
{
	try
	{
		// 计算存储路径
		static int imgSaveOrder = 1;

		// 图像数据有效
		// 说明:程序设计中,SrcFrame代表当前图像
		if (m_SrcFrame != NULL)
		{
			// 计算图像和复接数据存储路径
			SYSTEMTIME CurrentTime;
			GetLocalTime(&CurrentTime);

			CString ImgSavePath;
			ImgSavePath.Format(  "%04d%02d%02d_%02d%02d%02d%04d",
				CurrentTime.wYear, 
				CurrentTime.wMonth, 
				CurrentTime.wDay, 
				CurrentTime.wHour, 
				CurrentTime.wMinute,
				CurrentTime.wSecond,
				CurrentTime.wMilliseconds); 
			// 添加序号
			CString sImgSaveOlder;
			sImgSaveOlder.Format("%04d", imgSaveOrder);

			ImgSavePath = ImgSavePath + "_" + sImgSaveOlder;

			CString FJSavePath;
			FJSavePath = ImgSavePath; // 共享同一时间

			CString FImgSavePath;
			FImgSavePath = ImgSavePath; // 共享同一时间

			// 校验保存路径
			if (m_sSaveCurrentImgFolder == "" || false == SearchDirectory(m_sSaveCurrentImgFolder))
			{
				m_sSaveCurrentImgFolder = "";
			}

			if (m_sSaveCurrentImgFolder == "")
			{
				ImgSavePath = m_sImgSaveFolder + "\\" + ImgSavePath + ".bmp"; // 完整图像存储路径
			}
			else
			{
				ImgSavePath = m_sSaveCurrentImgFolder + "\\" + ImgSavePath + ".bmp"; // 完整图像存储路径
			}


			// 确保有文件夹,如果中途误删,会再次创建
			if (SearchDirectory(m_sRootFolder) == FALSE) // 没找到根文件夹
			{
				CreateDirectory(m_sRootFolder, NULL);
			}
			if (SearchDirectory(m_sImgSaveFolder) == FALSE) // 没找到【图像】文件夹
			{
				CreateDirectory(m_sImgSaveFolder, NULL);
			}

			// 转化
			cv::Mat img(m_SrcFrame, false);

			// 保存图像
			if (true == cv::imwrite(ImgSavePath.GetBuffer(0), img))
			{
				// 保存路径回调
				if (m_lpSendFilePath != NULL)
				{
					m_lpSendFilePath(ImgSavePath, 0);
				}
			}

			imgSaveOrder++;

			m_sSaveCurrentImgFolder = ""; // 复位

			return TRUE;
		}

		return FALSE;
	}
	catch(cv::Exception &e)
	{
		e.msg;
		m_sSaveCurrentImgFolder = ""; // 复位
		return FALSE;
	}
	catch(...)
	{
		m_sSaveCurrentImgFolder = ""; // 复位
		return FALSE;
	}
}

// 保存当前帧
void CImgShowDlg::OnSaveCurrentFrame()
{
	try
	{
		SaveCurrentDecodedFrame();
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}

// 功能:是否需要记忆前面多帧(18帧)图像信息
//   输入:
//       1. bMem TRUE:记忆 FALSE:不记忆
//   输出:无
void CImgShowDlg::MemPreMultiFrame(BOOL bMem)
{
	m_bMemPreMultiFrame = bMem;
}




// 左键按下消息响应
void CImgShowDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
	try
	{
		CDialog::OnLButtonDown(nFlags, point);

		if (m_SrcFrame == NULL) // 如果没有图像,不响应
		{
			return;
		}

		// Alt = 1  Ctrl = 5  Shift = 9
		if (nFlags == MK_CONTROL) // 当按住ctrl键时,不响应 因为与选择目标时冲突
		{
			return;
		}

		// 更新鼠标坐标
		m_LeftButtonDown = point; 

		// 鼠标是否在图像上
		if(m_LeftButtonDown.x > m_ShowRegionOnScreen.left && m_LeftButtonDown.x < m_ShowRegionOnScreen.right &&
			m_LeftButtonDown.y > m_ShowRegionOnScreen.top  && m_LeftButtonDown.y < m_ShowRegionOnScreen.bottom)
		{
			m_bStaisfyRoamImg = TRUE;

			// 计算一点的像素坐标
			int ShowRegionWidth = m_ShowRegionOnScreen.Width() + 1;
			int ShowRegionHeight = m_ShowRegionOnScreen.Height() + 1;
			double ratioW = double(m_ShowRegion.Width() + 1) / ShowRegionWidth;
			double ratioH = double(m_ShowRegion.Height() + 1) / ShowRegionHeight;
			m_LButtonDownPixelCoordinate.x = static_cast<int>((point.x - m_ShowRegionOnScreen.left) * ratioW + 0.5 + m_ShowRegion.left);
			m_LButtonDownPixelCoordinate.y = static_cast<int>((point.y - m_ShowRegionOnScreen.top)  * ratioH + 0.5 + m_ShowRegion.top);

			// 图像裁剪优先级高于目标扣取
			if (m_bClipImgOn == true)
			{
				if (m_haveValidFirstPt == FALSE)
				{
					m_clipImgFirstPt = m_LButtonDownPixelCoordinate;
					m_clipImgFirstPtScreen = point;
					m_haveValidFirstPt = TRUE;
				}
				else
				{
					m_clipImgSecondPt = m_LButtonDownPixelCoordinate;
					m_haveValidFirstPt = FALSE;

					// 弹出裁剪提示
					int Left = min(m_clipImgFirstPt.x, m_clipImgSecondPt.x);
					int Right = max(m_clipImgFirstPt.x, m_clipImgSecondPt.x);
					int Top = min(m_clipImgFirstPt.y, m_clipImgSecondPt.y);
					int Bottom = max(m_clipImgFirstPt.y, m_clipImgSecondPt.y);

					if (Right > Left && Bottom > Top)
					{
						cv::Mat img(m_SrcFrame, false);

						cv::Mat clipedImg;
						img(cv::Range(Top, Bottom), cv::Range(Left, Right)).copyTo(clipedImg);

						int ret = ::MessageBoxA(NULL, _T("确定裁剪图像?"),_T("操作提示"), MB_YESNO | MB_SYSTEMMODAL);

						if (ret == IDNO)
						{
							Invalidate();
						}
						else
						{
							m_bClipImgOn = false;

							// 创建临时情报结构体
							QBStru qbLocal;
							qbLocal.image.bValid = true;
							qbLocal.framePart.bValid = false;

							qbLocal.image.srcImg.ImgWidth = clipedImg.cols;
							qbLocal.image.srcImg.ImgHeight = clipedImg.rows;
							qbLocal.image.srcImg.bitcount = clipedImg.channels() * 8;

							// 步长:每行像素所占字节数 
							int lineByte = (clipedImg.cols * clipedImg.channels());

							// 位图数据缓冲区的大小,即图像大小
							int imgBufSize = clipedImg.rows * lineByte;

							if (imgBufSize > 0)
							{
								qbLocal.image.srcImg.buff = new BYTE[imgBufSize];
								if (qbLocal.image.srcImg.buff != nullptr)
								{
									// 复制实际字节数
									memcpy(qbLocal.image.srcImg.buff, clipedImg.data, static_cast<size_t>(imgBufSize)); // 图像数据复制

									if (m_boundbingBox.EastLon - m_boundbingBox.WestLon > 0 
										&& m_boundbingBox.WestLon >= -180 
										&& m_boundbingBox.WestLon <= 180 
										&& m_boundbingBox.EastLon >= -180  
										&& m_boundbingBox.EastLon <= 180 
										&& m_boundbingBox.NorthLat - m_boundbingBox.SouthLat > 0 
										&& m_boundbingBox.SouthLat >= -90 
										&& m_boundbingBox.SouthLat <= 90 
										&& m_boundbingBox.NorthLat >= -90 
										&& m_boundbingBox.NorthLat <= 90)
									{
										m_ImgRatioOnScreen = 0.9f;

										// 设置经纬度盒子
										GeoBoundingBox LLBox;
										double lonResolution = (m_boundbingBox.EastLon - m_boundbingBox.WestLon) / img.cols;
										double latResolution = (m_boundbingBox.NorthLat - m_boundbingBox.SouthLat) / img.rows;

										LLBox.WestLon = m_boundbingBox.WestLon + Left * lonResolution;
										LLBox.EastLon = m_boundbingBox.WestLon + Right * lonResolution;

										LLBox.NorthLat = m_boundbingBox.NorthLat - Top * latResolution;
										LLBox.SouthLat = m_boundbingBox.NorthLat - Bottom * latResolution;

										qbLocal.image.srcImg.BoundingBox = LLBox;

										DisposeQBData(&qbLocal); 
										SetBoundingBox(LLBox);

										SAFE_DELETE_ARRAY(m_midImg.buff);
										m_midImg.buff = NULL;
										m_iLatest = 0;
									}
									else
									{
										if (qbLocal.framePart.bValid == true)
										{
											int ret = ::MessageBoxA(NULL, _T("提示:图像将丧失定位能力,是否继续?"),_T("操作提示"), MB_OKCANCEL);

											if (ret == IDOK)
											{
												m_ImgRatioOnScreen = 0.9f;
												DisposeQBData(&qbLocal); 

												SAFE_DELETE_ARRAY(m_midImg.buff);
												m_midImg.buff = NULL;
												m_iLatest = 0;
											}
											else
											{
												Invalidate();
											}
										}
										else
										{
											m_ImgRatioOnScreen = 0.9f;
											DisposeQBData(&qbLocal); 

											SAFE_DELETE_ARRAY(m_midImg.buff);
											m_midImg.buff = NULL;
											m_iLatest = 0;
										}
									}

									delete [] qbLocal.image.srcImg.buff;
									qbLocal.image.srcImg.buff = NULL;
								}
							}
						}
					}
				}
			}
			else
			{
				// 目标扣取
				if (m_bGetTgtImgOn == true)
				{
					if (m_haveValidFirstPt == FALSE)
					{
						m_clipImgFirstPt = m_LButtonDownPixelCoordinate;
						m_clipImgFirstPtScreen = point;
						m_haveValidFirstPt = TRUE;
					}
					else
					{
						m_clipImgSecondPt = m_LButtonDownPixelCoordinate;
						m_haveValidFirstPt = FALSE;

						// 弹出裁剪提示
						int Left = min(m_clipImgFirstPt.x, m_clipImgSecondPt.x);
						int Right = max(m_clipImgFirstPt.x, m_clipImgSecondPt.x);
						int Top = min(m_clipImgFirstPt.y, m_clipImgSecondPt.y);
						int Bottom = max(m_clipImgFirstPt.y, m_clipImgSecondPt.y);

						if (Right > Left && Bottom > Top)
						{
							cv::Mat img(m_SrcFrame, false);

							cv::Mat clipedImg;
							img(cv::Range(Top, Bottom), cv::Range(Left, Right)).copyTo(clipedImg);

							int ret = ::MessageBoxA(NULL, _T("确定抓取目标图像?"),_T("操作提示"), MB_YESNO | MB_SYSTEMMODAL);

							if (ret == IDNO)
							{
								Invalidate();
							}
							else
							{
								m_bGetTgtImgOn = false;

								// 计算图像和复接数据存储路径
								SYSTEMTIME CurrentTime;
								GetLocalTime(&CurrentTime);

								CString ImgSavePath;
								ImgSavePath.Format(  "%04d%02d%02d_%02d%02d%02d%04d.jpg",
									CurrentTime.wYear, 
									CurrentTime.wMonth, 
									CurrentTime.wDay, 
									CurrentTime.wHour, 
									CurrentTime.wMinute,
									CurrentTime.wSecond,
									CurrentTime.wMilliseconds); 

								// 确保有文件夹,如果中途误删,会再次创建
								CString tgtFolder = GetSoftwareCurrentDirectory() + "\\targets";
								if (SearchDirectory(tgtFolder) == FALSE) // 没找到根文件夹
								{
									CreateDirectory(tgtFolder, NULL);
								}

								CString savePath = tgtFolder + "\\" + ImgSavePath;
								cv::imwrite(savePath.GetBuffer(0) ,clipedImg);

								if (m_lpSendFilePath != nullptr)
								{
									m_lpSendFilePath(savePath, 7);
								}
							}
						}
					}
				}
			}
		}
		else
		{
			m_bStaisfyRoamImg = FALSE;
		}
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}

// 功能:向图像中添加 经纬高 位置信息
//  输入:
//	    1: qb: 情报结构体
//      2: pt: 像素坐标
//      3. Lon: 经度
//      4. Lat: 纬度
//      5. H: 高度
//  返回值:无
void CImgShowDlg::TagLocationOnImgStru(ImgStru &imgData, cv::Point pt, double Lon, double Lat, double H)
{
	try
	{

		if (imgData.ImgWidth <= 0 || imgData.ImgHeight <= 0
			|| (imgData.bitcount != 8 && imgData.bitcount != 24)
			|| imgData.buff == NULL)
		{
			return;
		}

		if (pt.x < 0 || pt.y < 0)
		{
			return;
		}

		if (Lon < -180 || Lon > 180 || Lat < -90 || Lat > 90)
		{
			return;
		}

		if (imgData.ImgWidth > 0 
			&& imgData.ImgHeight > 0
			&&  (imgData.bitcount == 8 || imgData.bitcount == 24)
			&& imgData.buff != NULL)
		{
			cv::Mat img;
			unsigned int imgBufSize = 0;
			if (imgData.bitcount == 8 && imgData.ImgHeight * imgData.ImgWidth > 0)
			{
				img = cv::Mat(imgData.ImgHeight, imgData.ImgWidth, CV_8UC1);
				imgBufSize = static_cast<unsigned int>(imgData.ImgHeight * imgData.ImgWidth);
			}
			else
				if (imgData.bitcount == 24 && imgData.ImgHeight * imgData.ImgWidth * 3 > 0)
				{
					img = cv::Mat(imgData.ImgHeight, imgData.ImgWidth, CV_8UC3);
					imgBufSize = static_cast<unsigned int>(imgData.ImgHeight * imgData.ImgWidth * 3);
				}

				memcpy(img.data, imgData.buff, imgBufSize);     // 图像数据复制

				CString sLon;
				CString sLat;
				CString sH;

				sLon.Format("%.6f", Lon);
				sLat.Format("%.6f", Lat);
				sH.Format("%.1f", H);

				sLon = "Lon:" + sLon;
				sLat = "Lat:" + sLat;
				sH   = "H:" + sH;


				cv::Scalar color(0, 255, 255);

				cv::circle(img, pt, 2, color, 2);
				if (pt.x > (img.cols - 100))
				{
					cv::putText(img, sLon.GetBuffer(0), cv::Point(pt.x + 5 - 100, pt.y + 4 + 15),      1, 1, color);
					cv::putText(img, sLat.GetBuffer(0), cv::Point(pt.x + 5 - 100, pt.y + 4 + 15 + 15), 1, 1, color);
					cv::putText(img, sH.GetBuffer(0),   cv::Point(pt.x + 5 - 100, pt.y + 4 + 30 + 15), 1, 1, color);
				}
				else
				{
					cv::putText(img, sLon.GetBuffer(0), cv::Point(pt.x + 5, pt.y + 4),      1, 1, color);
					cv::putText(img, sLat.GetBuffer(0), cv::Point(pt.x + 5, pt.y + 4 + 15), 1, 1, color);
					cv::putText(img, sH.GetBuffer(0),   cv::Point(pt.x + 5, pt.y + 4 + 30), 1, 1, color);
				}

				memcpy(imgData.buff, img.data, imgBufSize); 
		}
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}

// 向图像中写信息
void CImgShowDlg::TagLocationOnQBData(QBStru &qb, cv::Point pt, double Lon, double Lat, double H)
{
	try
	{
		if (qb.image.bValid == true)
		{
			return;
		}

		if (pt.x < 0 || pt.y < 0)
		{
			return;
		}

		if (Lon < -180 || Lon > 180 || Lat < -90 || Lat > 90)
		{
			return;
		}

		// srcImg
		TagLocationOnImgStru(qb.image.srcImg, pt, Lon, Lat, H);

		// dstImg
		TagLocationOnImgStru(qb.image.dstImg, pt, Lon, Lat, H);
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}


// 功能:向图像中添加 经纬高 位置信息
//  输入:
//	    1: img: 情报结构体
//      2: pt: 像素坐标
//      3. Lon: 经度
//      4. Lat: 纬度
//      5. H: 高度
//  返回值:无
void CImgShowDlg::TagLocationOnMatImg(cv::Mat &img, cv::Point pt, double Lon, double Lat, double H)
{
	try
	{
		if (img.empty() == true || img.cols <= 0 || img.rows <= 0)
		{
			return;
		}

		if (pt.x < 0 || pt.y < 0)
		{
			return;
		}

		if (Lon < -180 || Lon > 180 || Lat < -90 || Lat > 90)
		{
			return;
		}

		CString sLon;
		CString sLat;
		CString sH;

		sLon.Format("%.6f", Lon);
		sLat.Format("%.6f", Lat);
		sH.Format("%.1f", H);

		sLon = "Lon:" + sLon;
		sLat = "Lat:" + sLat;
		sH   = "H:" + sH;

		cv::Scalar color(0, 255, 255);

		cv::circle(img, pt, 3, color, 2);

		if (pt.x > (img.cols - 100))
		{
			cv::putText(img, sLon.GetBuffer(0), cv::Point(pt.x + 5 - 100, pt.y + 4 + 15),      1, 1, color);
			cv::putText(img, sLat.GetBuffer(0), cv::Point(pt.x + 5 - 100, pt.y + 4 + 15 + 15), 1, 1, color);
			cv::putText(img, sH.GetBuffer(0),   cv::Point(pt.x + 5 - 100, pt.y + 4 + 30 + 15), 1, 1, color);
		}
		else
		{
			cv::putText(img, sLon.GetBuffer(0), cv::Point(pt.x + 5, pt.y + 4),      1, 1, color);
			cv::putText(img, sLat.GetBuffer(0), cv::Point(pt.x + 5, pt.y + 4 + 15), 1, 1, color);
			cv::putText(img, sH.GetBuffer(0),   cv::Point(pt.x + 5, pt.y + 4 + 30), 1, 1, color);
		}

	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}

// 功能:向图像中添加 文字 信息
//  输入:
//	    1: imgData: 图像结构体
//      2: pt: 像素坐标
//      3. text: 文字信息
//  返回值:无
void CImgShowDlg::TagTextOnImgStru(ImgStru &imgData, cv::Point pt, CString text)
{
	try
	{
		if (imgData.ImgWidth <= 0 || imgData.ImgHeight <= 0
			|| (imgData.bitcount != 8 && imgData.bitcount != 24)
			|| imgData.buff == NULL)
		{
			return;
		}

		if (text == "")
		{
			return;
		}

		if (pt.x < 0 || pt.y < 0)
		{
			return;
		}

		if (imgData.ImgWidth > 0 
			&& imgData.ImgHeight > 0
			&&  (imgData.bitcount == 8 || imgData.bitcount == 24)
			&& imgData.buff != NULL)
		{
			cv::Mat img;
			unsigned int imgBufSize = 0;
			if (imgData.bitcount == 8)
			{
				img = cv::Mat(imgData.ImgHeight, imgData.ImgWidth, CV_8UC1);
				imgBufSize = static_cast<unsigned int>(imgData.ImgHeight * imgData.ImgWidth);
			}
			else
			{
				img = cv::Mat(imgData.ImgHeight, imgData.ImgWidth, CV_8UC3);
				imgBufSize = static_cast<unsigned int>(imgData.ImgHeight * imgData.ImgWidth * 3);
			}

			memcpy(img.data, imgData.buff, imgBufSize);     // 图像数据复制

			cv::Scalar color(0, 255, 255);
			cv::putText(img, text.GetBuffer(0), cv::Point(pt.x + 5, pt.y - 5), 1, 1, color);

			memcpy(imgData.buff, img.data, imgBufSize); 
		}
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}

// 功能:向图像中添加 文字 信息
//  输入:
//	    1: qb: 情报结构体
//      2: pt: 像素坐标
//      3. text: 文字信息
//  返回值:无
void CImgShowDlg::TagTextOnQBData(QBStru &qb, cv::Point pt, CString text)
{
	try
	{
		if (qb.image.bValid == 0 || text == "")
		{
			return;
		}

		if (pt.x < 0 || pt.y < 0)
		{
			return;
		}

		// srcImg
		TagTextOnImgStru(qb.image.srcImg, pt, text);

		// dstImg
		TagTextOnImgStru(qb.image.dstImg, pt, text);
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}

// 功能:向图像中添加 文字 信息
//  输入:
//	    1: img: 情报结构体
//      2: pt: 像素坐标
//      3. text: 文字信息
//  返回值:无
void CImgShowDlg::TagTextOnMatImg(cv::Mat &img, cv::Point pt, CString text)
{
	try
	{
		if (img.empty() == true || text == "" || img.cols <= 0 || img.rows <= 0)
		{
			return;
		}

		if (pt.x < 0 || pt.y < 0)
		{
			return;
		}

		cv::Scalar color(0, 255, 255);
		cv::putText(img, text.GetBuffer(0), cv::Point(pt.x + 5, pt.y - 5), 1, 1, color);
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}

void CImgShowDlg::TagInfoReviseShotOnMatImg(cv::Mat &img, cv::Point pt1, cv::Point pt2, double *LLA1, double *LLA2)
{
	try
	{
		if (img.empty() == true || img.cols <= 0 || img.rows <= 0)
		{
			return;
		}

		if (pt1.x < 0 || pt1.x > img.cols - 1
			|| pt1.y < 0 || pt1.y > img.rows - 1)
		{
			return;
		}

		if (pt2.x < 0 || pt2.x > img.cols - 1
			|| pt2.y < 0 || pt2.y > img.rows - 1)
		{
			return;
		}

		if (LLA1[0] < -180 || LLA1[0] > 180 || LLA1[1] < -90 || LLA1[1] > 90)
		{
			return;
		}

		if (LLA2[0] < -180 || LLA2[0] > 180 || LLA2[1] < -90 || LLA2[1] > 90)
		{
			return;
		}

		// 计算距离和方位

		// 计算角度
		double distance = 0.0; // 距离
		double azAngle = 0.0;  // 方位

		// 计算两点间的距离和方位(顺时针:0 - 360) 
		CalculateTwoPtsDistanceAzimuth(distance, azAngle, LLA1[0], LLA1[1],  LLA2[0], LLA2[1], 3);

		// 计算 pt1 和 pt2 在图像中的夹角
		const int R = 30;

		double theta = 0;

		if (pt1.x == pt2.x && pt1.y > pt2.y)
		{
			theta = 0;
		}
		else if (pt1.x < pt2.x && pt1.y > pt2.y)
		{
			theta = atan2(double(pt2.x - pt1.x), double(pt1.y - pt2.y)) * 180 / 3.1415926;
		}
		else if (pt1.x < pt2.x && pt1.y == pt2.y)
		{
			theta = 90;
		}
		else if (pt1.x < pt2.x && pt1.y < pt2.y)
		{
			theta = atan2(double(pt2.y - pt1.y), double(pt2.x - pt1.x)) * 180 / 3.1415926 + 90;
		}
		else if (pt1.x == pt2.x && pt1.y < pt2.y)
		{
			theta = 180;
		}
		else if (pt1.x > pt2.x && pt1.y < pt2.y)
		{
			theta = atan2(double(pt1.x - pt2.x), double(pt2.y - pt1.y)) * 180 / 3.1415926 + 180;
		}
		else if (pt1.x > pt2.x && pt1.y == pt2.y)
		{
			theta = 270;
		}
		else
		{
			theta = atan2(double(pt1.y - pt2.y), double(pt1.x - pt2.x)) * 180 / 3.1415926 + 270;
		}

		// 计算

		cv::Scalar color = cv::Scalar(0,0, 255);

		cv::Point pt3;
		cv::Point pt4;

		pt3.x = pt2.x - static_cast<int>(R * cos((90 - theta - 30) * 3.1415926 / 180));
		pt3.y = pt2.y + static_cast<int>(R * sin((90 - theta - 30) * 3.1415926 / 180));

		pt4.x = pt2.x - static_cast<int>(R * cos((90 - theta + 30) * 3.1415926 / 180));
		pt4.y = pt2.y + static_cast<int>(R * sin((90 - theta + 30) * 3.1415926 / 180));

		cv::line(img, pt1, pt2, color, 1, 16);
		cv::line(img, pt2, pt3, color, 1, 16);
		cv::line(img, pt2, pt4, color, 1, 16);

		CString sDistance;
		CString sAngle;

		if (distance > 1000)
		{
			sDistance.Format("%.3fkm", distance / 1000);
		}
		else
		{
			sDistance.Format("%.1fm", distance);
		}

		sAngle.Format("%.1fd", azAngle);

		color = cv::Scalar(255, 0, 0);
		cv::putText(img, sDistance.GetBuffer(0), cv::Point(pt2.x + 5, pt2.y + 4), 1, 1, color);
		cv::putText(img, sAngle.GetBuffer(0), cv::Point(pt2.x + 5, pt2.y + 4 + 15), 1, 1, color);

		// 写字:“目标”
		color = cv::Scalar(0,0, 255);
		cv::putText(img, "T", cv::Point(pt1.x, pt1.y), 1, 2, color, 2);


		// 火炮校射信息回调输出
		if (m_lpSendArtilleryReviseInfo != NULL)
		{
			m_lpSendArtilleryReviseInfo(float(distance), float(azAngle));
		}
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}


void CImgShowDlg::TagInfoReviseShotOnImgStru(ImgStru &imgData, cv::Point pt1, cv::Point pt2, double *LLA1, double *LLA2)
{
	try
	{
		if (imgData.ImgWidth <= 0 || imgData.ImgHeight <= 0
			|| (imgData.bitcount != 8 && imgData.bitcount != 24)
			|| imgData.buff == NULL)
		{
			return;
		}

		if (pt1.x < 0 || pt1.x > imgData.ImgWidth - 1
			|| pt1.y < 0 || pt1.y > imgData.ImgHeight - 1)
		{
			return;
		}

		if (pt2.x < 0 || pt2.x > imgData.ImgWidth - 1
			|| pt2.y < 0 || pt2.y > imgData.ImgHeight - 1)
		{
			return;
		}

		if (LLA1[0] < -180 || LLA1[0] > 180 || LLA1[1] < -90 || LLA1[1] > 90)
		{
			return;
		}

		if (LLA2[0] < -180 || LLA2[0] > 180 || LLA2[1] < -90 || LLA2[1] > 90)
		{
			return;
		}

		if (imgData.ImgWidth > 0 
			&& imgData.ImgHeight > 0
			&&  (imgData.bitcount == 8 || imgData.bitcount == 24)
			&& imgData.buff != NULL)
		{
			cv::Mat img;
			unsigned int imgBufSize = 0;
			if (imgData.bitcount == 8)
			{
				img = cv::Mat(imgData.ImgHeight, imgData.ImgWidth, CV_8UC1);
				imgBufSize = static_cast<unsigned int>(imgData.ImgHeight * imgData.ImgWidth);
			}
			else
			{
				img = cv::Mat(imgData.ImgHeight, imgData.ImgWidth, CV_8UC3);
				imgBufSize = static_cast<unsigned int>(imgData.ImgHeight * imgData.ImgWidth * 3);
			}

			memcpy(img.data, imgData.buff, imgBufSize);     // 图像数据复制

			TagInfoReviseShotOnMatImg(img, pt1, pt2, LLA1, LLA2);

			memcpy(imgData.buff, img.data, imgBufSize); 
		}
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}


void CImgShowDlg::TagInfoReviseShotOnQBData(QBStru &qb, cv::Point pt1, cv::Point pt2, double *LLA1, double *LLA2)
{
	try
	{
		if (qb.image.bValid == 0)
		{
			return;
		}

		// srcImg
		TagInfoReviseShotOnImgStru(qb.image.srcImg, pt1, pt2, LLA1, LLA2);

		// dstImg
		TagInfoReviseShotOnImgStru(qb.image.dstImg, pt1, pt2, LLA1, LLA2);
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}

// 左键双击消息响应
void CImgShowDlg::OnLButtonDblClk(UINT nFlags, CPoint point)
{
	if (m_bFirstSignal == TRUE || m_bSecondSignal == TRUE)
	{
		return;
	}

	try
	{
		CDialog::OnLButtonDblClk(nFlags, point);

		// 要求按住Ctrl键
		if ((m_SrcFrame != NULL)/* && (nFlags == MK_CONTROL + 1)*/)  // SrcFrame 按住ctrl时,nFlags = 9
		{
			// 计算 CPoint point 对应的像素坐标 CPoint LButtonDblClkPixelCoordinate;
			if ((point.x > m_ShowRegionOnScreen.left) && (point.x < m_ShowRegionOnScreen.right) &&
				(point.y > m_ShowRegionOnScreen.top)  && (point.y < m_ShowRegionOnScreen.bottom)) // 鼠标在图像上
			{
				// 计算一点的像素坐标
				int ShowRegionWidth = m_ShowRegionOnScreen.Width() + 1;
				int ShowRegionHeight = m_ShowRegionOnScreen.Height() + 1;
				double ratioW = double(m_ShowRegion.Width() + 1) / ShowRegionWidth;
				double ratioH = double(m_ShowRegion.Height() + 1) / ShowRegionHeight;
				m_LButtonDblClkPixelCoordinate.x = static_cast<int>((point.x - m_ShowRegionOnScreen.left) * ratioW + 0.5 + m_ShowRegion.left);
				m_LButtonDblClkPixelCoordinate.y = static_cast<int>((point.y - m_ShowRegionOnScreen.top)  * ratioH + 0.5 + m_ShowRegion.top);

				// 地图匹配定位时,在图像中标绘目标
				if (m_lpSendTgrLocLeadLonLat != NULL && m_bDrawSquareOnImg == TRUE)
				{
					cv::Mat DrawTargetImg(m_SrcFrame, false);

					cv::Scalar color;
					cv::Mat Mask = Mat::zeros(DrawTargetImg.size(), CV_8U);

					if (DrawTargetImg.type() == 0)
					{
						color = cv::Scalar(255);
					}
					else
					{
						color = cv::Scalar(0, 0, 255); 
					}

					// 清理上次矩形标绘
					cv::Point leftUp    = m_TargetCenter + cv::Point(-25, -25);
					cv::Point rightUp   = m_TargetCenter + cv::Point(+25, -25);
					cv::Point rightDown = m_TargetCenter + cv::Point(+25, +25);
					cv::Point leftDown  = m_TargetCenter + cv::Point(-25, +25);					 

					try
					{
						cv::line(Mask, leftUp, rightUp, cv::Scalar(255),     1, 16);
						cv::line(Mask, leftUp, leftDown, cv::Scalar(255),    1, 16);
						cv::line(Mask, leftDown, rightDown, cv::Scalar(255), 1, 16);
						cv::line(Mask, rightUp, rightDown, cv::Scalar(255),  1, 16);

						cv::inpaint(DrawTargetImg, Mask, DrawTargetImg, 3, CV_INPAINT_TELEA);
					}
					catch (cv::Exception &e)
					{
						// 继续执行 即使修补失败,也能输出单点定位结果
						e;
					}


					// 确定矩形四个点
					cv::Point center = cv::Point(m_LButtonDblClkPixelCoordinate.x, m_LButtonDblClkPixelCoordinate.y);

					leftUp    = center + cv::Point(-25, -25);
					rightUp   = center + cv::Point(+25, -25);
					rightDown = center + cv::Point(+25, +25);
					leftDown  = center + cv::Point(-25, +25);

					cv::line(DrawTargetImg, leftUp, rightUp, color,     1, 16);
					cv::line(DrawTargetImg, leftUp, leftDown, color,    1, 16);
					cv::line(DrawTargetImg, leftDown, rightDown, color, 1, 16);
					cv::line(DrawTargetImg, rightUp, rightDown, color,  1, 16);

					// 上一次无效时,本次重绘
					if (m_TargetCenter.x = -100 && m_TargetCenter.y == -100)
					{
						OnPaint();
					}

					// 更新记忆
					m_TargetCenter = center;
				}
				else
				{
					m_bDrawSquareOnImg = FALSE;
					m_TargetCenter = cv::Point(-100, -100);
				}

				// 绘制标框
				// 设计技巧:利用m_bPlotRectOnPaint,避免在OnPaint中重绘一次
				m_bPlotRectOnPaint = FALSE;

				DrawSquareOnScreen(point, TRUE); 

				m_bPlotRectOnPaint = TRUE;


				// 函数回调 对外输出目标坐标
				if (m_lpSendCoordinate != NULL) // 函数指针有效性判断
				{
					m_lpSendCoordinate(m_LButtonDblClkPixelCoordinate);
				}

				// 对外输出像素信息:王家星 20150721 原因:解决多次双击时的像素信息输出问题

				//新增功能:计算当前图像 像素坐标 经纬度坐标 RGB值  回调输出
				// 计算 CPoint point 对应的像素坐标 CPoint LButtonDblClkPixelCoordinate;
				if ((point.x > m_ShowRegionOnScreen.left) && (point.x < m_ShowRegionOnScreen.right) &&
					(point.y > m_ShowRegionOnScreen.top)  && (point.y < m_ShowRegionOnScreen.bottom)) // 鼠标在图像上
				{
					// 图像尺寸与显示区域尺寸之间的比例
					double ratio = 1.0;

					// 分母0值判断
					if (m_ShowRegionOnScreen.Width() > 0)
					{
						ratio = (m_ShowRegion.Width() * 1.0) / m_ShowRegionOnScreen.Width();
					}			

					// 像素坐标
					m_imgPixel_XY_Coordinate.x = static_cast<LONG>((point.x - m_ShowRegionOnScreen.left) * ratio) + m_ShowRegion.left;
					m_imgPixel_XY_Coordinate.y = static_cast<LONG>((point.y - m_ShowRegionOnScreen.top)  * ratio) + m_ShowRegion.top;

					// 经纬度坐标
					double Lon = 0.0;
					double Lat = 0.0;
					double H = 0;
					if (true == DoCalAnyPtCoordinate(Lon, Lat, H, &m_LatestQBData.framePart, m_imgPixel_XY_Coordinate.x, m_imgPixel_XY_Coordinate.y))
					{
						m_imgPixel_LBH_Coordinate.x = Lon + m_deltaLon;
						m_imgPixel_LBH_Coordinate.y = Lat + m_deltaLat;

						CString DEMpath = GetSoftwareCurrentDirectory() + "\\ElevationData";
						float fDem = 0;
						GetElevation(fDem, m_imgPixel_LBH_Coordinate.x, m_imgPixel_LBH_Coordinate.y, DEMpath.GetBuffer(0));
						m_imgPixel_LBH_Coordinate.z = fDem;
					}
					else
					{
						if (m_boundbingBox.EastLon - m_boundbingBox.WestLon > 0 
							&& m_boundbingBox.WestLon >= -180 
							&& m_boundbingBox.WestLon <= 180 
							&& m_boundbingBox.EastLon >= -180  
							&& m_boundbingBox.EastLon <= 180 
							&& m_boundbingBox.NorthLat - m_boundbingBox.SouthLat > 0 
							&& m_boundbingBox.SouthLat >= -90 
							&& m_boundbingBox.SouthLat <= 90 
							&& m_boundbingBox.NorthLat >= -90 
							&& m_boundbingBox.NorthLat <= 90)
						{
							double LonResolution = (m_boundbingBox.EastLon -  m_boundbingBox.WestLon) / m_SrcFrame->width;
							double LatResolution = (m_boundbingBox.NorthLat - m_boundbingBox.SouthLat) / m_SrcFrame->height;

							m_imgPixel_LBH_Coordinate.x = (m_boundbingBox.WestLon +  m_imgPixel_XY_Coordinate.x * LonResolution);
							m_imgPixel_LBH_Coordinate.y = (m_boundbingBox.NorthLat - m_imgPixel_XY_Coordinate.y * LatResolution);

							// 修正
							m_imgPixel_LBH_Coordinate.x += (m_deltaLon);
							m_imgPixel_LBH_Coordinate.y += (m_deltaLat);

							CString DEMpath = GetSoftwareCurrentDirectory() + "\\ElevationData";

							float fDem = 0;
							GetElevation(fDem, m_imgPixel_LBH_Coordinate.x, m_imgPixel_LBH_Coordinate.y, DEMpath.GetBuffer(0));
							m_imgPixel_LBH_Coordinate.z = fDem;
						} 
						else
						{
							m_imgPixel_LBH_Coordinate.x = -200.0;
							m_imgPixel_LBH_Coordinate.y = -200.0;
							m_imgPixel_LBH_Coordinate.z = -200.0;
						} 
					}
				}
				else
				{
					// 设置为 小于0 的无效值
					m_imgPixel_XY_Coordinate.x = -1;
					m_imgPixel_XY_Coordinate.y = -1;
					m_imgPixel_LBH_Coordinate.x = -200.0;
					m_imgPixel_LBH_Coordinate.y = -200.0; 
					m_imgPixel_LBH_Coordinate.z = -200.0; 
				}

				// 定位标记
				if (m_iImgEditType == 0)
				{
					m_bHaveOnPt = false; // 清零

					m_bEnhanceEdit = true; // 增强
				}
				else if (m_iImgEditType == 1)  // 定位标记
				{
					m_bEnhanceEdit = false; // 编辑

					// 未作任何处理
					if (m_LatestQBData.image.dstImg.buff == NULL/* && m_midImg.buff == NULL*/)
					{
						CloneImgStru(m_LatestQBData.image.srcImg, m_LatestQBData.image.dstImg);
						CloneImgStru(m_LatestQBData.image.srcImg, m_midImg);

						TagLocationOnImgStru(m_LatestQBData.image.dstImg, cv::Point(m_imgPixel_XY_Coordinate.x, m_imgPixel_XY_Coordinate.y), 
							m_imgPixel_LBH_Coordinate.x, 
							m_imgPixel_LBH_Coordinate.y, 
							m_imgPixel_LBH_Coordinate.z);

						// 标记 m_SrcFrame
						cv::Mat srcFrameMat(m_SrcFrame, false);

						if (srcFrameMat.type() == CV_8UC1 
							&& srcFrameMat.data != NULL 
							&& m_LatestQBData.image.dstImg.buff != NULL
							&& srcFrameMat.cols > 0 && srcFrameMat.rows > 0
							&& srcFrameMat.cols * srcFrameMat.rows < 1e8)
						{
							memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows);     // 图像数据复制
						}
						else 
							if (srcFrameMat.type() == CV_8UC3
								&& srcFrameMat.data != NULL 
								&& m_LatestQBData.image.dstImg.buff != NULL
								&& srcFrameMat.cols > 0 && srcFrameMat.rows > 0
								&& srcFrameMat.cols * srcFrameMat.rows < 1e8)
							{
								memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows * 3);     // 图像数据复制
							}

							Invalidate();
					}
					else
					{
						CloneImgStru(m_LatestQBData.image.dstImg, m_midImg);

						TagLocationOnImgStru(m_LatestQBData.image.dstImg, cv::Point(m_imgPixel_XY_Coordinate.x, m_imgPixel_XY_Coordinate.y), 
							m_imgPixel_LBH_Coordinate.x, 
							m_imgPixel_LBH_Coordinate.y, 
							m_imgPixel_LBH_Coordinate.z);

						// 标记 m_SrcFrame
						cv::Mat srcFrameMat(m_SrcFrame, false);

						if (srcFrameMat.type() == CV_8UC1
							&& srcFrameMat.data != NULL 
							&& m_LatestQBData.image.dstImg.buff != NULL
							&& srcFrameMat.cols > 0 && srcFrameMat.rows > 0
							&& srcFrameMat.cols * srcFrameMat.rows < 1e8)
						{
							memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows);     // 图像数据复制
						}
						else 
							if (srcFrameMat.type() == CV_8UC3
								&& srcFrameMat.data != NULL 
								&& m_LatestQBData.image.dstImg.buff != NULL
								&& srcFrameMat.cols > 0 && srcFrameMat.rows > 0
								&& srcFrameMat.cols * srcFrameMat.rows < 1e8)
							{
								memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows * 3);     // 图像数据复制
							}

							Invalidate();
					}
				} 
				else if (m_iImgEditType == 2) // 文字标记
				{
					m_bEnhanceEdit = false; // 编辑

					CAddTextDlg addTextDlg;
					if (addTextDlg.DoModal() == IDOK)
					{
						CString inputText = addTextDlg.GetText();

						// 未作任何处理
						if (m_LatestQBData.image.dstImg.buff == NULL/* && m_midImg.buff == NULL*/)
						{
							CloneImgStru(m_LatestQBData.image.srcImg, m_LatestQBData.image.dstImg);
							CloneImgStru(m_LatestQBData.image.srcImg, m_midImg);

							TagTextOnImgStru(m_LatestQBData.image.dstImg, cv::Point(m_imgPixel_XY_Coordinate.x, m_imgPixel_XY_Coordinate.y), inputText);

							// 标记 m_SrcFrame
							cv::Mat srcFrameMat(m_SrcFrame, false);

							if (srcFrameMat.type() == CV_8UC1
								&& srcFrameMat.data != NULL 
								&& m_LatestQBData.image.dstImg.buff != NULL
								&& srcFrameMat.cols > 0 && srcFrameMat.rows > 0
								&& srcFrameMat.cols * srcFrameMat.rows < 1e8)
							{
								memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows);     // 图像数据复制
							}
							else 
								if (srcFrameMat.type() == CV_8UC3
									&& srcFrameMat.data != NULL 
									&& m_LatestQBData.image.dstImg.buff != NULL
									&& srcFrameMat.cols > 0 && srcFrameMat.rows > 0
									&& srcFrameMat.cols * srcFrameMat.rows < 1e8)
								{
									memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows * 3);     // 图像数据复制
								}

								Invalidate();
						}
						else
						{
							CloneImgStru(m_LatestQBData.image.dstImg, m_midImg);

							TagTextOnImgStru(m_LatestQBData.image.dstImg, cv::Point(m_imgPixel_XY_Coordinate.x, m_imgPixel_XY_Coordinate.y), inputText);

							// 标记 m_SrcFrame
							cv::Mat srcFrameMat(m_SrcFrame, false);

							if (srcFrameMat.type() == CV_8UC1
								&& srcFrameMat.data != NULL 
								&& m_LatestQBData.image.dstImg.buff != NULL
								&& srcFrameMat.cols > 0 && srcFrameMat.rows > 0
								&& srcFrameMat.cols * srcFrameMat.rows < 1e8)
							{
								memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows);     // 图像数据复制
							}
							else 
								if (srcFrameMat.type() == CV_8UC3
									&& srcFrameMat.data != NULL 
									&& m_LatestQBData.image.dstImg.buff != NULL
									&& srcFrameMat.cols > 0 && srcFrameMat.rows > 0
									&& srcFrameMat.cols * srcFrameMat.rows < 1e8)
								{
									memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows * 3);     // 图像数据复制
								}

								Invalidate();
						}
					}
				}
				else if (m_iImgEditType == 3) // 火炮校射标记
				{
					m_bEnhanceEdit = false; // 编辑

					if (m_bHaveOnPt == false)
					{
						m_bHaveOnPt = true;

						m_beginPixPt.x = m_LButtonDblClkPixelCoordinate.x;
						m_beginPixPt.y = m_LButtonDblClkPixelCoordinate.y;

						m_beginLLA[0] = m_imgPixel_LBH_Coordinate.x;
						m_beginLLA[1] = m_imgPixel_LBH_Coordinate.y; 
						m_beginLLA[2] = m_imgPixel_LBH_Coordinate.z;
					}
					else
					{
						m_bHaveOnPt = false;
						m_endPixPt.x = m_LButtonDblClkPixelCoordinate.x;
						m_endPixPt.y = m_LButtonDblClkPixelCoordinate.y;

						m_endLLA[0] = m_imgPixel_LBH_Coordinate.x;
						m_endLLA[1] = m_imgPixel_LBH_Coordinate.y; 
						m_endLLA[2] = m_imgPixel_LBH_Coordinate.z;

						// 未作任何处理
						if (m_LatestQBData.image.dstImg.buff == NULL/* && m_midImg.buff == NULL*/)
						{
							CloneImgStru(m_LatestQBData.image.srcImg, m_LatestQBData.image.dstImg);
							CloneImgStru(m_LatestQBData.image.srcImg, m_midImg);

							TagInfoReviseShotOnImgStru(m_LatestQBData.image.dstImg, m_beginPixPt, m_endPixPt, m_beginLLA, m_endLLA);

							// 标记 m_SrcFrame
							cv::Mat srcFrameMat(m_SrcFrame, false);

							if (srcFrameMat.type() == CV_8UC1
								&& srcFrameMat.data != NULL 
								&& m_LatestQBData.image.dstImg.buff != NULL
								&& srcFrameMat.cols > 0 && srcFrameMat.rows > 0
								&& srcFrameMat.cols * srcFrameMat.rows < 1e8)
							{
								memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows);     // 图像数据复制
							}
							else 
								if (srcFrameMat.type() == CV_8UC3
									&& srcFrameMat.data != NULL 
									&& m_LatestQBData.image.dstImg.buff != NULL
									&& srcFrameMat.cols > 0 && srcFrameMat.rows > 0
									&& srcFrameMat.cols * srcFrameMat.rows < 1e8)
								{
									memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows * 3);     // 图像数据复制
								}

								Invalidate();
						}
						else
						{
							CloneImgStru(m_LatestQBData.image.dstImg, m_midImg);
							TagInfoReviseShotOnImgStru(m_LatestQBData.image.dstImg, m_beginPixPt, m_endPixPt, m_beginLLA, m_endLLA);

							// 标记 m_SrcFrame
							cv::Mat srcFrameMat(m_SrcFrame, false);

							if (srcFrameMat.type() == CV_8UC1
								&& srcFrameMat.data != NULL 
								&& m_LatestQBData.image.dstImg.buff != NULL
								&& srcFrameMat.cols > 0 && srcFrameMat.rows > 0
								&& srcFrameMat.cols * srcFrameMat.rows < 1e8)
							{
								memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows);     // 图像数据复制
							}
							else
								if (srcFrameMat.type() == CV_8UC3
									&& srcFrameMat.data != NULL 
									&& m_LatestQBData.image.dstImg.buff != NULL
									&& srcFrameMat.cols > 0 && srcFrameMat.rows > 0
									&& srcFrameMat.cols * srcFrameMat.rows < 1e8)
								{
									memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows * 3);     // 图像数据复制
								}

								Invalidate();
						}
					}
				}
				else
				{
					m_bEnhanceEdit = true; // 增强
				}


				// 回调输出信息即可
				if (m_lpSendPixInfoProc != NULL)
				{
					CPoint pt;
					pt.x = m_imgPixel_XY_Coordinate.x;
					pt.y = m_imgPixel_XY_Coordinate.y;
					m_lpSendPixInfoProc(pt, m_imgPixel_LBH_Coordinate.x, m_imgPixel_LBH_Coordinate.y, m_imgPixel_LBH_Coordinate.z);
				}
			}
			else
			{
				// 设置为 小于0 的无效值
				m_LButtonDblClkPixelCoordinate.x = -1;
				m_LButtonDblClkPixelCoordinate.y = -1;
			}
		}
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}

// 功能:获取当前图像中心的经纬度坐标
bool CImgShowDlg::GetCurrentImgCenterLonLat(double &lon, double &lat)
{
	try
	{
		if (m_SrcFrame == NULL)
		{
			return false;
		}

		// 经纬度坐标
		double Lon = 0.0;
		double Lat = 0.0;
		double H = 0;
		if (true == DoCalImgCenterCoordinate(Lon, Lat, H, &m_LatestQBData.framePart))
		{
			lon = Lon + m_deltaLon;
			lat = Lat + m_deltaLat;
			return true;
		}
		else
		{
			if (m_boundbingBox.EastLon - m_boundbingBox.WestLon > 0 
				&& m_boundbingBox.WestLon >= -180 
				&& m_boundbingBox.WestLon <= 180 
				&& m_boundbingBox.EastLon >= -180  
				&& m_boundbingBox.EastLon <= 180 
				&& m_boundbingBox.NorthLat - m_boundbingBox.SouthLat > 0 
				&& m_boundbingBox.SouthLat >= -90 
				&& m_boundbingBox.SouthLat <= 90 
				&& m_boundbingBox.NorthLat >= -90 
				&& m_boundbingBox.NorthLat <= 90)
			{
				lon = (m_boundbingBox.EastLon -  m_boundbingBox.WestLon) / 2 + m_boundbingBox.WestLon;
				lat = (m_boundbingBox.NorthLat - m_boundbingBox.SouthLat) / 2 + m_boundbingBox.SouthLat;

				return true;
			} 
		}

		return false;
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return false;
	}
	catch(...)
	{
		return false;
	}
}

// 鼠标移动消息响应
void CImgShowDlg::OnMouseMove(UINT nFlags, CPoint point)
{
	try
	{
		CDialog::OnMouseMove(nFlags, point);

		if (nFlags == MK_LBUTTON) // 首要条件:左键按下
		{
			// 如果有外部信号输入 操作与视频模式相同
			if (m_bFirstSignal == TRUE || m_bSecondSignal == TRUE)
			{
				if(m_bSatisfyMove == TRUE)
				{
					// 更新偏移量
					m_ImgShowShift.x += (point.x - m_LeftButtonDown.x);
					m_ImgShowShift.y += (point.y - m_LeftButtonDown.y);

					// 更新鼠标左键按下点
					m_LeftButtonDown = point;
				}

				return;
			}

			//  满足图像漫游条件
			if(m_bStaisfyRoamImg == TRUE)
			{
				// 图像未全部显示
				if (m_ShowRegion.Width() < m_SrcFrame->width - 1 || m_ShowRegion.Height() < m_SrcFrame->height - 1)
				{
					// 策略1:更新显示区域
					int ShowRegionWidth = m_ShowRegionOnScreen.Width() + 1;
					int ShowRegionHeight = m_ShowRegionOnScreen.Height() + 1;
					double ratioW = double(m_ShowRegion.Width() + 1) / ShowRegionWidth;
					double ratioH = double(m_ShowRegion.Height() + 1) / ShowRegionHeight;

					// 像素坐标偏移量
					int delatX = int((point.x - m_LeftButtonDown.x) * ratioW);
					int delatY = int((point.y - m_LeftButtonDown.y) * ratioH);

					m_LeftButtonDown = point;

					// 计算显示区域
					CRect new_ShowRegion = GetNewRegionWhenRoamImg(delatX, delatY);


					// 如果有显示区域变动
					if( new_ShowRegion.left   - m_ShowRegion.left   != 0 ||
						new_ShowRegion.right  - m_ShowRegion.right  != 0 ||
						new_ShowRegion.top    - m_ShowRegion.top    != 0 ||
						new_ShowRegion.bottom - m_ShowRegion.bottom != 0)
					{
						// 更新显示区域
						m_ShowRegion = new_ShowRegion;

						// 图像显示拉伸比例控制
						m_ImgRatioOnScreen = 1.0F;

						// 显示图像
						ShowOneImage(m_SrcFrame, TRUE, m_ShowRegion, m_ImgRatioOnScreen, m_ImgShowShift);

						// 更新标绘窗口
						DrawSquareOnScreen(GetScreenCoordinateBasedOnPixelCoordinate(m_LButtonDblClkPixelCoordinate),FALSE);
					}

				} 
				else
				{
					// 策略2:图像已经全部显示

					// 更新偏移量
					m_ImgShowShift.x += (point.x - m_LeftButtonDown.x);
					m_ImgShowShift.y += (point.y - m_LeftButtonDown.y);

					// 更新鼠标左键按下点
					m_LeftButtonDown = point;

					// 显示图像
					ShowWholeImage(m_SrcFrame, m_ImgRatioOnScreen, m_ImgShowShift);

					// 更新标绘窗口
					DrawSquareOnScreen(GetScreenCoordinateBasedOnPixelCoordinate(m_LButtonDblClkPixelCoordinate), FALSE);

				}
			}
		}

		// 已经有一个点了
		if ((m_bGetTgtImgOn == true || m_bClipImgOn == true)&& m_haveValidFirstPt == TRUE)
		{
			// 计算 CPoint point 对应的像素坐标 CPoint LButtonDblClkPixelCoordinate;
			if ((point.x > m_ShowRegionOnScreen.left) && (point.x < m_ShowRegionOnScreen.right) &&
				(point.y > m_ShowRegionOnScreen.top)  && (point.y < m_ShowRegionOnScreen.bottom)) // 鼠标在图像上
			{
				m_clipImgSecondPtScreen = point;

				// 重新计算第一个点的屏幕坐标
				m_clipImgFirstPtScreen = GetScreenCoordinateBasedOnPixelCoordinate(m_clipImgFirstPt);

				CDC* pDC = this->GetDC();
				CPen newPen1; // 创建新画笔
				newPen1.CreatePen(PS_SOLID, 2, RGB(0, 255, 255));

				// 显示区域的地理边界
				CRect rect;
				GetClientRect(&rect);
				InvalidateRect(&rect, FALSE);
				UpdateWindow();

				CPen *pOldPen = pDC->SelectObject(&newPen1);

				CPoint pts[4];
				pts[0] = m_clipImgFirstPtScreen;
				pts[1].x = m_clipImgSecondPtScreen.x;
				pts[1].y = m_clipImgFirstPtScreen.y;
				pts[2] = m_clipImgSecondPtScreen;
				pts[3].x = m_clipImgFirstPtScreen.x;
				pts[3].y = m_clipImgSecondPtScreen.y;

				pDC->MoveTo(pts[0]);
				pDC->LineTo(pts[1]);
				pDC->LineTo(pts[2]);
				pDC->LineTo(pts[3]);
				pDC->LineTo(pts[0]);

				// 释放设备上下文指针
				ReleaseDC(pDC);
				pDC = NULL;
			}
		}

		//新增功能:计算当前图像 像素坐标 经纬度坐标 RGB值  回调输出
		if (m_bFirstSignal == FALSE && m_bSecondSignal == FALSE && m_SrcFrame != NULL && m_bPlotRect == FALSE) 
		{
			// 计算 CPoint point 对应的像素坐标 CPoint LButtonDblClkPixelCoordinate;
			if ((point.x > m_ShowRegionOnScreen.left) && (point.x < m_ShowRegionOnScreen.right) &&
				(point.y > m_ShowRegionOnScreen.top)  && (point.y < m_ShowRegionOnScreen.bottom)) // 鼠标在图像上
			{
				int ShowRegionWidth = m_ShowRegionOnScreen.Width() + 1;
				int ShowRegionHeight = m_ShowRegionOnScreen.Height() + 1;
				double ratioW = double(m_ShowRegion.Width() + 1) / ShowRegionWidth;
				double ratioH = double(m_ShowRegion.Height() + 1) / ShowRegionHeight;
				m_imgPixel_XY_Coordinate.x = static_cast<int>((point.x - m_ShowRegionOnScreen.left) * ratioW + 0.5 + m_ShowRegion.left);
				m_imgPixel_XY_Coordinate.y = static_cast<int>((point.y - m_ShowRegionOnScreen.top)  * ratioH + 0.5 + m_ShowRegion.top);

				// 经纬度坐标
				double Lon = 0.0;
				double Lat = 0.0;
				double H = 0;
				if (true == DoCalAnyPtCoordinate(Lon, Lat, H, &m_LatestQBData.framePart, m_imgPixel_XY_Coordinate.x, m_imgPixel_XY_Coordinate.y))
				{
					m_imgPixel_LBH_Coordinate.x = Lon +  m_deltaLon;
					m_imgPixel_LBH_Coordinate.y = Lat +  m_deltaLat;

					CString DEMpath = GetSoftwareCurrentDirectory() + "\\ElevationData";

					float fDem = 0;
					GetElevation(fDem, m_imgPixel_LBH_Coordinate.x, m_imgPixel_LBH_Coordinate.y, DEMpath.GetBuffer(0));
					m_imgPixel_LBH_Coordinate.z = fDem;
				}
				else
				{
					if (m_boundbingBox.EastLon - m_boundbingBox.WestLon > 0 
						&& m_boundbingBox.WestLon >= -180 
						&& m_boundbingBox.WestLon <= 180 
						&& m_boundbingBox.EastLon >= -180  
						&& m_boundbingBox.EastLon <= 180 
						&& m_boundbingBox.NorthLat - m_boundbingBox.SouthLat > 0 
						&& m_boundbingBox.SouthLat >= -90 
						&& m_boundbingBox.SouthLat <= 90 
						&& m_boundbingBox.NorthLat >= -90 
						&& m_boundbingBox.NorthLat <= 90)
					{
						double LonResolution = (m_boundbingBox.EastLon -  m_boundbingBox.WestLon) / m_SrcFrame->width;
						double LatResolution = (m_boundbingBox.NorthLat - m_boundbingBox.SouthLat) / m_SrcFrame->height;

						m_imgPixel_LBH_Coordinate.x = (m_boundbingBox.WestLon +  m_imgPixel_XY_Coordinate.x * LonResolution);
						m_imgPixel_LBH_Coordinate.y = (m_boundbingBox.NorthLat - m_imgPixel_XY_Coordinate.y * LatResolution);

						// 修正
						m_imgPixel_LBH_Coordinate.x += (m_deltaLon);
						m_imgPixel_LBH_Coordinate.y += (m_deltaLat);

						CString DEMpath = GetSoftwareCurrentDirectory() + "\\ElevationData";

						float fDem = 0;
						GetElevation(fDem, m_imgPixel_LBH_Coordinate.x, m_imgPixel_LBH_Coordinate.y, DEMpath.GetBuffer(0));
						m_imgPixel_LBH_Coordinate.z = fDem;
					} 
					else
					{
						m_imgPixel_LBH_Coordinate.x = -200.0;
						m_imgPixel_LBH_Coordinate.y = -200.0;
						m_imgPixel_LBH_Coordinate.z = -200.0;
					}
				}
			}
			else
			{
				// 设置为 小于0 的无效值
				m_imgPixel_XY_Coordinate.x = -1;
				m_imgPixel_XY_Coordinate.y = -1;
				m_imgPixel_LBH_Coordinate.x = -200.f;
				m_imgPixel_LBH_Coordinate.y = -200.f; 
				m_imgPixel_LBH_Coordinate.z = -200.f; 
			}

			// 回调输出信息即可
			if (m_lpSendPixInfoProc != NULL)
			{
				CPoint pt;
				pt.x = m_imgPixel_XY_Coordinate.x;
				pt.y = m_imgPixel_XY_Coordinate.y;

				m_lpSendPixInfoProc(pt, m_imgPixel_LBH_Coordinate.x, m_imgPixel_LBH_Coordinate.y, m_imgPixel_LBH_Coordinate.z);
			}
		}
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}

// 滚轮消息响应
BOOL CImgShowDlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
	try
	{
		// 放大
		if (zDelta > 0)
		{
			if (m_SrcFrame != NULL)
			{
				// 放大并显示图像
				DoZoomInImg();

				// 更新标绘窗口
				DrawSquareOnScreen(GetScreenCoordinateBasedOnPixelCoordinate(m_LButtonDblClkPixelCoordinate), FALSE);
			}
		}else // 缩小
		{
			if (m_SrcFrame != NULL)
			{
				// 放大并显示图像
				DoZoomOutImg();

				// 更新标绘窗口
				DrawSquareOnScreen(GetScreenCoordinateBasedOnPixelCoordinate(m_LButtonDblClkPixelCoordinate), FALSE);
			}
		}
		return TRUE;
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return FALSE;
	}
	catch(...)
	{
		return FALSE;
	}
}


BOOL CImgShowDlg::OnInitDialog()
{
	try
	{
		CDialog::OnInitDialog();

		// 数据存储目录
		m_sRootFolder = GetSoftwareCurrentDirectory() + "\\QB_RESULT";
		m_sImgSaveFolder = m_sRootFolder + "\\EDITED_IMAGE";

		// 创建文件夹
		CreateDirectory(m_sRootFolder, NULL);
		CreateDirectory(m_sImgSaveFolder, NULL);

		m_hMutex_ProcessData = CreateMutexA(NULL, FALSE, NULL);

		m_pFastLookUpDlg = new CFastLookUpDlg();

		if (m_pFastLookUpDlg != NULL)
		{
			m_pFastLookUpDlg->Create(IDD_DLG_FAST_LOOKUP_IMGS, this);
			m_pFastLookUpDlg->SetParentPt(this);
		}

		return TRUE; 
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return FALSE;
	}
	catch(...)
	{
		return FALSE;
	}
}


// 设置一路信号是否正在输入
void CImgShowDlg::SetFirstSignal(BOOL bflag)
{
	m_bFirstSignal = bflag;
}

BOOL CImgShowDlg::GetFirstSignal()
{
	return m_bFirstSignal;
}

// 设置2路信号是否正在输入
void CImgShowDlg::SetSecondSignal(BOOL bflag)
{
	m_bSecondSignal = bflag;
}

BOOL CImgShowDlg::GetSecondSignal()
{
	return m_bSecondSignal;
}

// 释放m_LatestQBData
void CImgShowDlg::ReleaseLatestQBData()
{
	try
	{
		ReleaseQBData(&m_LatestQBData);
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}


// 设置m_LatestQBData
void CImgShowDlg::SetLatestQBData(const QBStru &qbData)
{
	try
	{
		ReleaseQBData(&m_LatestQBData);
		CloneQBData(qbData, m_LatestQBData);
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}

// 设置经纬度盒子
void CImgShowDlg::SetBoundingBox(GeoBoundingBox box)
{
	m_boundbingBox = box;
}

// 设置iLatest
void CImgShowDlg::SetiLatest(int i)
{
	m_iLatest = i;
}

int CImgShowDlg::GetiLatest()
{
	return m_iLatest;
}

// 设置iPreLatest
void CImgShowDlg::SetiPreLatest(int i)
{
	m_iPreLatest = i;
}

int CImgShowDlg::GetiPreLatest()
{
	return m_iPreLatest;
}

//功能:解压后的情报数据处理函数(包括三项:更新本地情报、显示、入队列和对外传递数据)
void CImgShowDlg::DisposeQBData(const QBStru* qbData)
{
	try
	{
		// 空值判断
		if (qbData == nullptr)
		{
			return;
		}


		// 输入数据有效性判断 如果复接数据和图像数据均无效,直接返回
		if ((qbData->framePart.bValid == false) && (qbData->image.bValid == false))
		{
			return;
		}

		// 功能1:更新数据 m_LatestQBData
		CloneQBData(*qbData, m_LatestQBData);

		// 设置为 小于0 的无效值
		m_LButtonDblClkPixelCoordinate.x = -1;
		m_LButtonDblClkPixelCoordinate.y = -1;

		// 功能2:显示(显示图像)和 指北针  dstImg 或 srcImg,不显示geoImg(暂时觉得没必要)
		ShowLatestQBData();

		// 功能3:入队列: 按需入队
		if (m_bMemPreMultiFrame == TRUE)
		{
			PushLatestQBData2Deque();

			// 功能4:送入 快速查询模块
			if (m_pFastLookUpDlg != NULL)
			{
				m_pFastLookUpDlg->SetImgData(m_LatestQBData.image.srcImg);
				if (m_pFastLookUpDlg->IsWindowVisible() == TRUE)
				{
					m_pFastLookUpDlg->ShowImgData();
				}
			}
		}

		// 更新数目,注意不是+1
		WaitForSingleObject(m_hMutex_ProcessData, INFINITE);
		m_currentImgOrder = static_cast<int>(m_QBDataDeque.size());
		ReleaseMutex(m_hMutex_ProcessData);
		
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}


// 功能:m_LatestQBData 入队列
// 输入:
// 输出: 
// 说明:只有当m_LatestQBData图像数据有效时,方可入队
// 功能:LatestQBData 入队列,
void CImgShowDlg::PushLatestQBData2Deque()
{
	WaitForSingleObject(m_hMutex_ProcessData, INFINITE);
	try
	{
		if (m_LatestQBData.image.bValid == true) // 图像数据有效
		{
			if ( m_QBDataDeque.size() < 18U)
			{
				QBStru local; // 局部变量
				CloneQBData(m_LatestQBData,local); // 深度复制

				
				m_QBDataDeque.push_back(local); // 入队,浅复制
				

				// 设置局部变量buffer指向空,否则,local超出作用域会析构其指向的内存单元,
				// 从而使local中已入队的结构体成为野指针;
				local.image.srcImg.buff    = NULL;
				local.image.dstImg.buff    = NULL;
				local.image.geoImg.buff    = NULL;
			}
			else
			{
				while(m_QBDataDeque.size() >= 18U) // 设计原因:中途可能设置小于当前数目的容量
				{
					// 弹出
					std::deque<QBStru>::iterator iter; // 定义迭代器
					iter = m_QBDataDeque.begin();

					// 释放指针指向的内存
					SAFE_DELETE_ARRAY(iter->image.srcImg.buff);
					SAFE_DELETE_ARRAY(iter->image.dstImg.buff);
					SAFE_DELETE_ARRAY(iter->image.geoImg.buff);

					// 弹出
					m_QBDataDeque.pop_front(); 
				}

				// 当前帧入队
				QBStru local; // 局部变量
				CloneQBData(m_LatestQBData, local); // 深度复制

				m_QBDataDeque.push_back(local); // 入队,浅复制

				// 设置局部变量buffer指向空,否则,local超出作用域会析构其指向的内存单元,
				// 从而使local中已入队的结构体成为野指针;
				local.image.srcImg.buff = NULL;
				local.image.dstImg.buff = NULL;
				local.image.geoImg.buff = NULL;
			}
		}
	}
	catch(cv::Exception &e)
	{
		e.msg;
	}
	catch(...)
	{
	}
	ReleaseMutex(m_hMutex_ProcessData);
}



// 1.29 功能:清理内存及记忆
//   输入:无
//
//   输出:无
void CImgShowDlg::ClearMemory()
{
	if (m_bFirstSignal == TRUE || m_bSecondSignal == TRUE)
	{
		return;
	}

	try
	{
		// 如果有图像 需要释放该图像
		if (m_SrcFrame != NULL)
		{
			cvReleaseImage(&m_SrcFrame);
			m_SrcFrame = NULL;
		}

		// 当前情报数据结构体:LatestQBData
		ReleaseQBData(&m_LatestQBData);

		WaitForSingleObject(m_hMutex_ProcessData, INFINITE);
		// 情报队列销毁
		if(m_QBDataDeque.size() > 0) 
		{
			for (size_t i = 0; i < m_QBDataDeque.size(); ++i)
			{
				SAFE_DELETE_ARRAY(m_QBDataDeque[i].image.srcImg.buff);
				SAFE_DELETE_ARRAY(m_QBDataDeque[i].image.dstImg.buff);
				SAFE_DELETE_ARRAY(m_QBDataDeque[i].image.geoImg.buff);
			}

			m_QBDataDeque.clear(); 
		}
		ReleaseMutex(m_hMutex_ProcessData);
		

		// midImg 释放
		SAFE_DELETE_ARRAY(m_midImg.buff);

		// 复位
		m_ShowRegion = CRect(0,0,0,0);

		m_ShowRegionOnScreen.left   = 0;
		m_ShowRegionOnScreen.right  = 0;
		m_ShowRegionOnScreen.top    = 0;
		m_ShowRegionOnScreen.bottom = 0;

		m_LButtonDownPixelCoordinate = CPoint(0,0);
		m_bStaisfyRoamImg = FALSE;
		m_LatestPlotRect = CRect(0,0,0,0);
		m_LButtonDblClkPixelCoordinate = CPoint(-1, -1);

		m_LeftButtonDown.x = 0;
		m_LeftButtonDown.y = 0;

		m_RButtonPt.x = 0;
		m_RButtonPt.y = 0;

		m_SrcFrame = NULL;
		m_ImgRatioOnScreen = 1.0F;

		m_ImgShowShift.x = 0L;
		m_ImgShowShift.y = 0L;

		m_bFirstSignal = FALSE; 
		m_bSecondSignal = FALSE;
		m_bSatisfyMove = FALSE;

		m_iLatest = 0;
		m_iPreLatest = 0;

		m_LatestQuadrangle = CRect(0,0,0,0);

		// 像素信息
		m_imgPixel_XY_Coordinate.x = -1;
		m_imgPixel_XY_Coordinate.y = -1;
		m_imgPixel_LBH_Coordinate.x = -200.0;
		m_imgPixel_LBH_Coordinate.y = -200.0;
		m_imgPixel_LBH_Coordinate.z = -200.0;

		m_currentImgOrder = 0;

		m_TargetCenter = cv::Point(-100, -100);
		m_bDrawSquareOnImg = TRUE;

		m_deltaLon = 0;
		m_deltaLat = 0;

		// 使窗口无效
		Invalidate();

		// 释放快速浏览对话框内存图像
		if (m_pFastLookUpDlg != NULL)
		{
			m_pFastLookUpDlg->ClearMemory();
		}
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}

}

// 3.12 功能:保存图像为tiff,并回调保存路径
// 说明:当保存为tiff图像时,忽略校准量,牵扯面太广,且不可靠
//       如果实在想高精度保存一幅图像为tiff,可通过GCP几何校正实现
void CImgShowDlg::SaveToGeoTiff()
{
	try
	{
		// 计算保存路径
		CString savePath;
		CString sRootFolder;
		CString sImgSaveFolder;

		// 数据存储目录
		sRootFolder = GetSoftwareCurrentDirectory() + "\\QB_RESULT";
		sImgSaveFolder = sRootFolder + "\\EDITED_IMAGE";

		// 创建文件夹
		CreateDirectory(sRootFolder, NULL);
		CreateDirectory(sImgSaveFolder, NULL);

		// 计算存储路径
		SYSTEMTIME CurrentTime;
		GetLocalTime(&CurrentTime);
		savePath.Format( "%04d%02d%02d_%02d%02d%02d%04d",
			CurrentTime.wYear, 
			CurrentTime.wMonth, 
			CurrentTime.wDay, 
			CurrentTime.wHour, 
			CurrentTime.wMinute,
			CurrentTime.wSecond,
			CurrentTime.wMilliseconds);
		savePath = "Geo_" + savePath;

		savePath = savePath + _T(".tif");
		savePath = sImgSaveFolder + "\\" + savePath;

		bool bret = false;

		// 保存为tiff
		if (true == SaveToGeoTIFF(&m_LatestQBData, savePath.GetBuffer(0)))
		{
			bret = true;
		}
		else if (true == SaveToGeoTIFF(&m_LatestQBData.image.dstImg, savePath.GetBuffer(0)))
		{
			bret = true;
		}
		else if (true == SaveToGeoTIFF(&m_LatestQBData.image.srcImg, savePath.GetBuffer(0)))
		{
			bret = true;
		}
		else
		{
			bret = false;
		}

		if (bret == true)
		{
			// 保存路径回调
			if (m_lpSendFilePath != NULL)
			{
				m_lpSendFilePath(savePath, 6);
			}
		}

		// 清理 geoImg
		SAFE_DELETE_ARRAY(m_LatestQBData.image.geoImg.buff);
		m_LatestQBData.image.geoImg.buff = NULL;
	}
	catch(cv::Exception &e)
	{
		e.what();
		return;
	}
	catch (...)
	{
		return;
	}
}

// 右键 清理内存记忆
void CImgShowDlg::OnClearMemory()
{
	try
	{
		ClearMemory();

		// 复位目标标绘
		m_bPlotRect = FALSE;
	}
	catch(cv::Exception &e)
	{
		e.what();
		return;
	}
	catch (...)
	{
		return;
	}
}

// 单帧校正采集
void CImgShowDlg::OnSaveImgToTiff()
{
	SaveToGeoTiff();
}

// 功能:图像去雾
void CImgShowDlg::AdjustImgDehaze(BOOL bAdjust, int A_MAX, double degree)
{
	try
	{
		if (bAdjust == TRUE)
		{
			if(m_bEnhanceEdit == true) // 增强
			{
				if (GetiLatest() == 0) // 如果刚什么也没做
				{
					if (m_LatestQBData.image.dstImg.buff == NULL && m_midImg.buff == NULL)
					{
						CloneImgStru(m_LatestQBData.image.srcImg, m_midImg);
						DoDehazeCtrl(&m_midImg, &m_LatestQBData.image.dstImg, A_MAX, degree);
						ShowLatestQBData(); // 显示图像
						SetTargetPixelCoordinate(GetTargetCoordinate());

						SetiPreLatest(GetiLatest());
						SetiLatest(1);
					}
					else
					{
						CloneImgStru(m_LatestQBData.image.dstImg, m_midImg);
						DoDehazeCtrl(&m_midImg, &m_LatestQBData.image.dstImg, A_MAX, degree);
						ShowLatestQBData(); // 显示图像
						SetTargetPixelCoordinate(GetTargetCoordinate());

						SetiPreLatest(GetiLatest());
						SetiLatest(1);
					}	
				} 
				else if (GetiLatest() == 1) // 如果刚才就是去雾
				{
					DoDehazeCtrl(&m_midImg, &m_LatestQBData.image.dstImg, A_MAX,degree); 
					ShowLatestQBData(); // 显示图像
					SetTargetPixelCoordinate(GetTargetCoordinate());

					SetiPreLatest(GetiLatest());
				}
				else // 其它
				{
					CloneImgStru(m_LatestQBData.image.dstImg, m_midImg);

					DoDehazeCtrl(&m_midImg, &m_LatestQBData.image.dstImg, A_MAX,degree); 
					ShowLatestQBData(); // 显示图像
					SetTargetPixelCoordinate(GetTargetCoordinate());

					SetiPreLatest(GetiLatest());
					SetiLatest(1);
				}
			}
		}
	}
	catch(cv::Exception &e)
	{
		e.what();
		return;
	}
	catch (...)
	{
		return;
	}
}

// 功能:图像亮度调节
void CImgShowDlg::AdjustImgIntensity(BOOL bAdjust, int degree)
{
	try
	{
		// 执行亮度调节
		if(bAdjust == TRUE)
		{
			if (degree == 10)
			{
				return;
			}

			if (m_bEnhanceEdit == true) // 增强
			{
				if (GetiLatest() == 0)
				{
					if (m_LatestQBData.image.dstImg.buff == NULL && m_midImg.buff == NULL)
					{
						CloneImgStru(m_LatestQBData.image.srcImg, m_midImg);
						DoIntensityCtrl(&m_midImg, &m_LatestQBData.image.dstImg, degree);
						ShowLatestQBData(); // 显示图像
						SetTargetPixelCoordinate(GetTargetCoordinate());

						SetiPreLatest(GetiLatest());
						SetiLatest(2);
					}
					else
					{
						CloneImgStru(m_LatestQBData.image.dstImg, m_midImg);
						DoIntensityCtrl(&m_midImg, &m_LatestQBData.image.dstImg, degree);
						ShowLatestQBData(); // 显示图像
						SetTargetPixelCoordinate(GetTargetCoordinate());

						SetiPreLatest(GetiLatest());
						SetiLatest(2);
					}
				} 
				else if(GetiLatest() == 2)
				{
					DoIntensityCtrl(&m_midImg, &m_LatestQBData.image.dstImg, degree); 
					ShowLatestQBData(); // 显示图像
					SetTargetPixelCoordinate(GetTargetCoordinate());

					SetiPreLatest(GetiLatest());
				}
				else
				{
					CloneImgStru(m_LatestQBData.image.dstImg, m_midImg);

					DoIntensityCtrl(&m_midImg, &m_LatestQBData.image.dstImg, degree); 
					ShowLatestQBData(); // 显示图像
					SetTargetPixelCoordinate(GetTargetCoordinate());

					SetiPreLatest(GetiLatest());
					SetiLatest(2);
				}
			}
		}
	}
	catch(cv::Exception &e)
	{
		e.what();
		return;
	}
	catch (...)
	{
		return;
	}
}

// 功能:图像对比度调节
void CImgShowDlg::AdjustImgContrast(BOOL bAdjust, int degree)
{
	try
	{
		if(bAdjust == TRUE)
		{
			if (degree == 10)
			{
				return;
			}

			if (m_bEnhanceEdit == true) // 增强
			{
				if (GetiLatest() == 0)
				{
					if (m_LatestQBData.image.dstImg.buff == NULL && m_midImg.buff == NULL)
					{
						CloneImgStru(m_LatestQBData.image.srcImg, m_midImg);
						DoContrastCtrl(&m_midImg, &m_LatestQBData.image.dstImg, degree);

						ShowLatestQBData(); // 显示图像
						SetTargetPixelCoordinate(GetTargetCoordinate());

						SetiPreLatest(GetiLatest());
						SetiLatest(3);
					}
					else
					{
						CloneImgStru(m_LatestQBData.image.dstImg, m_midImg);
						DoContrastCtrl(&m_midImg, &m_LatestQBData.image.dstImg, degree);

						ShowLatestQBData(); // 显示图像
						SetTargetPixelCoordinate(GetTargetCoordinate());

						SetiPreLatest(GetiLatest());
						SetiLatest(3);
					}
				} 
				else if(GetiLatest() == 3)
				{
					DoContrastCtrl(&m_midImg, &m_LatestQBData.image.dstImg, degree); 
					ShowLatestQBData(); // 显示图像
					SetTargetPixelCoordinate(GetTargetCoordinate());

					SetiPreLatest(GetiLatest());
				}
				else
				{
					CloneImgStru(m_LatestQBData.image.dstImg, m_midImg);

					DoContrastCtrl(&m_midImg, &m_LatestQBData.image.dstImg, degree); 
					ShowLatestQBData(); // 显示图像
					SetTargetPixelCoordinate(GetTargetCoordinate());

					SetiPreLatest(GetiLatest());
					SetiLatest(3);
				}
			}
		}
	}
	catch(cv::Exception &e)
	{
		e.what();
		return;
	}
	catch (...)
	{
		return;
	}
}

// 功能:图像清晰度调节
void CImgShowDlg::AdjustImgDefinition(BOOL bAdjust, int degree)
{
	try
	{
		if(bAdjust == TRUE)
		{
			if (degree == 10)
			{
				return;
			}

			if (m_bEnhanceEdit == true)  // 增强
			{
				if (GetiLatest() == 0)
				{
					if (m_LatestQBData.image.dstImg.buff == NULL && m_midImg.buff == NULL)
					{
						CloneImgStru(m_LatestQBData.image.srcImg,m_midImg);
						DoDefinitionCtrl(&m_midImg, &m_LatestQBData.image.dstImg, degree);
						ShowLatestQBData(); // 显示图像
						SetTargetPixelCoordinate(GetTargetCoordinate());

						SetiPreLatest(GetiLatest());
						SetiLatest(4);
					}
					else
					{
						CloneImgStru(m_LatestQBData.image.dstImg,m_midImg);
						DoDefinitionCtrl(&m_midImg, &m_LatestQBData.image.dstImg, degree);
						ShowLatestQBData(); // 显示图像
						SetTargetPixelCoordinate(GetTargetCoordinate());

						SetiPreLatest(GetiLatest());
						SetiLatest(4);
					}

				} 
				else if(GetiLatest() == 4)
				{
					DoDefinitionCtrl(&m_midImg, &m_LatestQBData.image.dstImg, degree); 
					ShowLatestQBData(); // 显示图像
					SetTargetPixelCoordinate(GetTargetCoordinate());

					SetiPreLatest(GetiLatest());
				}
				else
				{
					CloneImgStru(m_LatestQBData.image.dstImg, m_midImg);

					DoDefinitionCtrl(&m_midImg, &m_LatestQBData.image.dstImg, degree); 
					ShowLatestQBData(); // 显示图像
					SetTargetPixelCoordinate(GetTargetCoordinate());

					SetiPreLatest(GetiLatest());
					SetiLatest(4);
				}
			}
		}
	}
	catch(cv::Exception &e)
	{
		e.what();
		return;
	}
	catch (...)
	{
		return;
	}
}

// 功能:返回图像调节上一步图像状态
void CImgShowDlg::ReturnToPreImgState()
{
	try
	{
		if (m_bEnhanceEdit == true)
		{
			CloneImgStru(m_midImg, m_LatestQBData.image.dstImg);

			ShowLatestQBData(); // 显示图像
			SetTargetPixelCoordinate(GetTargetCoordinate());

			// 返回一步
			SetiLatest(GetiPreLatest());
		}
		else
		{
			CloneImgStru(m_midImg, m_LatestQBData.image.dstImg);

			// 标记 m_SrcFrame
			cv::Mat srcFrameMat(m_SrcFrame, false);

			if (srcFrameMat.type() == CV_8UC1)
			{
				memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows);     // 图像数据复制
			}
			else if (srcFrameMat.type() == CV_8UC3)
			{
				memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows * 3);     // 图像数据复制
			}

			Invalidate();
		}
	}
	catch(cv::Exception &e)
	{
		e.what();
		return;
	}
	catch (...)
	{
		return;
	}
}

// 功能:返回原始图像状态
void CImgShowDlg::ReturnToSrcImgState()
{
	try
	{
		if (m_bEnhanceEdit == true)
		{
			SAFE_DELETE_ARRAY(m_midImg.buff);
			m_midImg.buff = NULL;

			SAFE_DELETE_ARRAY(m_LatestQBData.image.dstImg.buff);
			m_LatestQBData.image.dstImg.buff = NULL;

			ShowLatestQBData(); // 显示图像
			SetTargetPixelCoordinate(GetTargetCoordinate());

			// 一步还原
			SetiLatest(0);
			SetiPreLatest(0);
		}
		else
		{
			CloneImgStru(m_LatestQBData.image.srcImg, m_midImg);
			CloneImgStru(m_LatestQBData.image.srcImg, m_LatestQBData.image.dstImg);

			// 标记 m_SrcFrame
			cv::Mat srcFrameMat(m_SrcFrame, false);

			if (srcFrameMat.type() == CV_8UC1)
			{
				memcpy(srcFrameMat.data, m_LatestQBData.image.srcImg.buff, srcFrameMat.cols * srcFrameMat.rows);     // 图像数据复制
			}
			else if (srcFrameMat.type() == CV_8UC3)
			{
				memcpy(srcFrameMat.data, m_LatestQBData.image.srcImg.buff, srcFrameMat.cols * srcFrameMat.rows * 3);     // 图像数据复制
			}

			Invalidate();
		}
	}
	catch(cv::Exception &e)
	{
		e.what();
		return;
	}
	catch (...)
	{
		return;
	}
}

// 18 功能:设置图像编辑类型
void CImgShowDlg::SetImgEditType(int type)
{
	m_iImgEditType = type;

	if (type == 1 || type == 2 || type == 3)
	{
		m_bEnhanceEdit = false;
	}
	else
	{
		m_bEnhanceEdit = true;
	}
}

// 获取图像编辑模式 true 增强 false 标记
bool CImgShowDlg::GetImgEditMode()
{
	return m_bEnhanceEdit;
}

// 20 功能:显示记忆图像队列中的指定某一张图像
void CImgShowDlg::ShowSelectedImgInMem(int order)
{
	WaitForSingleObject(m_hMutex_ProcessData, INFINITE);
	try
	{
		if (m_QBDataDeque.empty() == false)
		{
			if (order >= 1 && order <= static_cast<int>(m_QBDataDeque.size())/* && m_currentImgOrder != order*/)
			{
				// 释放 
				ReleaseQBData(&m_LatestQBData);

				SAFE_DELETE(m_midImg.buff);
				m_midImg.buff = NULL;

				CloneQBData(m_QBDataDeque[order - 1], m_LatestQBData); 

				ShowLatestQBData();
				m_currentImgOrder = order;
			}
		}
		
	}
	catch(cv::Exception &e)
	{
		e.what();
	}
	catch (...)
	{
		int a = 8;
	}
	ReleaseMutex(m_hMutex_ProcessData);
}

// 快速查找图像
void CImgShowDlg::OnFastLookupImgs()
{
	try
	{
		if (m_pFastLookUpDlg != NULL)
		{
			// 为空时
			if (m_pFastLookUpDlg->isEmpty() == true)
			{
				::MessageBoxA(NULL, _T("无记忆图像供查找!"),_T("操作提示"), MB_OK);
				m_pFastLookUpDlg->ShowWindow(SW_HIDE);
				return;
			}
			else
			{
				if (TRUE == m_pFastLookUpDlg->IsWindowVisible())
				{
					m_pFastLookUpDlg->ShowWindow(SW_HIDE);
				}
				else
				{
					m_pFastLookUpDlg->ShowWindow(SW_SHOW);
					m_pFastLookUpDlg->ShowImgData();
				}
			}
		}
	}
	catch(cv::Exception &e)
	{
		e.what();
		return;
	}
	catch (...)
	{
		return;
	}
}


// 定位引导
void CImgShowDlg::OnTgtLocLead()
{
	try
	{
		// 右键坐标
		CPoint point;
		point.x = m_RButtonPt.x;
		point.y = m_RButtonPt.y;

		if (m_bFirstSignal == TRUE || m_bSecondSignal == TRUE)
		{
			return;
		}

		if (m_SrcFrame != NULL)
		{
			// 计算 CPoint point 对应的像素坐标 CPoint LButtonDblClkPixelCoordinate;
			if ((point.x > m_ShowRegionOnScreen.left) && (point.x < m_ShowRegionOnScreen.right) &&
				(point.y > m_ShowRegionOnScreen.top)  && (point.y < m_ShowRegionOnScreen.bottom)) // 鼠标在图像上
			{
				// 图像尺寸与显示区域尺寸之间的比例
				double ratio = 1.0;

				// 分母0值判断
				if (m_ShowRegionOnScreen.Width() > 0)
				{
					ratio = (m_ShowRegion.Width() * 1.0) / m_ShowRegionOnScreen.Width();
				}			

				CPoint PixelCoordinate; // 像素坐标
				PixelCoordinate.x = static_cast<LONG>((point.x - m_ShowRegionOnScreen.left) * ratio) + m_ShowRegion.left;
				PixelCoordinate.y = static_cast<LONG>((point.y - m_ShowRegionOnScreen.top)  * ratio) + m_ShowRegion.top;


				// 经纬度坐标
				double Lon = -200;
				double Lat = -200;
				double H = 0;

				// 图像四个顶点的经纬度坐标
				double Lon1 = -200, Lat1 = -200, H1 = -200;
				double Lon2 = -200, Lat2 = -200, H2 = -200;
				double Lon3 = -200, Lat3 = -200, H3 = -200;
				double Lon4 = -200, Lat4 = -200, H4 = -200;

				if (false == DoCalAnyPtCoordinate(Lon, Lat, H, &m_LatestQBData.framePart, PixelCoordinate.x, PixelCoordinate.y))
				{
					if (m_boundbingBox.EastLon - m_boundbingBox.WestLon > 0 
						&& m_boundbingBox.WestLon >= -180 
						&& m_boundbingBox.WestLon <= 180 
						&& m_boundbingBox.EastLon >= -180  
						&& m_boundbingBox.EastLon <= 180 
						&& m_boundbingBox.NorthLat - m_boundbingBox.SouthLat > 0 
						&& m_boundbingBox.SouthLat >= -90 
						&& m_boundbingBox.SouthLat <= 90 
						&& m_boundbingBox.NorthLat >= -90 
						&& m_boundbingBox.NorthLat <= 90)
					{
						double LonResolution = (m_boundbingBox.EastLon -  m_boundbingBox.WestLon) / m_SrcFrame->width;
						double LatResolution = (m_boundbingBox.NorthLat - m_boundbingBox.SouthLat) / m_SrcFrame->height;

						Lon = float(m_boundbingBox.WestLon +  PixelCoordinate.x * LonResolution);
						Lat = float(m_boundbingBox.NorthLat - PixelCoordinate.y * LatResolution);


						// 四个角点经纬度
						Lon1 = m_boundbingBox.WestLon, Lat1 = m_boundbingBox.NorthLat;
						Lon2 = m_boundbingBox.EastLon, Lat2 = m_boundbingBox.NorthLat;
						Lon3 = m_boundbingBox.EastLon, Lat3 = m_boundbingBox.SouthLat;
						Lon4 = m_boundbingBox.WestLon, Lat4 = m_boundbingBox.SouthLat;
					} 
					else
					{
						Lon = -200.f;
						Lat = -200.f;
					}
				}
				else
				{
					// 计算四个角点的经纬度坐标
					bool ret1 = DoCalAnyPtCoordinate(Lon1, Lat1, H1, &m_LatestQBData.framePart, 0, 0);
					bool ret2 = DoCalAnyPtCoordinate(Lon2, Lat2, H2, &m_LatestQBData.framePart, m_SrcFrame->width - 1, 0);
					bool ret3 = DoCalAnyPtCoordinate(Lon3, Lat3, H3, &m_LatestQBData.framePart, m_SrcFrame->width - 1, m_SrcFrame->height - 1);
					bool ret4 = DoCalAnyPtCoordinate(Lon4, Lat4, H4, &m_LatestQBData.framePart, 0, m_SrcFrame->height - 1);
				}

				// 修正
				if (abs(Lon) < 180 && abs(Lat) < 90)
				{
					Lon += m_deltaLon;
					Lat += m_deltaLat;

					Lon1 += m_deltaLon, Lat1 += m_deltaLat;
					Lon2 += m_deltaLon, Lat2 += m_deltaLat;
					Lon3 += m_deltaLon, Lat3 += m_deltaLat;
					Lon4 += m_deltaLon, Lat4 += m_deltaLat;
				}

				// 回调输出
				if (m_lpSendTgrLocLeadLonLat != NULL)
				{
					m_lpSendTgrLocLeadLonLat(Lon, Lat,
						Lon1, Lat1,
						Lon2, Lat2,
						Lon3, Lat3,
						Lon4, Lat4);
				}

			}
		}
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}

void CImgShowDlg::LeadImgLoc()
{
	CRect rect;
	GetClientRect(&rect);

	// 右键坐标
	m_RButtonPt.x = rect.Width() / 2;
	m_RButtonPt.y = rect.Height() / 2;

	OnTgtLocLead();
}

// 几何校正 并显示图像
void CImgShowDlg::OnGeoCorrectAndShow()
{
	try
	{
		// 当未设置定位导引输出函数指针时,即不用于地图匹配定位时,该功能设为无效 
		if (m_lpSendTgrLocLeadLonLat == NULL)
		{
			return;
		}


		// 几何校正: 选择该模式的原因是牵扯到图像增强等操作
		if (TRUE == DoSysGeoCorrect(&m_LatestQBData))
		{
			SAFE_DELETE_ARRAY(m_LatestQBData.image.srcImg.buff);
			SAFE_DELETE_ARRAY(m_LatestQBData.image.dstImg.buff);

			CloneImgStru(m_LatestQBData.image.geoImg, m_LatestQBData.image.srcImg);

			SAFE_DELETE_ARRAY(m_LatestQBData.image.geoImg.buff);

			// 复接数据设置为0 无效
			m_LatestQBData.framePart.bValid = false;
			memset(&m_LatestQBData.framePart, 0, sizeof(m_LatestQBData.framePart));

			// 设置经纬度盒子
			SetBoundingBox(m_LatestQBData.image.srcImg.BoundingBox);

			// 显示图像
			ShowLatestQBData();
		}
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch (...)
	{
		return;
	}
}


// 设置文件夹
void CImgShowDlg::SetSaveCurrentImgFolder(CString str)
{
	m_sSaveCurrentImgFolder = str;
}

void CImgShowDlg::SetSavePreMultiImgFolder(CString str)
{
	m_sSavePreMultiImgFolder = str;
}

// 21 功能:几何校正并显示图像
void CImgShowDlg::GeoCorrectAndShowImg()
{
	OnGeoCorrectAndShow();
}

// 在图像中标绘目标 矩形 定位用
void CImgShowDlg::OnDrawSqureOnImg()
{
	// 只有设置了目标导引情况下操作
	if (m_lpSendTgrLocLeadLonLat != NULL)
	{
		m_bDrawSquareOnImg = !m_bDrawSquareOnImg;
	}
	else
	{
		m_bDrawSquareOnImg = FALSE;
	}
}


// 图像加载线程(GDAL)
UINT LoadImgThroughGDAL(void *pt)
{
	CImgShowDlg *ptr = (CImgShowDlg*)pt;
	if (ptr == nullptr)
	{
		return 0;
	}

	CString ImgFilePath = ptr->m_GDALLoadImgPath;

	try
	{
		// 注册
		GDALAllRegister();
		CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");

		// 打开图像
		GDALDataset* srcDataSet = nullptr;
		srcDataSet = (GDALDataset*)GDALOpen(ImgFilePath, GA_ReadOnly);

		if (srcDataSet != nullptr)
		{
			// 获取图像参数
			int Width  = srcDataSet->GetRasterXSize();
			int Height = srcDataSet->GetRasterYSize();
			int nBound = srcDataSet->GetRasterCount();

			if (nBound == 1 || nBound == 3)
			{
				double r = 0;
				if (Width > Height)
				{
					r = 10000.0 / Width;
				}
				else
				{
					r = 10000.0 / Height;
				}

				if (r > 1)
				{
					r = 1.0;
				}

				int scaledWidth = int(Width * r);;
				int scaledHeight = int(Height * r);
				
				if (scaledWidth > 0 && scaledHeight > 0)
				{
					GDALRasterBand *pBand = srcDataSet->GetRasterBand(1);
					GDALDataType type = pBand->GetRasterDataType();

					cv::Mat img;
					if (nBound == 1)
					{
						img = cv::Mat(scaledHeight, scaledWidth, CV_8UC1, cv::Scalar(0));
						pBand->RasterIO(GF_Read, 0,0, Width, Height, img.data, img.cols, img.rows, type, 0, 0);
					}
					else
					{
						img = cv::Mat(scaledHeight, scaledWidth, CV_8UC3, cv::Scalar(0));
						int bandMap[3] = {3, 2, 1};
						CPLErr error = srcDataSet->RasterIO(GF_Read, 0,0, 
							Width, Height, 
							img.data, 
							img.cols, img.rows, 
							type, 
							3, 
							bandMap, 
							3,  // nPixelSpace
							3 * scaledWidth, // nLineSpace
							1); // nBandSpace
					}

					BITMAPINFO info;
					info.bmiHeader.biWidth    = img.cols;
					info.bmiHeader.biHeight   = img.rows;
					info.bmiHeader.biBitCount = static_cast<WORD>(img.channels() * 8);

					double GISDATA[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};

					srcDataSet->GetGeoTransform(GISDATA);

					double WLon = GISDATA[0];
					double ELon = GISDATA[0] + Width * GISDATA[1];
					double NLat = GISDATA[3];
					double SLat = GISDATA[3] + Height * GISDATA[5];

					GeoBoundingBox LBbox;
					LBbox.WestLon = WLon;
					LBbox.EastLon = ELon;
					LBbox.SouthLat = SLat;
					LBbox.NorthLat = NLat;

					ptr->LoadOneImgFromMenu(&info, img.data, LBbox);
				}
			}
		}

		GDALClose(srcDataSet);
		srcDataSet = NULL;
	}
	catch(...)
	{
		return 0;
	}

	return 0;
}


// 右键打开一副图像
void CImgShowDlg::OnOpenOneImg()
{
	CFileDialog ImgDialog(
		TRUE, 
		NULL,
		NULL,
		OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_HIDEREADONLY,
		_T("Image files (*.bmp;*.jpg;*.tif;) |*.bmp;*.jpg;*.tif;| All Files (*.*) |*.*||"),
		NULL);

	ImgDialog.m_ofn.lpstrTitle = _T("打开一幅图像");
	if (ImgDialog.DoModal() != IDOK)
	{
		return;
	}

	CString ImgFilePath = ImgDialog.GetPathName();

	m_GDALLoadImgPath = ImgFilePath;

	int len = ImgFilePath.GetLength();
	int leftLen = ImgFilePath.ReverseFind('.');

	CString Type = ImgFilePath.Right(len - leftLen);

	std::string path = ImgFilePath.GetString();

	try
	{
		cv::Mat img = cv::imread(path, -1);

		if (img.empty() == true)
		{
			return;
		}
		else
		{
			BITMAPINFO info;
			info.bmiHeader.biWidth    = img.cols;
			info.bmiHeader.biHeight   = img.rows;
			info.bmiHeader.biBitCount = static_cast<WORD>(img.channels() * 8);

			if (Type == ".tif")
			{
				// 读取文件地理信息
				GDALAllRegister();
				CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");

				GDALDataset* tempdata = nullptr;
				tempdata = ( GDALDataset* )GDALOpen((LPSTR)(LPCTSTR)ImgFilePath, GA_ReadOnly);

				double GISDATA[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};

				if (tempdata != NULL)
				{
					tempdata->GetGeoTransform(GISDATA);

					// 获取尺寸
					int width  = tempdata->GetRasterXSize();
					int height = tempdata->GetRasterYSize();

					double WLon = GISDATA[0];
					double ELon = GISDATA[0] + width * GISDATA[1];
					double NLat = GISDATA[3];
					double SLat = GISDATA[3] + height * GISDATA[5];

					GeoBoundingBox LBbox;
					LBbox.WestLon = WLon;
					LBbox.EastLon = ELon;
					LBbox.SouthLat = SLat;
					LBbox.NorthLat = NLat;

					LoadOneImgFromMenu(&info, img.data, LBbox);
				}
				else
				{
					LoadOneImgFromMenu(&info, img.data);
				}

				GDALClose( tempdata );
				tempdata = NULL;
			} 
			else
			{
				LoadOneImgFromMenu(&info, img.data);
			}
		}
	}
	catch(cv::Exception &e)
	{
		e.what();

		::MessageBoxA(NULL, _T("图像过大,缩放显示!"),_T("操作提示"), MB_OK);

		// 启动GDAL数据加载线程 
		AfxBeginThread(LoadImgThroughGDAL, this);
	}
	catch(...)
	{
	}
}


void CImgShowDlg::LoadOneImgFromMenu(const BITMAPINFO* pImgInfo,
	BYTE* pImgData, 
	GeoBoundingBox LBbox,
	BOOL isNeedFlip,
	BOOL isNeedClip,
	const CRect* pShowRegion,
	float Strecth_Ratio, 
	POINT xyShift)
{
	try
	{
		// 数据有效性验证
		if ( (pImgInfo == NULL) || (pImgData == NULL))
		{
			return;
		}

		// 设置一路输入正在输入标识
		SetFirstSignal(TRUE);

		// biBitCount 验证
		if(pImgInfo->bmiHeader.biBitCount != 24 && pImgInfo->bmiHeader.biBitCount != 8)
		{
			SetFirstSignal(FALSE);
			return;
		}

		// 更新数据至全局变量:LatestQBData 
		if (pImgInfo->bmiHeader.biWidth > 0 && 
			pImgInfo->bmiHeader.biHeight > 0 && 
			pImgData != NULL)
		{
			// 设置一路输入正在输入标识
			SetFirstSignal(TRUE);

			// 构建临时对象
			QBStru local;
			local.image.srcImg.ImgWidth  = pImgInfo->bmiHeader.biWidth;
			local.image.srcImg.ImgHeight = pImgInfo->bmiHeader.biHeight;
			local.image.srcImg.bitcount  = pImgInfo->bmiHeader.biBitCount;

			// 步长:每行像素所占字节数 
			int lineByte = (pImgInfo->bmiHeader.biWidth * pImgInfo->bmiHeader.biBitCount / 8);

			// 位图数据缓冲区的大小,即图像大小
			int imgBufSize = pImgInfo->bmiHeader.biHeight * lineByte;

			if ( imgBufSize > 0)
			{
				local.image.srcImg.buff = new BYTE[imgBufSize];

				if (local.image.srcImg.buff != NULL)
				{
					// 复制实际字节数
					memcpy(local.image.srcImg.buff, pImgData, static_cast<size_t>(imgBufSize)); // 图像数据复制

					// 设置图像数据有效
					local.image.bValid = true; 

					// 是否需要反转
					if (isNeedFlip == TRUE)
					{
						FlipImgStru(&local.image.srcImg);
					}
				}
			}

			local.image.srcImg.BoundingBox = LBbox;

			/*m_boundbingBox = LBbox;*/

			// 将 local 复制到 m_LatestQBData
			SetLatestQBData(local);

			SetBoundingBox(LBbox);

			// 释放 local
			if (local.image.srcImg.buff != NULL)
			{
				SAFE_DELETE_ARRAY(local.image.srcImg.buff);
			}


			// 显示图像
			// 接口转换
			CRect ShowRegion;

			if (pShowRegion != NULL)
			{
				ShowRegion = *pShowRegion;
			}

			ShowOneImage(const_cast<BITMAPINFO*>(pImgInfo), pImgData, isNeedClip, ShowRegion, isNeedFlip, Strecth_Ratio, xyShift);

			// 图像去雾 亮度调节 对比度调节 清晰度调节 复位
			SetiLatest(0);    // 最近的一次
			SetiPreLatest(0); // 最近的一次的前一次

			// 关闭1路正在输入标识
			SetFirstSignal(FALSE);
		}
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}

// 单点定位校准
void CImgShowDlg::OnTgtloccalibrate()
{
	try
	{
		CTgtLocCalibrateDlg TLCdlg;
		if (TLCdlg.DoModal() == IDOK)
		{
			// 获取校准值
			double calibrateLon = TLCdlg.GetCalibrateLon();
			double calibrateLat = TLCdlg.GetCalibrateLat();

			if (abs(calibrateLon) > 180 || abs(calibrateLat) > 90)
			{
				return;
			}

			// 取消校准
			if (abs(calibrateLon) + abs(calibrateLat) < 1e-5)
			{
				m_deltaLon = 0;
				m_deltaLat = 0;
			}

			// 获取校准前的值

			// 经纬度坐标
			double Lon = -200;
			double Lat = -200;
			double H = 0;

			// 右键坐标
			CPoint point;
			point.x = m_RButtonPt.x;
			point.y = m_RButtonPt.y;

			if (m_bFirstSignal == TRUE || m_bSecondSignal == TRUE)
			{
				return;
			}

			if (m_SrcFrame != NULL)
			{
				// 计算 CPoint point 对应的像素坐标 CPoint LButtonDblClkPixelCoordinate;
				if ((point.x > m_ShowRegionOnScreen.left) && (point.x < m_ShowRegionOnScreen.right) &&
					(point.y > m_ShowRegionOnScreen.top)  && (point.y < m_ShowRegionOnScreen.bottom)) // 鼠标在图像上
				{
					// 图像尺寸与显示区域尺寸之间的比例
					double ratio = 1.0;

					// 分母0值判断
					if (m_ShowRegionOnScreen.Width() > 0)
					{
						ratio = (m_ShowRegion.Width() * 1.0) / m_ShowRegionOnScreen.Width();
					}			

					CPoint PixelCoordinate; // 像素坐标
					PixelCoordinate.x = static_cast<LONG>((point.x - m_ShowRegionOnScreen.left) * ratio) + m_ShowRegion.left;
					PixelCoordinate.y = static_cast<LONG>((point.y - m_ShowRegionOnScreen.top)  * ratio) + m_ShowRegion.top;

					if (false == DoCalAnyPtCoordinate(Lon, Lat, H, &m_LatestQBData.framePart, PixelCoordinate.x, PixelCoordinate.y))
					{
						if (m_boundbingBox.EastLon - m_boundbingBox.WestLon > 0 
							&& m_boundbingBox.WestLon >= -180 
							&& m_boundbingBox.WestLon <= 180 
							&& m_boundbingBox.EastLon >= -180  
							&& m_boundbingBox.EastLon <= 180 
							&& m_boundbingBox.NorthLat - m_boundbingBox.SouthLat > 0 
							&& m_boundbingBox.SouthLat >= -90 
							&& m_boundbingBox.SouthLat <= 90 
							&& m_boundbingBox.NorthLat >= -90 
							&& m_boundbingBox.NorthLat <= 90)
						{
							double LonResolution = (m_boundbingBox.EastLon -  m_boundbingBox.WestLon) / m_SrcFrame->width;
							double LatResolution = (m_boundbingBox.NorthLat - m_boundbingBox.SouthLat) / m_SrcFrame->height;

							Lon = float(m_boundbingBox.WestLon +  PixelCoordinate.x * LonResolution);
							Lat = float(m_boundbingBox.NorthLat - PixelCoordinate.y * LatResolution);
						} 
						else
						{
							return;
						}
					}

				}
				else
				{
					return;
				}
			}
			else
			{
				return;
			}

			// 计算修正量
			double deltaLon = calibrateLon - Lon;
			double deltaLat = calibrateLat - Lat;

			if (abs(deltaLon) > 1 || abs(deltaLat) > 1)
			{
				return;
			}
			else
			{
				m_deltaLon = deltaLon;
				m_deltaLat = deltaLat;
			}
		} 
	}
	catch(cv::Exception &e)
	{
		e.msg;
		return;
	}
	catch(...)
	{
		return;
	}
}

// 查看 经纬度校准量
void CImgShowDlg::OnViewDeltaLonLat()
{
	// TODO: 在此添加命令处理程序代码
	CString sDeltaLon;
	sDeltaLon.Format("%.6f", m_deltaLon);
	CString sDeltaLat;
	sDeltaLat.Format("%.6f", m_deltaLat);

	CString msg = "delatLon = " + sDeltaLon + "\n" + "deltaLat = " + sDeltaLat;

	::MessageBoxA(NULL, _T(msg), _T("操作提示"), MB_OK);
}


// 22 功能:获取当前显示图像
cv::Mat CImgShowDlg::GetCurrentImg()
{
	cv::Mat img;

	if (m_SrcFrame != NULL)
	{
		img = cv::Mat(m_SrcFrame, true);
	}

	return img;
}


// 24 功能:标注图像(矩形、区域边缘)
//    输入:
//         1. 区域边缘点 集合
void CImgShowDlg::MarkRegionOnImg(std::vector<std::vector<cv::Point>> &valisContours)
{
	try
	{
		if (valisContours.size() > 0)
		{
			if (m_SrcFrame != NULL && m_SrcFrame->width > 0 && m_SrcFrame->height > 0)
			{
				cv::Mat img(m_SrcFrame, false);

				for (size_t i = 0; i < valisContours.size(); i++)
				{
					cv::Rect rect = cv::boundingRect(valisContours[i]);
					cv::rectangle(img, rect, cv::Scalar(0,255,255), 2);
				}
				cv::drawContours(img, valisContours, -1, cv::Scalar(0,255,255), 1);

				// m_midImg
				if (m_LatestQBData.image.dstImg.buff != NULL)
				{
					memcpy(m_LatestQBData.image.dstImg.buff, img.data, img.cols * img.rows * img.channels());
				}

				if (m_LatestQBData.image.srcImg.buff != NULL)
				{
					memcpy(m_LatestQBData.image.srcImg.buff, img.data, img.cols * img.rows * img.channels());
				}

				ShowLatestQBData();
			}
		}
	}
	catch(cv::Exception &e)
	{
		e.what();
	}
	catch (...)
	{
	}
}

// 功能:屏蔽右键按钮菜单
void CImgShowDlg::CloseRightBtnDownMenu(bool bClose)
{
	m_bCloseRughtBtnMenu = bClose;
}

// 功能:设置空屏文字
void CImgShowDlg::SetThemeText(CString str)
{
	m_sThemeText = str;
}

void CImgShowDlg::OnGetTargetImg()
{
	if (m_bClipImgOn == true)
	{
		m_bGetTgtImgOn = false;
		m_haveValidFirstPt = false;
	}
	else
	{
		m_bGetTgtImgOn = !m_bGetTgtImgOn;

		if (m_bGetTgtImgOn == false)
		{
			m_haveValidFirstPt = false;
		}
	}
}

// 功能:获取图像边界地理坐标
bool CImgShowDlg::GetImgBoundingBox(double &leftLon, double &topLat, double &rigtLon, double &bottomLat)
{
	double leftLon0 = m_LatestQBData.image.srcImg.BoundingBox.WestLon;
	double rigtLon0 = m_LatestQBData.image.srcImg.BoundingBox.EastLon;
	double topLat0 = m_LatestQBData.image.srcImg.BoundingBox.NorthLat;
	double bottomLat0 = m_LatestQBData.image.srcImg.BoundingBox.SouthLat;

	if (abs(leftLon0) <= 180 && abs(rigtLon0) <= 180 && leftLon0 < rigtLon0 && 
		abs(topLat0) <= 90 && abs(bottomLat0) <= 90 && bottomLat0 < topLat0)
	{
		leftLon = leftLon0;
		rigtLon = rigtLon0;
		topLat = topLat0;
		bottomLat = bottomLat0;

		return true;
	}
	else
	{
		return false;
	}
}

void CImgShowDlg::OnClipImg()
{
	m_bClipImgOn = !m_bClipImgOn;

	if (m_bClipImgOn == true)
	{
		m_bGetTgtImgOn = false;
	}

	m_haveValidFirstPt = false;
}