📄 pcx_provider_generic.cpp
字号:
//Use background/green/red/yellow palette
unsigned char cga_pal2[12] =
{ 0,0,0,
0,255,0,
255,0,0,
255,255,0 };
memcpy (cga_pal, cga_pal2, 12);
}
//set the background color palette
unsigned char backcolors[3][16] =
{ {0,0,0,
0,0,128,
0,128,0,
0,128,128,
128,0,0,
128},{0,128,
192,96,0,
192,192,192,
128,128,128,
0,0,255,
0,255},{0,
0,255,255,
255,0,0,
255,0,255,
255,255,0,
255,255,255}};
memcpy (cga_pal, &backcolors[0][header[16] & 240 >> 4], 3);
//set the intensity
for (int x=3;x < 12; x++)
{
if (!(header[19] & 32) && cga_pal[x])
{
cga_pal[x] = 128;
}
}
for (int i=0; i<4; i++)
palette[i].set_color(cga_pal[i*3],cga_pal[i*3+1],cga_pal[i*3+2]);
}
//1 color plane, 4 bits per pixel per plane
if (bits_per_pixel_per_plane == 4)
{
//This is an EGA image.
//the palette needs to normalized
//normalize the EGA palette before loading it
//Clanlib needs palette manipulation functions...
if (bits_per_pixel_per_plane == 4)
{
for (int x = 0; x < 48; x++)
{
header[16+x]=header[16+x]/64*64;
}
}
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]);
}
}
break;
case 2:
//nothing special to do here. A 4 color palette is used (already loaded).
break;
case 3:
{
if (bits_per_pixel_per_plane == 1)
{
//Assign the 8 possible combinations of RGB to the palette
//to simulate 8 color RGB display. Otherwise, it is a 256
//color picture.
//8 color untested. 256 color working.
unsigned char rgb3_pal[24] =
{ 0,0,0,
0,0,255,
0,255,0,
0,255,255,
255,0,0,
255,0,255,
255,255,0,
255,255,255 };
for (int i=0; i<8; i++)
palette[i].set_color(rgb3_pal[i*3],rgb3_pal[i*3+1],rgb3_pal[i*3+2]);
}
}
break;
case 4:
//This is a 16 color arbitrary palette image.
//working.
break;
}
}
else
{
//This is an RGBA8888 image.
}
//This is number of bytes to allocate for the final image
bytes_to_allocate = (8 / bits_per_pixel_per_plane) * pitch * height * dest_num_planes;
//allocate the image
image = new unsigned char[bytes_to_allocate];
cl_assert(image != NULL);
if (pixelformat == 8)
{
//Set all pixels to be opaque for RGBA8888
memset(image, 255, bytes_to_allocate);
}
else
{
//initialize bits to 0 so that bitwise operations work correctly
memset(image, 0, bytes_to_allocate);
}
}
void CL_PCXProvider_Generic::read_data()
{
// Do not run if we already have image data
if (image != NULL) return;
// open the file and make sure its valid
cl_assert(provider != NULL);
CL_InputSource *datafile = provider->open_source(name.c_str());
cl_assert(datafile != NULL);
// Read the file header and initialize the variables
read_header(datafile);
// This section reads the file data into memory
datafile->seek(128, CL_InputSource::seek_set);
int size_data = datafile->size() - 128;
unsigned char *temp = new unsigned char[size_data];
int read = datafile->read(temp, size_data);
if (read != size_data)
throw CL_Error("Invalid pcx file!?");
delete datafile;
//init decoding variables
unsigned char *p = temp;
unsigned char *cur_line = image;
// unsigned char *base = image;
unsigned char packed_byte;
unsigned char bitmask = 0;
int skip_planes = 0;
//used later to select bits in bit depths less than 8.
switch (bits_per_pixel_per_plane)
{
case 1:
bitmask = 0x01;
break;
case 2:
bitmask = 0x03;
break;
case 4:
bitmask = 0x0F;
break;
case 8:
bitmask = 0xFF;
break;
}
if (pixelformat == 32)
skip_planes = 1;
//This section decodes the PCX data.
for (int scanline=0;scanline<height;scanline++)
{
//For every scanline
for (int plane = num_planes - 1; plane >= 0; plane--)
{
//for every plane (count backward to convert from RGB to ABGR)
//tracks bytes decoded from data
int decoded_bytes = 0;
//tracks position within final image
int line_position = 0;
while (decoded_bytes < decode_pitch)
{
//while we have not reached the end of the decoded line
//increment the data pointer
packed_byte = *(p++);
if (packed_byte < 192)
{
// top two bits are off... this byte is data
//The processing is now broken down to bit depths of 1, 2, 4, or 8.
for (int bitcounter = 0; bitcounter < 8; bitcounter += bits_per_pixel_per_plane)
{
//For every pixel to be decoded (8 / bits_per_pixel_per_plane
if (bits_per_pixel_per_plane < 8)
{
//The bit depth is below 8. Because we are converting all
//bit depths below 8 to 8, the current line_position is
//always where we are writing data.
//This line pulls the packed bits out of the data.
unsigned char packed_bits = ((packed_byte >> (8 - bits_per_pixel_per_plane - bitcounter)) & bitmask);
//This part pulls bits from multiple planes. Because the bits
//of a palette reference may be spread across multiple planes,
//we modify the data that is already at the line position
//(rather than simply overwriting it).
packed_bits = (packed_bits << (num_planes - plane - 1));
//Add bits to current position. In the case of a
//palette that is referenced by bits in only one plane,
//this is only executed once per line_position.
cur_line[line_position] = cur_line[line_position] + packed_bits;
}
else
{
//The image is 8 bit/pallete or 24 bit. In either case,
//we simply add the number of color planes to the line position.
//Then we add 1 plane for alpha support in a 24(32) bit image
//to skip over the alpha channel (which we assume has been set
//to 0xFF).
int image_dest = line_position *dest_num_planes + plane + skip_planes;
cur_line[image_dest] = packed_byte;
}
line_position++;
}
if (transparent && packed_byte != trans_col)
{
if (decoded_bytes < bounding_left) bounding_left = decoded_bytes;
if (scanline < bounding_top) bounding_top = scanline;
if (decoded_bytes > bounding_right) bounding_right = decoded_bytes;
if (scanline > bounding_bottom) bounding_bottom = scanline;
}
decoded_bytes++;
}
else
// top two bits are on... This is a run. The other bits contain
// a run count for the RLE compression. The next byte will
// contain data to repeat.
{
unsigned char rle_count = packed_byte&0x3f;
packed_byte = *(p++);
//get data byte to repeat.
for(unsigned char rle_iterator = 0; rle_iterator < rle_count; rle_iterator++)
//repeat data value based on rle_count
{
//check for end of plane
if (decoded_bytes >= decode_pitch)
{
plane--;
decoded_bytes = 0;
line_position = 0;
}
//The processing is now broken down to bit depths of 1, 2, 4, or 8
for (int bitcounter = 0; bitcounter < 8; bitcounter += bits_per_pixel_per_plane)
{
// The decoding process here is the same as above (in the non-RLE code)
if (bits_per_pixel_per_plane < 8)
{
unsigned char packed_bits = ((packed_byte >> (8 - bits_per_pixel_per_plane - bitcounter)) & bitmask);
packed_bits = (packed_bits << (num_planes - plane - 1));
cur_line[line_position] = cur_line[line_position] + packed_bits;
}
else
{
int image_dest = line_position *dest_num_planes + plane + skip_planes;
cur_line[image_dest] = packed_byte;
}
line_position++;
}
if (transparent && packed_byte != trans_col)
{
if ((decoded_bytes+rle_iterator) < bounding_left) bounding_left = decoded_bytes+rle_iterator;
if (scanline < bounding_top) bounding_top = scanline;
if ((decoded_bytes+rle_iterator) > bounding_right) bounding_right = decoded_bytes+rle_iterator;
if (scanline > bounding_bottom) bounding_bottom = scanline;
}
decoded_bytes++;
}
}
}
}
cur_line += pitch;
}
delete[] temp;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -