手机电子书UMD转换BRM格式详解

百阅视听是一款手机上看图书的软件. 比起掌上书院确实好很多, 首先从压缩比例,和打开文档速度来说 百阅视听都占有很大的优势,所以我找空开发了一个转换的软件 可是百阅视听实在是太令人失望了.我以为做个这样的软件可以给百阅带来很多好处 也许是我想错了 不知道是不是看我做出来了这样的转换软件. 会让百阅损失很多东西 百阅竟然改变了只能从他们网站上下载书.  其实什么样的软件别人都可以破解. 我觉得没有必要这样做吧 别人自己制作的为什么就不能用呢? 也许以后有兴趣我会再做个转换的来. 不过暂时是不会了 现在把转换分析的过程和大家分享了下

由于太多人需要特把源码放上 [下载]

  首先想把一个文件转换成另一个文件 必须知道这两个文件的格式. 拿掌上书院来说吧 .UMD 文件 其实用的是C#里的一个压缩控件 icsharpcode.sharpziplib 所以 做这个转换程序的用.net工具来开发是最好的了 .(也不完全是)    经过分析 UMD的文件存储格式分为两种(普通的和漫画)这里只讲普通的格式
UMD首先会在文件头写入一个
     UINT类型 值为 0xde9a9b89 可能是用于识别版本类别什么的.
然后的格式大概如下
#
short 1  //文件信息
byte 0
byte 8   //这个值用是用来定义后面长度的.  实际长度为 值-5
byte 2   //这里1为普通书 2为漫画书
short random1.Next(0x401, 0x7fff) % 0xffff //PGKSeed

#
short 2 //文件标题
byte 0
byte  *  //标题长度=*-5
byte[] * //写入标题

#
short 3 //作者名称
byte 0
byte  *  //作者名称长度=*-5
byte[] * //写入作者名称

接下来的是可选的其格式和上面的一样
#4 //年  #5 //月 #6 //日 #7 //书的类别 #8 //出版人 #9 //出售人

写入文章长度
#
short 11
byte 0
byte 9
int * //长度
写入章节数
#
short 0x83
byte 1
byte 9
uint 0x3000 + random1.Next(0xfff); //这个值用来关联0x83
$
uint * //这个值就是上面关联0x83随机产生的值
uint 9 + (章节长度 * 4) //章节长度
byte[] * 写入每章的偏移值

写入章节标题
#
short 0x84
byte 1
byte 9
uint 0x4000 + random1.Next(0xfff); //这个值用来关联0x84
$
uint * //这个值就是上面关联0x84随机产生的值
uint 9 + 所有标题相加的长度
byte[] * 写入所有章节标题

写入压缩后的内容
$
uint random1.Next(1, 0xfffffff) * -1
uint 9+压缩后的长度
byte[] * //写入压缩后的内容

在压缩的时候 有可能把文章分成了很几段 所以 前面写压缩内容也许会接着再写一次 并且在中间随机写入
#
short 10
byte 0
byte 9
int CID //标识用的

写入结束
#
short 0xf1
byte 0
byte 0x15
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0
最后还要写封面数据 代号 # 0x81 这里就不多讲了.
好了知道文件格式后 并掌握其它格式规律 我们就可以做一个类
并用循环方法把内容读出来

主要循环方法

char ch1 = (char) ((ushort) reader.PeekChar());
          while (ch1 == '#')
           {
 reader.ReadChar(); //读#号 提升一个字节
 short num2 = reader.ReadInt16(); //读取类型 上面#号后面根的编码
 byte num3 = reader.ReadByte(); 
 byte num4 = (byte) (reader.ReadByte() - 5);//读取长度
                //ReadSection 这个函数会根据num2将数据写入自己的属性
              this.ReadSection(num2, num3, num4, reader);
 ch1 = (char) ((ushort) reader.PeekChar());
                //防止随机插入的标识
 if ((num2 == 0xf1) || (num2 == 10))
 {
 if (ch1=='$'&&this.type=="2")
    num2 = this.imgtype;
 else
 num2 = 0x84;
 } 
                //为$是实体内容   
 while (ch1 == '$')
 {
 reader.ReadChar();
 uint num5 = reader.ReadUInt32();
 uint num6 = reader.ReadUInt32() - 9;
                 //ReadAdditional 根据num2 来读入章节标题 和被压缩的章节内容
 this.ReadAdditional(num2, num5, num6, reader);
 ch1 = (char) ((ushort) reader.PeekChar());
 }
}

接着我们可以把压缩后的数据再解压  这里就不详解.
BRM文件格式分析:
  对于BRM文件还不是很了解 只知道他们的做法是生成一个XML文档 然后再用一个编译器编译 .所以需要做的就是生成格式一样的XML文档 用他们的编译器来编译
 下面是BRM的XML文件格式分析的一个例子和解释

<BRM.Document.XML>//头部
<Version>1</Version>//版本
<Title>我的书屋</Title>//标题
<Author>游戏人生</Author>//作者
<Producer>游戏人生</Producer>//制作
<ProduceDate>2005-10-18</ProduceDate>//日期
<ContentID>5ECA850C-0038-4434-8786-DA0EC59CCCBB</ContentID>//GUID标识
<Retailer>游戏人生</Retailer>//发售人
<Gender>游戏人生</Gender>//类别
<GlobalText length="90049">//length为内容长度
//这里是内容
//内容格式为  \n\n\n章节\n\n\n+内容
</GlobalText>
<PictureLayout count="1">//图片
<pl global="0" orientation="0" width="176" height="208">1018//这里是图片的id 是通过当前日期来生成的</pl></PictureLayout>
<MultiMediaClips count="1">
<clip id="1018" mime="image/jpeg">//这里是图片数据</clip>
</MultiMediaClips>
<HyperLinks count="4"> //章节内容 count = 章节数量
<href id="1019" to="153" global="3" length="6">第一章 刘烟</href>
//href id=上面的id+1
//to= 当前开始的位置 因为内容前面有3个分行符 所以从3开始
//length = 当前章节标题的长度
<href id="1020" to="2741" global="10" length="8">第二章 奇异世界</href>
<href id="1021" to="10963" global="19" length="8">第三章 女奴拍卖</href>
<href id="1022" to="17975" global="28" length="8">第四章 奇特遭遇</href>
</HyperLinks>
</BRM.Document.XML>

现在知道UMD的内容读出来了. 并且也知道BRM的XML格式了
就可以利用.net里的XML类来写文件了.
最后用他们的编译器进行编译

System.CodeDom.Compiler.TempFileCollection tf = new System.CodeDom.Compiler.TempFileCollection();
   System.CodeDom.Compiler.Executor.ExecWait(@"Genbrm.exe "+path,tf);

大功告成 .转换后就可以放到手机上看了

Share