C++ Ondraw函数在vc++;用ImageMagick

C++ Ondraw函数在vc++;用ImageMagick,c++,visual-c++,image-processing,mfc,imagemagick,C++,Visual C++,Image Processing,Mfc,Imagemagick,现在我试图在MFC的对话框中显示视图中的图像 代码如下所示 void CTestview::OnDraw(CDC* pDC) { CDocument* pDoc = GetDocument(); // TODO: add draw code here CRect rcWin; GetWindowRect( &rcWin ); double ff; ff=rcWin.Width(); rcWin.Height(); DoDisplayImage(); } #pragma once

现在我试图在MFC的对话框中显示视图中的图像

代码如下所示

void CTestview::OnDraw(CDC* pDC)
{
CDocument* pDoc = GetDocument();
// TODO: add draw code here

CRect rcWin;
GetWindowRect( &rcWin );
double ff;
ff=rcWin.Width();
rcWin.Height();

DoDisplayImage(); 
}
#pragma once
#include <Magick++.h>


// CTestview view

class CTestview : public CScrollView
{
    DECLARE_DYNCREATE(CTestview)

protected:
    CTestview();           // protected constructor used by dynamic creation
    virtual ~CTestview();

public:
#ifdef _DEBUG
    virtual void AssertValid() const;
#ifndef _WIN32_WCE
    virtual void Dump(CDumpContext& dc) const;
#endif
#endif

protected:
    virtual void OnDraw(CDC* pDC);      // overridden to draw this view
    virtual void OnInitialUpdate();     // first time after construct

    DECLARE_MESSAGE_MAP()
public:
    void DoDisplayImage(void);
    Image m_image


};
------ Build started: Project: mfc_test5, Configuration: Release Win32 ------
Build started 
PrepareForBuild:
  Creating directory "C:\work\mfc_test5\mfc_test5\Release\".
InitializeBuildStatus:
  Creating "Release\mfc_test5.unsuccessfulbuild" because "AlwaysCreate" was specified.
ClCompile:
  stdafx.cpp
  mfc_test5.cpp
c:\program files\imagemagick-6.8.6-q8\include\magick/pixel-accessor.h(160): warning C4244: '=' : conversion from 'double' to 'MagickCore::MagickRealType', possible loss of data
c:\work\mfc_test5\mfc_test5\mfc_test5\Testview.h(33): error C2143: syntax error : missing ';' before '}'
  mfc_test5Dlg.cpp
c:\program files\imagemagick-6.8.6-q8\include\magick/pixel-accessor.h(160): warning C4244: '=' : conversion from 'double' to 'MagickCore::MagickRealType', possible loss of data
c:\work\mfc_test5\mfc_test5\mfc_test5\Testview.h(33): error C2143: syntax error : missing ';' before '}'
C:\Program Files\Intel\plsuite\include\ipl.h(778): warning C4819: The file contains a character that cannot be represented in the current code page (949). Save the file in Unicode format to prevent data loss
C:\Program Files\Intel\plsuite\examples\Tutorial.IPL\IPLROOMS\COOKROOM\macros.inc(21): warning C4005: '_ASSERTE' : macro redefinition
          C:\Program Files\Microsoft Visual Studio 10.0\VC\include\crtdbg.h(213) : see previous definition of '_ASSERTE'

Build FAILED.

Time Elapsed 00:00:37.30
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

问题是,当我将图像显示到视图中时,显示图像有太多的延迟。 我不知道该怎么解决这个问题

更新1 我已经更新代码如下

void CTestview::OnDraw(CDC* pDC)
{
CDocument* pDoc = GetDocument();
// TODO: add draw code here

CRect rcWin;
GetWindowRect( &rcWin );
double ff;
ff=rcWin.Width();
rcWin.Height();

DoDisplayImage(); 
}
#pragma once
#include <Magick++.h>


// CTestview view

class CTestview : public CScrollView
{
    DECLARE_DYNCREATE(CTestview)

protected:
    CTestview();           // protected constructor used by dynamic creation
    virtual ~CTestview();

public:
#ifdef _DEBUG
    virtual void AssertValid() const;
#ifndef _WIN32_WCE
    virtual void Dump(CDumpContext& dc) const;
#endif
#endif

protected:
    virtual void OnDraw(CDC* pDC);      // overridden to draw this view
    virtual void OnInitialUpdate();     // first time after construct

    DECLARE_MESSAGE_MAP()
public:
    void DoDisplayImage(void);
    Image m_image


};
------ Build started: Project: mfc_test5, Configuration: Release Win32 ------
Build started 
PrepareForBuild:
  Creating directory "C:\work\mfc_test5\mfc_test5\Release\".
InitializeBuildStatus:
  Creating "Release\mfc_test5.unsuccessfulbuild" because "AlwaysCreate" was specified.
ClCompile:
  stdafx.cpp
  mfc_test5.cpp
c:\program files\imagemagick-6.8.6-q8\include\magick/pixel-accessor.h(160): warning C4244: '=' : conversion from 'double' to 'MagickCore::MagickRealType', possible loss of data
c:\work\mfc_test5\mfc_test5\mfc_test5\Testview.h(33): error C2143: syntax error : missing ';' before '}'
  mfc_test5Dlg.cpp
c:\program files\imagemagick-6.8.6-q8\include\magick/pixel-accessor.h(160): warning C4244: '=' : conversion from 'double' to 'MagickCore::MagickRealType', possible loss of data
c:\work\mfc_test5\mfc_test5\mfc_test5\Testview.h(33): error C2143: syntax error : missing ';' before '}'
C:\Program Files\Intel\plsuite\include\ipl.h(778): warning C4819: The file contains a character that cannot be represented in the current code page (949). Save the file in Unicode format to prevent data loss
C:\Program Files\Intel\plsuite\examples\Tutorial.IPL\IPLROOMS\COOKROOM\macros.inc(21): warning C4005: '_ASSERTE' : macro redefinition
          C:\Program Files\Microsoft Visual Studio 10.0\VC\include\crtdbg.h(213) : see previous definition of '_ASSERTE'

Build FAILED.

Time Elapsed 00:00:37.30
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
我发现了一些参考代码,如下所示

它怎么能这样用呢

// NtMagickView.h : interface of the CNtMagickView class
//
/////////////////////////////////////////////////////////////////////////////

#if !defined(AFX_NTMAGICKVIEW_H__8A45000C_6176_11D4_AC4F_400070168026__INCLUDED_)
#define AFX_NTMAGICKVIEW_H__8A45000C_6176_11D4_AC4F_400070168026__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#define NTMAGICK_DEFEXT                "*.JPG;*.JPEG"
#define NTMAGICK_ALL                   "All Files (*.*)|*.*|"
#define NTMAGICK_BMP                   "Bitmaps (*.BMP;*.RLE)|*.BMP;*.RLE|"
#define NTMAGICK_GIF                   "GIF (*.GIF)|*.GIF|"
#define NTMAGICK_TIF                   "TIF (*.TIF;*.TIFF)|*.TIF;*.TIFF|"
#define NTMAGICK_JPEG                  "JPEG (*.JPG;*.JPEG)|*.JPG;*.JPEG|"
#define NTMAGICK_ICON                  "Icons (*.ICO)|*.ICO|"

class CNtMagickView : public CView
{
protected: // create from serialization only
        CNtMagickView();
        DECLARE_DYNCREATE(CNtMagickView)

// Attributes
public:
        CString       m_szFile;
        Image       * m_pImage;
        CNtMagickDoc* GetDocument();
        void          DoDisplayError(CString szFunction, CString szCause);
        void          DoDisplayImage();
        BOOL          DoReadImage();
        CSize         Scale(CSize sizeSrc, CSize sizeTgt);
        float         ScaleFactor(BOOL bAllowZoom, CSize sizeSrc, CSize sizeTgt);
        void          UpdateUI(CCmdUI* pCmdUI);

// Operations
public:

// Overrides
        // ClassWizard generated virtual function overrides
        //{{AFX_VIRTUAL(CNtMagickView)
        public:
        virtual void OnDraw(CDC* pDC);  // overridden to draw this view
        virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
        protected:
        //}}AFX_VIRTUAL

// Implementation
public:
        virtual ~CNtMagickView();
#ifdef _DEBUG
        virtual void AssertValid() const;
        virtual void Dump(CDumpContext& dc) const;
#endif

protected:

// Generated message map functions
protected:
        //{{AFX_MSG(CNtMagickView)
        afx_msg void OnFileOpen();
        afx_msg void OnImageFlipHorizontal();
        afx_msg void OnUpdateImageFlipHorizontal(CCmdUI* pCmdUI);
        afx_msg void OnImageFlipVertical();
        afx_msg void OnUpdateImageFlipVertical(CCmdUI* pCmdUI);
        afx_msg void OnImageRotate180();
        afx_msg void OnUpdateImageRotate180(CCmdUI* pCmdUI);
        afx_msg void OnImageRotate90();
        afx_msg void OnUpdateImageRotate90(CCmdUI* pCmdUI);
        afx_msg void OnImageRotate90ccw();
        afx_msg void OnUpdateImageRotate90ccw(CCmdUI* pCmdUI);
    afx_msg void OnFileClear();
    afx_msg void OnUpdateFileClear(CCmdUI* pCmdUI);
    //}}AFX_MSG
        DECLARE_MESSAGE_MAP()
};

#ifndef _DEBUG  // debug version in NtMagickView.cpp
inline CNtMagickDoc* CNtMagickView::GetDocument()
   { return (CNtMagickDoc*)m_pDocument; }
#endif

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_NTMAGICKVIEW_H__8A45000C_6176_11D4_AC4F_400070168026__INCLUDED_)
更新2 我编辑过如下内容,但它从未被称为。是这样吗?它什么时候调用这个函数

void CTestview::OnInitialUpdate()
{
    CScrollView::OnInitialUpdate();

    CSize sizeTotal;
    // TODO: calculate the total size of this view
    sizeTotal.cx = sizeTotal.cy = 100;
    SetScrollSizes(MM_TEXT, sizeTotal);

    m_pimage.read(fileposition);
}

您不应该直接在TestView的DC上绘制,而是创建一个兼容的内存DC,在那里进行所有绘制,然后将内存DC的内容复制到视图的DC上。因为它快多了

为此,您可以将函数更改为从OnDraw调用以接收作为内存DC的参数,并禁止您在任何地方执行GetDC(),除非创建内存DC并将其内容复制回视图DC

你的头发应该是这样的

void CTestview::OnDraw(CDC* pDC)
{
CDocument* pDoc = GetDocument();
// TODO: add draw code here

CDC draw_dc;
CBitmap draw_bitmap;
CBitmap* old_bitmap;

CRect draw_area;
pDC->GetClipBox(draw_area);

draw_dc.CreateCompatibleDC(pDC);
draw_bitmap.CreateCompatibleBitmap(pDC, draw_area.Width(), draw_area.Height());
old_bitmap = (CBitmap*)draw_dc.SelectObject(&draw_bitmap);

OnPrepareDC(&draw_dc, NULL);

pDC->LPtoDP(draw_area);
draw_dc.OffsetViewportOrg(-draw_area.left, -draw_area.top);
pDC->DPtoLP(draw_area);
draw_dc.IntersectClipRect(draw_area);

DoDisplayImage(&draw_dc);

pDC->BitBlt(draw_area.left, draw_area.top, draw_area.Width(), draw_area.Height(), &draw_dc, 0, 0, SRCCOPY);

draw_dc.SelectObject(old_bitmap);
DeleteObject(draw_bitmap);
DeleteDC(draw_dc);  
}
您可能已经注意到有一些剪辑代码;它使绘制速度更快,因为它不会在不需要绘制的地方绘制。最重要的部分是
draw_dc.CreateCompatibleDC(pDC)创建内存DC;以及
pDC->BitBlt(…,srcopy)将内容从内存复制到视图

旁注:我删除了你上面的台词,因为它们对我来说毫无用处

现在,您的
DoDisplayImage
函数应该是:

void CTestview::DoDisplayImage(CDC* pDC)
{
    CPoint pt;
    CRect rectClient;

    GetClientRect(rectClient);


    int ii;
    ii=slider_val;
    (void) MagickCore::SetClientPath(fileposition);
    InitializeMagick(fileposition);
    Image m_Image;
    Image m_blurgray;
    int _imageHeight;

    try {
        //C:\work\mfc_test5\mfc_test5
        m_Image.read(fileposition);

    }
    catch(Exception)
    {
    return ;
    }


    char str_x[10];
    char str_y[10];
    if (pDC != NULL)
    {
        m_blurgray.gaussianBlur(20,2); //blur


        int   nImageY;
        int   nImageX;
        CSize sizeScaled;

        // Clear the background
        pDC->FillSolidRect(rectClient,pDC->GetBkColor());


        pt = rectClient.TopLeft();
        nImageX= m_Image.columns() ;
        //nImageY = m_Image.rows();
        CPoint aa;
        aa = rectClient.Size();

        // Extract the pixels from Magick++ image object
        PixelPacket *pPixels = m_Image.getPixels(0,0,m_Image.columns(),m_Image.rows());


        // Set up the Windows bitmap header
        BITMAPINFOHEADER bmi;
        bmi.biSize = sizeof(BITMAPINFOHEADER);
        bmi.biWidth =m_Image.columns();

        bmi.biHeight =  (-1)*m_Image.rows();
        bmi.biPlanes = 1;
        bmi.biBitCount = 32;
        bmi.biCompression = BI_RGB;
        bmi.biSizeImage = 0;
        bmi.biXPelsPerMeter = 0;
        bmi.biYPelsPerMeter = 0;
        bmi.biClrUsed = 0;
        bmi.biClrImportant = 0;

        // Blast it to the device context

        SetStretchBltMode(pDC->m_hDC,COLORONCOLOR);

        StretchDIBits(pDC->m_hDC,
            0,
            0,
            m_Image.columns(),
            m_Image.rows(),
            0,
            0,
            m_Image.columns(),
            m_Image.rows(),
            pPixels,
            (BITMAPINFO *)&bmi,
            DIB_RGB_COLORS,
            SRCCOPY);
        //UpdateData(FALSE);
    }
}

旁注:这里似乎也有一些无用的代码,即带有aa和ii变量的部分。

您是否尝试过使用计时器检测代码,以查看花费了多少时间?你的档案有多大?更新需要多长时间?是否可以在程序开始时而不是每次图形刷新前仅初始化一次ImageMagick?这是一个20像素的高斯模糊吗?这肯定会很慢。试着暂时删除它。@MarkSetchell在OnDraw()中作为显示方法的那种方法怎么样?我有什么需要改变的地方吗?很小的一点,但ff是用来做什么的,为什么它是双倍的?正确::Width()返回int.@Colin谢谢让我知道,我会尝试修复。但我认为它对显示延迟图像没有任何影响。对吗?为什么每次调用
OnDraw
时都要从磁盘读取图像文件?