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