设为首页收藏本站

中国膜结构网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

膜结构车棚
膜结构车棚膜结构资质国产膜材 膜结构网中国膜结构协会
查看: 115|回复: 0

在对话框中显示图片,放大,缩小和移动( c++ MFC)

[复制链接]
  • TA的每日心情
    开心
    2021-6-20 09:04
  • 签到天数: 1540 天

    [LV.Master]伴坛终老

    发表于 2021-2-23 21:56 | 显示全部楼层 |阅读模式
    核心代码:

    void CShowInPicCtrlDlg::OnBnClickedOk()
    {
            // TODO: 在此添加控件通知处理程序代码
            CString strFilePath = CMfcStrFile::OpenFile();

            if (m_pGDALShow)
            {
                    delete m_pGDALShow;
                    m_pGDALShow = nullptr;
            }

            //DC可能随着窗口的改变而改变
            CRect rcPicture;
            GetDlgItem(IDC_STATIC_PIC)->GetWindowRect(rcPicture);
            ScreenToClient(rcPicture);

            m_nDCWidth = rcPicture.Width();
            m_nDCHeight = rcPicture.Height();

            //宽度应为4的整数倍
            m_nDCWidth = ((m_nDCWidth + 3) / 4) * 4;

            if (m_hBmp)
            {
                    :eleteObject(m_hBmp);
                    m_hBmp = nullptr;
            }

            BITMAPINFO bmpInfo;
            bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
            bmpInfo.bmiHeader.biWidth = m_nDCWidth;
            bmpInfo.bmiHeader.biHeight = m_nDCHeight;
            bmpInfo.bmiHeader.biPlanes = 1;
            bmpInfo.bmiHeader.biBitCount = 24;
            bmpInfo.bmiHeader.biCompression = BI_RGB;
            bmpInfo.bmiHeader.biSizeImage = 0;
            bmpInfo.bmiHeader.biXPelsPerMeter = 0;
            bmpInfo.bmiHeader.biYPelsPerMeter = 0;
            bmpInfo.bmiHeader.biClrUsed = 0;
            bmpInfo.bmiHeader.biClrImportant = 0;

            m_hBmp = CreateDIBSection(m_memDC.m_hDC, &bmpInfo, DIB_RGB_COLORS, (void **)&m_pFrontBuffer, NULL, 0);

            m_bmp.Detach();
            m_bmp.Attach(m_hBmp);

            if (strFilePath.GetLength())
            {
                    std::string sFilePath = CStdStr::ws2s(CMfcStrFile::CString2string(strFilePath));
                    m_pGDALShow = new CGDALShow(FromHandle(m_hWnd), sFilePath.c_str(), m_pFrontBuffer, m_nDCWidth, m_nDCHeight,
                            TRUE, GetDlgItem(IDC_STATIC_PIC), &m_bmp, &m_memDC, &m_hBmp, &m_hOldBmp);
                    m_pGDALShow->ShowImage(TRUE);
                    m_pGDALShow->ThreadReadingData();
            }
    }
    相关的头文件:

    //[5/25/2018 autumoon]

    #pragma once
    #include "GdalUser.h"

    //MEM_ALLOC_X、MEM_ALLOC_X必须是1或者3,为1时节省内存,为3时拖动体验更好
    #define        MEM_ALLOC_X                        3
    #define        MEM_ALLOC_Y                        3
    #define        MEM_ALLOC_NUM                (MEM_ALLOC_X * MEM_ALLOC_Y)
    #define DC_OFFSET_NUM_X                ((MEM_ALLOC_X - 1) >> 1)
    #define DC_OFFSET_NUM_Y                ((MEM_ALLOC_Y - 1) >> 1)

    #define AU_MIN(x,y)        ((x) < (y) ? (x) : (y))
    #define AU_MAX(x,y)        ((x) > (y) ? (x) : (y))

    //必须使用外部双缓存
    class CGDALShow
    {
    public:
            //如果不是对话框,第二行参数全部取默认值即可
            CGDALShow(CWnd* pWnd, const char* imgPath, unsigned char* pFrontBuffer, int nDCWidth, int nDCHeight,
                    BOOL bIsDlg = FALSE, CWnd* pCtrlWnd = nullptr, CBitmap* pbmp = nullptr, CDC* pmemDC = nullptr, HBITMAP* phBmp = nullptr, HBITMAP* phOldBmp = nullptr);
            ~CGDALShow(void);
    public:
            bool m_bIsLBtnDown;                                                        //左键是否按下
            bool m_bIsMBtnDown;                                                        //中键是否按下
            bool m_bUpdateScale;                                                //是否需要更新比例
            CBitmap* m_pbmp;                                                        //外部显示使用的变量,尺寸变化时内部可能更新
            CDC* m_pmemDC;
            CWnd* m_pCtrlWnd;
            HBITMAP* m_phBmp;
            HBITMAP* m_phOldBmp;
            int m_nDCWidth;                                                                //显示区域的宽度
            int m_nDCHeight;                                                        //显示区域的高度

            unsigned char* m_pFrontBuffer;                                //内存buffer
            unsigned char* m_pFrontBufferDrag;                        //DCbuffer备份,用于拖动的时候缓冲
            unsigned char* m_pFrontBufferDragThread;        //DCbuffer备份,用于线程读取

            //根据控件坐标,获取信息
            bool GetPixValue(int nCtrlX, int nCtrlY, std::vector<int>& values, bool bGetRealValue = false);
            bool GetImgCoors(int nCtrlX, int nCtrlY, int& nImgX, int& nImgY, bool bYReverse = false);

            int ThreadReadingData(BOOL bThread = TRUE);
            void OnLButtonDown(POINT point);
            void OnLButtonUp(POINT point);
            void OnMButtonDown(POINT point);
            void OnMButtonUp(POINT point);
            void OnMouseMove(POINT point);
            void OnMouseWheel(short zDelta, CPoint pt);
            void ShowImage(BOOL bDirectDC = FALSE);

            static double m_dMaxScale;                                        //缩放最大比例
            static double m_dMinScale;                                        //缩放最小比例
            static double m_dScaleStep;                                        //缩放步进值
            static double m_dXoffset;                                        //显示区域留白x
            static double m_dYoffset;                                        //显示区域留白y
            static int m_nBgValue;                                                //背景值
            static int m_nButtonMove;                                        //使用鼠标按钮移动 1代表左键 2代表中键
           
    protected:
            bool m_bIsDlg;
            bool m_bDragDataReady;
            CGdalUser* m_pGu;
            double* m_pHist;                                        //直方图统计
            double* m_plfCount;                                        //累计概率
            double m_dScale;                                        //当前比例
            double m_dScaleLast;                                //上一次比例
            double m_dIniScale;                                        //金字塔比例
            unsigned char* m_pBufferPy;                        //金字塔Buffer
            unsigned char* m_pClrLut;                        //颜色查找表

            bool CreatePyramid();
            bool GetRealPixValue(int nCtrlX, int nCtrlY, std::vector<int>& vRealValues);
            int GetPointerForDlgShow(CWnd* pDlgWnd, CBitmap* pbmp, CDC* pmemDC, HBITMAP* phBmp, HBITMAP* phOldBmp);
            int ResampleArray(int nSrcBufWidth, int nSrcBufHeight, int nSrcLeft, int nSrcTop, int nSrcRight, int nSrcBottom, unsigned char* pSrc,
                    int nDstBufWidth, int nDstBufHeight, int nDstLeft, int nDstTop, int nDstRight, int nDstBottom, unsigned char* pDst);
            int ResampleArray2BGR(int nSrcBufWidth, int nSrcBufHeight, int nSrcLeft, int nSrcTop, int nSrcRight, int nSrcBottom, unsigned char* pSrc, int nSrcBandNum,
                    int nDstBufWidth, int nDstBufHeight, int nDstLeft, int nDstTop, int nDstRight, int nDstBottom, unsigned char* pDst, int nDstBandNum,
                    int nSizeOfPointer = 1, int nSrcSkip = 0, int nDestSkip = 0);

            //用于线程读取备用数据
            static bool PreReadFrontBufferDrag(LPVOID lpParameters);
            void ResetOffset();
            void ResetParameters();

    private:
            CWnd* m_pWnd;
            double m_pXoffset;
            double m_pYoffset;
            double m_pXstart;
            double m_pYstart;

            int m_nImgWidth;
            int m_nImgHeight;
            int m_nIniWidth, m_nIniHeight, m_nBandNum, m_nBPB;
            int m_nX;
            int m_nY;
            int m_nShowWidth;
            int m_nShowHeight;

            POINT m_pMouDownPnt;
    };

    //对话框外部双缓存
    /************************************************************************
    //Dlg中定义
    CGDALShow* m_pGDALShow;
    int m_nDCHeight;
    int m_nDCWidth;
    unsigned char* m_pFrontBuffer;
    CBitmap m_bmp;
    CDC m_memDC;
    HBITMAP m_hBmp;
    HBITMAP m_hOldBmp;
    //构造函数中初始化
    m_pGDALShow = nullptr;
    m_nDCWidth = -1;
    m_nDCHeight = -1;
    m_pFrontBuffer = nullptr;
    //析构函数中释放
    if (m_pGDALShow)
    {
            delete m_pGDALShow;
            m_pGDALShow = nullptr;
    }
    //添加static控件或者picturectrl控件
    //动作按钮中添加如下内容
    CString strFilePath = CMfcStrFile::OpenFile();
    if (m_pGDALShow)
    {
            delete m_pGDALShow;
            m_pGDALShow = nullptr;
    }
    //DC可能随着窗口的改变而改变
    CRect rcPicture;
    GetDlgItem(IDC_STATIC_PIC)->GetWindowRect(rcPicture);
    ScreenToClient(rcPicture);
    m_nDCWidth = rcPicture.Width();
    m_nDCHeight = rcPicture.Height();
    //宽度应为4的整数倍
    m_nDCWidth = ((m_nDCWidth + 3) / 4) * 4;
    if (m_hBmp)
    {
            :eleteObject(m_hBmp);
            m_hBmp = nullptr;
    }
    BITMAPINFO bmpInfo;
    bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmpInfo.bmiHeader.biWidth = m_nDCWidth;
    bmpInfo.bmiHeader.biHeight = m_nDCHeight;
    bmpInfo.bmiHeader.biPlanes = 1;
    bmpInfo.bmiHeader.biBitCount = 24;
    bmpInfo.bmiHeader.biCompression = BI_RGB;
    bmpInfo.bmiHeader.biSizeImage = 0;
    bmpInfo.bmiHeader.biXPelsPerMeter = 0;
    bmpInfo.bmiHeader.biYPelsPerMeter = 0;
    bmpInfo.bmiHeader.biClrUsed = 0;
    bmpInfo.bmiHeader.biClrImportant = 0;
    m_hBmp = CreateDIBSection(m_memDC.m_hDC, &bmpInfo, DIB_RGB_COLORS, (void **)&m_pFrontBuffer, NULL, 0);
    m_bmp.Detach();
    m_bmp.Attach(m_hBmp);
    if (strFilePath.GetLength())
    {
            std::string sFilePath = CStdStr::ws2s(CMfcStrFile::CString2string(strFilePath));
            m_pGDALShow = new CGDALShow(FromHandle(m_hWnd), sFilePath.c_str(), m_pFrontBuffer, m_nDCWidth, m_nDCHeight,
                    TRUE, GetDlgItem(IDC_STATIC_PIC), &m_bmp, &m_memDC, &m_hBmp, &m_hOldBmp);
            m_pGDALShow->ShowImage(TRUE);
            m_pGDALShow->ThreadReadingData();
    }
    //PreTranslateMessage(MSG* pMsg)
    CRect rect;
    GetDlgItem(IDC_STATIC_PIC)->GetWindowRect(&rect);
    if (pMsg->message == WM_LBUTTONDOWN && m_pGDALShow && rect.PtInRect(pMsg->pt))
    {
            m_pGDALShow->OnLButtonDown(pMsg->pt);
    }
    if (pMsg->message == WM_LBUTTONUP && m_pGDALShow && rect.PtInRect(pMsg->pt))
    {
            m_pGDALShow->OnMButtonUp(pMsg->pt);
    }
    if (pMsg->message == WM_MBUTTONDOWN && m_pGDALShow && rect.PtInRect(pMsg->pt))
    {
    m_pGDALShow->OnMButtonDown(pMsg->pt);
    }
    if (pMsg->message == WM_MBUTTONUP && m_pGDALShow && rect.PtInRect(pMsg->pt))
    {
    m_pGDALShow->OnMButtonUp(pMsg->pt);
    }
    if (pMsg->message == WM_MOUSEMOVE && m_pGDALShow && rect.PtInRect(pMsg->pt))
    {
            m_pGDALShow->OnMouseMove(pMsg->pt);
    }
    //OnMouseWheel()
    if (m_pGDALShow)
    {
            m_pGDALShow->OnMouseWheel(zDelta, pt);
    }
    //OnPaint()
    CPaintDC dc(GetDlgItem(IDC_STATIC_PIC));
    CRect rcclient;
    GetDlgItem(IDC_STATIC_PIC)->GetClientRect(&rcclient);//获取控件的屏幕坐标
    CWnd:efWindowProc(WM_PAINT, (WPARAM)m_memDC.m_hDC, 0);
    CBrush brush;
    brush.CreatePatternBrush(&m_bmp);
    dc.FillRect(rcclient, &brush);
    dc.BitBlt(rcclient.left, rcclient.top, rcclient.Width(), rcclient.Height(), &m_memDC, rcclient.left, rcclient.top, SRCPAINT);
    brush.DeleteObject();
    //OnSize()若对话框尺寸可能发生改变
    if (cx < 1 || cy < 1)
    {
            return;
    }
    CWnd* pWnd = GetDlgItem(IDC_STATIC_PIC);
    if (pWnd)
    {
            CRect rect;
            pWnd->GetClientRect(&rect);
            m_nDCHeight = rect.Height();
            m_nDCWidth = rect.Width();
            m_nDCWidth = ((m_nDCWidth + 3) / 4) * 4;
    }
    if (m_pGDALShow)
    {
            m_pGDALShow->m_nDCWidth = m_nDCWidth;
            m_pGDALShow->m_nDCHeight = m_nDCHeight;
    }
    size_t nDCMemSize = m_nDCWidth * m_nDCHeight * 3;
    BITMAPINFO bmpInfo;
    bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmpInfo.bmiHeader.biWidth = m_nDCWidth;
    bmpInfo.bmiHeader.biHeight = m_nDCHeight;
    bmpInfo.bmiHeader.biPlanes = 1;
    bmpInfo.bmiHeader.biBitCount = 24;
    bmpInfo.bmiHeader.biCompression = BI_RGB;
    bmpInfo.bmiHeader.biSizeImage = 0;
    bmpInfo.bmiHeader.biXPelsPerMeter = 0;
    bmpInfo.bmiHeader.biYPelsPerMeter = 0;
    bmpInfo.bmiHeader.biClrUsed = 0;
    bmpInfo.bmiHeader.biClrImportant = 0;
    if (m_hBmp)
    {
            SelectObject(m_memDC.m_hDC, m_hOldBmp);
            m_hOldBmp = NULL;
            DeleteObject(m_hBmp);
            m_hBmp = NULL;
    }
    m_hBmp = CreateDIBSection(m_memDC.m_hDC, &bmpInfo, DIB_RGB_COLORS, (void **)&m_pFrontBuffer, NULL, 0);
    m_hOldBmp = (HBITMAP)::SelectObject(m_memDC.m_hDC, m_hBmp);
    if (m_pGDALShow)
    {
            //必须要更新这个buffer的指针
            m_pGDALShow->m_bUpdateScale = false;
            m_pGDALShow->m_pFrontBuffer = m_pFrontBuffer;
            m_pGDALShow->ThreadReadingData(FALSE);
            m_pGDALShow->ShowImage();
            m_pGDALShow->m_bUpdateScale = true;
    }
    /************************************************************************/

    //视图中外部双缓存参考
    /***********************************************************************
    //View类中定义
    CGDALShow* m_pGDALShow;
    int m_nDCHeight;
    int m_nDCWidth;
    unsigned char* m_pFrontBuffer;
    CBitmap m_bmp;
    CDC m_memDC;
    HBITMAP m_hBmp;
    HBITMAP m_hOldBmp;
    //构造函数中初始化
    m_pGDALShow = nullptr;
    m_nDCWidth = -1;
    m_nDCHeight = -1;
    m_pFrontBuffer = nullptr;
    //析构函数中释放
    if (m_pGDALShow)
    {
            delete m_pGDALShow;
            m_pGDALShow = nullptr;
    }
    //OnCreate()
    CDC *pDC = GetDC();
    m_memDC.CreateCompatibleDC(pDC);
    ReleaseDC(pDC);
    //OnSize()
    if (cx < 1 || cy < 1)
    {
    return;
    }
    m_nDCHeight = cy;
    m_nDCWidth = cx;
    m_nDCWidth = ((m_nDCWidth + 3) / 4) * 4;
    if (m_pGDALShow)
    {
    m_pGDALShow->m_nDCWidth = m_nDCWidth;
    m_pGDALShow->m_nDCHeight = m_nDCHeight;
    }
    size_t nDCMemSize = m_nDCWidth * m_nDCHeight * 3;
    BITMAPINFO bmpInfo;
    bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmpInfo.bmiHeader.biWidth = m_nDCWidth;
    bmpInfo.bmiHeader.biHeight = m_nDCHeight;
    bmpInfo.bmiHeader.biPlanes = 1;
    bmpInfo.bmiHeader.biBitCount = 24;
    bmpInfo.bmiHeader.biCompression = BI_RGB;
    bmpInfo.bmiHeader.biSizeImage = 0;
    bmpInfo.bmiHeader.biXPelsPerMeter = 0;
    bmpInfo.bmiHeader.biYPelsPerMeter = 0;
    bmpInfo.bmiHeader.biClrUsed = 0;
    bmpInfo.bmiHeader.biClrImportant = 0;
    if (m_hBmp)
    {
    SelectObject(m_memDC.m_hDC, m_hOldBmp);
    m_hOldBmp = NULL;
    DeleteObject(m_hBmp);
    m_hBmp = NULL;
    }
    m_hBmp = CreateDIBSection(m_memDC.m_hDC, &bmpInfo, DIB_RGB_COLORS, (void **)&m_pFrontBuffer, NULL, 0);
    m_hOldBmp = (HBITMAP)::SelectObject(m_memDC.m_hDC, m_hBmp);
    if (m_pGDALShow)
    {
    //必须要更新这个buffer的指针
    m_pGDALShow->m_bUpdateScale = false;
    m_pGDALShow->m_pFrontBuffer = m_pFrontBuffer;
    m_pGDALShow->ThreadReadingData(FALSE);
    m_pGDALShow->ShowImage();
    m_pGDALShow->m_bUpdateScale = true;
    }
    //PreTranslateMessage(MSG* pMsg)
    if (pMsg->message == WM_KEYDOWN && m_pGDALShow)
    {
    if (pMsg->wParam == VK_SPACE)
    {
    if (m_pGDALShow->m_nButtonMove == 2)
    {
    //切换移动图像的鼠标按键为左键
    m_pGDALShow->m_nButtonMove = 1;
    }
    else
    {        //恢复为中键
    m_pGDALShow->m_nButtonMove = 2;
    }
    }
    }
    else
    {
    if (pMsg->message == WM_LBUTTONDOWN && m_pGDALShow)
    {
    m_pGDALShow->OnLButtonDown(pMsg->pt);
    }
    if (pMsg->message == WM_LBUTTONUP && m_pGDALShow)
    {
    m_pGDALShow->OnLButtonUp(pMsg->pt);
    }
    if (pMsg->message == WM_MBUTTONDOWN && m_pGDALShow)
    {
    m_pGDALShow->OnMButtonDown(pMsg->pt);
    }
    if (pMsg->message == WM_MBUTTONUP && m_pGDALShow)
    {
    m_pGDALShow->OnMButtonUp(pMsg->pt);
    }
    if (pMsg->message == WM_MOUSEMOVE && m_pGDALShow)
    {
    m_pGDALShow->OnMouseMove(pMsg->pt);
    }
    }
    //OnMouseWheel()
    if (m_pGDALShow)
    {
            m_pGDALShow->OnMouseWheel(zDelta, pt);
    }
    //OnDraw()
    if (m_pGDALShow)
    {
            BitBlt(pDC->m_hDC, 0, 0, m_nDCWidth, m_nDCHeight, m_memDC.m_hDC, 0, 0, SRCCOPY);
    }
    //动作函数中
    if (m_pGDALShow)
    {
    delete m_pGDALShow;
    m_pGDALShow = nullptr;
    }
    m_pGDALShow = new CGDALShow(FromHandle(m_hWnd), CStdStr::ws2s(strFilePath).c_str(), m_pFrontBuffer, m_nDCWidth, m_nDCHeight);
    m_pGDALShow->ShowImage();
    m_pGDALShow->ThreadReadingData();
    /************************************************************************/
    实现文件:

    #include "..\StdAfx.h"
    #include "GDALShow.h"
    #include "afxdialogex.h"

    //[6/26/2016 yufuxiang]
    //[5/24/2018 autumoon]


    CMutex mutexDrag;
    CMutex mutexDragThread;


    double CGDALShow::m_dMaxScale = 8.0;
    double CGDALShow::m_dMinScale = 0.01;
    double CGDALShow::m_dScaleStep = 120.0 / 0.125;
    double CGDALShow::m_dXoffset = 0.0;
    double CGDALShow::m_dYoffset = 0.0;
    int CGDALShow::m_nBgValue = 240;
    int CGDALShow::m_nButtonMove = 2;

    CGDALShow::CGDALShow(CWnd* pWnd, const char* imgPath, unsigned char* pFrontBuffer, int nDCWidth, int nDCHeight,
            BOOL bIsDlg /*= FALSE*/, CWnd* pCtrlWnd /*= nullptr*/, CBitmap* pbmp /*= nullptr*/, CDC* pmemDC /*= nullptr*/, HBITMAP* phBmp /*= nullptr*/, HBITMAP* phOldBmp /*= nullptr*/)
    {
            if (pWnd == nullptr || imgPath == nullptr)
            {
                    return;
            }
           
            //复位所有参数
            ResetParameters();
           
            //获取重要参数
            if (bIsDlg)
            {
                    //对话框的时候每次显示都会计算宽度与高度
                    GetPointerForDlgShow(pCtrlWnd, pbmp, pmemDC, phBmp, phOldBmp);
            }
            else
            {
                    if (pFrontBuffer == nullptr || nDCWidth < 1 || nDCHeight < 1)
                    {
                            return;
                    }
            }
           
            m_bIsDlg = bIsDlg == TRUE;
            m_pWnd = pWnd;
            m_pFrontBuffer = pFrontBuffer;

            m_pGu = new CGdalUser();
            if (!m_pGu->InitializeRead(imgPath))
            {
                    return;
            }
            //先获取这些数据是为了计算偏移
            m_nImgWidth = m_pGu->m_nImgWidth;
            m_nImgHeight = m_pGu->m_nImgHeight;
            m_nDCWidth = nDCWidth;
            m_nDCHeight = nDCHeight;
           
            //居中显示
            ResetOffset();
            //剩下的数据在这里获取
            CreatePyramid();
    }

    CGDALShow::~CGDALShow(void)
    {
            if (m_pGu)
            {
                    delete m_pGu;
                    m_pGu = nullptr;
            }

            if (m_pHist)
            {
                    delete[] m_pHist;
                    m_pHist = nullptr;
            }

            if (m_plfCount)
            {
                    delete[] m_plfCount;
                    m_plfCount = nullptr;
            }

            if (m_pBufferPy)
            {
                    delete[] m_pBufferPy;
                    m_pBufferPy = nullptr;
            }

            if (m_pClrLut)
            {
                    delete[] m_pClrLut;
                    m_pClrLut = nullptr;
            }

            if (m_pFrontBufferDrag)
            {
                    delete[] m_pFrontBufferDrag;
                    m_pFrontBufferDrag = nullptr;
            }

            if (m_pFrontBufferDragThread)
            {
                    delete[] m_pFrontBufferDragThread;
                    m_pFrontBufferDragThread = nullptr;
            }
    }

    void CGDALShow::OnLButtonDown(POINT point)
    {
            if (m_nButtonMove == 1)
            {
                    CRect rect;
                    if (m_bIsDlg)
                    {
                            m_pCtrlWnd->GetWindowRect(&rect);
                    }
                    else
                    {
                            m_pWnd->GetWindowRect(&rect);
                            SetCapture(m_pWnd->GetSafeHwnd());
                    }

                    if (rect.PtInRect(point))
                    {
                            m_bIsLBtnDown = true;
                            m_bUpdateScale = false;
                            m_pMouDownPnt = point;
                    }
            }
    }

    void CGDALShow::OnLButtonUp(POINT point)
    {
            if (m_nButtonMove == 1)
            {
                    m_bIsLBtnDown = false;
                    m_pMouDownPnt = point;

                    m_pXstart += m_pXoffset;
                    m_pYstart += m_pYoffset;
                    m_dXoffset = m_pXoffset;
                    m_dYoffset = m_pYoffset;
                    m_pXoffset = 0.0;
                    m_pYoffset = 0.0;

                    if (!m_bIsDlg)
                    {
                            ReleaseCapture();
                    }

                    ThreadReadingData();
            }
    }

    void CGDALShow::OnMButtonDown(POINT point)
    {
            if (m_nButtonMove == 2)
            {
                    CRect rect;
                    if (m_bIsDlg)
                    {
                            m_pCtrlWnd->GetWindowRect(&rect);
                    }
                    else
                    {
                            m_pWnd->GetWindowRect(&rect);
                            SetCapture(m_pWnd->GetSafeHwnd());
                    }

                    if (rect.PtInRect(point))
                    {
                            m_bIsMBtnDown = true;
                            m_bUpdateScale = false;
                            m_pMouDownPnt = point;
                    }
            }
    }

    void CGDALShow::OnMButtonUp(POINT point)
    {
            if (m_nButtonMove == 2)
            {
                    m_bIsMBtnDown = false;
                    m_pMouDownPnt = point;

                    m_pXstart += m_pXoffset;
                    m_pYstart += m_pYoffset;
                    m_dXoffset = m_pXoffset;
                    m_dYoffset = m_pYoffset;
                    m_pXoffset = 0.0;
                    m_pYoffset = 0.0;

                    if (!m_bIsDlg)
                    {
                            ReleaseCapture();
                    }

                    ThreadReadingData();
            }
    }

    void CGDALShow::OnMouseMove(POINT point)
    {
            if (m_bIsLBtnDown  && m_bIsLBtnDown == 1|| m_bIsMBtnDown && m_nButtonMove == 2 )
            {
                    CRect rect;
                    if (m_bIsDlg)
                    {
                            m_pCtrlWnd->GetWindowRect(&rect);
                    }
                    else
                    {
                            m_pWnd->GetWindowRect(&rect);
                    }
                    if (rect.PtInRect(point) || !m_bIsDlg)
                    {
                            m_nX = int(m_pXstart + m_pXoffset + 0.5);
                            m_nY = int(m_pYstart + m_pYoffset + 0.5);
                            m_nShowWidth = int(m_nImgWidth*m_dScale + 0.5);
                            m_nShowHeight = int(m_nImgHeight*m_dScale + 0.5);

                            m_pXoffset = point.x - m_pMouDownPnt.x;
                            m_pYoffset = m_pMouDownPnt.y - point.y;
                            ShowImage();
                    }
            }
    }

    void CGDALShow::OnMouseWheel(short zDelta, CPoint pt)
    {
            if(zDelta>120)  zDelta=120;
            if(zDelta<-120) zDelta=-120;

            double tmpOffsetX=0;double tmpOffsetY=0;

            CRect rect;
            if (m_bIsDlg)
            {
                    m_pCtrlWnd->GetWindowRect(&rect);
            }
            else
            {
                    m_pWnd->GetWindowRect(&rect);
            }
           
            POINT point;
            point.x=pt.x;
            point.y=pt.y;

            if (rect.PtInRect(point))
            {
                    if(m_dScale > m_dMinScale && zDelta < 0 || m_dScale < m_dMaxScale && zDelta > 0)
                    {
                            double tmpscale = zDelta/m_dScaleStep;
                            tmpscale *= m_dScale;

                            tmpOffsetX=m_nImgWidth*tmpscale*((double)(point.x-rect.left-m_pXstart)/(double)(m_nImgWidth*(m_dScale)));
                            tmpOffsetY=m_nImgHeight*tmpscale*((double)(rect.bottom - point.y - m_pYstart)/(double)(m_nImgHeight*(m_dScale)));

                            int nX = int(m_pXstart-tmpOffsetX + 0.5);
                            int nY = int(m_pYstart-tmpOffsetY + 0.5);
                            int nShowWidth = int(m_nImgWidth*(m_dScale+tmpscale) + 0.5);
                            int nShowHeight = int(m_nImgHeight*(m_dScale+tmpscale) + 0.5);
                            if (nShowWidth > 0 && nShowHeight > 0)
                            {
                                    //这里需要同步缩放drag中的数据
                                    int nBufferWidth = m_nDCWidth * MEM_ALLOC_X;
                                    int nBufferHeight = m_nDCHeight * MEM_ALLOC_Y;

                                    int nSrcLeft = m_nDCWidth * DC_OFFSET_NUM_X + m_nX;
                                    int nSrcTop = m_nDCHeight * DC_OFFSET_NUM_Y + m_nY;
                                    int nSrcRight = nSrcLeft + m_nShowWidth;
                                    int nSrcBottom = nSrcTop + m_nShowHeight;

                                    int nDstLeft = m_nDCWidth * DC_OFFSET_NUM_X + nX;
                                    int nDstTop = m_nDCHeight * DC_OFFSET_NUM_Y + nY;
                                    int nDstRight = nDstLeft + nShowWidth;
                                    int nDstBottom = nDstTop + nShowHeight;

                                    mutexDrag.Lock();
                                    ResampleArray(nBufferWidth, nBufferHeight, nSrcLeft, nSrcTop, nSrcRight, nSrcBottom, m_pFrontBufferDrag,
                                            nBufferWidth, nBufferHeight, nDstLeft, nDstTop, nDstRight, nDstBottom, m_pFrontBufferDrag);
                                    mutexDrag.Unlock();

                                    //采用此次缩放的结果
                                    m_nX = nX;
                                    m_nY = nY;
                                    m_nShowWidth = nShowWidth;
                                    m_nShowHeight = nShowHeight;
                                    ShowImage();
                                    m_dScale += tmpscale;
                                    m_pXstart -= tmpOffsetX;
                                    m_pYstart -= tmpOffsetY;
                            }
                    }
            }

            m_bUpdateScale = fabs(m_dScale - m_dScaleLast) > 0.00001;
            m_dScaleLast = m_dScale;

            ThreadReadingData();
    }

    bool CGDALShow::CreatePyramid()
    {
            //显示照片
            m_nBandNum = m_pGu->m_nBandNum;
            m_nBPB = m_pGu->m_nBPB;

            //金字塔buffer,用于显示全局的时候读取显示
            const int nPyIniLength = 10000;

            double dWidthIniProp = (double)nPyIniLength / m_nImgWidth;
            double dHeightIniProp = (double)nPyIniLength / m_nImgHeight;
            m_dIniScale = dWidthIniProp < dHeightIniProp ? dWidthIniProp : dHeightIniProp;
            m_nIniWidth = int(m_pGu->m_nImgWidth * m_dIniScale + 0.5);
            m_nIniHeight = int(m_pGu->m_nImgHeight * m_dIniScale + 0.5);

            if (m_dIniScale >= 1.0)
            {
                    //此时不需要缩放
                    m_dIniScale = 1.0;
                    m_nIniWidth = m_nImgWidth;
                    m_nIniHeight = m_nImgHeight;
            }

            //分块读取更高效
            const int nBlock = 1024;
            BYTE* pBlockBuffer = new BYTE[m_nImgWidth * m_nBandNum * m_nBPB * nBlock];
            memset(pBlockBuffer, 0, sizeof(BYTE)* m_nImgWidth * m_nBandNum * m_nBPB * nBlock);
            int nBPP = m_nBPB * m_nBandNum;

            //用于显示的金字塔
            m_pBufferPy = new BYTE[m_nIniWidth * m_nIniHeight * 3];
            memset(m_pBufferPy, 0, m_nIniWidth * m_nIniHeight * 3);
            int nRowBlockNum = (m_nImgHeight + nBlock - 1) / nBlock;
           
            if (m_nBPB == 2)
            {
                    //16位影像需要读取源数据,取得颜色查找表
                    unsigned char* pBufferPyOri = new BYTE[m_nIniWidth * m_nIniHeight * m_nBandNum * m_nBPB];
                    memset(pBufferPyOri, 0, m_nIniWidth * m_nIniHeight * m_nBandNum * m_nBPB);

                    for (int j = 0; j < nRowBlockNum; ++j)
                    {
                            memset(pBlockBuffer, 0, sizeof(BYTE)* m_nImgWidth * m_nBandNum * m_nBPB * nBlock);
                            m_pGu->ReadImg(0, j * nBlock, m_nImgWidth, j * nBlock + nBlock, pBlockBuffer,
                                    m_nImgWidth, nBlock, m_nBandNum, 0, 0, m_nImgWidth, nBlock, -1, 0);

                            for (int m = 0; m < m_nIniHeight; m++)
                            {
                                    int nSrcRows = int(m / m_dIniScale /*+ 0.5*/) - j * nBlock;
                                    if (nSrcRows >= nBlock || nSrcRows < 0)
                                    {
                                            continue;
                                    }
                                    BYTE *pBufferPyIndex = pBufferPyOri + m * m_nIniWidth * nBPP;
                                    BYTE *pBufferBlockIndex = pBlockBuffer + nSrcRows * m_nImgWidth * nBPP;
                                    for (int n = 0; n < m_nIniWidth; n++)
                                    {
                                            int nSrcCols = int(n / m_dIniScale /*+ 0.5*/);
                                            if (nSrcCols >= m_nImgWidth)
                                            {
                                                    continue;
                                            }
                                            BYTE *pSubBufferPyIndex = pBufferPyIndex + n * nBPP;
                                            BYTE *pSubBufferBlockIndex = pBufferBlockIndex + nSrcCols * nBPP;
                                            memcpy(pSubBufferPyIndex, pSubBufferBlockIndex, nBPP);
                                    }
                            }
                    }
                    //如果是16位影像
                    if (m_pHist)
                    {
                            delete[] m_pHist;
                            m_pHist = NULL;
                    }
                    m_pHist = new double[65536 * m_nBandNum];
                    memset(m_pHist, 0, sizeof(double) * 65536 * m_nBandNum);

                    for (int j = 0; j < m_nIniHeight; ++j)
                    {
                            unsigned short *pBufferIndex = (unsigned short*)pBufferPyOri + j * m_nIniWidth * m_nBandNum;
                            for (int i = 0; i < m_nIniWidth; ++i)
                            {
                                    unsigned short *pSubBufferIndex = pBufferIndex + i * m_nBandNum;
                                    for (int k = 0; k < m_nBandNum; ++k)
                                    {
                                            m_pHist[k * 65536 + pSubBufferIndex[k]] += 1.0;
                                    }
                            }
                    }

                    if (m_pClrLut)
                    {
                            delete[] m_pClrLut;
                            m_pClrLut = NULL;
                    }

                    m_pClrLut = new BYTE[m_nBandNum * 65536];
                    memset(m_pClrLut, 0, sizeof(BYTE) * 65536 * m_nBandNum);

                    if (m_plfCount)
                    {
                            delete[] m_plfCount;
                            m_plfCount = NULL;
                    }
                    m_plfCount = new double[10];
                    memset(m_plfCount, 0, sizeof(double) * 10);
                    for (int i = 0; i < m_nBandNum; i++)
                    {
                            for (int j = 1; j < 65536; j++)
                            {
                                    m_plfCount += m_pHist[i * 65536 + j];
                            }
                    }

                    double lfMinThreshold = 0.001, lfMaxThreshold = 0.001;

                    for (int i = 0; i < m_nBandNum; i++)
                    {
                            double lfTmpCount = 0.0001;
                            int nMinCut = 1, nMaxCut = 65535;
                            for (int j = 1; j < 65536; j++)
                            {
                                    lfTmpCount += m_pHist[i * 65536 + j];
                                    if (lfTmpCount / m_plfCount > lfMinThreshold)
                                    {
                                            nMinCut = j;
                                            break;
                                    }
                            }
                            int nMinValue = 0, nMaxValue = 0;
                            for (int j = 1; j < 65536; j++)
                            {
                                    if (m_pHist[i * 65536 + j] > 1e-3)
                                    {
                                            nMinValue = j;
                                            break;
                                    }
                            }
                            for (int j = 65534; j > 0; j--)
                            {
                                    if (m_pHist[i * 65536 + j] > 1e-3)
                                    {
                                            nMaxValue = j;
                                            break;
                                    }
                            }

                            lfTmpCount = 0.0001;
                            for (int j = 65534; j > 0; j--)
                            {
                                    lfTmpCount += m_pHist[i * 65536 + j];
                                    if (lfTmpCount / m_plfCount > lfMaxThreshold)
                                    {
                                            nMaxCut = j;
                                            break;
                                    }
                            }
                            for (int j = 1; j < nMinCut; j++)
                            {
                                    m_pClrLut[i * 65536 + j] = 1;
                            }
                            for (int j = nMinCut; j <= nMaxCut; j++)
                            {
                                    m_pClrLut[i * 65536 + j] = max(1, min(253, (int)(251.0 * ((double)j - nMinCut) / ((double)nMaxCut - nMinCut) + 2)));
                            }
                            for (int j = nMaxCut + 1; j < 65536; j++)
                            {
                                    m_pClrLut[i * 65536 + j] = 254;
                            }
                    }

                    //删除
                    delete[] pBufferPyOri;
                    pBufferPyOri = nullptr;
            }

            for (int j = 0; j < nRowBlockNum; ++j)
            {
                    int nReadHeight = min(nBlock, m_nImgHeight - nBlock * j);
                    memset(pBlockBuffer, 0, sizeof(BYTE)* m_nImgWidth * m_nBandNum * m_nBPB * nBlock);
                    m_pGu->ReadImg(0, j * nBlock, m_nImgWidth, j * nBlock + nReadHeight, pBlockBuffer, m_nImgWidth, nReadHeight, m_nBandNum, 0, 0, m_nImgWidth, nReadHeight, -1, 0);

                    //将当前读取的块,转换为RGB
                    int nDstLeft = 0;
                    int nDstTop = int(j * nBlock * m_dIniScale + 0.5);
                    int nDstRight = m_nIniWidth;
                    int nDstBottom = int((j * nBlock + nReadHeight) * m_dIniScale + 0.5);
                    ResampleArray2BGR(m_nImgWidth, nReadHeight, 0, 0, m_nImgWidth, nReadHeight, pBlockBuffer, m_nBandNum,
                            m_nIniWidth, m_nIniHeight, nDstLeft, nDstTop, nDstRight, nDstBottom, m_pBufferPy, 3);
            }

            delete[] pBlockBuffer;
            pBlockBuffer = nullptr;

            return 0;
    }

    bool CGDALShow::GetRealPixValue(int nCtrlX, int nCtrlY, std::vector<int>& vRealValues)
    {
            int nImgX = 0, nImgY = 0;

            //用GDALUser读取的时候,y是反的
            if (!GetImgCoors(nCtrlX, nCtrlY, nImgX, nImgY, true))
            {
                    return false;
            }

            vRealValues.clear();
            //读取当前行的数据,保留原始数据
            unsigned char* pData = new unsigned char[m_nBandNum * m_nBPB];
            m_pGu->ReadImage(nImgX, nImgY, 1, 1, pData);

            if (m_nBPB == 1)
            {
                    for (int i = 0; i < m_nBandNum; ++i)
                    {
                            vRealValues.push_back(pData);
                    }
            }
            else if (m_nBPB == 2)
            {
                    unsigned short* pSData = (unsigned short*)pData;
                    for (int i = 0; i < m_nBandNum; ++i)
                    {
                            vRealValues.push_back(pSData);
                    }
            }

            //如果是单通道,则需要复制结果
            if (m_nBandNum < 3)
            {
                    vRealValues.resize(3);
                    vRealValues[1] = vRealValues[0];
                    vRealValues[2] = vRealValues[0];
            }

            delete[] pData;
            pData = nullptr;

            return true;
    }

    bool CGDALShow:reReadFrontBufferDrag(LPVOID lpParameters)
    {
            mutexDragThread.Lock();
            CGDALShow* pGs = (CGDALShow*)lpParameters;

            //获取参数
            CGdalUser* pGu = pGs->m_pGu;
            unsigned char** ppBufferPy = &pGs->m_pBufferPy;
            unsigned char** ppFrontBuffer = &pGs->m_pFrontBuffer;
            unsigned char** ppFrontBufferDrag = &pGs->m_pFrontBufferDrag;
            unsigned char** ppFrontBufferDragThread = &pGs->m_pFrontBufferDragThread;
            const double& dScale = pGs->m_dScale;
            const double& dXoffset = pGs->m_dXoffset;
            const double& dYoffset = pGs->m_dYoffset;
            const double& dIniScale = pGs->m_dIniScale;
            const int& nDCWidth = pGs->m_nDCWidth;
            const int& nDCHeight = pGs->m_nDCHeight;
            const int& nBPB = pGs->m_nBPB;
            const int& nBandNum = pGs->m_nBandNum;
            const int& nIniWidth = pGs->m_nIniWidth;
            const int& nIniHeight = pGs->m_nIniHeight;
            const int& nX = pGs->m_nX;
            const int& nY = pGs->m_nY;
            const int& nShowWidth = pGs->m_nShowWidth;
            const int& nShowHeight = pGs->m_nShowHeight;

            if (pGu == nullptr && ppBufferPy == nullptr)
            {
                    return false;
            }

            //根据当前的比例和金字塔比例,决定从金字塔还是从影像直接读取数据
            int nBufferWidth = nDCWidth * MEM_ALLOC_X;
            int nBufferHeight = nDCHeight * MEM_ALLOC_Y;
            const int nBufferSize = nBufferWidth * nBufferHeight * 3;

            if (*ppFrontBufferDragThread != nullptr)
            {
                    delete[] *ppFrontBufferDragThread;
            }

            *ppFrontBufferDragThread = new unsigned char[nBufferSize];
            memset(*ppFrontBufferDragThread, m_nBgValue, nBufferSize);

            const int nBufferSizeOri = nBufferWidth * nBufferHeight * nBandNum * nBPB;
            BYTE* pFrontBufferDragOri = new BYTE[nBufferSizeOri];

            //将用于拖动的缓存刷成背景色
            memset(pFrontBufferDragOri, m_nBgValue, nBufferSizeOri);

            int nPosOffsetX = 0;
            int nPosOffsetY = 0;
            int nWidthOffset = 0;
            int nHeightOffset = 0;

            if (dIniScale < 1.0 && dScale > dIniScale)
            {
                    //此时需要从影像直接读取
                    int nSrcLeft = 0;
                    int nSrcTop = 0;
                    int nSrcRight = pGs->m_nImgWidth;
                    int nSrcBottom = pGs->m_nImgHeight;

                    int nDstLeft = 0;
                    int nDstTop = 0;
                    int nDstRight = nShowWidth;
                    int nDstBottom = nShowHeight;

                    if (nShowWidth > nBufferWidth || nShowHeight > nBufferHeight)
                    {
                            //此时需要读取的数据太多,用缓存读取部分数据即可
                            if (nDCWidth + nX < 0)
                            {
                                    //此时读取起点需要变更
                                    nSrcLeft = int(-(nDCWidth + nX) / dScale - 0.5);
                                    nPosOffsetX = -(nDCWidth + nX);
                                    nDstRight -= nPosOffsetX;
                            }

                            if (nDCHeight + nY < 0)
                            {
                                    nSrcTop = int(-(nDCHeight + nY) / dScale - 0.5);
                                    nPosOffsetY = -(nDCHeight + nY);
                                    nDstBottom -= nPosOffsetY;
                            }

                            if (nDstRight > nBufferWidth)
                            {
                                    nWidthOffset = nDstRight - nBufferWidth;
                                    nSrcRight = int(nSrcLeft + nBufferWidth / dScale /*+ 0.5*/);
                                    nDstRight = nBufferWidth;
                            }

                            if (nDstBottom > nBufferHeight)
                            {
                                    nHeightOffset = nDstBottom - nBufferHeight;
                                    nSrcBottom = int(nSrcTop + nBufferHeight / dScale /*+ 0.5*/);
                                    nDstBottom = nBufferHeight;
                            }
                    }

                    int nPosLeft = nDCWidth + nX + nPosOffsetX;
                    int nPosTop = nDCHeight + nY + nPosOffsetY;
                    int nPosRight = nPosLeft + nShowWidth - nPosOffsetX - nWidthOffset;
                    int nPosBottom = nPosTop + nShowHeight - nPosOffsetY - nHeightOffset;

                    //读取9倍区域到drag缓存中
                    HRESULT hRes = pGu->ReadImg(nSrcLeft, nSrcTop, nSrcRight, nSrcBottom, pFrontBufferDragOri,
                            nBufferWidth, nBufferHeight, nBandNum, nDstLeft, nDstTop, nDstRight, nDstBottom, -1, 0);
                    //偏移到指定的位置,可能越界(已经有越界处理)
                    pGs->ResampleArray2BGR(nBufferWidth, nBufferHeight, 0, 0, nDstRight, nDstBottom, pFrontBufferDragOri, nBandNum,
                            nBufferWidth, nBufferHeight, nPosLeft, nPosTop, nPosRight, nPosBottom, *ppFrontBufferDragThread, 3);
            }
            else
            {
                    //金字塔直接处理
                    int nPosLeft = nDCWidth + nX + nPosOffsetX;
                    int nPosTop = nDCHeight + nY + nPosOffsetY;
                    int nPosRight = nPosLeft + nShowWidth - nPosOffsetX - nWidthOffset;
                    int nPosBottom = nPosTop + nShowHeight - nPosOffsetY - nHeightOffset;
                    //偏移到指定的位置,可能越界(已经有越界处理)
                    pGs->ResampleArray(nIniWidth, nIniHeight, 0, 0, nIniWidth, nIniHeight, *ppBufferPy,
                            nBufferWidth, nBufferHeight, nPosLeft, nPosTop, nPosRight, nPosBottom, *ppFrontBufferDragThread);
            }

            mutexDrag.Lock();
            //这个量专门用于读写时候的拖拽
            if (*ppFrontBufferDrag != nullptr)
            {
                    delete[] * ppFrontBufferDrag;
            }
            *ppFrontBufferDrag = new unsigned char[nBufferSize];
            memcpy(*ppFrontBufferDrag, *ppFrontBufferDragThread, nBufferSize);
            mutexDrag.Unlock();

            mutexDragThread.Unlock();
            pGs->m_bDragDataReady = true;

            delete[] pFrontBufferDragOri;
            pFrontBufferDragOri = nullptr;

            return true;
    }

    int CGDALShow::GetPointerForDlgShow(CWnd* pCtrlWnd, CBitmap* pbmp, CDC* pmemDC, HBITMAP* phBmp, HBITMAP* phOldBmp)
    {
            //DC可能随着窗口的改变而改变
            m_pCtrlWnd = pCtrlWnd;
            m_pbmp = pbmp;
            m_pmemDC = pmemDC;
            m_phBmp = phBmp;
            m_phOldBmp = phOldBmp;

            return 0;
    }

    int CGDALShow::ResampleArray(int nSrcBufWidth, int nSrcBufHeight, int nSrcLeft, int nSrcTop, int nSrcRight, int nSrcBottom, unsigned char* pSrc,
            int nDstBufWidth, int nDstBufHeight, int nDstLeft, int nDstTop, int nDstRight, int nDstBottom, unsigned char* pDst)
    {
            if (pSrc == nullptr || pDst == nullptr)
            {
                    return -1;
            }

            //左上为小
            int nSrcWidth = nSrcRight - nSrcLeft;
            int nSrcHeight = nSrcBottom - nSrcTop;
            int nDstWidth = nDstRight - nDstLeft;
            int nDstHeight = nDstBottom - nDstTop;

            if (nSrcWidth < 0 || nSrcHeight < 0 || nDstWidth < 0 || nDstHeight < 0)
            {
                    return -1;
            }

            double dWidthProp = (double)nDstWidth / nSrcWidth;
            double dHeightProp = (double)nDstHeight / nSrcHeight;

            //如果源地址和目标地址一样
            unsigned char* pSrcBak(pSrc);
            if (pSrc == pDst)
            {
                    int nSrcMemSize = nSrcBufWidth * nSrcBufHeight * 3;
                    pSrcBak = new unsigned char[nSrcMemSize];
                    memcpy(pSrcBak, pSrc, nSrcMemSize);
                    memset(pSrc, m_nBgValue, nSrcMemSize);
            }

            //处理8位图像
            for (int j = 0; j < nDstHeight; ++j)
            {
                    int nyc = nDstTop + j;
                    int nyp = nSrcTop + int(j / dHeightProp/* + 0.5*/);
                    if (nyp >= AU_MAX(0, nSrcTop) && nyp < AU_MIN(nSrcBottom, nSrcBufHeight)
                            && nyc >= AU_MAX(0, nDstTop) && nyc < AU_MIN(nDstBottom, nDstBufHeight))
                    {
                            unsigned char* pBufferDst = pDst + (nyc * nDstBufWidth) * 3;
                            unsigned char* pBufferSrc = pSrcBak + (nyp * nSrcBufWidth) * 3;
                            for (int i = 0; i < nDstWidth; ++i)
                            {
                                    int nxc = nDstLeft + i;
                                    int nxp = nSrcLeft + int(i / dWidthProp/* + 0.5*/);
                                    if (nxp >= AU_MAX(0, nSrcLeft) && nxp < AU_MIN(nSrcRight, nSrcBufWidth)
                                            && nxc >= AU_MAX(0, nDstLeft) && nxc < AU_MIN(nDstRight, nDstBufWidth))
                                    {
                                            unsigned char* pSubBufferDst = pBufferDst + nxc * 3;
                                            unsigned char* pSubBufferSrc = pBufferSrc + nxp * 3;
                                            memcpy(pSubBufferDst, pSubBufferSrc, 3);
                                    }
                            }
                    }
            }

            if (pSrc == pDst && pSrcBak != nullptr)
            {
                    delete[] pSrcBak;
                    pSrcBak = nullptr;
            }

            return 0;
    }

    int CGDALShow::ResampleArray2BGR(int nSrcBufWidth, int nSrcBufHeight, int nSrcLeft, int nSrcTop, int nSrcRight, int nSrcBottom, unsigned char* pSrc, int nSrcBandNum,
            int nDstBufWidth, int nDstBufHeight, int nDstLeft, int nDstTop, int nDstRight, int nDstBottom, unsigned char* pDst, int nDstBandNum,
            int nSizeOfPointer /*= 1*/, int nSrcSkip /*= 0*/, int nDestSkip /*= 0*/)
    {
            if (pSrc == nullptr || pDst == nullptr || nDstBandNum < 3)
            {
                    //必须转成BGR
                    return -1;
            }

            //左上为小
            int nSrcWidth = nSrcRight - nSrcLeft;
            int nSrcHeight = nSrcBottom - nSrcTop;
            int nDstWidth = nDstRight - nDstLeft;
            int nDstHeight = nDstBottom - nDstTop;

            if (nSrcWidth < 0 || nSrcHeight < 0 || nDstWidth < 0 || nDstHeight < 0)
            {
                    return -1;
            }

            double dWidthProp = (double)nDstWidth / nSrcWidth;
            double dHeightProp = (double)nDstHeight / nSrcHeight;

            //如果源地址和目标地址一样
            unsigned char* pSrcBak(pSrc);
            if (pSrc == pDst)
            {
                    int nSrcMemSize = nSrcBufWidth * nSrcBufHeight * nSrcBandNum * nSizeOfPointer;
                    pSrcBak = new unsigned char[nSrcMemSize];
                    memcpy(pSrcBak, pSrc, nSrcMemSize);
                    memset(pSrc, m_nBgValue, nSrcMemSize);
            }

            //采样
            const int nBandNum = AU_MIN(nDstBandNum, nSrcBandNum);

            if (m_nBPB == 1)
            {
                    //处理8位图像
                    for (int j = 0; j < nDstHeight; ++j)
                    {
                            int nyc = nDstTop + j;
                            int nyp = nSrcTop + int(j / dHeightProp/* + 0.5*/);
                            if (nyp >= AU_MAX(0, nSrcTop) && nyp < AU_MIN(nSrcBottom, nSrcBufHeight)
                                    && nyc >= AU_MAX(0, nDstTop) && nyc < AU_MIN(nDstBottom, nDstBufHeight))
                            {
                                    unsigned char* pBufferDst = pDst + (nyc * nDstBufWidth) * nDstBandNum * nSizeOfPointer + nSrcSkip;
                                    unsigned char* pBufferSrc = pSrcBak + (nyp * nSrcBufWidth) * nSrcBandNum * nSizeOfPointer + nDestSkip;
                                    for (int i = 0; i < nDstWidth; ++i)
                                    {
                                            int nxc = nDstLeft + i;
                                            int nxp = nSrcLeft + int(i / dWidthProp/* + 0.5*/);
                                            if (nxp >= AU_MAX(0, nSrcLeft) && nxp < AU_MIN(nSrcRight, nSrcBufWidth)
                                                    && nxc >= AU_MAX(0, nDstLeft) && nxc < AU_MIN(nDstRight, nDstBufWidth))
                                            {
                                                    unsigned char* pSubBufferDst = pBufferDst + nxc * nDstBandNum * nSizeOfPointer;
                                                    unsigned char* pSubBufferSrc = pBufferSrc + nxp * nSrcBandNum * nSizeOfPointer;
                                                    if (nSrcBandNum == 1)
                                                    {
                                                            for (int k = 0; k < 3; ++k)
                                                            {
                                                                    memcpy(pSubBufferDst + k, pSubBufferSrc, nSizeOfPointer);
                                                            }
                                                    }
                                                    else if (nSrcBandNum >= 3)
                                                    {
                                                            for (int k = 0; k < 3; ++k)
                                                            {
                                                                    //bmp为BGR的顺序
                                                                    memcpy(pSubBufferDst + k, pSubBufferSrc + 2 - k, nSizeOfPointer);
                                                            }
                                                    }
                                            }
                                    }
                            }
                    }
            }
            else
            {
                    //处理16位图像
                    unsigned short* pBuffer = (unsigned short*)pSrcBak;
                    for (int j = 0; j < nDstHeight; ++j)
                    {
                            int nyc = nDstTop + j;
                            int nyp = nSrcTop + int(j / dHeightProp/* + 0.5*/);
                            if (nyp >= AU_MAX(0, nSrcTop) && nyp < AU_MIN(nSrcBottom, nSrcBufHeight)
                                    && nyc >= AU_MAX(0, nDstTop) && nyc < AU_MIN(nDstBottom, nDstBufHeight))
                            {
                                    unsigned char* pBufferDst = pDst + (nyc * nDstBufWidth) * nDstBandNum + nSrcSkip;
                                    unsigned short* pBufferSrc = pBuffer + (nyp * nSrcBufWidth) * nSrcBandNum + nDestSkip;
                                    for (int i = 0; i < nDstWidth; ++i)
                                    {
                                            int nxc = nDstLeft + i;
                                            int nxp = nSrcLeft + int(i / dWidthProp/* + 0.5*/);
                                            if (nxp >= AU_MAX(0, nSrcLeft) && nxp < AU_MIN(nSrcRight, nSrcBufWidth)
                                                    && nxc >= AU_MAX(0, nDstLeft) && nxc < AU_MIN(nDstRight, nDstBufWidth))
                                            {
                                                    unsigned char* pSubBufferDst = pBufferDst + nxc * nDstBandNum;
                                                    unsigned short* pSubBufferSrc = pBufferSrc + nxp * nSrcBandNum;
                                                    if (nSrcBandNum == 1)
                                                    {
                                                            for (int k = 0; k < 3; k++)
                                                            {
                                                                    pSubBufferDst[k] = m_pClrLut[pSubBufferSrc[0]];
                                                            }
                                                    }
                                                    else if (nSrcBandNum >= 3)
                                                    {
                                                            for (int k = 0; k < 3; k++)
                                                            {
                                                                    //bmp为BGR的顺序
                                                                    pSubBufferDst[k] = m_pClrLut[(2 - k) * 65536 + pSubBufferSrc[2 - k]];
                                                            }
                                                    }
                                            }
                                    }
                            }
                    }
            }

            if (pSrc == pDst && pSrcBak != nullptr)
            {
                    delete[] pSrcBak;
                    pSrcBak = nullptr;
            }

            return 0;
    }

    int CGDALShow::ThreadReadingData(BOOL bThread /*= TRUE*/)
    {
            m_bDragDataReady = false;

            if (bThread)
            {
                    AfxBeginThread(AFX_THREADPROC(PreReadFrontBufferDrag), this);
            }
            else
            {
                    PreReadFrontBufferDrag(this);
            }

            return 0;
    }

    //
    void CGDALShow::ResetOffset()
    {
            if (m_nDCWidth < 1 || m_nDCHeight < 1 || m_nImgWidth < 1 || m_nImgHeight < 1)
            {
                    return;
            }

            CRect rect;
            if (m_bIsDlg)
            {
                    m_pCtrlWnd->GetWindowRect(&rect);
            }
            else
            {
                    m_pWnd->GetWindowRect(&rect);
            }

            //计算比例
            double dWidthProp = (double)m_nDCWidth / m_nImgWidth;
            double dHeightProp = (double)m_nDCHeight / m_nImgHeight;
            m_dScale = min(dWidthProp, dHeightProp);
            m_dScale = min(1.0, m_dScale);

            double dNeedWidth = m_nImgWidth * m_dScale;
            double dNeedHeight = m_nImgHeight * m_dScale;
            //计算可能需要的偏移
            if (dNeedWidth < m_nDCWidth)
            {
                    //此时需要显示的图像比较小
                    m_pXstart = (m_nDCWidth - dNeedWidth) / 2;
            }

            if (dNeedHeight < m_nDCHeight)
            {
                    //此时需要显示的图像比较小
                    m_pYstart = (m_nDCHeight - dNeedHeight) / 2;
            }

            m_nX = int(m_pXstart + 0.5);
            m_nY = int(m_pYstart + 0.5);
            m_nShowWidth = int(m_nImgWidth*m_dScale + 0.5);
            m_nShowHeight = int(m_nImgHeight*m_dScale + 0.5);
    }

    void CGDALShow::ResetParameters()
    {
            m_bDragDataReady = false;
            m_bIsLBtnDown = false;
            m_bIsMBtnDown = false;
            m_bIsDlg = false;
            m_bUpdateScale = true;

            m_dIniScale = 1.0;
            m_dScaleLast = 1.0;

            m_nDCWidth = 0;
            m_nDCHeight = 0;
           
            m_pGu = nullptr;
            m_pHist = nullptr;
            m_plfCount = nullptr;
            m_pFrontBuffer = nullptr;
            m_pFrontBufferDrag = nullptr;
            m_pFrontBufferDragThread = nullptr;       
            m_pBufferPy = nullptr;
            m_pClrLut = nullptr;
            m_pWnd = nullptr;
            m_pMouDownPnt = POINT();

            m_dXoffset = 0.0;
            m_dYoffset = 0.0;
            m_pXoffset = 0.0;
            m_pYoffset = 0.0;
            m_pXstart = 0.0;
            m_pYstart = 0.0;

            m_nImgWidth = 0;
            m_nImgHeight = 0;
            m_nIniWidth = 0;
            m_nIniHeight = 0;
            m_nBandNum = 1;
            m_nBPB = 1;

            m_nX = 0;
            m_nY = 0;

            m_nShowWidth = 0;
            m_nShowHeight = 0;
            m_dScale = 1.0;

            m_pbmp = nullptr;
            m_pmemDC = nullptr;
            m_pCtrlWnd = nullptr;
            m_phBmp = nullptr;
            m_phOldBmp = nullptr;

            //static变量
            m_dMaxScale = 8.0;
            m_dMinScale = 0.01;
            m_dScaleStep = 120.0 / 0.125;
            m_dXoffset = 0.0;
            m_dYoffset = 0.0;
            m_nBgValue = 240;
    }

    void CGDALShow::ShowImage(BOOL bDirectDC /*= false*/)
    {
            //如果是对话框,需要做以下操作
            if (m_bIsDlg && m_pCtrlWnd && m_phBmp && m_pbmp)
            {
                    CRect rcPicture;
                    m_pCtrlWnd->GetWindowRect(rcPicture);
                    m_nDCWidth = rcPicture.Width();
                    m_nDCHeight = rcPicture.Height();

                    //宽度应为4的整数倍
                    m_nDCWidth = ((m_nDCWidth + 3) / 4) * 4;

                    if (*m_phBmp)
                    {
                            :eleteObject(*m_phBmp);
                            *m_phBmp = nullptr;
                    }

                    BITMAPINFO bmpInfo;
                    bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
                    bmpInfo.bmiHeader.biWidth = m_nDCWidth;
                    bmpInfo.bmiHeader.biHeight = m_nDCHeight;
                    bmpInfo.bmiHeader.biPlanes = 1;
                    bmpInfo.bmiHeader.biBitCount = 24;
                    bmpInfo.bmiHeader.biCompression = BI_RGB;
                    bmpInfo.bmiHeader.biSizeImage = 0;
                    bmpInfo.bmiHeader.biXPelsPerMeter = 0;
                    bmpInfo.bmiHeader.biYPelsPerMeter = 0;
                    bmpInfo.bmiHeader.biClrUsed = 0;
                    bmpInfo.bmiHeader.biClrImportant = 0;

                    *m_phBmp = CreateDIBSection(m_pmemDC->m_hDC, &bmpInfo, DIB_RGB_COLORS, (void **)&m_pFrontBuffer, NULL, 0);
                    *m_phOldBmp = (HBITMAP)::SelectObject(m_pmemDC->m_hDC, *m_phBmp);

                    m_pbmp->Detach();
                    m_pbmp->Attach(*m_phBmp);
            }

            //必须使用外部双缓存
            memset(m_pFrontBuffer, m_nBgValue, m_nDCWidth * m_nDCHeight * 3);
            if(m_bUpdateScale || !m_bDragDataReady)
            {
                    //线程正在读取数据的时候,读取金字塔
                    ResampleArray(m_nIniWidth, m_nIniHeight, 0, 0, m_nIniWidth, m_nIniHeight, m_pBufferPy, m_nDCWidth, m_nDCHeight,
                            m_nX, m_nY, m_nX + m_nShowWidth, m_nY + m_nShowHeight, m_pFrontBuffer);
            }
            else if (m_pFrontBufferDragThread)
            {
                    //显示部分影像时,将m_pFrontBufferDrag中间部分的内容平移到当前DC当中
                    int nBufferWidth = m_nDCWidth * MEM_ALLOC_X;
                    int nBufferHeight = m_nDCHeight * MEM_ALLOC_Y;

                    int nSrcLeft = int(m_nDCWidth - m_pXoffset - 0.5);
                    int nSrcTop = int(m_nDCHeight - m_pYoffset - 0.5);
                    int nSrcRight = nSrcLeft + m_nDCWidth;
                    int nSrcBottom = nSrcTop + m_nDCHeight;

                    int nDstLeft = 0;
                    int nDstTop = 0;
                    int nDstRight = m_nDCWidth;
                    int nDstBottom = m_nDCHeight;

                    mutexDrag.Lock();
                    for (int j = 0; j < m_nDCHeight; ++j)
                    {
                            unsigned char* pBufferDst = m_pFrontBuffer + (j * m_nDCWidth) * 3;
                            unsigned char* pBufferSrc = m_pFrontBufferDrag + ((nSrcTop + j) * nBufferWidth) * 3 + nSrcLeft * 3;
                            if (nSrcTop + j >= 0 && nSrcTop + j < nBufferHeight)
                            {
                                    int nCopyWidth = AU_MIN((nBufferWidth - nSrcLeft), m_nDCWidth);
                                    if (nCopyWidth > 0)
                                    {
                                            memcpy(pBufferDst, pBufferSrc, nCopyWidth * 3);
                                    }
                            }
                    }
                    mutexDrag.Unlock();
            }

            m_pWnd->Invalidate(FALSE);
    }

    bool CGDALShow::GetPixValue(int nCtrlX, int nCtrlY, std::vector<int>& values, bool bGetRealValue /*= false*/)
    {
            if (nCtrlX < 0 || nCtrlX >= m_nDCWidth || nCtrlY <= 0 || nCtrlY > m_nDCHeight)
            {
                    return false;
            }

            if (bGetRealValue)
            {
                    //获取真实的像素值
                    return GetRealPixValue(nCtrlX, nCtrlY, values);
            }

            //读取当前屏幕像素值
            nCtrlY = m_nDCHeight - nCtrlY;
            values.clear();
            int x1 = *(m_pFrontBuffer + (nCtrlY * m_nDCWidth + nCtrlX) * 3 + 0);
            int x2 = *(m_pFrontBuffer + (nCtrlY * m_nDCWidth + nCtrlX) * 3 + 1);
            int x3 = *(m_pFrontBuffer + (nCtrlY * m_nDCWidth + nCtrlX) * 3 + 2);

            //输出RGB
            values.push_back(x3);
            values.push_back(x2);
            values.push_back(x1);

            return true;
    }

    bool CGDALShow::GetImgCoors(int nCtrlX, int nCtrlY, int& nImgX, int& nImgY, bool bYReverse /*= false*/)
    {
            nImgX = int((nCtrlX - m_nX) / m_dScale);
            nImgY = int((nCtrlY - (m_nDCHeight - m_nShowHeight - m_nY)) / m_dScale);

            if (bYReverse)
            {
                    //从0开始到m_nImgHeight - 1
                    nImgY = m_nImgHeight - 1 - nImgY;
            }

            return nImgX >= 0 && nImgX < m_nImgWidth && nImgY >= 0 && nImgY < m_nImgHeight;
    }


    https://blog.csdn.net/autumoonch ... tm_term=OnMButtonUp
    回复


    http://www.mjgw.org/ 专业从事膜结构设计、制作加工、施工安装的膜结构工程服务,能够为客户提供专业的膜结构整体解决方案。做中国最好的膜结构综合服务平台。欢迎大家联系电话:198-7840-1958,QQ:463017170.
    相关关键词:膜结构车棚,膜结构车棚覆盖,膜结构车棚公司,膜结构车棚多少钱,膜结构车棚厂家,膜结构车棚价格,社区膜结构车棚,膜结构车棚膜布厂家 ,膜结构车棚哪家好,膜结构车棚多少钱一米,膜结构车棚报价,膜结构车棚哪里有,膜结构车棚定制,膜结构车棚安装,膜结构车棚设计,膜结构车棚电话,膜结构车棚加工,膜结构车棚膜布价格,膜结构车棚批发,膜结构车棚制造商,膜结构车棚生产厂家,膜结构车棚设计,膜结构车棚施工,膜结构车棚多少钱一平米,膜结构车棚订制,张拉膜车棚,张拉膜车棚覆盖,张拉膜车棚公司,张拉膜车棚多少钱,张拉膜车棚厂家,张拉膜车棚价格,社区张拉膜车棚,张拉膜车棚膜布厂家 ,张拉膜车棚哪家好,张拉膜车棚多少钱一米,张拉膜车棚报价,张拉膜车棚哪里有,张拉膜车棚定制,张拉膜车棚安装,张拉膜车棚设计,张拉膜车棚电话,张拉膜车棚加工,张拉膜车棚膜布价格,张拉膜车棚批发,张拉膜车棚制造商,张拉膜车棚生产厂家,张拉膜车棚设计,张拉膜车棚施工,张拉膜车棚多少钱一平米,张拉膜车棚订制,常用膜材品牌:德国杜肯、法国法拉利、德国海德斯、德国米乐、日本平岗、韩国秀博、比利时希运、美国赫虏伯、中国科宝、上海慧遥。

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    关闭

    推荐膜材品牌上一条 /6 下一条

    进口膜材 国产膜材 pvdf膜材ptfe膜材ETFE膜材
    最好的膜结构公司 一级膜结构资质 膜结构一级资质
    膜结构设计-膜结构十大品牌-etfe设计-充气膜结构
    诺科膜结构
    遨都膜结构设计
    中国膜结构网
    中国空间膜结构

    QQ|申请友链|手机版|中国膜结构论坛