盛大传奇客户端的图片资源都保存在data目录下的wzl文件中,wzl文件结构比较简单,由一个文件头结构和若干图片数据组成。

找了个最小的wzl文件作为例子

蓝色高亮部分就是文件头,其中只有ImageCount有意义,其他的字段不清楚是做什么的,也不用关心,因为不会影响图片解析。

ImageCount表示该文件中一共有多少张图片,但是研究后发现,后面出现的图片数量不一定就是这个总数,因为有空图存在。就好比你有一个数组int arr[10],但是只用到5个元素一样。

接着后面就是若干个IMAGE结构了

typedef struct {byte pixelFormat;  // 图片位深byte compressed;   // 表示图片数据是否经过gzip压缩byte reserve;byte compressLevel; // 如果图片数据是压缩过,这个就表示压缩的等级short width;  // 图片宽度short height;  // 图片高度short x;short y;int size;  // 图片数据长度
} IMAGE;

结构后面紧跟着就是图片的原始数据,根据compressed可以得知这段数据是不是zlib压缩过的数据,如果是的则需要解压。

而PixelFormat指明了这张图片的位深度,它的值对应Delphi中的TPixelFormat枚举类型(因为传奇就是Delphi开发的)。

因为历史原因,传奇的图片资源基本都是8bit或16bit的位图。

bmp文件格式规定,8bit的图片颜色是由调色板来指定的,调色板是一个包含256个元素的RGBQuad数组

MirPalette: array[0..255] of TRGBQuad;

传奇使用的调色板数据如下(这里用C#来表示,看上去舒服点)

private static readonly Color[] MirPalette =
{Color.FromArgb(0, 0, 0),Color.FromArgb(128, 0, 0),Color.FromArgb(0, 128, 0),Color.FromArgb(128, 128, 0),Color.FromArgb(0, 0, 128),Color.FromArgb(128, 0, 128),Color.FromArgb(0, 128, 128),Color.FromArgb(192, 192, 192),Color.FromArgb(85, 128, 151),Color.FromArgb(157, 185, 200),Color.FromArgb(123, 115, 115),Color.FromArgb(45, 41, 41),Color.FromArgb(90, 82, 82),Color.FromArgb(99, 90, 90),Color.FromArgb(66, 57, 57),Color.FromArgb(29, 24, 24),Color.FromArgb(24, 16, 16),Color.FromArgb(41, 24, 24),Color.FromArgb(16, 8, 8),Color.FromArgb(242, 121, 113),Color.FromArgb(225, 103, 95),Color.FromArgb(255, 90, 90),Color.FromArgb(255, 49, 49),Color.FromArgb(214, 90, 82),Color.FromArgb(148, 16, 0),Color.FromArgb(148, 41, 24),Color.FromArgb(57, 8, 0),Color.FromArgb(115, 16, 0),Color.FromArgb(181, 24, 0),Color.FromArgb(189, 99, 82),Color.FromArgb(66, 24, 16),Color.FromArgb(255, 170, 153),Color.FromArgb(90, 16, 0),Color.FromArgb(115, 57, 41),Color.FromArgb(165, 74, 49),Color.FromArgb(148, 123, 115),Color.FromArgb(189, 82, 49),Color.FromArgb(82, 33, 16),Color.FromArgb(123, 49, 24),Color.FromArgb(45, 24, 16),Color.FromArgb(140, 74, 49),Color.FromArgb(148, 41, 0),Color.FromArgb(189, 49, 0),Color.FromArgb(198, 115, 82),Color.FromArgb(107, 49, 24),Color.FromArgb(198, 107, 66),Color.FromArgb(206, 74, 0),Color.FromArgb(165, 99, 57),Color.FromArgb(90, 49, 24),Color.FromArgb(42, 16, 0),Color.FromArgb(21, 8, 0),Color.FromArgb(58, 24, 0),Color.FromArgb(8, 0, 0),Color.FromArgb(41, 0, 0),Color.FromArgb(74, 0, 0),Color.FromArgb(157, 0, 0),Color.FromArgb(220, 0, 0),Color.FromArgb(222, 0, 0),Color.FromArgb(251, 0, 0),Color.FromArgb(156, 115, 82),Color.FromArgb(148, 107, 74),Color.FromArgb(115, 74, 41),Color.FromArgb(82, 49, 24),Color.FromArgb(140, 74, 24),Color.FromArgb(136, 68, 17),Color.FromArgb(74, 33, 0),Color.FromArgb(33, 24, 16),Color.FromArgb(214, 148, 90),Color.FromArgb(198, 107, 33),Color.FromArgb(239, 107, 0),Color.FromArgb(255, 119, 0),Color.FromArgb(165, 148, 132),Color.FromArgb(66, 49, 33),Color.FromArgb(24, 16, 8),Color.FromArgb(41, 24, 8),Color.FromArgb(33, 16, 0),Color.FromArgb(57, 41, 24),Color.FromArgb(140, 99, 57),Color.FromArgb(66, 41, 16),Color.FromArgb(107, 66, 24),Color.FromArgb(123, 74, 24),Color.FromArgb(148, 74, 0),Color.FromArgb(140, 132, 123),Color.FromArgb(107, 99, 90),Color.FromArgb(74, 66, 57),Color.FromArgb(41, 33, 24),Color.FromArgb(70, 57, 41),Color.FromArgb(181, 165, 148),Color.FromArgb(123, 107, 90),Color.FromArgb(206, 177, 148),Color.FromArgb(165, 140, 115),Color.FromArgb(140, 115, 90),Color.FromArgb(181, 148, 115),Color.FromArgb(214, 165, 115),Color.FromArgb(239, 165, 74),Color.FromArgb(239, 198, 140),Color.FromArgb(123, 99, 66),Color.FromArgb(107, 86, 57),Color.FromArgb(189, 148, 90),Color.FromArgb(99, 57, 0),Color.FromArgb(214, 198, 173),Color.FromArgb(82, 66, 41),Color.FromArgb(148, 99, 24),Color.FromArgb(239, 214, 173),Color.FromArgb(165, 140, 99),Color.FromArgb(99, 90, 74),Color.FromArgb(189, 165, 123),Color.FromArgb(90, 66, 24),Color.FromArgb(189, 140, 49),Color.FromArgb(53, 49, 41),Color.FromArgb(148, 132, 99),Color.FromArgb(123, 107, 74),Color.FromArgb(165, 140, 90),Color.FromArgb(90, 74, 41),Color.FromArgb(156, 123, 57),Color.FromArgb(66, 49, 16),Color.FromArgb(239, 173, 33),Color.FromArgb(24, 16, 0),Color.FromArgb(41, 33, 0),Color.FromArgb(156, 107, 0),Color.FromArgb(148, 132, 90),Color.FromArgb(82, 66, 24),Color.FromArgb(107, 90, 41),Color.FromArgb(123, 99, 33),Color.FromArgb(156, 123, 33),Color.FromArgb(222, 165, 0),Color.FromArgb(90, 82, 57),Color.FromArgb(49, 41, 16),Color.FromArgb(206, 189, 123),Color.FromArgb(99, 90, 57),Color.FromArgb(148, 132, 74),Color.FromArgb(198, 165, 41),Color.FromArgb(16, 156, 24),Color.FromArgb(66, 140, 74),Color.FromArgb(49, 140, 66),Color.FromArgb(16, 148, 41),Color.FromArgb(8, 24, 16),Color.FromArgb(8, 24, 24),Color.FromArgb(8, 41, 16),Color.FromArgb(24, 66, 41),Color.FromArgb(165, 181, 173),Color.FromArgb(107, 115, 115),Color.FromArgb(24, 41, 41),Color.FromArgb(24, 66, 74),Color.FromArgb(49, 66, 74),Color.FromArgb(99, 198, 222),Color.FromArgb(68, 221, 255),Color.FromArgb(140, 214, 239),Color.FromArgb(115, 107, 57),Color.FromArgb(247, 222, 57),Color.FromArgb(247, 239, 140),Color.FromArgb(247, 231, 0),Color.FromArgb(107, 107, 90),Color.FromArgb(90, 140, 165),Color.FromArgb(57, 181, 239),Color.FromArgb(74, 156, 206),Color.FromArgb(49, 132, 181),Color.FromArgb(49, 82, 107),Color.FromArgb(222, 222, 214),Color.FromArgb(189, 189, 181),Color.FromArgb(140, 140, 132),Color.FromArgb(247, 247, 222),Color.FromArgb(0, 8, 24),Color.FromArgb(8, 24, 57),Color.FromArgb(8, 16, 41),Color.FromArgb(8, 24, 0),Color.FromArgb(8, 41, 0),Color.FromArgb(0, 82, 165),Color.FromArgb(0, 123, 222),Color.FromArgb(16, 41, 74),Color.FromArgb(16, 57, 107),Color.FromArgb(16, 82, 140),Color.FromArgb(33, 90, 165),Color.FromArgb(16, 49, 90),Color.FromArgb(16, 66, 132),Color.FromArgb(49, 82, 132),Color.FromArgb(24, 33, 49),Color.FromArgb(74, 90, 123),Color.FromArgb(82, 107, 165),Color.FromArgb(41, 57, 99),Color.FromArgb(16, 74, 222),Color.FromArgb(41, 41, 33),Color.FromArgb(74, 74, 57),Color.FromArgb(41, 41, 24),Color.FromArgb(74, 74, 41),Color.FromArgb(123, 123, 66),Color.FromArgb(156, 156, 74),Color.FromArgb(90, 90, 41),Color.FromArgb(66, 66, 20),Color.FromArgb(57, 57, 0),Color.FromArgb(89, 89, 0),Color.FromArgb(202, 53, 44),Color.FromArgb(107, 115, 33),Color.FromArgb(41, 49, 0),Color.FromArgb(49, 57, 16),Color.FromArgb(49, 57, 24),Color.FromArgb(66, 74, 0),Color.FromArgb(82, 99, 24),Color.FromArgb(90, 115, 41),Color.FromArgb(49, 74, 24),Color.FromArgb(24, 33, 0),Color.FromArgb(24, 49, 0),Color.FromArgb(24, 57, 16),Color.FromArgb(99, 132, 74),Color.FromArgb(107, 189, 74),Color.FromArgb(99, 181, 74),Color.FromArgb(99, 189, 74),Color.FromArgb(90, 156, 74),Color.FromArgb(74, 140, 57),Color.FromArgb(99, 198, 74),Color.FromArgb(99, 214, 74),Color.FromArgb(82, 132, 74),Color.FromArgb(49, 115, 41),Color.FromArgb(99, 198, 90),Color.FromArgb(82, 189, 74),Color.FromArgb(16, 255, 0),Color.FromArgb(24, 41, 24),Color.FromArgb(74, 136, 74),Color.FromArgb(74, 231, 74),Color.FromArgb(0, 90, 0),Color.FromArgb(0, 136, 0),Color.FromArgb(0, 148, 0),Color.FromArgb(0, 222, 0),Color.FromArgb(0, 238, 0),Color.FromArgb(0, 251, 0),Color.FromArgb(74, 90, 148),Color.FromArgb(99, 115, 181),Color.FromArgb(123, 140, 214),Color.FromArgb(107, 123, 214),Color.FromArgb(119, 136, 255),Color.FromArgb(198, 198, 206),Color.FromArgb(148, 148, 156),Color.FromArgb(156, 148, 198),Color.FromArgb(49, 49, 57),Color.FromArgb(41, 24, 132),Color.FromArgb(24, 0, 132),Color.FromArgb(74, 66, 82),Color.FromArgb(82, 66, 123),Color.FromArgb(99, 90, 115),Color.FromArgb(206, 181, 247),Color.FromArgb(140, 123, 156),Color.FromArgb(119, 34, 204),Color.FromArgb(221, 170, 255),Color.FromArgb(240, 180, 42),Color.FromArgb(223, 0, 159),Color.FromArgb(227, 23, 179),Color.FromArgb(255, 251, 240),Color.FromArgb(160, 160, 164),Color.FromArgb(128, 128, 128),Color.FromArgb(255, 0, 0),Color.FromArgb(0, 255, 0),Color.FromArgb(255, 255, 0),Color.FromArgb(0, 0, 255),Color.FromArgb(255, 0, 255),Color.FromArgb(0, 255, 255),Color.FromArgb(255, 255, 255)
};

而对于16bit的图片来说,又有几种颜色模式之分,我们这里只需要知道,传奇的16bit图是用的RGB565模式。

至此,wzl文件差不多就这样了,是不是可以解析了?不是,因为上面说过,图片和图片之间可能存在空图,而空图不仅只是一个image header而已,后面可能跟着若干字节数据(不清楚这个数据有什么用),而这个长度也没办法知道,所以单单靠wzl一个文件想提取图片和其对应的索引号是不可能的,于是wzx文件诞生了。

wzx文件非常简单,就是一个索引数组,记录每张图片在wzl文件中的偏移量

非常简单,除了file header外剩下的数据就是一个偏移量数组。

正确提取图片的方法是:

1、读取wzx文件,取出偏移量数组

2、读取wzl文件中对应的image struct

3、解压图片数据

4、根据image struct中记录的图片位深、宽高信息导出图片

热血传奇资源文件wzl、wzx解析相关推荐

  1. 【Cocos2d-x】模仿热血传奇开门动画

    一.准备素材 传奇登录场景背景资源在ChrSel.wzl文件中,背景图索引是22号,开门动画是24~32号(共9张). 至于图片提取,可以参考之前写过的一篇关于热血传奇资源文件的文章https://b ...

  2. 《热血传奇2》wix、wil文件解析Java实现

    在百度上搜索java+wil只有iteye上一篇有丁点儿内容,不过他说的是错的!或者说是不完整的,我个人认为我对于热血传奇客户端解析还是有一定研究的,请移步: <JMir--Java版热血传奇2 ...

  3. javascript高仿热血传奇游戏

    前言 游戏的第一个版本开发于14年,浏览器端使用html+css+js,服务端使用asp+php,通讯采用ajax,数据存储使用access+mySql.不过由于一些问题(当时还不会用node,用as ...

  4. [Python]:热血传奇-Wzl,Wzx的解析

    首先我们要了解,wzl与wzx的对应关系,wzx里面存的是每张二进制图片数据在wzl中的偏移量,所以取到wzx中的偏移数据就可以取到wzl每张图片数据,其实就这么简单. 1[取wzx中偏移量数据]:以 ...

  5. 《热血传奇》wix、wil文件解析Java实现

    解析的教程在网络上一抓一大把,我都分不清那个是原创了.不过有一点肯定的是,目前都没有Java版本,恩恩:),处于好奇,我稍稍用Java写了一个以供消遣. 写的过程中发现,其实教程有部分是错误的.而且很 ...

  6. springboot配置国际化资源文件 使用themself模板进行解析

    2019独角兽企业重金招聘Python工程师标准>>> @ConfigurationProperties(prefix = "spring.messages") ...

  7. Symbian 资源文件解析

    一.何为资源文件:<?XML:NAMESPACE PREFIX = O /> 在symbian应用程序中,资源文件指的是后缀名为.rss的文件,每个应用程序至少要有一个与之关联的资源文件. ...

  8. PHP下载m3u8视频及解析下载ts资源文件

    上一篇写了PHP生成合并ts脚本,后来又想直接下载m3u8里面的ts,又码了一段. <?php /** PHP下载m3u8视频和及解析下载ts资源文件** @file m3u8download. ...

  9. Java笔记-读取资源文件应该注意的问题(大文件解析、\r\n分割相关的)

    目前在弄一个模拟程序,数据是从XXXXXXX里XXXXX获取的,也算是真实的把,将其放到资源文件中. 如下代码在IDEA开发环境里面是正常的: byte[] bytesxxx = new byte[i ...

最新文章

  1. 31万奖金算法赛事来了!
  2. mysql groupby having_mysql group by having的使用方法
  3. ng-repeat支持的输入种类
  4. Python应用与实践【转】
  5. SVN 放弃修改或撤销删除
  6. 【建议收藏】这个工具专门用于寻找路由器中的安全漏洞
  7. poj1061-青蛙的约会(拓展欧几里得java)
  8. C++选择排序(附完整源码)
  9. ASA/PIX: Load balancing between two ISP - options
  10. 对计算机组装和维护课的总结,计算机组装与维护教师工作总结
  11. 10个你必须知道的jQueryMobile代码片段
  12. java程序开发个人笔记_Java程序开发入门笔记
  13. 论文笔记:Few-Shot Segmentation Without Meta-Learning : A Good Transductive Inference Is All You Need
  14. Ubuntu 18.04 通过 ufw route 配置网关服务器
  15. CFS调度主要代码分析一
  16. 田字格写汉字word模板下载可打印【教程】
  17. 【生信可视化】ChemDraw基础操作教程
  18. Fork\Join分而治之--RecursiveTask和RecursiveAction(一)
  19. JAVA使用wkhtmltopdf 将Html 导出PDF
  20. Google Guava 的 5 个鲜为人知的特性

热门文章

  1. 复数的加法(友元函数)
  2. 【Windows11】【3050Ti显卡】下进行PaddleDetetion安装指南
  3. excel爬虫相关学习1:简单的excel爬虫
  4. 如何调试Pro/TOOLKIT程序
  5. cannot open https //centos7.iuscommunity.org/ius-release.rpm. skipping
  6. web平台安装程序_Galaxy 生信平台(一):安装
  7. 500 字写一篇程序员的个人发展计划
  8. Qt中Widget Aplication项目的文件内容介绍
  9. Error type 3 Error: Activity class {com.xxx/com.xxx.MainActivity} does not
  10. 读书/观影-《红箭 红箭》话剧-观后感/我的第一篇的博文