jmpjmpje 2023-09-24 15:29 采纳率: 40%
浏览 31
已结题

这是什么压缩算法?如何解压?

《这是什么压缩算法?如何解压?》

鉴于一些原因,这里无法直接贴出原代码。

//--------------------//

首先,产生一个表,初始大小是 256 + 2 头尾2字节为空格,中间的 256字节 对应数据 0 - 255

即,这个表初始是这样的: 空格(20h), 0, 1, 2, 3 .... 254, 255, 空格(20h),所以它的初始大小是 258字节

初始化 2个 重要的 double值, A = 1, B = 0

//--------------------//

循环开始(压缩开始), 对 [原数据 - SrcData] 进行 "逐字节" 地处理。

假设, SrcData[0] 是 74h, 那么:

X = 74h 在[表]中的偏移值。(如, 由于是第0字节, [表]还是初始状态, 所以 X = 75h, 注意 [表] 在后面还会变动! 下面会描述)

Y = (74h + 1) 在[表]中的偏移值。(接上例, Y = 76h)

//--------------------//

计算那2个 double值:

double dbVal = (A - B) / 表的当前长度; (注意表是变动的, 长度也会变动, 下面会描述)
A = B + (dbVal * Y); //接上例, A = 0.45736434108527130
B = B + (dbVal * X); //接上例, B = 0.45348837209302323

将这2个double值转换到 '二进制' 的表示形式,则:

A = 0.011101010001010111010100010101110101000101011101010001

B = 0.011101000001011111010000010111110100000101111101000001

截取出 A B 的 [小数部分] 的 "头部相同部分"

A = 0.011101010 ...
B = 0.011101000 ...

这里可以看到, 相同部分的长度(设为 Z ) = 7, 即为:0111010

那么,这个 0111010 就是最终结果! 即 74h 最终变成了 0111010

注:这里有个需要特别注意的情况, 就是 '相同部分' 的长度为 0, 此时, 直接就是没有结果, 不记录!

例如(只是假设), 原数据: 58 69 05, 58 = 000 69 = 没有结果 05 = 110, 那么这3字节的压缩后会是 000110

//--------------------//

A B 值 步进:

A = A * (1 << Z); //如 A = 0.45736434108527130, Z = 7, 则此处结果为 58.54263565891472609
A = A - 整数部分; //也就是说, 只取 [小数部分], 那么 A 最终结果是 0.54263565891472609

而 B 值也是同样的计算:

B = B * (1 << Z);
B = B - 整数部分; //接上例, 此时 B 值为 0.046511627906973274

//--------------------//

在最后, 对 [表] 进行变动!

取 Y 值; (注: Y = (原数据 + 1) 在[表]中的偏移值)

在 "表[Y]" 处, 插入(增加) 14个 0, 注意表的长度也增加 14 //注, 14 这个值是可以通过输入参数来配置的, 比如, 可以设为 27, 那么压缩结果会不同(这个有点像压缩级别?)

//--------------------//

至此, 当前1个字节处理完毕; 将继续处理下一个字节: 即 SrcData[1], SrcData[2], ... 直至处理完;

在处理完之后, 记录 B 的 "最后值":

假设 SrcData 只有 1个字节, 即, 74h, 处理后为 0111010

处理完后 B 值为: 0.046511627906973274, 其二进值为: 0.00001011111010000010111110100000101111101000001 (只取 [小数部分])

特别注意! 此时 B值 的二进制,如果后面有 0 存在,是要删除掉的! 长度是不固定的!至少看起来没有方法来确定它的长度。

那么最终得到的, 压缩后的数据是: 0111010 + 00001011111010000010111110100000101111101000001, 即: 011101000001011111010000010111110100000101111101000001

然后, 还会将 "原数据的原始长度"(即 解压后长度), 通知给 <解压方>

//--------------------//

经实测, "test12345", 压缩后的最终结果为: 011101000111011101111110111100001101111101110110110001010110111101001101100100001110110101011011101101101111001

然后将二进制转换到十六进制(每次取8bit为1字节): 74 77 7e f0 df 76 c5 6f 4d 90 ed 5b b6 f2 //此转换只是方便存储与转输, 与压缩算法没有实质性的关联

经实测, 一段长度为 256字节的数据, 压缩后可达到 100多字节; 一段 500多的字节的数据, 可以压缩到 400字节左右。

//--------------------//

它的代码并不复杂,我已经用 C语言 自己写了一个函数, 然后对原程序进行多次反复调试, 对不同的数据进行压缩, 然后对比结果, 都是一样的。

现在是不明白它的压缩原理是什么, 或者是叫什么压缩算法, 该如何去解压;

请指教, 谢谢!

  • 写回答

13条回答 默认 最新

  • 2301_76247172 2023-09-24 21:20
    关注

    这是区间编码的另类实现,都由算术编码而来。你先搞清楚 算术编码

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(12条)

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 9月25日
  • 已采纳回答 9月25日
  • 修改了问题 9月24日
  • 修改了问题 9月24日
  • 展开全部

悬赏问题

  • ¥15 基于卷积神经网络的声纹识别
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 stm32开发clion时遇到的编译问题