事情是这样的我想从一个游戏客户端的bin文件里面提取出该游戏的图片。我已知此bin文件的图像数据存放规则(有固定的数据块)。但是我读取出指定数据块的数据后,我不懂该怎么把它转换成我们可以在屏幕上看见的图像。比如下面的这段数据,便是我从bin这个二进制文件中读取出来的二进制数据。用for循环,循环已知图像数据大小的次数,用byte类型接收,一个字节一个字节接收出来。再inttohex转换成16进制字符。得到的数据如下1F02A77FD03C06A7A79EA77F7FD039087FA7A77FA77EA7A7D037067F9E9E7F5E7F84A7D0340EA7A77F9E5E9E7FA77FA7A7BB7FBBD0311010A7A77F5E7F9E5E7FA7A7BB7FA7A77FBBD02F839E08A77FBDA77EA77FA7839E047F7F7EBBD02C84A70D5E7FA77FA7A7BDA77F5E9E9E5E837F029E9ED029089E7E7EA77FA77FA7837E0DBDA6A79E705EA7A77F5E9E9E7FD027101A9E9EA77E7EA77FA77FA75D7E5D7DBB7CBC5C7E7DA7BDA77FA77FD0240B7C9EBC9E7F9EA77FA77FA7837E0B5D7EBC7DBD7D7CBDA7BCBD83A7027F7FD02110207F9E7CBC9EA69E7FA77F5E9EA77E5D7EBD53BDA77E7CA6A75D7E7EA77FA77EA7D01F04A7A77BBC84A6101ABBBDA77F5E7FA7A77E7EA77FA77E7EBCA77FA76FA77FA77EA77ED01C83A704BD7EBD6E83A61013BC7FA77F5E7FA7BDA7A77FA76FA7BDBC7D9E7F83A7067EA77EBDBBA7D01910127F9EA79EA77DBABA5BBB7CA67F7F9E9E5E7F837E10139E7F7D7E7E5DA67E5EA77E7DBD7E537BBBA77FD01783BC1014BBBDBC7EA67B5BBBBBA67FBD5E5E7FBDBC7D5C7E83A710109EBD5CBDA77FA77E7EBDBD7CBCA7BBA7D014019E83BC07A6BC7D7E7BBBA683BB10209EA7BDA77EA7BD537DBCBDA77F9E9E7DA6BD7EA77EA7A76F9E9EA7BB7FBD7C7FD011839E102A5DBCBC9EBB7EBB7FBCA6BC9EA6A77E7EA77F7EBD7D537EA7BC9EBC9EA77EA76FA7A6BBBBA69EBC9E9EA7839ECF0EA7A7BCBC7F9EBCBC7EBBBDBBBB9E83A60CBD7E7EBDA77F5E9E9EA7A69E83A710129EA79EA79EBBA7BB9EA77EA7A77F9EBC9EA6CC1020A6BB5BBBBBA7A7BDA7BBBBBD7E5A7D5BBD7D5A5C7D53A6A65CBCA79EBBBBBDBB83A783BD10105D7D7BBDA6A77EA79E9E5E9EA6A7BBA7C908BCBCA6BBA6BBA7A7837E1024BB7B7BA6A77F9EA7BC5C7D7E7E7D7DBD9EBC9EBB7EA79E7F9EA77EBDBD537D7E9EA7A7BD839E06A7BB7EBD7FA6C7103A7FBBA67CA6BBA77E7EA7A77EA77FBBBBA7A77F9E7D7D5D7D7E537E7E9E5E9EA7A7BD5E7F5E7FA7BD53BDBD7FBB7F6E7DBC7E7FA7BDA7BB9EA77EC40D9EBBA7BBBC9EBB5BBCA69EA77E83A7102B7FA77EA7BBBD5D7EA77F7F9E9EBCBC7DBBA77F9E7F5E9E7F7F9E9EA79E9EA77A3BA67D7EA77FA77FA7A6BB83A7101500BBA67F7F9E9EBBA7A79C7FA6A7A63D7D7F5E7F5E839E047FA77F5E839E06BCBCBDBD9E5E839E1015BDA75E7FBBA7BBBDBB7EA6A6535D7FA77FA79E7F7F84A71011009EA77F5EA77EA7A77FBCBCA7A6BCBBA6849E102A5E9E7EA7A77FA7A6A69E9EA77E7F9E5F9E9EBD9E7FBBA77EBDA6A75BBB7F7EA77EBB7EA77F5E7FA77FA7C4101AA77F7FA7A77FBC9EBCA6BB5A59A66D7FA7BD9E9E7E7EA7A7BDBB83BC101D9EA7A75E9EA7A7BD7FBBBDBBA75B7FBC9C9EBC7E5B5BBBBD7F5E7F9EA7C705A7A77F9E7F839E0FBBBA59B95CA65CA6A7A76FBD5AA6A683BC10179CBC9EA77FA77F7E9E7FA7BDA7BB7FA6BCBB9E9EBC9E9E83A7047F5E9E9EC9029E5E839E1016BCA65BA6B9B9A6A65C7E9EA77DBCA65BBB7BA6BCA6A6839E0C7EA7A77F5E7FA7A7BB5BBCA684BC849E047F5E7F7FCC059E9E5E9EBC83BB0F7B7DBC3DBDBD7E7D7D53BDBA7BBB5D849E0D5E7F7E7F5E9E7FA7A7BBBBA6A684BC069E9E5F9E5E9ECF1014A7A6BCBBBB5B5BA75E7EA65D7EA77EBDA7A7BCBB839E05A6BC5E709E83A7049E5E9E9E83BB0A5BA69CBC9E5E9E709E7FD011102EA69E5BBB7C7EA5BD7DBD7E7EA77EA77FBD7DBB9EA6A7BBBCBC9EBC9E7F9E9E709EBCBCA6BBBBBABBA69E9E5F9E9ED0141024A69EBCA6BC7EA7A79E7F9E5E7F9EBDB96E6EA7BDBBA69CBCBC9E5E9E9E5EBC9E7C7CA6BB83BC03A65E9ED01705BC9E7FBA9E83A710205EBD7FA77DBA3B7CB97DA7A6A6BCBC5DBCBC9E5F9E9E7FBBBB5BA6A6BCBC9E9ED01910117FA7BDA77F5E7F9EA7A7BDA5A77B7D7C5D839E08A6A6BCBC9E9EA7BD83A704A6A69EA6839ED01C0F7DBDBD9E9E5E9EA79EBD7FA77F7EA6839E83BD0D5B7BA7A79EA77F9E7F9E9EA79ED01F101B7EBD9E9E70A7A6BBA77CA77F9EA79E5F9E5E9E7F9EBB7E7F9E9E5F859ED021101E7F9E5EA77FBBBBA77FA79E5EBD9E9E709E9EBB9EA7BD5E705F9E5E705E9ED024101A7EBBBBA77F9E9E5E7F7FA77E5E9E5EBCA79EA77EA75E9E709E9ED02783BB1015A69E9E7F5EA7A77FBDA7BC7E5ABDA6A7BD5E9E5F9ED02910167BBBBB9E705E7FA77FA77FA7BDBD5BBDBCBCBB7EA7BBD02C0EBC9E9E5E7F7FA77FA7BD7E7EBBB983A601BBD02F10109E9E709E5E7FA7A77E7E7F7CBBA67C7BD0310B7F5E9E709E9EA7A79E7F7D83A6D0340ABC5E5F9E7F9E9EBC9CBCD037839E055E5EBC9EBCD03906BC5E709EA79ED03C029E7FD01F52440110400000002F000000A0060000D0
以上二进制数据应该是一副完整的图像了。这个游戏客户端图像数据压缩用的是自定义的RLE算法。算法的具体已经有人发文章了,我转过来,如下:++++++++++++++++++++++++++++++++++
这是JSS自定的一种Run-Length算法,用于StoneAge和CrossGate,下面是说明:首字节(00) 01 02 03 说明
0n String 长度为n的字符串
1n m String 长度为n*0x100+m的字符串
2x y z String 长度为x*0x10000+y*0x100+z的字符串
8n X 填充n个X
9n X m 填充n*0x100+m个X
Ax X y z 填充x*0x10000+y*0x100+z个X
Cn 填充n个背景色
Dn m 填充n*0x100+m个背景色
Ex y z 填充x*0x10000+y*0x100+z个背景色
比如,C9表示填充9个背景色,D1 10表示填充0x110个背景色,12 50表示后面跟着一个长度为0x250的字符串,91 02 30则表示将0x02重复0x130遍。
RLE压缩方式,具体的压缩编码如下:
0a xx xx xx
a 个单独的颜色点
1a bb xx xx xx
abb 个单独的颜色点
2a bb cc xx xx xx
abbcc个单独的点Ca
a 个透明色
Da bb
abb 个透明色
Ea bb cc
abbcc个透明色
8a xx
a 个颜色是XX的点
9a xx bb
abb 个颜色为xx的点
Aa xx bb cc
abbcc 个颜色为xx的点+++++++++++++++++++++++++++++++++这个是RLE算法的解释,可是我看不太懂……。我不知道这个算法是不是说要我自己写一个解压算法,将我上面提取出来的二进制数据解码?郁闷……,谁能告诉我怎么解码?要不就告诉我怎么理解上面那个RLE算法,它那个说明0N,1N的我无法理解另外,图像要完整显示,还跟调色板有关系。游戏客户端有调色板文件。但是我同样因为没有做过这方面的程序,不理解调色板是做什么用的?我只知道,如果没有应用调色板,图像的色彩会失真,有时候会错乱,但是图像的轮廓还是存在的。希望高手可以告诉我一下,首先就是如何将我上面提取的二进制数据还原成一个图像。
然后就是调色板的应用是怎么一回事~~!谢谢谢谢~,分不多,只有一百,……多多包涵~,在下实在是被它困扰多日,寝食难安……
以上二进制数据应该是一副完整的图像了。这个游戏客户端图像数据压缩用的是自定义的RLE算法。算法的具体已经有人发文章了,我转过来,如下:++++++++++++++++++++++++++++++++++
这是JSS自定的一种Run-Length算法,用于StoneAge和CrossGate,下面是说明:首字节(00) 01 02 03 说明
0n String 长度为n的字符串
1n m String 长度为n*0x100+m的字符串
2x y z String 长度为x*0x10000+y*0x100+z的字符串
8n X 填充n个X
9n X m 填充n*0x100+m个X
Ax X y z 填充x*0x10000+y*0x100+z个X
Cn 填充n个背景色
Dn m 填充n*0x100+m个背景色
Ex y z 填充x*0x10000+y*0x100+z个背景色
比如,C9表示填充9个背景色,D1 10表示填充0x110个背景色,12 50表示后面跟着一个长度为0x250的字符串,91 02 30则表示将0x02重复0x130遍。
RLE压缩方式,具体的压缩编码如下:
0a xx xx xx
a 个单独的颜色点
1a bb xx xx xx
abb 个单独的颜色点
2a bb cc xx xx xx
abbcc个单独的点Ca
a 个透明色
Da bb
abb 个透明色
Ea bb cc
abbcc个透明色
8a xx
a 个颜色是XX的点
9a xx bb
abb 个颜色为xx的点
Aa xx bb cc
abbcc 个颜色为xx的点+++++++++++++++++++++++++++++++++这个是RLE算法的解释,可是我看不太懂……。我不知道这个算法是不是说要我自己写一个解压算法,将我上面提取出来的二进制数据解码?郁闷……,谁能告诉我怎么解码?要不就告诉我怎么理解上面那个RLE算法,它那个说明0N,1N的我无法理解另外,图像要完整显示,还跟调色板有关系。游戏客户端有调色板文件。但是我同样因为没有做过这方面的程序,不理解调色板是做什么用的?我只知道,如果没有应用调色板,图像的色彩会失真,有时候会错乱,但是图像的轮廓还是存在的。希望高手可以告诉我一下,首先就是如何将我上面提取的二进制数据还原成一个图像。
然后就是调色板的应用是怎么一回事~~!谢谢谢谢~,分不多,只有一百,……多多包涵~,在下实在是被它困扰多日,寝食难安……
解决方案 »
- 关于delphi开发webservice问题,100分送上
- 有是一个DELPHI的初学者,问一个简单的问题?
- 如何连接远程数据库哦???
- Bitbtn 有沒有類似 Speedbutton 的 Flat 屬性?
- 請問delphi7裡面有沒有toolbutton這樣的控件啊/
- Delphi入门书推荐???
- 我想利用autocad的acad.tlb进行CAD的开发,能否实现?
- delphi中可否直接使用Sql语句(象pb一样)?如果可以该怎么写?
- 怎样使用Tregistry对象的WriteBinaryData方法向注册表中的添加二进制值?(请举例说明)
- 求解:扑克牌的秘密
- delphi多层架构设想
- 如何向多个进程发送数据?
至于RLE算法应该是一个压缩算法,需要另外找个解压缩算法就行了
不知道是你的数据有问题,还是你表诉的算法有问题,或着是我理解有问题.反正我理解下来,无法解码1F02A77FD0 3C06A7A79EA7...
按你的表诉, 由1a bb xx xx xx 表示为: abb 个单独的颜色点
则 有连续的 0xF02 个颜色为A77FD0的颜色点
但是,接下来3C06A7A79EA7... 3c 无法解码了.晕死....况且,这个东西解码出来,没有图形,比如 高,宽等信息,你还是无法画..
至于调色板,可能只有8a 9a Aa 下用,
如果你所有信息的得到 且数据解码了, 创建一个位图,就可以画出来了(这种画图代码,网上随便抓一把都是.).
0a xx xx xx
xx xx xx我理解为颜色, 看来只是每一个xx 代表一个颜色信息而已.
表示为有a 个 颜色点的数据字节
是说后面有F02个象素值(非压缩), A7 7F D0 3C 06 A7 ... 就是了。
不过楼主给出的这一段数据连F02都不够啊,而且宽度、高度都不知道,没法还原。
只要把二进制读入入数组中就可以了,其余用流就可以,你试试吧!
我最近也在做这方面的东西,交流一下!
以下是代码:
var
S: TStream;
B: TMemoryStream;
T:TSTREAM;
I: Integer;
C:ARRAY[0..8000] OF Byte;
begin
B := TMemoryStream.Create;
B.LoadFromFile('D:\lfg\手机照片\Image00001.bmp');
B.Position := 0;
S := TMemoryStream.Create;
S.Position :=0;
for I := 0 to B.Size-1 do
begin
B.Read(C[I], 1);
S.Write(C[I],SIZEOF(C[I])) ;
end;
S.Position :=0;
image1.Picture.Bitmap.LoadFromStream(S);
B.Free;
S.Free;
end;
看了你后面说的高度,和宽度,还有图形形状,我找了半天哪天写的代码,知道为什么是一个斜放的四方形(菱形吧),
你给的数据有问题,前面应该还有一个D0,也就是说D01F02A77FD03C06... 这样正好解码出来是
3008个数据,解码到52440110400000002F000000A0060000D0停止. 画出来就是一个菱形,
加D0是我自己猜的,至于解码方式就按前面的提示来做.省得你再问,在说一点,解码出数据后用CreateBitmap 来创建位图,而不是用Bitmap.LoadFromStream(S)来读取,之后做的事情,自己去查帮助.
var
rle_code:Word;
ptr_instream:Word;
ptr_outstream:Word;
i,loopcnt:Word;
c:Char;
begin
if( instream = nil) or (in_len = 0) or (outstream = nil) or (out_len = 0) or (in_len > out_len ) then exit ;
ptr_instream:=0;
ptr_outstream:=0;
i:=0;
loopcnt:=0;
while ptr_instream < in_len do
begin
//c:=instream[ptr_instream];
rle_code := Word(instream[ptr_instream]);
//rle_code:=Integer(c);
Inc(ptr_instream);
case rle_code and $f0 of
$00:
begin
loopcnt := rle_code;
for i := 0 to loopcnt - 1 do
begin
outstream[ptr_outstream] := instream[ptr_instream];
Inc(ptr_instream);
Inc(ptr_outstream);
end;
end;
$10:
begin
loopcnt:= (rle_code and $0f)*$100+Word(instream[ptr_instream]);
Inc(ptr_instream);
for i := 0 to loopcnt - 1 do
begin
outstream[ptr_outstream] := instream[ptr_instream];
Inc(ptr_instream);
Inc(ptr_outstream);
end;
end;
$20:
begin
loopcnt := (rle_code and $0f) * $10000 + Word(instream[ptr_instream]) * $100 + Word(instream[ptr_instream+1]);
Inc(ptr_instream,2);
for i := 0 to loopcnt - 1 do
begin
outstream[ptr_outstream] := instream[ptr_instream];
Inc(ptr_instream);
Inc(ptr_outstream);
end;
end;
$80:
begin
loopcnt := rle_code and $0f;
rle_code := Word(instream[ptr_instream]);
Inc(ptr_instream);
for i := 0 to loopcnt - 1 do
begin
outstream[ptr_outstream] := Char(rle_code);
Inc(ptr_outstream);
end;
end;
$90:
begin
loopcnt := (rle_code and $0f) * $100 + Word(instream[ptr_instream + 1]);
rle_code := Word(instream[ptr_instream]);
Inc(ptr_instream,2);
for i := 0 to loopcnt - 1 do
begin
outstream[ptr_outstream] := Char(rle_code);
Inc(ptr_outstream);
end;
end; //end $90
$a0:
begin
loopcnt := (rle_code and $0f) * $10000 + Word(instream[ptr_instream + 1]) * $100 + Word(instream[ptr_instream + 2]);
rle_code := Word(instream[ptr_instream]);
Inc(ptr_instream,3);
for i := 0 to loopcnt - 1 do
begin
outstream[ptr_outstream] := Char(rle_code);
Inc(ptr_outstream);
end;
end; //end $a0
$c0:
begin
loopcnt := rle_code and $0f;
for i := 0 to loopcnt - 1 do
begin
outstream[ptr_outstream] := #$ff;
Inc(ptr_outstream);
end;
end;
$d0:
begin
loopcnt := (rle_code and $0f) * $100 + Word(instream[ptr_instream]);
Inc(ptr_instream);
for i := 0 to loopcnt - 1 do
begin
outstream[ptr_outstream] := #$ff;
Inc(ptr_outstream);
end;
end;
$e0:
begin
loopcnt := (rle_code and $0f) * $10000 + Word(instream[ptr_instream]) * $100 + Word(instream[ptr_instream+1]);
Inc(ptr_instream,2);
for i := 0 to loopcnt - 1 do
begin
outstream[ptr_outstream] := #$ff;
Inc(ptr_outstream);
end;
end; end; //end case
Inc(ptr_instream);
end; //end whileend;找到这一份代码其中有些不理解的地方希望各位高手能够帮忙解答解答。其中这一句rle_code := Word(instream[ptr_instream]);word()表示什么意思?强制转换成word类型?