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

📄 compositebitmap.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.
*/

#include "csbitmap.h"

// See the header file for a full description of how this function
// behaves.
void CompositeBitmap(CSBitmap* Bottom, const CSBitmap* Top, int startX, int startY, uint8_t globalOpacity /* = 255*/)
{
	assert(Bottom);
	assert(Top);
	assert(Bottom->HasBitmap());
	assert(Top->HasBitmap());

	// If this is zero then there is nothing to do - our top bitmap will be
	// completely transparent.
	if (globalOpacity == 0)
		return;
	int topChannels = Top->GetChannels();
	int bottomChannels = Bottom->GetChannels();

	// Setup coordinates to specify our starting location on the top and
	// bottom bitmap, and the composite size, so that we can adjust these
	// as we do our clipping.
	int bottomStartX = startX;
	int bottomStartY = startY;
	int topStartX = 0;
	int topStartY = 0;
	int compWidth = Top->GetWidth();
	int compHeight = Top->GetHeight();
	// Check for being off the left edge of the Bottom bitmap.
	if (bottomStartX < 0)
	{
		// Shift over our Top and Bottom x coordinates as needed, and
		// adjust our width.
		topStartX = -bottomStartX;	// Shrink the width.
		compWidth += bottomStartX;
		bottomStartX = 0;
	}
	// Check for being off the top edge of the Bottom bitmap.
	if (bottomStartY < 0)
	{
		// Shift over our Top and Bottom t coordinates as needed, and
		// adjust our height.
		topStartY = -bottomStartY;
		compHeight += bottomStartY;	// Shrink the height.
		bottomStartY = 0;
	}

	// Check for being off the right edge of the Bottom bitmap.
	if (bottomStartX + compWidth > Bottom->GetWidth())
		compWidth = Bottom->GetWidth() - bottomStartX;
	// Check for being off the bottom edge of the Bottom bitmap.
	if (bottomStartY + compHeight > Bottom->GetHeight())
		compHeight = Bottom->GetHeight() - bottomStartY;

	RGBQUAD	palette[256];	// Needed for compositing from an eight bit bitmap.
	// Get the palette outside of the loops.
	if (topChannels == 1)
		Top->GetPalette(0, 256, palette);
	// We need to check for compWidth being zero because the memcpy()
	// optimization below will fail otherwise.
	if (compWidth <= 0)
		return;
	// compHeight may be negative or zero at this point. That's OK.
	// If it is, the loop will run zero times.
	for (int y = 0; y < compHeight; y++)
	{
		uint8_t* pSourceLine = Top->GetPixelPtr(topStartX, y + topStartY);
		uint8_t* pDestLine = Bottom->GetPixelPtr(bottomStartX, y + bottomStartY);
		if (topChannels == 1)
		{
			// Simple optimization - avoid the globalOpacity multiplications if
			// they aren't needed.
			if (globalOpacity == 255)
			{
				// Simple 8-bit case with no globalOpacity support.
				for (int x = 0; x < compWidth; x++)
				{
					// Get the appropriate palette entry for this pixel.
					RGBQUAD	SourcePixel = palette[pSourceLine[0]];
					// And copy it to the destination.
					pDestLine[RED_BITMAP_OFFSET] = SourcePixel.rgbRed;
					pDestLine[GREEN_BITMAP_OFFSET] = SourcePixel.rgbGreen;
					pDestLine[BLUE_BITMAP_OFFSET] = SourcePixel.rgbBlue;
					pDestLine += bottomChannels;
					pSourceLine += topChannels;
				}
			}
			else
			{
				// Simple 8-bit case with globalOpacity support.
				for (int x = 0; x < compWidth; x++)
				{
					// Get the appropriate palette entry for this pixel.
					RGBQUAD	SourcePixel = palette[pSourceLine[0]];
					// And copy it to the destination.
					pDestLine[RED_BITMAP_OFFSET] = pDestLine[RED_BITMAP_OFFSET] + ((SourcePixel.rgbRed - pDestLine[RED_BITMAP_OFFSET]) * globalOpacity + 127) / 255;
					pDestLine[GREEN_BITMAP_OFFSET] = pDestLine[GREEN_BITMAP_OFFSET] + ((SourcePixel.rgbGreen - pDestLine[GREEN_BITMAP_OFFSET]) * globalOpacity + 127) / 255;
					pDestLine[BLUE_BITMAP_OFFSET] = pDestLine[BLUE_BITMAP_OFFSET] + ((SourcePixel.rgbBlue - pDestLine[BLUE_BITMAP_OFFSET]) * globalOpacity + 127) / 255;
					pDestLine += bottomChannels;
					pSourceLine += topChannels;
				}
			}
		}
		else if (topChannels == 3)
		{
			if (bottomChannels == 3 && globalOpacity == 255)
			{
				// This is the one case where a raw memory copy can be
				// used. There's no alpha channel, no palette, globalOpacity
				// is 255 and the destination
				// is also 24-bits. Memcpy doubles the performance in this case.
				// Might as well make this case go REALLY fast.
				memcpy(pDestLine, pSourceLine, compWidth * topChannels);
			}
			else
			{
				// Simple optimization - avoid the globalOpacity multiplications if
				// they aren't needed.
				if (globalOpacity == 255)
				{
					// Simple 24-bit case with no globalOpacity support.
					for (int x = 0; x < compWidth; x++)
					{
						pDestLine[0] = pSourceLine[0];
						pDestLine[1] = pSourceLine[1];
						pDestLine[2] = pSourceLine[2];
						pDestLine += bottomChannels;
						pSourceLine += topChannels;
					}
				}
				else
				{
					// Simple 24-bit case with globalOpacity support.
					for (int x = 0; x < compWidth; x++)
					{
						pDestLine[0] = pDestLine[0] + ((pSourceLine[0] - pDestLine[0]) * globalOpacity + 127) / 255;
						pDestLine[1] = pDestLine[1] + ((pSourceLine[1] - pDestLine[1]) * globalOpacity + 127) / 255;
						pDestLine[2] = pDestLine[2] + ((pSourceLine[2] - pDestLine[2]) * globalOpacity + 127) / 255;
						pDestLine += bottomChannels;
						pSourceLine += topChannels;
					}
				}
			}
		}
		else	// topChannels must equal 4 - yes?
		{
			assert(topChannels == 4);
			for (int x = 0; x < compWidth; x++)
			{
				uint8_t Alpha = pSourceLine[ALPHA_BITMAP_OFFSET];
				if (Alpha)
				{
					Alpha = (Alpha * globalOpacity + 127) / 255;
					// The Alpha==255 and Alpha==0 cases are well worth
					// checking for because they are very common, and let
					// you avoid three multiplies and divides.
					if (Alpha == 255)
					{
						pDestLine[0] = pSourceLine[0];
						pDestLine[1] = pSourceLine[1];
						pDestLine[2] = pSourceLine[2];
					}
					else if (Alpha > 0)
					{
						// Simple 32-bit case.
						pDestLine[0] = pDestLine[0] + ((pSourceLine[0] - pDestLine[0]) * Alpha + 127) / 255;
						pDestLine[1] = pDestLine[1] + ((pSourceLine[1] - pDestLine[1]) * Alpha + 127) / 255;
						pDestLine[2] = pDestLine[2] + ((pSourceLine[2] - pDestLine[2]) * Alpha + 127) / 255;
					}
				}
				pDestLine += bottomChannels;
				pSourceLine += topChannels;
			}
		}
	}
}

⌨️ 快捷键说明

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