📄 pcx_provider_generic.cpp
字号:
/* $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 + -