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

📄 csbitmap.cpp

📁 游戏编程精华02-含有几十个游戏编程例子
💻 CPP
字号:
#include "priv_precompiled.h"

/*
Copyright 2001 Bruce Dawson, Cygnus Software
For more information, visit http://www.cygnus-software.com/papers/
or e-mail: comments@cygnus-software.com

This code may be redistributed as long as this notice is kept intact.
*/

#define	WIN32_LEAN_AND_MEAN
#include <windows.h>	// If we include windows it has to be before csbitmap.h
//Needed for SelectBitmap, etc.
#include <windowsx.h>

#include "csbitmap.h"

#define	RENAME_WINDOWS_STRUCTS
#include "bmpdefs.h"
CompileTimeAssert(sizeof(BITMAPINFOHEADER) == sizeof(PortableBITMAPINFOHEADER));
CompileTimeAssert(sizeof(BITMAPFILEHEADER) == sizeof(PortableBITMAPFILEHEADER));

static void DisplayError(long LastError, const char *ErrorText /*= 0*/)
{
	char	ErrorBuffer[1000];
	if (ErrorText)
		sprintf(ErrorBuffer, "%s\nError code is %d.", ErrorText, LastError);
	else
		sprintf(ErrorBuffer, "Error code %d encountered.", LastError);
	MessageBox(0, ErrorBuffer, "Message", MB_OK);
}

static void DisplayLastError(const char *ErrorText /*= 0*/)
{
	DisplayError(GetLastError(), ErrorText);
}


CSBitmap::CSBitmap()
{
	mWidth = mHeight = mChannels = -1;
	mSurfaceBits = 0;
	mBitmapNew = 0;
	mBitmapDC = 0;
	mBitmapMonochrome = 0;
}

CSBitmap::~CSBitmap()
{
	FreeBitmap();
}

void CSBitmap::FreeBitmap()
{
	if (mBitmapDC)
	{
		if (mBitmapMonochrome)
		{
			// Select the stock 1x1 monochrome bitmap back in
			HBITMAP hBitmapOld = SelectBitmap(mBitmapDC, mBitmapMonochrome);
			assert(hBitmapOld == mBitmapNew);
		}
		if (mBitmapNew)
			verify(DeleteObject(mBitmapNew));
		if (mBitmapDC)
			verify(DeleteDC(mBitmapDC));
		// Mark the bitmap as unallocated.
		mBitmapDC = 0;
		mWidth = mHeight = mChannels = -1;
	}
}

HDC CSBitmap::GetDrawSurface() const
{
	assert(HasBitmap());
	return mBitmapDC;
}

HBITMAP CSBitmap::GetDrawBitmap() const
{
	assert(HasBitmap());
	return mBitmapNew;
}

// Theoretically we should be paying attention to this:
// From the CreateDIBSection help:
// Windows NT: You need to guarantee that the GDI subsystem has completed any
// drawing to a bitmap created by CreateDIBSection before you draw to the
// bitmap yourself. Access to the bitmap must be synchronized. Do this by
// calling the GdiFlush function. This applies to any use of the pointer
// to the bitmap抯 bit values, including passing the pointer in calls to
// functions such as SetDIBits. 
uint8_t *CSBitmap::GetLinePtr(int y) const
{
	assert(HasBitmap());
	assert(y >= 0 && y < mHeight);
	return mLineZeroPointer + y * mStride;
}

uint8_t *CSBitmap::GetPixelPtr(int x, int y) const
{
	assert(HasBitmap());
	assert(y >= 0 && y < mHeight);
	assert(x >= 0 && x < mWidth);
	return GetLinePtr(y) + x * mChannels;
}

void CSBitmap::InitDerivedData()
{
	// Here is where we have to calculate the actual number of bytes per line,
	// respecting the Win32 rules for bitmap allocations. When we requested
	// the bitmap we specified a width, which Windows will have padded to
	// a multiple of four bytes - so we'd better allow for that.
	mBytesPerLine = (mWidth * mChannels + 3) & ~3;
	// Calculate the address of line zero - defined here as the line that is
	// at the top when the bitmap is copied to the screen. This is the last
	// line in memory.
	mLineZeroPointer = mSurfaceBits + (mHeight - 1) * mBytesPerLine;
	// Calculate the distance from line to line to be consistent with
	// mLineZeroPointer.
	mStride = -mBytesPerLine;
}

void CSBitmap::SetPalette(int StartColor, int NumColors, RGBQUAD* pColors)
{
	assert(HasBitmap());
	assert(GetChannels() == 1);
	SetDIBColorTable(GetDrawSurface(), StartColor, NumColors, pColors);
}

bool CSBitmap::GetPalette(int StartColor, int NumColors, RGBQUAD* pColors) const
{
	int GotCount;
	assert(HasBitmap());
	assert(GetChannels() == 1);
	// Zero the destination array to make sure all bytes get cleared.
	memset(pColors, 0, sizeof(RGBQUAD) * NumColors);
	GotCount = GetDIBColorTable(GetDrawSurface(), StartColor, NumColors, pColors);
	return GotCount == NumColors;
}

struct DIBData
{
	BITMAPINFOHEADER InfoHeader;
	RGBQUAD ColorTable[256];
};

bool CSBitmap::SetSize(int width, int height, int channels)
{
	// Make sure that the InitBitmap() function was called before calling
	// SetSize() for the first time.
	assert(HasBitmap() || mWidth == -1);
	assert(HasBitmap() || mHeight == -1);
	assert(HasBitmap() || mChannels == -1);
	// This function doesn't support allocating zero size or negative
	// size bitmaps.
	assert(width > 0);
	assert(height > 0);
	assert(channels == 1 || channels == 3 || channels == 4);
	FreeBitmap();
	mWidth = width;
	mHeight = height;
	mChannels = channels;

	// Set up an optimal bitmap
	DIBData	Info = {0};
	Info.InfoHeader.biSize = sizeof(BITMAPINFOHEADER);
	Info.InfoHeader.biWidth = width;
	Info.InfoHeader.biHeight = height;
	Info.InfoHeader.biPlanes = 1;
	Info.InfoHeader.biBitCount = channels * 8;
	Info.InfoHeader.biCompression = BI_RGB;
	// Support for 256 colour bitmaps.
	Info.InfoHeader.biClrUsed = (channels == 1 ? 256 : 0);

	HDC TempDC = CreateDC("Display", 0, 0, 0);
	if (TempDC)
	{
		mBitmapNew = CreateDIBSection(TempDC, (BITMAPINFO *)&Info, DIB_RGB_COLORS,
						(void **)&mSurfaceBits, 0, 0L);
		if (mBitmapNew)
		{
			mBitmapDC = CreateCompatibleDC(TempDC);
			if (mBitmapDC)
				mBitmapMonochrome = SelectBitmap(mBitmapDC, mBitmapNew);
			else
				DisplayLastError("SelectBitmap failed.");
		}
		else
			DisplayLastError("CreateDIBSection failed.");
		DeleteDC(TempDC);
	}
	else
		DisplayLastError("CreateDC failed.");

	// If the allocation failed, clean up.
	if (!mBitmapMonochrome)
		FreeBitmap();

	InitDerivedData();
	return HasBitmap();
}

void CSBitmap::StretchDraw(HDC DestDC, int destx, int desty, int destwidth, int destheight,
									int sourcex, int sourcey, int sourcewidth, int sourceheight) const
{
	if (HasBitmap())
	{
		StretchBlt(DestDC, destx, desty, destwidth, destheight, GetDrawSurface(),
					sourcex, sourcey, sourcewidth, sourceheight, SRCCOPY);
	}
}

void CSBitmap::Draw(HDC DestDC, int destx, int desty, int destwidth, int destheight, int sourcex, int sourcey) const
{
	if (HasBitmap())
	{
		StretchBlt(DestDC, destx, desty, destwidth, destheight, GetDrawSurface(),
					sourcex, sourcey, destwidth, destheight, SRCCOPY);
	}
}

void CSBitmap::DrawAll(HDC DestDC) const
{
	Draw(DestDC, 0, 0, GetWidth(), GetHeight(), 0, 0);
}

void CSBitmap::Swap(CSBitmap& otherBitmap)
{
	std::swap(mWidth, otherBitmap.mWidth);
	std::swap(mHeight, otherBitmap.mHeight);
	std::swap(mChannels, otherBitmap.mChannels);
	std::swap(mBitmapDC, otherBitmap.mBitmapDC);
	std::swap(mSurfaceBits, otherBitmap.mSurfaceBits);
	std::swap(mBitmapNew, otherBitmap.mBitmapNew);
	std::swap(mBitmapMonochrome, otherBitmap.mBitmapMonochrome);

	InitDerivedData();
	otherBitmap.InitDerivedData();
}

⌨️ 快捷键说明

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