Click here to Skip to main content
15,886,110 members
Articles / Desktop Programming / ATL

2D Water Effect in WTL

Rate me:
Please Sign up or sign in to vote.
4.66/5 (22 votes)
28 Apr 2011CPOL4 min read 144.1K   3.7K   55  
A WTL control class to add water effect to an image, like what's done in the TortoiseSVN About dialog
// TortoiseSVN - a Windows shell extension for easy version control

// Copyright (C) 2003-2006 - Stefan Kueng

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//

// refactored by Tan, Zhi(tomgee) 4/28/2011


#include "stdafx.h"
#include "Renderer.h"

#include <atlimage.h>

#include "cimage_pixel_access_opt.h"

// FOR BPP=32, Each DWORD in the bitmap array represents the relative intensities of blue, green, and red, respectively, for a pixel.
COLORREF ConvertToBPP32(COLORREF clr)
{
	return RGB(GetBValue(clr), GetGValue(clr), GetRValue(clr));
}

CRenderer::~CRenderer()
{
    DeleteObject();
}

void CRenderer::DeleteObject()
{
	// release memory allocated by CreateDIBSection()
    if (m_bmp)    ::DeleteObject(m_bmp);
    m_bmp = NULL;
    m_buffer_source = NULL;
}

void CRenderer::create_buffers(const CDC& dc)
{
	// create source buffer to hold initial background image
    m_bmp_info.bmiHeader.biSize          = sizeof(BITMAPINFOHEADER);
    m_bmp_info.bmiHeader.biWidth         = m_width;		// The width of the bitmap, in pixels.
    m_bmp_info.bmiHeader.biHeight        = m_height;	// The height of the bitmap, in pixels.If positive, the bitmap is a bottom-up DIB, If negative, then top-down DIB
    m_bmp_info.bmiHeader.biPlanes        = 1;			// This value must be set to 1
    m_bmp_info.bmiHeader.biBitCount      = 32;			// maximum of 2^32 colors
    m_bmp_info.bmiHeader.biCompression   = BI_RGB;		// An uncompressed format.
    m_bmp_info.bmiHeader.biSizeImage     = 0;			// set to zero for BI_RGB bitmaps
    m_bmp_info.bmiHeader.biXPelsPerMeter = 0;			// don't care, not to be used by CreateDIBSection()
    m_bmp_info.bmiHeader.biYPelsPerMeter = 0;			// don't care, not to be used by CreateDIBSection() 
    m_bmp_info.bmiHeader.biClrUsed       = 0;			// uses the maximum number of colors corresponding to the value of the biBitCount member for the compression mode specified by biCompression
    m_bmp_info.bmiHeader.biClrImportant  = 0;			// all colors are required.
	
	// Create a 32 bit bitmap
	m_bmp = CreateDIBSection(
			dc, 
			&m_bmp_info, 
			DIB_RGB_COLORS,		// The BITMAPINFO structure contains an array of literal RGB values.
			&m_buffer_source,	// A pointer to a variable that receives a pointer to the location of the DIB bit values
			NULL,				// the system allocates memory for the DIB
			0					// don't care
		);
    GdiFlush();


	// create target buffer to hold processed image and to be rendered from
	m_buffer_target.reset(m_height * m_width);  
}

void CRenderer::fill_buffers(const CImage& img)
{
	// Copy background picture into the 32 bit dib pointed to by m_buffer_source & m_buffer_target.
	//  upside down,  and reverse rgbs.
	DWORD* pAr		=	(DWORD*)m_buffer_source;

	CImagePixelAccessOptimizer p(&img);
	for(int row = 0; row < m_height; row++)
	{	
		for(int col = 0; col < m_width; col++)
		{
			size_t index = row * m_width + col;
			pAr[index] = ConvertToBPP32(/*img*/p.GetPixel(col, row ));			
			m_buffer_target[index] = ConvertToBPP32(/*img*/p.GetPixel(col, row ));			
		}
	}
}

void CRenderer::init (const CImage& img, const CDC& dc)
{
	// init dimensions
	m_width = img.GetWidth();
	m_height= img.GetHeight();

	// init buffers
	create_buffers(dc);
	fill_buffers(img);
}

BOOL CRenderer::Draw(const CPoint& ptDest, CDC& dc) 
{ 
    if (!m_bmp) return FALSE;

    CPoint ScanOrigin(0,0);

	// To reduce the amount of memory required to set bits from a large DIB on a device surface, 
	// an application can band the output by repeatedly calling SetDIBitsToDevice, 
	// placing a different portion of the bitmap into the lpvBits array each time. 
	// The values of the uStartScan and cScanLines parameters identify the portion of 
	// the bitmap contained in the lpvBits array.
    BOOL result = SetDIBitsToDevice(dc, 
                                ptDest.x, ptDest.y,			// upper-left corner of the destination rectangle,
                                m_width, m_height,			// The width & height of the image
                                ScanOrigin.x, ScanOrigin.y,	// lower-left corner of the image
                                ScanOrigin.y,				// The starting scan line in the image
								m_height - ScanOrigin.y,	// The number of DIB scan lines pointed to by the m_buffer_target
                                m_buffer_target, 
								&m_bmp_info, 
                                DIB_RGB_COLORS	// Indicates whether the m_bmp_info.bmiColors contains explicit red, green, blue (RGB) values
								); 

    return result;
}


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
Team Leader
China China
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions