Click here to Skip to main content
15,896,912 members
Articles / Multimedia / Image Processing

Oil Paint Effect: Implementation of Oil Painting Effect on an Image

Rate me:
Please Sign up or sign in to vote.
4.89/5 (41 votes)
20 Oct 2012CPOL8 min read 116.2K   5.3K   68  
Applying oil painting effect on an image.
// PaintEffectDlg.cpp : implementation file
//

#include "stdafx.h"
#include "PaintEffect.h"
#include "PaintEffectDlg.h"
#include "BMPLoader.h"
#include "PaintEffectImpl.h"
#include "GLSetup.h"
#include "GLTexture.h"
#include "GLVertexBuffer.h"
#include "gdiplus.h"
#include "GdiplusImaging.h"
#include "Gdipluspixelformats.h"
#include "math.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPaintEffectDlg dialog

CPaintEffectDlg::CPaintEffectDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CPaintEffectDlg::IDD, pParent)
    , m_bPaintingEffect(FALSE)
    , m_bOpenGLDisplay(FALSE)
{
	//{{AFX_DATA_INIT(CPaintEffectDlg)
	m_nIntensity = 0;
	m_nRadius = 0;
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	m_pbyEffectAppliedData = 0;
	m_pbyImageInputData = 0;
    m_pImageTexture = 0;
}

CPaintEffectDlg::~CPaintEffectDlg()
{
    // Release all resources on exit.
    Gdiplus::GdiplusShutdown( m_gdiplusToken );
    if( m_pVertexBuffer )
    {
        delete m_pVertexBuffer;
        m_pVertexBuffer = 0;
    }

    if( m_pImageTexture )
    {
        delete m_pImageTexture;
        m_pImageTexture = 0;
    }

    if( m_pbyEffectAppliedData )
    {
        delete[] m_pbyEffectAppliedData;
        m_pbyEffectAppliedData = 0;
    }

    if( m_pbyImageInputData )
    {
        delete[] m_pbyImageInputData;
        m_pbyImageInputData = 0;
    }

    if( m_pGLSetup )
    {
        delete m_pGLSetup;
        m_pGLSetup = 0;
    }
}

void CPaintEffectDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CPaintEffectDlg)
    DDX_Text(pDX, IDC_EDIT_INTENSITY, m_nIntensity);
    DDV_MinMaxInt(pDX, m_nIntensity, 0, 1000);
    DDX_Text(pDX, IDC_EDIT_RADIUS, m_nRadius);
    DDV_MinMaxInt(pDX, m_nRadius, 0, 100);
    //}}AFX_DATA_MAP
    DDX_Check(pDX, IDC_CHECK_PAINTING_EFFECT, m_bPaintingEffect);
    DDX_Check(pDX, IDC_CHECK_OPENGL_DISPLAY, m_bOpenGLDisplay);
    DDX_Control(pDX, IDC_SLIDER_RADIUS, m_SliderRadius);
    DDX_Control(pDX, IDC_SLIDER_INTENSITY, m_SliderIntensity);
}

BEGIN_MESSAGE_MAP(CPaintEffectDlg, CDialog)
	//{{AFX_MSG_MAP(CPaintEffectDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON_LOAD_BITMAP, OnButtonLoadBitmap)
	//}}AFX_MSG_MAP
    ON_EN_CHANGE(IDC_EDIT_RADIUS, CPaintEffectDlg::OnEnChangeEditRadius)
    ON_EN_CHANGE(IDC_EDIT_INTENSITY, CPaintEffectDlg::OnEnChangeEditIntensity)
    ON_WM_SIZE()
    ON_BN_CLICKED(IDC_BUTTON_SAVE, CPaintEffectDlg::OnBnClickedButtonSave)
    ON_BN_CLICKED(IDC_BUTTON_ABOUT, CPaintEffectDlg::OnBnClickedButtonAbout)
    ON_BN_CLICKED(IDC_CHECK_PAINTING_EFFECT, CPaintEffectDlg::OnBnClickedCheckPaintingEffect)
    ON_BN_CLICKED(IDC_CHECK_OPENGL_DISPLAY, CPaintEffectDlg::OnBnClickedCheckOpenglDisplay)
    ON_WM_HSCROLL()
//    ON_WM_ERASEBKGND()
//    ON_WM_SETFOCUS()
//    ON_WM_ACTIVATE()
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPaintEffectDlg message handlers

BOOL CPaintEffectDlg::OnInitDialog()
{
    // Initialization of GDI+ library.
    // GDI+ is used for loading images of different file format.
    Gdiplus::GdiplusStartupInput gdiplusStartupInput;
    Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);

	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
    // OpenGL is initialised to enable OpenGL display.
    // Texture image is not prepared here.
    // If OpenGL display is enabled, then texture will be loaded and drawn.
    m_pGLSetup = new GLSetup();
    if( !m_pGLSetup->InitGL( GetDlgItem( IDC_STATIC_IMAGE )->m_hWnd ))
    {
        AfxMessageBox( L"OpenGL initialisation failed." );
        GetDlgItem( IDC_CHECK_OPENGL_DISPLAY )->EnableWindow( false );
    }
    // Vertex buffer created for displaying Quad image with Texture mapping.
    m_pVertexBuffer = new GLVertexBuffer();
    m_pVertexBuffer->CreateQuadVertexBuffer();

    // Update UI with default values.
    m_nRadius = 4;
    m_nIntensity = 20;
    m_bPaintingEffect = true;
    // OpenGL is disabled because some machine maynot support big sized textures.
    m_bOpenGLDisplay = false;
    UpdateData( false );


    // Initial dialog displayed with controls in proper position.
    // 690 and 440 is required to display default image properly.
    RECT rect;
    GetClientRect( &rect );
    m_nOldDlgWidth = rect.right;

    // For Center display.
    RECT DesktopRegon;
    GetDesktopWindow()->GetClientRect( &DesktopRegon );
    // SetWindowPos is called for proper display of initial bitmap.
    int nLeft = DesktopRegon.right / 2 - 690 / 2;
    int nTop = DesktopRegon.bottom / 2 - 440 / 2;
    SetWindowPos( 0, nLeft, nTop, 690, 440, SWP_SHOWWINDOW );

    // Load initial image from Resource.
    BMPLoader imageloader;
    if( imageloader.LoadBMP( IDB_BITMAP_AUTUMN, m_nImageWidth, m_nImageHeight, m_pbyImageInputData ))
    {
        int nBytesInARow = ceil( m_nImageWidth * 3 / 4.0 ) * 4.0;
        // Allocate image for effect applied data.
        m_pbyEffectAppliedData = new BYTE[ nBytesInARow * m_nImageHeight ];

        // Applying effect on startup.
        ProcessEffect();
    }

    m_SliderRadius.SetRange( 0, 10 );
    m_SliderRadius.SetPos( m_nRadius );

    m_SliderIntensity.SetRange( 0, 50 );
    m_SliderIntensity.SetPos( m_nIntensity / 5 );

    return TRUE;  // return TRUE  unless you set the focus to a control
}

void CPaintEffectDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
        // if( ( nID & 0xFFF0 ) == SC_MINIMIZE )
        {
            TRACE( "Minim Identified" );
            GetDlgItem( IDC_SLIDER_INTENSITY )->InvalidateRect( 0 );
        }
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CPaintEffectDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);

        TRACE( L"Iconic\n" );

        GetDlgItem( IDC_STATIC_IMAGE )->InvalidateRect( 0 );
	}
	else
	{
        TRACE( L"Paint\n" );
        CDialog::OnPaint();
        if( m_bOpenGLDisplay )
        {
            // Drawing with OpenGL.
            // Output image from texture is mapped to screen.
            DrawWithOpenGL();
        }
        else
        {
            // Drawing with GDI.
            // Output image from Bitmap object is mapped to screen.
            DrawWithGDI();
        }
        GetDlgItem( IDC_STATIC_STATUS )->SetWindowText(L"");

        // After drawing to dc, dc is set as drawn.
        GetDlgItem( IDC_STATIC_IMAGE )->ValidateRect( 0 );
    }
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CPaintEffectDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CPaintEffectDlg::OnButtonLoadBitmap() 
{
    // Create a file open Dialog for opening .bmp file.
    CFileDialog* pFileOpenDlg = new CFileDialog( TRUE,L"image", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
                                                 L"Input Image (*.bmp;*.jpg;*.png;*.tga)|*.bmp;*.jpg;*.png;*.tga||");
    if( IDOK == pFileOpenDlg->DoModal())
    {
        CString csFileName = pFileOpenDlg->GetPathName();
        int nWidth = 0;
        int nHeight = 0;
        BYTE* pbyData = 0;
        BMPLoader BMPLoaderObj;
        if( !BMPLoaderObj.LoadBMP( csFileName.GetBuffer( 0 ), nWidth, nHeight, pbyData ))
        {
            AfxMessageBox( L"BMP Loading failed" );
            return;
        }
        if( 0 == pbyData )
        {
            AfxMessageBox( L"Memory Allocation failed." );
            return;
        }
        if( m_pbyImageInputData )
        {
            delete[] m_pbyImageInputData;
            m_pbyImageInputData = 0;
        }
        if( m_pbyEffectAppliedData )
        {
            delete[] m_pbyEffectAppliedData;
            m_pbyEffectAppliedData = 0;
        }

        // Change data to new data.
        m_pbyImageInputData = pbyData;
        m_nImageWidth = nWidth;
        m_nImageHeight = nHeight;
        // Prepare buffer to hold ouput data.
        int nBytesInARow = ceil( m_nImageWidth * 3 / 4.0 ) * 4.0;
        m_pbyEffectAppliedData = new BYTE[nBytesInARow * m_nImageHeight];

        ProcessEffect();

        Invalidate( false );
    }
    delete pFileOpenDlg;
}

/*
 This function is called when a parameter changing, or loading a new image.
 */
void CPaintEffectDlg::ProcessEffect()
{
    if( m_pbyImageInputData && m_pbyEffectAppliedData )
    {
        if( m_bPaintingEffect )
        {
            // A static window is used to inform the user, processing of oil paint effect 
            // is going on.. Processing Effect...
            GetDlgItem( IDC_STATIC_STATUS )->SetWindowText( L"Processing Effect..." );
            PaintEffect EffectProcessor;
            EffectProcessor.Process( m_pbyImageInputData, m_nRadius, m_nIntensity,
                                     m_nImageWidth, m_nImageHeight, m_pbyEffectAppliedData );

            // After processing the effect, Processing finished is set.
            // This text will be removed on next on paint.
            GetDlgItem( IDC_STATIC_STATUS )->SetWindowText( L"Processing Finished..." );
        }
        else
        {
            // On disable oil painting effect, source image is copied to output image.
            int nBytesInARow = ceil( m_nImageWidth * 3 / 4.0 ) * 4.0;
            memcpy( m_pbyEffectAppliedData, m_pbyImageInputData, nBytesInARow * m_nImageHeight );
        }

        // Changed data is copied to Bitmap or OpenGL texture.
        BITMAPINFO stBitmapInfo;
        stBitmapInfo.bmiHeader.biClrImportant = 0;
        stBitmapInfo.bmiHeader.biClrUsed = 0;
        stBitmapInfo.bmiHeader.biCompression = 0;
        stBitmapInfo.bmiHeader.biPlanes = 1;
        stBitmapInfo.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
        stBitmapInfo.bmiHeader.biXPelsPerMeter = 0;
        stBitmapInfo.bmiHeader.biYPelsPerMeter = 0;
        stBitmapInfo.bmiHeader.biBitCount = 3 * 8;
        stBitmapInfo.bmiHeader.biSizeImage = m_nImageWidth * m_nImageHeight;
        stBitmapInfo.bmiHeader.biHeight = m_nImageHeight;
        stBitmapInfo.bmiHeader.biWidth = m_nImageWidth;
        stBitmapInfo.bmiColors[0].rgbBlue = 0x0;
        stBitmapInfo.bmiColors[0].rgbGreen = 0x0;
        stBitmapInfo.bmiColors[0].rgbRed = 0x0;
        stBitmapInfo.bmiColors[0].rgbReserved = 0x0;

        HDC hdc = ::GetDC(NULL);

        HBITMAP hbmDest = ::CreateCompatibleBitmap(hdc, m_nImageWidth, m_nImageHeight);

        if (hbmDest)
        {
            if (SetDIBits(hdc, hbmDest, 0, m_nImageHeight, m_pbyEffectAppliedData, &stBitmapInfo, DIB_RGB_COLORS))
            {
                m_BitmapObject.DeleteObject();
                m_BitmapObject.Attach( hbmDest );
            }
        }

        // If OpenGL is enabled, copying processed data to opengl texture.
        if( m_bOpenGLDisplay && m_pImageTexture )
        {
            delete m_pImageTexture;
            m_pImageTexture = new GLTexture();
            m_pImageTexture->Create( m_nImageWidth, m_nImageHeight, m_pbyEffectAppliedData );
        }
    }
}

/*
    OnSize() handles repositioning of all controls on resizing the dialog.
    The size of parameters and button are kept same on all redrawing.
    The size of image drawing static window is changed on resize of main dialog.
 */
void CPaintEffectDlg::OnSize(UINT nType, int cx, int cy)
{
    CDialog::OnSize(nType, cx, cy);

    // Finding left position of Image display static window.
    RECT rcOldRegon;
    if(GetDlgItem( IDC_STATIC_IMAGE ))
    {
        GetDlgItem( IDC_STATIC_IMAGE )->GetClientRect( &rcOldRegon );
    }
    else
    {
        return;
    }
    RECT rcScreenRect = rcOldRegon;
    if( GetDlgItem( IDC_STATIC_IMAGE ))
    {
        GetDlgItem( IDC_STATIC_IMAGE )->ClientToScreen( &rcScreenRect );
    }
    POINT LeftTopPos;

    RECT rcWindowRelativePos = rcScreenRect;
    ScreenToClient( &rcWindowRelativePos );

    int nParameterWindowWidth = 0;
    RECT parameterWindowRgn;
    if( GetDlgItem( IDC_STATIC_PARAM ))
    {
        GetDlgItem( IDC_STATIC_PARAM )->GetClientRect( &parameterWindowRgn );
    }
    nParameterWindowWidth = parameterWindowRgn.right;

    // Find new position of Image area.
    RECT rcNewImagePos = rcWindowRelativePos; // Left and top will be same 
    rcNewImagePos.bottom = cy - rcWindowRelativePos.top; // Keep same space in top and bottom.
    rcNewImagePos.right = cx - nParameterWindowWidth - 20;

    int nImageWidth = rcNewImagePos.right - rcNewImagePos.left + 1;
    int nImageHeight = rcNewImagePos.bottom - rcNewImagePos.top + 1;

    // Change size of Image Area.
    if( GetDlgItem( IDC_STATIC_IMAGE ))
    {
        GetDlgItem( IDC_STATIC_IMAGE )->SetWindowPos( 0, rcNewImagePos.left, rcNewImagePos.top,
                                                  nImageWidth, nImageHeight, SWP_NOREDRAW );
    }

    // Change position of parameters window.

    int nParamWindowMoveX = cx - m_nOldDlgWidth;
    m_nOldDlgWidth = cx;

    // All windows other than image display window is moved in X direction.
    MoveWindowInXDirection( IDC_EDIT_RADIUS, nParamWindowMoveX );
    MoveWindowInXDirection( IDC_STATIC_RADIUS, nParamWindowMoveX );
    MoveWindowInXDirection( IDC_EDIT_INTENSITY, nParamWindowMoveX );
    MoveWindowInXDirection( IDC_STATIC_INTENSITY, nParamWindowMoveX );
    MoveWindowInXDirection( IDC_STATIC_PARAM, nParamWindowMoveX );
    MoveWindowInXDirection( IDC_STATIC_PARAM_2, nParamWindowMoveX );
    MoveWindowInXDirection( IDC_BUTTON_LOAD_BITMAP, nParamWindowMoveX );
    MoveWindowInXDirection( IDC_BUTTON_SAVE, nParamWindowMoveX );
    MoveWindowInXDirection( IDC_BUTTON_ABOUT, nParamWindowMoveX );
    MoveWindowInXDirection( IDC_CHECK_PAINTING_EFFECT, nParamWindowMoveX );
    MoveWindowInXDirection( IDC_STATIC_STATUS, nParamWindowMoveX );
    MoveWindowInXDirection( IDC_CHECK_OPENGL_DISPLAY, nParamWindowMoveX );
    MoveWindowInXDirection( IDC_SLIDER_RADIUS, nParamWindowMoveX );
    MoveWindowInXDirection( IDC_SLIDER_INTENSITY, nParamWindowMoveX );


    // Change opengl view port.
    glViewport( 0, 0, nImageWidth, nImageHeight );

    // Request redraw of the window.
    Invalidate( true );
}

/*
This function is responsible to move a window with in X direction.
nDistance_i indicates the number of pixels to move in X direction.
 */
void CPaintEffectDlg::MoveWindowInXDirection( const int nControlID_i, const int nDistance_i )
{
    RECT oldRect;
    // Get current region.
    if( GetDlgItem( nControlID_i ) )
    {
        GetDlgItem( nControlID_i )->GetWindowRect( &oldRect );
    }
    ScreenToClient( &oldRect );

    // Add offset to current region. 
    oldRect.left += nDistance_i;
    oldRect.right += nDistance_i;

    // Change position of window with new region.
    if( GetDlgItem( nControlID_i ) )
    {
        GetDlgItem( nControlID_i )->SetWindowPos( 0, oldRect.left, oldRect.top,
                                              oldRect.right - oldRect.left,
                                              oldRect.bottom - oldRect.top, SWP_NOREDRAW );
    }

}

// To save the processed image.
void CPaintEffectDlg::OnBnClickedButtonSave()
{
    // Construct file name. Radius and Intensity parameters are added in the deafult file name.
    CString csFileName;
    csFileName.Format( L"OilPaintEffect_radius%d_Intensity%d.bmp",m_nRadius, m_nIntensity );
    CFileDialog SaveDlg( false, L"*.bmp", csFileName );
    if( IDOK == SaveDlg.DoModal())
    {
        CString csFileName = SaveDlg.GetPathName();
        BMPLoader SaveBmp;
        SaveBmp.SaveBMP( csFileName, m_nImageWidth, m_nImageHeight, m_pbyEffectAppliedData );
    }
}

// About button handler.
void CPaintEffectDlg::OnBnClickedButtonAbout()
{
    CAboutDlg aboutDlg;
    aboutDlg.DoModal();
}

// Handling Radius parameter change.
void CPaintEffectDlg::OnEnChangeEditRadius()
{
    // Handle changes in GUI.
    HandleGUIChanges();
}

// Handling Intensity parameter change.
void CPaintEffectDlg::OnEnChangeEditIntensity()
{
    // Handle changes in GUI.
    HandleGUIChanges();
}

// Handling Painting Effect enable or disable.
void CPaintEffectDlg::OnBnClickedCheckPaintingEffect()
{
    // Handle changes in GUI.
    HandleGUIChanges();
}

/*
 Function called on changing any gui parameter by user.
 Here retrieves new parameter from GUI and proecsses effect,
 and request repainting the image.
 */
void CPaintEffectDlg::HandleGUIChanges()
{
    // Get data from UI.
    UpdateData( true );

    ProcessEffect();
    Invalidate( false );
}

/*
 Function draws bitmap object to screen.
 */
void CPaintEffectDlg::DrawWithGDI()
{
    // Use GDI method to draw the bitmap to screen.
    // CDC* pDC = GetDlgItem( IDC_STATIC_IMAGE )->GetDC();

    CPaintDC dc(GetDlgItem( IDC_STATIC_IMAGE ));
    CDC* pDC = &dc;

    if (m_BitmapObject.GetSafeHandle())
    {
        CDC dcMem;

        if (dcMem.CreateCompatibleDC(pDC))
        {
            CBitmap* pOldBM = dcMem.SelectObject(&m_BitmapObject);
            BITMAP BM;

            m_BitmapObject.GetBitmap(&BM);

            RECT ClientRegion;
            GetDlgItem( IDC_STATIC_IMAGE )->GetClientRect( &ClientRegion );

            // StretchBlt is used to resize the actual image to region of static window.
            pDC->StretchBlt( 0, 0, ClientRegion.right, ClientRegion.bottom,
                             &dcMem, 0, 0, m_nImageWidth, m_nImageHeight, SRCCOPY );

            dcMem.SelectObject(pOldBM);
            
        }
        GetDlgItem( IDC_STATIC_IMAGE )->ReleaseDC( pDC );
    }
    else
    {
        TRACE( "FAILED" );
    }
}

void CPaintEffectDlg::DrawWithOpenGL()
{
    // Use OpenGL method to draw the bitmap to screen.
    glClearColor( 0.0, 0.0, 0.0, 0.0 );
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    // OPenGL drawing, Enable the texture,
    // draw vertex buffer and swap the buffer to screen..
    if( m_pVertexBuffer && m_pGLSetup && m_pImageTexture )
    {
        m_pImageTexture->Enable();
        m_pVertexBuffer->DrawVertexBuffer( GL_QUADS );
        m_pGLSetup->Draw();
    }
}

/*
 This function handles openGL disply enable and disable.
 On enabling openGL display, new texture is created in image size.
 On disabling previous openGL texture is deleted.
 */
void CPaintEffectDlg::OnBnClickedCheckOpenglDisplay()
{
    m_bOpenGLDisplay = !m_bOpenGLDisplay;
    if( m_bOpenGLDisplay )
    {
        if( m_pImageTexture )
        {
            delete m_pImageTexture;
            m_pImageTexture = 0;
        }
        // Create OpenGL resources.
        m_pImageTexture = new GLTexture();
        m_pImageTexture->Create( m_nImageWidth, m_nImageHeight,
                                 m_pbyEffectAppliedData );
    }
    else
    {
        if( m_pImageTexture )
        {
            // Delete opengl resources.
            delete m_pImageTexture;
            m_pImageTexture = 0;
        }
    }

    // Request repainting...
    Invalidate( false );
}

void CPaintEffectDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{

    if( nSBCode == SB_THUMBPOSITION )
    {
        if( pScrollBar->m_hWnd == GetDlgItem( IDC_SLIDER_INTENSITY )->m_hWnd )
        {
            m_nIntensity = nPos * 5;
            UpdateData( false );
            HandleGUIChanges();
            m_SliderIntensity.SetPos( nPos );
        }
        else
        {
            m_nRadius = nPos;
            UpdateData( false );
            HandleGUIChanges();
            m_SliderRadius.SetPos( nPos );
        }
    }
    else
    {
        CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions