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

📄 pcx_provider_generic.cpp

📁 这是一款2d游戏引擎
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*  $Id: pcx_provider_generic.cpp,v 1.6 2003/07/20 22:31:49 grumbel Exp $
**
**  ClanLib Game SDK
**  Copyright (C) 2003  The ClanLib Team
**  For a total list of contributers see the file CREDITS.
**
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Lesser General Public
**  License as published by the Free Software Foundation; either
**  version 2.1 of the License, or (at your option) any later version.
**
**  This library 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
**  Lesser General Public License for more details.
**
**  You should have received a copy of the GNU Lesser General Public
**  License along with this library; if not, write to the Free Software
**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
*/

#include "Display/display_precomp.h"
#include "pcx_provider_generic.h"
#include "API/Core/System/error.h"

/////////////////////////////////////////////////////////////////////////////
// CL_PCXProvider_Generic construction:

CL_PCXProvider_Generic::CL_PCXProvider_Generic(
	std::string _name, 
	CL_InputSourceProvider *_provider, 
	bool _transparent, 
	unsigned char _trans_col)
{
	provider = _provider != NULL ? _provider->clone() : CL_InputSourceProvider::create_file_provider(".");
	pitch = height = 0;
	bounding_left = bounding_top = bounding_right = bounding_bottom = 0;
	
	transparent = _transparent;
	if (!transparent) trans_col = -1;
	else trans_col = _trans_col;
	
	name = _name;
	image = NULL;
	pixelformat = 8;
}

CL_PCXProvider_Generic::~CL_PCXProvider_Generic()
{
	perform_unlock();
	delete provider;
}

/////////////////////////////////////////////////////////////////////////////
// CL_PCXProvider_Generic attributes:

unsigned int CL_PCXProvider_Generic::get_depth() const
{
	return pixelformat;
}

unsigned int CL_PCXProvider_Generic::get_red_mask() const
{
	return 0xff000000;
}

unsigned int CL_PCXProvider_Generic::get_green_mask() const
{
	return 0x00ff0000;
}

unsigned int CL_PCXProvider_Generic::get_blue_mask() const
{
	return 0x0000ff00;
}

unsigned int CL_PCXProvider_Generic::get_alpha_mask() const
{
	return 0x000000ff;
}

/////////////////////////////////////////////////////////////////////////////
// CL_PCXProvider_Generic operations:

void CL_PCXProvider_Generic::perform_lock()
{
	//The PCX decoding code was moved to read_data() and read_header()
	//to make it easier to follow the code.
	read_data();

	// this could be integrated better, but I'm too tired, so I just hack CL_PixelBuffer
	// support into it. -- mbn 21. feb 2002

	CL_PixelBuffer_Generic::format.enable_colorkey(uses_src_colorkey());
	CL_PixelBuffer_Generic::format.set_colorkey(get_src_colorkey());
	CL_PixelBuffer_Generic::format.set_depth(get_depth());
	CL_PixelBuffer_Generic::format.set_red_mask(get_red_mask());
	CL_PixelBuffer_Generic::format.set_green_mask(get_green_mask());
	CL_PixelBuffer_Generic::format.set_blue_mask(get_blue_mask());
	CL_PixelBuffer_Generic::format.set_alpha_mask(get_alpha_mask());
	CL_PixelBuffer_Generic::pitch = get_pitch();
	CL_PixelBuffer_Generic::width = get_width();
	CL_PixelBuffer_Generic::height = get_height();
}

void CL_PCXProvider_Generic::perform_unlock()
{
	delete[] image;
	image = NULL;
}

/////////////////////////////////////////////////////////////////////////////
// CL_PCXProvider_Generic implementation:

void CL_PCXProvider_Generic::read_header(CL_InputSource *_datafile)
{
	//: This method was created to breakup the PCX decoding code
	//: so the initializing code was separated from the actual
	//: decoding algorithm
	
	unsigned char header[128];  
	
	int read = _datafile->read(header, 128);
	if (read != 128)
		throw CL_Error("Invalid pcx file!?");
	
	pcx_version = header[1];

	// int compressed = header[2];

	bits_per_pixel_per_plane = header[3];

	short xmin = header[5] * 256 + header[4];	
	short ymin = header[7] * 256 + header[6];
	short xmax = header[9] * 256 + header[8];
	short ymax = header[11] * 256 + header[10];

	height = ymax - ymin + 1;

	num_planes = header[65];
	dest_num_planes = num_planes;
	decode_pitch = header[67] * 256 + header[66];

	//decide which pixelformat to use (8 bit palette or 32 bit)
	switch (num_planes)		
	{
	case 1:
		{
			//palettized image
			//Deluxe Paint IIe compatible 4 color CGA or
			//Monochrome or
			//256 color palette based image
			//force the final image to 8 bit/palette.
			dest_num_planes = 1;
			pixelformat = 8;
		}
		break;
	case 2:
		{
			//force the final image to 8 bit/palette.
			dest_num_planes = 1;
			pixelformat = 8;
		}
		break;
	case 3:
		{
			if (bits_per_pixel_per_plane == 1)
			{
				//This means 8 color/palette
				pixelformat = 8;
				dest_num_planes = 1;
			}
			else
			{
				//This means it is 24 bit RGB.
				//24 bit images are being forced into 32 bit.
				//Pixelformat RGB888 did not appear to work at the time
				//of this PCX decoder rewrite.
				pixelformat = 32;
				dest_num_planes = 4;
			}
		}
		break;
	case 4:
		{
			//no palette
			//force the final image to 8 bit/palette.
			//This case represents 16 color EGA or 4 color CGA where only
			//1 bit is stored in each plane.  The 4th plane is the
			//intensity bit.
			dest_num_planes = 1;
			pixelformat = 8;
		}
		break;
	default:
		{
			throw CL_Error("Unrecognized or invalid pcx file!?");
		}
		break;
	}

	//set bytes per scanline of final image.  Requires dest_num_planes to be defined.
	pitch = (xmax - xmin  + 1) * dest_num_planes;
	
	if (transparent)
	{
		bounding_left = pitch / dest_num_planes;
		bounding_top = height;
		bounding_right = 0;
		bounding_bottom = 0;
	}
	else
	{
		bounding_left = 0;
		bounding_top = 0;
		bounding_right = pitch / dest_num_planes;
		bounding_bottom = height;
	}

	//get number of bites in encoded data (including possible palette after data)
	size_data = _datafile->size() - 128;

	//Now we deal with the palette which can be in the header,
	//or at the end of the file, or defined here.  It is possible that these
	//palette definitions should have been placed in palette.h
	if (pixelformat == 8)
	{
		//If the pcx version is 5, the palette may be at the end of the file.
		//Otherwise it is in the header.
		if (pcx_version >= 5)	
		{
			if (num_planes == 1)
			{
				//The palette information is stored at the end of the file.
				//read the last 768 bytes from the file.
				char pal[768];
				_datafile->seek(128+size_data-768,CL_InputSource::seek_set);
				read = _datafile->read(pal, 768);
				for (int i=0; i<256; i++)
					palette[i].set_color(pal[i*3+0],pal[i*3+1],pal[i*3+2]);
			}
			else
			{
				//The palette information is stored in the header.
				for (int i=0; i<16; i++)
					palette[i].set_color(header[16+i*3], header[16+i*3+1], header[16+i*3+2]);
			}
		}
		else
		{
			//The palette information is stored in the header.
			for (int i=0; i<16; i++)
				palette[i].set_color(header[16+i*3], header[16+i*3+1], header[16+i*3+2]);
		}
		
		//Setup palette for PCX types that rely on a pre-defined palette
		//(MONO, CGA, EGA)
		switch (num_planes)
		{
		case 1:
			{	
				//1 color plane, 1 bit per pixel per plane
				if (bits_per_pixel_per_plane == 1)
				{
					//Simulate a monochrome display.
					//Assign "Black" and "White" colors to palette
					//(assume "White" assigned to "On" bits)
					//It works!
					palette[0].set_color(0,0,0);
					palette[1].set_color(255,255,255);
				}

				//1 color plane, 2 bits per pixel per plane
				if (bits_per_pixel_per_plane == 2)
				{
					//CGA 4 color
					//It works!
					unsigned char cga_pal[12];

					if (header[19] & 64)
					{
						//Use background/cyan/magenta/white palette
						unsigned char cga_pal1[12] = 
							{ 0,0,0,
							0,255,255,
							255,0,255,
							255,255,255 };
						memcpy (cga_pal, cga_pal1, 12);
					}
					//eveything from here forward was not tested for this mode.
					else
					{

⌨️ 快捷键说明

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