⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 colorbuffer.cpp

📁 计算机图形学原理及算法教程(VC++版)程序代码
💻 CPP
字号:
/////////////////////////////////////////////////////////////////////////////////
//	
// ColorBuffer.cpp: implementation of the CColorBuffer class.
#include "stdafx.h"
#include "ColorBuffer.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CColorBuffer::CColorBuffer(int nWidth,  int nHeight)
{

	m_nWidth = (nWidth < 0) ? 0 : nWidth;
	m_nHeight = (nHeight < 0) ? 0 : nHeight;

	//申请全局内存(z-buffer的缺点)
	//并将颜色清成黑色
	m_pbyColor = new BYTE[m_nWidth * m_nHeight * 4];
	
	if(m_pbyColor == NULL)
	{
		AfxMessageBox("内存分配失败!");
		exit(1);
	}
	memset(m_pbyColor,  0,  m_nWidth * m_nHeight * 4);
 
}

CColorBuffer::~CColorBuffer()
{
	if(m_pbyColor)
	{
		delete[] m_pbyColor;
		m_pbyColor = NULL;
	}
}


//查询函数

//获取颜色缓冲区宽度
int CColorBuffer::GetWidth() const
{
	return m_nWidth;
}

//获取颜色缓冲区高度
int CColorBuffer::GetHeight() const
{
	return m_nHeight;
}

//获取颜色缓冲区指针
BYTE* CColorBuffer::GetColorPtr() const
{
	return m_pbyColor;
}

//设置背景颜色

//将指定的颜色设置为背景色
//单一颜色(r, g, b, a)
void CColorBuffer::SetBkColor(BYTE r,  BYTE g,  BYTE b,  BYTE a)
{
	//蓝, 绿, 红, alpha
	BYTE* pbyColor = m_pbyColor;
	for(int i = 0; i < m_nWidth; i++)
	{
		*pbyColor++ = b;
		*pbyColor++ = g;
		*pbyColor++ = r;
		*pbyColor++ = a;
	}

	//内存之间拷贝, 拷贝剩下的 (m_nHeight - 1)行.
	DWORD dwScanLength = 4 * (DWORD)m_nWidth;
	for(i = 1; i < m_nHeight; i++)
	{
		//指向一行开始的位置
		pbyColor = m_pbyColor + (i * dwScanLength);
		//从第一行拷贝至第 i 行:
		memcpy(pbyColor,  m_pbyColor,  dwScanLength);
	}
}

//设置为一个指定的背景图像
//使用时的警告:图像必须与颜色缓冲区尺寸完全相同!
void CColorBuffer::SetBkImage(const BYTE* pbyImage,  int nWidth,  int nHeight)
{
	ASSERT(pbyImage);
	if((nWidth != m_nWidth) || (nHeight != m_nHeight))
	{
		::AfxMessageBox("图像尺寸与颜色缓冲区大小不匹配");
		return;
	}

	::CopyMemory(m_pbyColor,  pbyImage,  m_nWidth * m_nHeight * 4);
}


//设置一个点的颜色
//这是z-buffer算法关于颜色缓冲区的主要操作
void CColorBuffer::SetPixel(int x,  int y,  float r,  float g,  float b , float a)
{
	if((x < 0) || (y < 0) || (x >= m_nWidth) || (y >= m_nHeight))return;

	DWORD dwIndex = y * m_nWidth * 4 + 4 * x;

	BYTE byRed = (BYTE)(r * 255.0f);
	BYTE byGreen = (BYTE)(g * 255.0f);
	BYTE byBlue = (BYTE)(b * 255.0f);
	BYTE byAlpha = (BYTE)(a * 255.0f);
	BYTE* pbyColor = (m_pbyColor + dwIndex);
	*pbyColor++ = byBlue;
	*pbyColor++ = byGreen;
	*pbyColor++ = byRed;
	*pbyColor++ = byAlpha;
}


void CColorBuffer::SetPixel(int x,  int y,  BYTE r,  BYTE g,  BYTE b ,  BYTE a)
{
	if((x < 0) || (y < 0) || (x >= m_nWidth) || (y >= m_nHeight))return;

	DWORD dwIndex = y * m_nWidth * 4 + 4 * x;

	BYTE* pbyColor = m_pbyColor + dwIndex;

	//蓝、绿、红、Alpha
	*pbyColor++ = b;
	*pbyColor++ = g;
	*pbyColor++ = r;
	*pbyColor++ = a;
} 

//获取颜色
PIXELCOLORRGBA CColorBuffer::GetPixel(int x,  int y) const
{
	PIXELCOLORRGBA rgba = {0,  0,  0,  0};
	
	if((x < 0) || (y < 0) || (x >= m_nWidth) || (y >= m_nHeight))
		return rgba;

	DWORD dwIndex = y * m_nWidth * 4 + 4 * x;

	BYTE* pbyColor = m_pbyColor + dwIndex;

	
	//蓝、绿、红、Alpha
	rgba.blue = *pbyColor++;
	rgba.green = *pbyColor++;
	rgba.red = *pbyColor++;
	rgba.alpha = *pbyColor++;
	return rgba;
}

//由颜色缓冲区中的数据直接创建一个DDB对象, 即HBITMAP对象
HBITMAP CColorBuffer::CreateDdb(HDC hDC)
{
	// 创建一个BITMAPV4HEADER结构

	//分配内存:
	BYTE* pbyBits = new BYTE[sizeof(BITMAPV4HEADER)];
	if(pbyBits == NULL) return NULL;
	//指向像素数据的指针, 
	BITMAPV4HEADER* pbmih = (BITMAPV4HEADER*)pbyBits;
	
	pbmih->bV4Size = sizeof(BITMAPV4HEADER);	//108
	pbmih->bV4Width = (LONG)m_nWidth;
	pbmih->bV4Height = (LONG)(-m_nHeight);
	pbmih->bV4Planes = 1;
	pbmih->bV4BitCount = 32;

    pbmih->bV4V4Compression = BI_RGB;    
	pbmih->bV4SizeImage = 0;
	pbmih->bV4XPelsPerMeter = 0;    
	pbmih->bV4YPelsPerMeter = 0;
	pbmih->bV4ClrUsed = 0;    
	pbmih->bV4ClrImportant = 0;
 
	//第二步, 创建一个DDB
	HBITMAP hBitmap = ::CreateDIBitmap(hDC, (BITMAPINFOHEADER*)pbmih, CBM_INIT, m_pbyColor, (BITMAPINFO*)pbmih, DIB_RGB_COLORS);

	delete[] pbyBits;
	return hBitmap;
}

//将颜色缓冲区的内容交换到前台(即输出颜色缓冲区)
void CColorBuffer::SwapBuffer(CDC* pDC)
{
	CDC memDC;
	memDC.CreateCompatibleDC(pDC);
	HBITMAP hBitmap = CreateDdb(pDC->m_hDC);
	HBITMAP hOldBitmap = (HBITMAP)memDC.SelectObject(hBitmap);
	pDC->BitBlt(0, 0, m_nWidth, m_nHeight, &memDC, 0, 0, SRCCOPY);
	::DeleteObject(hBitmap);
	memDC.SelectObject(hOldBitmap);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -