标签:
-----------------------------------------------------------------------------
!!警告!!
游戏资源所有权,归游戏开发商所有
以下转换算法与代码,仅供学习交流使用,请勿用于非法或商业用途
由此引起的一切后果,与博主(我)无关
-----------------------------------------------------------------------------
这游戏的资源本身没有被打包,直接就可以看到所有的资源文件,唯独有一种后缀名为 PIC 的图片经过特殊处理,其余都是游戏数值数据文件,音频文件直接就可以用,所以这次针对 PIC 文件做分析;
废话不多说,PIC 文件与 BMP 文件有着几乎一模一样的文件头,用下面结构体可以直接一次性读取 PIC 文件信息:
1 struct PIC_INFO { 2 char sig[ 4 ]; // ‘PIC ‘ 3 char u1[ 14 ]; // all 00 4 int image_width; 5 int image_height; 6 short u2; // 1 7 short bit_per_pixel; // 24 8 int u3; // 00 00 00 00 9 int u4; // 00 00 00 00 10 int u5; // 12 0B 00 00 11 int u6; // 12 0B 00 00 12 int u7; // 00 00 00 00 13 int u8; // 00 00 00 00 14 };
还是老规矩,以 u 开头的数据成员依旧没有摸清楚具体用途,虽然基本上已经确认与 BMP 的 BITMAPINFOHEADER 有着一一对应的意义;
文件开头是 4 个字节的签名,该值永远为 ‘PIC ‘,随后是图片的宽度和高度,以及每像素占多少个字节(也就是色深 bit per pixel ),然后根据色深来确认是否包含调色板数据,8 位色深的 PIC 包含一个大小为 RGBQUAD 乘以 256 个字节的调色板数据,24 位色深 PIC 不包含调色板数据,随后就是像素自身的颜色数值;
下面代码直接将一个 PIC 图片转换成一张 BMP 图片:
1 #include <stdio.h> 2 #include <string.h> 3 #include <Windows.h> 4 5 #pragma pack( push, 2 ) 6 struct PIC_INFO { 7 char sig[ 4 ]; // ‘PIC ‘ 8 char u1[ 14 ]; // all 00 9 int image_width; 10 int image_height; 11 short u2; // 1 12 short bit_per_pixel; // 24 13 int u3; // 00 00 00 00 14 int u4; // 00 00 00 00 15 int u5; // 12 0B 00 00 16 int u6; // 12 0B 00 00 17 int u7; // 00 00 00 00 18 int u8; // 00 00 00 00 19 }; 20 #pragma pack( pop ) 21 22 const char * buildBMPFileNameFromPicFileName( const char * _pic_name ){ 23 static char file_name[ 256 ] = { 0 }; 24 memset( file_name, 0, sizeof( file_name ) ); 25 unsigned int len = strlen( _pic_name ); 26 strcpy_s( file_name, sizeof( file_name ), _pic_name ); 27 for( unsigned int i = len; i >= 0; -- i ){ 28 if( ‘.‘ == file_name[ i ] ){ 29 file_name[ i ] = ‘\0‘; 30 strcat_s( file_name, sizeof( file_name ), ".bmp" ); 31 break; 32 } 33 } 34 return ( const char * ) file_name; 35 } 36 37 void convertPICtoBMP( const char * _pic_name ){ 38 FILE * pic_file = nullptr; 39 FILE * bmp_file = nullptr; 40 char bmp_file_name[ 256 ] = { 0 }; 41 BITMAPFILEHEADER bfh = { 0 }; 42 BITMAPINFOHEADER bih = { 0 }; 43 DWORD pixel_data_size = 0; 44 BYTE * pixel_data_ptr = nullptr; 45 RGBQUAD palette[ 256 ] = { 0 }; 46 47 // read PIC info 48 PIC_INFO info = { 0 }; 49 fopen_s( & pic_file, _pic_name, "rb" ); 50 fread( & info, 1, sizeof( PIC_INFO ), pic_file ); 51 printf( "[ %4d x %4d ] bpp %2d %s \n", 52 info.image_width, 53 info.image_height, 54 info.bit_per_pixel, 55 _pic_name ); 56 if( 8 == info.bit_per_pixel ){ 57 fread( palette, 1, sizeof( palette ), pic_file ); 58 } 59 60 // read PIC pixel data 61 pixel_data_size = ( info.image_height * info.image_width * info.bit_per_pixel / 8 ); 62 pixel_data_ptr = new BYTE[ pixel_data_size ]; 63 fread( pixel_data_ptr, 1, pixel_data_size, pic_file ); 64 65 // build BMP file 66 strcpy_s( bmp_file_name, sizeof( bmp_file_name ), 67 buildBMPFileNameFromPicFileName( _pic_name ) ); 68 fopen_s( & bmp_file, bmp_file_name, "wb" ); 69 70 bfh.bfSize = sizeof( bfh ); 71 bfh.bfOffBits = sizeof( bfh ) + sizeof( bih ); 72 bfh.bfType = 0x4D42; 73 74 bih.biSize = sizeof( bih ); 75 bih.biBitCount = info.bit_per_pixel; 76 bih.biCompression = BI_RGB; 77 bih.biPlanes = 1; 78 bih.biWidth = info.image_width; 79 bih.biHeight = info.image_height; 80 81 fwrite( & bfh, 1, sizeof( bfh ), bmp_file ); 82 fwrite( & bih, 1, sizeof( bih ), bmp_file ); 83 84 // write pixel data to BMP file 85 if( 8 == info.bit_per_pixel ){ 86 fwrite( palette, 1, sizeof( palette ), bmp_file ); 87 } 88 fwrite( pixel_data_ptr, 1, pixel_data_size, bmp_file ); 89 90 fclose( pic_file ); 91 fclose( bmp_file ); 92 delete [ ] pixel_data_ptr; 93 } 94 95 int main( int argc, char * argv[ ] ){ 96 convertPICtoBMP( "aka.PIC" ); 97 convertPICtoBMP( "abura.PIC" ); 98 return 0; 99 }
上面代码中,convertPICtoBMP( ) 函数把一张 PIC 图片转换成一张 BMP 图片,buildBMPFileNameFromPicFileName( ) 函数则将文件的 PIC 后缀名改成 BMP 后缀名;
最后展示一下转换好的 BMP 图片:
标签:
原文地址:http://www.cnblogs.com/gamedes/p/5061478.html