Ondraw函数在使用ImageMagick的vc ++中有很多延迟

时间:2015-11-25 14:30:38

标签: 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(); 
}

void CTestview::DoDisplayImage(void)
{

    CPoint pt;
    CRect rectClient;
    CDC * pDC;

    pDC = GetDC();
    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);
    }
}

问题是当我将图像显示到视图中时,显示图像有很多延迟。 我不知道应该怎样做才能解决这个问题。

更新1

我已将代码更新如下。

#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 ==========

我找到了一些参考代码如下所示。您可以看到,以下代码使用Image m_image。

它怎么能这样使用?

// 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);
}

1 个答案:

答案 0 :(得分:0)

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

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

你的OnDraw应该是

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);  
}

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

旁注:我删除了上面的行,因为它们对我来说似乎毫无用处。

现在您的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变量的部分。