PCX圖檔較常用於3D紋理,你的3D遊戲引擎無任何理由拒絕支持PCX格式的圖檔.幸好PCX格式非常簡單.渲染演示程式下載:
它主要由三部份組成:
- 文檔頭部
- 經RLE編碼的圖像數據
- 調色板,只用於256色
PCX文檔頭部結構 | 簡介 |
typedef struct PCX_HEADER_TAG{ | |
UCHAR manufacturer; | PCX標記:總是 0x0A |
UCHAR version; | 版本號 |
UCHAR encoding; | 編碼:總為 1,使用RLE編碼 |
UCHAR bits_per_pixel; | 每像數所占的位數 1,2,4,8 |
USHORT xmin, ymin; | 圖像的左下角邊界 |
USHORT xmax, ymax; | 圖像的右上角邊界 |
USHORT hres; | 水平分辨率 |
USHORT yres; | 垂直分辨率 |
UCHAR EGAcolors[48]; | EGA(16色)調色板,這種圖檔以較小式用 |
UCHAR reserved; | 保留字節 |
UCHAR color_planes; | 色彩平面量 (24Bit圖檔為3) |
USHORT bytes_per_line; | 每行字節數(單個顏色分量) |
USHORT palette_type; | 1為灰度,2為彩色調色板 |
USHORT scrnw; | 屏幕水平像素 |
USHORT scrnh; | 屏幕垂直像素 |
UCHAR filler[54]; | 54BYTE全零 |
} PCX_HEADER, *PCX_HEADER_PTR; |
你需要定義新的PCX結構用於保存PCX信息.
PCX | 結構 |
typedef struct PCX_TAG{ | |
int width; | 圖寬=xmax – xmin + 1 |
int height; | 圖高=ymax – ymin + 1 |
int bitCount; | 位圖像素的bits 8位,16位,24位,32位
bitCount=color_planes*bytes_per_line |
PCX_PALETTEENTRY palette[256]; | 調色板,當圖檔為256色時出現 |
PBYTE buffer; | 圖像數據 |
} PCX, *PCX_PTR; |
我實現PCX解釋器支持『256色』『16BIT』兩種常見格式:
bool Load_PCX(PCX_PTR pcx,PBYTE data,int size)
{
int index; // 循环变量
PBYTE image;// 图像数据
int image_size;// 像数个数
PBYTE RLE;// RLE编码图像数据
PCX_HEADER_PTR header;// 文档的头部
PCX_PALETTEENTRY_PTR palette;// 读取PCX的调色版
header = (PCX_HEADER_PTR)data; // 文档的头部
pcx->width = (header->xmax – header->xmin) + 1;// 图像宽度(像数)
pcx->height = (header->ymax – header->ymin) + 1;// 图像高度(像数)
pcx->bitCount = header->bits_per_pixel * header->color_planes;// 计算每像数所占的位数
RLE = data + sizeof(PCX_HEADER);
if (pcx->bitCount == 8)
{ // 分配图像记忆体
pcx->buffer = (PBYTE)malloc(pcx->width*pcx->height * 3);
image = (PBYTE)malloc(pcx->width*pcx->height);
image_size = pcx->width * pcx->height;// 图像的像素
Load_RLE_PCX(image, RLE, pcx->width, pcx->height);// RLE解码
// 读取PCX的调色版
palette = (PCX_PALETTEENTRY_PTR)(data + size – 768);// 在文件的结束的位置前移768字节即移动到调色板的开始位置
for (int i = 0; i < image_size; ++i)
{//掉转红色和绿色
index = image[i];
pcx->buffer[i*3 + 0] = palette[index].red;// 红色部分
pcx->buffer[i*3 + 1] = palette[index].green;// 取的绿色部分
pcx->buffer[i*3 + 2] = palette[index].blue;// 取的蓝色部分
}
pcx->bitCount = 24;
free(image);// 释放记忆体
}
else
if (pcx->bitCount == 24)
{// 分配图像记忆体
pcx->buffer = (PBYTE)malloc(pcx->widthpcx->height3);
Load_RLE24_PCX(pcx->buffer, RLE, pcx->width, pcx->height);// RLE解码
}
return true;
}