|
上次看了WindLucid的文章,就写了一个程序,MPC包是likesmoke给我的,所以不知道具体对于那些版本适用
// ExtractMPC.cpp : 定义控制台应用程序的入口点。
//
// 作 者 : 风舞影天(snwcwt)
// 完成时间 : 二零零四年五月十九日
// 小组网站 : http://www.gamefps.com/
#include "stdafx.h"
#include <iostream>
#include <windows.h>
using namespace std;
struct MPCPALETE
{
unsigned blue : 8; // 蓝
unsigned green : 8; // 绿
unsigned red : 8; // 红
unsigned alpha : 8; // Alpha值
};
//图片数据的头结构:
struct MPCPICDATAHEADER
{
int picDataSize; // 图片数据大小
int picWidth; // 图片宽
int picHeight; // 图片高
int NULL1; // 0 可能是保留值,设为NULL
int NULL2; // 0
};
//MPC 图片文件的头结构:
struct MPCFILEHEADER
{
char mpcFlag[16]; // 标志 "MPC File Ver2.0"
int mpcNULL1[12]; // 0
int mpcPicDataSize; // 图片数据长度
int mpcMaxWidth; // 所有图片中最大宽
int mpcMaxHeight; // 所有图片中最大高
int mpcPicCount; // 图片数量
int mpcPicBitCount; // 8 图片象素位数?
int mpcPalleteSize; // 调色板中颜色索引个数
int mpcNull2; // 0x64
int mpcNull3[9]; // 保留为0
};
void mpc2bmp( const char* szFileName );
void savebmp(const char *bmpfileName,unsigned char* bmpData,int nDataLen,int nWidth,int nHeight);
int _tmain(int argc, _TCHAR* argv[])
{
if( argc != 2 )
std::cout << "请输入MPC文件名。" << std::endl;
mpc2bmp( argv[1] );
return 0;
}
void mpc2bmp( const char* szFileName )
{
FILE* pFile = NULL;
char szBmpFileName[MAX_PATH];
pFile = fopen( szFileName, "rb" );
if( pFile == NULL )
{
std::cout << "打开文件时出错。" << std::endl;
return;
}
MPCFILEHEADER fileHeader;
// 读入MPC文件头
fread( &fileHeader, sizeof(MPCFILEHEADER), 1, pFile );
// 创建并读入调色板数据
MPCPALETE* pPalete = new MPCPALETE[fileHeader.mpcPalleteSize];
fread( pPalete, sizeof(MPCPALETE), fileHeader.mpcPalleteSize, pFile );
// 读入所有图片文件的偏移量(相对)
int* pFileOffset = new int[fileHeader.mpcPicCount];
fread( pFileOffset, sizeof(int), fileHeader.mpcPicCount, pFile );
// 循环读入图片数据并保存为BMP图片
MPCPICDATAHEADER picHeader; // 图片数据头
for( int i = 0; i < fileHeader.mpcPicCount; ++i )
{
// 读入图片数据头信息
fread( &picHeader, sizeof(MPCPICDATAHEADER), 1, pFile );
int iDataLen = picHeader.picDataSize - sizeof(MPCPICDATAHEADER);
// 分配MPC图片数据缓冲区并读入
unsigned char* pMpcData = new unsigned char[iDataLen];
fread( pMpcData, 1, iDataLen, pFile );
// 分配BMP图数据缓冲区
int iBmpLen = picHeader.picHeight*( picHeader.picWidth*3+picHeader.picWidth%4 );
unsigned char* pBmpData = new unsigned char[iBmpLen];
// 解析图片数据
int iPos = 0;
int iBmpPos = 0;
int iRow = 0;
int iCol = 0;
int iNumber = 0;
while( iPos < iDataLen )
{
if( pMpcData[iPos] > 0x80 )
{ // 透明色
iNumber = pMpcData[iPos]&0x7f;
iCol += iNumber; // 调整列数
while( iNumber-- )
{
pBmpData[iBmpPos++] = 0xFF;
pBmpData[iBmpPos++] = 0x00;
pBmpData[iBmpPos++] = 0xFF;
}
}
else
{
iNumber = pMpcData[iPos]; // 接下来的iNumber个象素为调色板数据
iCol += iNumber; // 调整列数
while( iNumber-- )
{
++iPos; // 调整偏移位置
pBmpData[iBmpPos++] = pPalete[pMpcData[iPos]].red;
pBmpData[iBmpPos++] = pPalete[pMpcData[iPos]].green;
pBmpData[iBmpPos++] = pPalete[pMpcData[iPos]].blue;
}
}
if( iCol == picHeader.picWidth )
{ // 存储一行数据
iRow++;
iCol = 0;
// 填充行尾数据
for( int j = 0; j < picHeader.picWidth%4; ++j )
{
pBmpData[iBmpPos++] = 0;
}
}
iPos++;
}
// 存储图片
sprintf( szBmpFileName, "%s-%d.bmp", szFileName, i );
savebmp( szBmpFileName, pBmpData, iBmpLen, picHeader.picWidth, picHeader.picHeight );
delete[] pMpcData;
delete[] pBmpData;
}
delete[] pFileOffset;
delete[] pPalete;
fclose( pFile );
}
void savebmp(const char *bmpfileName,unsigned char *
bmpData,int nDataLen,int nWidth,int nHeight)
{
FILE *bmpFile=NULL;
BITMAPFILEHEADER bmpHeader;
BITMAPINFO bmpInfo;
unsigned char *tempData;
int nPitch = nWidth*3+nWidth%4;
tempData = bmpData+nDataLen-nPitch;
bmpFile = fopen( bmpfileName, "w+b" );
if( bmpFile == NULL )
return ;
bmpHeader.bfOffBits = 54;
bmpHeader.bfSize = nDataLen+54;
bmpHeader.bfType = 19778; //"BM"
bmpHeader.bfReserved1 = 0;
bmpHeader.bfReserved2 = 0;
bmpInfo.bmiHeader.biSize = 40;
bmpInfo.bmiHeader.biWidth = nWidth;
bmpInfo.bmiHeader.biHeight = nHeight;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biBitCount = 24;
bmpInfo.bmiHeader.biCompression = 0;
bmpInfo.bmiHeader.biSizeImage = nDataLen;
bmpInfo.bmiHeader.biXPelsPerMeter = 3780;
bmpInfo.bmiHeader.biYPelsPerMeter = 3780;
bmpInfo.bmiHeader.biClrUsed = 0;
bmpInfo.bmiHeader.biClrImportant = 0;
fwrite( &bmpHeader, 1, sizeof(bmpHeader), bmpFile );
fwrite( &bmpInfo, 1, sizeof(bmpInfo), bmpFile );
fseek( bmpFile, (-1)*sizeof(bmpInfo.bmiColors), SEEK_CUR );
for( ; nHeight > 0; --nHeight )
{
fwrite( tempData, 1, nPitch, bmpFile );
tempData -= nPitch;
}
fclose( bmpFile );
}
|
|