适用于嵌入式单片机的压缩算法
1. 简介
因为MCU的内存和算力的限制,那些对内存消耗大或算力需求大的压缩算法就不适合在MCU中使用。适用于MCU的压缩算法主要有:RLE、LZ77、Huffman、LZO、DEFLATE、LZ4。
2. 算法
2.1. RLE
RLE(Run Length Encoding),也称为行程编码,压缩算法是一种无损压缩算法。算法特点:简单、易实现。使用RLE压缩方法可以将 RRRRRGGBBBBBBABCD 压缩为 5R2G6B1A1B1C1D。基于RLE算法升级,可以将RRRRRGGBBBBBBABCD可以压缩为b’\x85R\x82G\x86B\x03ABCD’,0x85表示后面有5个相同的字符,0x03表示后面有3个不连续的字符。
RLE的实现非常简单,针对一些图片颜色少或重复字符多的文件有非常好的压缩率,RLE的适用场景比较少,通用压缩率较差。
2.2. LZ77
LZ77是一种基于字典的算法,它将长字符串(也称为短语)编码成短小的标记,用小标记代替字典中的短语,从而达到压缩的目的。LZ77算法的压缩率、速度、内存消费都是中等,但是代码复杂度较低,适用于MCU的使用。
2.3. LZO
LZO压缩算法采用(重复长度L,指回距离D)代替当前已经在历史字符串中出现过的字符串。LZO致力于解压速度,不同的参数下的LZO压缩率不同。LZO内存消耗中等,解压速度较快,压缩速度较快,但是代码复杂度较低,适用于Bootloader等追求压缩率和解压速度的场景。
2.4. Huffman
霍夫曼(Huffman)编码使用变长编码表对源符号进行编码,其中变长编码表是通过一种评估来源符号出现机率的方法得到的,出现机率高的字母使用较短的编码,反之出现机率低的则使用较长的编码,这便使编码之后的字符串的平均长度、期望值降低,从而达到无损压缩数据的目的。霍夫曼编码使用的编码表,使用霍夫曼树来进行存储,让出现概率最高的编码最容易查找,以提升解码速度。霍夫曼编码算法的压缩率分布在20%-90%,因为要扫描整个数据来构建霍夫曼树,所以其压缩速度较慢,且需要一定的内存来存储编码表,但是解压速度较快。霍夫曼的算法复杂度较简单。
2.5. DEFLATE
DEFLATE是同时使用了LZ77算法与哈夫曼编码(Huffman Coding)的一个无损数据压缩算法。DEFLATE压缩与解代码可以在自由、通用的压缩库zlib上找到。DEFLATE算法压缩速度、解压速度均处于中等,却有着比较好的压缩率,所以是zlib、gzip使用的主要压缩算法。DEFLATE的算法复杂度较高,但是性能表现优秀,适用于比较大型的MCU系统。
2.6. LZ4
LZ4是一种LZ系列压缩算法,着重于压缩和解压的速度,压缩率相对较低。LZ4压缩率较低,算法复杂度和内存消耗中等,但是压缩和解压速度,尤其是解压速度远超其他算法。因为其综合性能优秀,在Linux、Android中的内存压缩技术一般使用LZ4压缩算法。LZ4 HC,有着更好的压缩率,但是算法复杂度大幅提升,且压缩速度也大幅减慢,但是依然有着很好的解压速度,适合Bootloader这种应用场景。LZ4的内存消耗从几百字节到几十K字节。
3. 基准测试
3.1. 工具用法
- RLE
● 测试文件
I:\Linux>RLE.exe d:\a.exe
d:\a.exe
Orignal Size:132096-Compressed Size:125400
Compressed rate:94%
● 测试目录
I:\Linux>RLE.exe E:\ATLDemo\Demo\Debug
E:\ATLDemo\Demo\Debug\ATLProject1.exe
Orignal Size:9160192-Compressed Size:7105584
Compressed rate:77%
E:\ATLDemo\Demo\Debug\ATLProject1.map
Orignal Size:19710649-Compressed Size:16943928
Compressed rate:85%
- Huffman
● 测试文件
I:\Linux>Huffman.exe d:\a.exe
d:\a.exe
Orignal Size:132096-Compressed Size:123772
Compressed rate:93%
● 测试目录
I:\Linux>Huffman.exe E:\ATLDemo\Demo\Debug
E:\ATLDemo\Demo\Debug\ATLProject1.exe
Orignal Size:9160192-Compressed Size:7695483
Compressed rate:84%
E:\ATLDemo\Demo\Debug\ATLProject1.map
Orignal Size:19710649-Compressed Size:15878850
Compressed rate:80%
- LZ77
I:\Linux>lzbench18.exe -elz4 d:\a.exe
lzbench 1.8 (64-bit Windows) Assembled by P.Skibinski
Compressor name Compress. Decompress. Compr. size Ratio Filename
memcpy 35490 MB/s 35924 MB/s 132096 100.00 a.exe
lz4 1.9.2 616 MB/s 4388 MB/s 91011 68.90 a.exe
done... (cIters=1 dIters=1 cTime=1.0 dTime=2.0 chunkSize=1706MB cSpeed=0MB)
- LZO
I:\Linux>lzbench18.exe -elzo1 d:\a.exe
lzbench 1.8 (64-bit Windows) Assembled by P.Skibinski
Compressor name Compress. Decompress. Compr. size Ratio Filename
memcpy 35442 MB/s 36160 MB/s 132096 100.00 a.exe
lzo1 2.10 -1 150 MB/s 433 MB/s 90130 68.23 a.exe
lzo1 2.10 -99 70 MB/s 415 MB/s 85293 64.57 a.exe
done... (cIters=1 dIters=1 cTime=1.0 dTime=2.0 chunkSize=1706MB cSpeed=0MB)
- LZ4
I:\Linux>lzbench18.exe -elz4 d:\a.exe
lzbench 1.8 (64-bit Windows) Assembled by P.Skibinski
Compressor name Compress. Decompress. Compr. size Ratio Filename
memcpy 35085 MB/s 34689 MB/s 132096 100.00 a.exe
lz4 1.9.2 615 MB/s 4388 MB/s 91011 68.90 a.exe
done... (cIters=1 dIters=1 cTime=1.0 dTime=2.0 chunkSize=1706MB cSpeed=0MB)
I:\Linux>lzbench18.exe -elz4hc d:\a.exe
lzbench 1.8 (64-bit Windows) Assembled by P.Skibinski
Compressor name Compress. Decompress. Compr. size Ratio Filename
memcpy 34462 MB/s 35944 MB/s 132096 100.00 a.exe
lz4hc 1.9.2 -1 79 MB/s 3851 MB/s 81847 61.96 a.exe
lz4hc 1.9.2 -2 79 MB/s 3840 MB/s 81847 61.96 a.exe
lz4hc 1.9.2 -3 69 MB/s 3862 MB/s 81207 61.48 a.exe
lz4hc 1.9.2 -4 63 MB/s 3885 MB/s 80896 61.24 a.exe
lz4hc 1.9.2 -5 59 MB/s 3885 MB/s 80750 61.13 a.exe
lz4hc 1.9.2 -6 56 MB/s 3896 MB/s 80650 61.05 a.exe
lz4hc 1.9.2 -7 53 MB/s 3908 MB/s 80604 61.02 a.exe
lz4hc 1.9.2 -8 51 MB/s 3919 MB/s 80586 61.01 a.exe
lz4hc 1.9.2 -9 47 MB/s 3943 MB/s 80568 60.99 a.exe
lz4hc 1.9.2 -10 29 MB/s 3919 MB/s 80454 60.91 a.exe
lz4hc 1.9.2 -11 22 MB/s 3931 MB/s 80442 60.90 a.exe
lz4hc 1.9.2 -12 20 MB/s 3896 MB/s 80420 60.88 a.exe
done... (cIters=1 dIters=1 cTime=1.0 dTime=2.0 chunkSize=1706MB cSpeed=0MB)
- DEFLATE
I:\Linux>lzbench18.exe -elibdeflate d:\a.exe
lzbench 1.8 (64-bit Windows) Assembled by P.Skibinski
Compressor name Compress. Decompress. Compr. size Ratio Filename
memcpy 35711 MB/s 36420 MB/s 132096 100.00 a.exe
libdeflate 1.3 -1 92 MB/s 382 MB/s 69917 52.93 a.exe
libdeflate 1.3 -2 88 MB/s 387 MB/s 69425 52.56 a.exe
libdeflate 1.3 -3 85 MB/s 391 MB/s 69207 52.39 a.exe
libdeflate 1.3 -4 81 MB/s 394 MB/s 69085 52.30 a.exe
libdeflate 1.3 -5 70 MB/s 411 MB/s 68098 51.55 a.exe
libdeflate 1.3 -6 67 MB/s 408 MB/s 68034 51.50 a.exe
libdeflate 1.3 -7 62 MB/s 409 MB/s 67972 51.46 a.exe
libdeflate 1.3 -8 22 MB/s 413 MB/s 67138 50.83 a.exe
libdeflate 1.3 -9 17 MB/s 403 MB/s 66693 50.49 a.exe
libdeflate 1.3 -10 16 MB/s 401 MB/s 66627 50.44 a.exe
libdeflate 1.3 -11 13 MB/s 400 MB/s 66604 50.42 a.exe
libdeflate 1.3 -12 10 MB/s 407 MB/s 66598 50.42 a.exe
done... (cIters=1 dIters=1 cTime=1.0 dTime=2.0 chunkSize=1706MB cSpeed=0MB)
3.2. 脚本测试
脚本是基于Cygwin环境执行的shell脚本。用法如下:
26/01/2024 11:15.41/drives/i/Linux/compression_test.sh
请输入待测目录:
e:\ATLDemototal size 297101065 , total compressed size: 210777636
RLE compression rate: 70%total size 297101065 , total compressed size: 205327668
Huffman compression rate: 69%total size 297059235 , total compressed size: 109202247
LZ4 compression rate: 36%total size 296918510 , total compressed size: 115966722
LZO compression rate: 39%
4. 总结
4.1. 性能
● 综合压缩率排名:DEFLATE > LZ4HC > LZO > LZ77 > Huffman > LZ4 >> RLE。
● 压缩速度排名:LZ4 > LZO > RLE > LZ77 > DEFLATE > Huffman > LZ4HC。
● 解压速度排名:RLE > LZ4=LZ4HC >> Huffman > LZO > DEFLATE > LZ77。
● 算法复杂度排名:RLE < Huffman < LZ77 < LZ4 < LZO < LZ4HC < DEFLATE。
● 算法内存消耗排名:RLE < LZ4 < LZO < LZ77 < Huffman < DEFLATE < LZ4 HC。
4.2. 应用场景
不同的压缩算法,有不同的应用场景。
- 高压缩率,压缩速度慢,但是解压速度快的算法,适用于Bootloader。高压缩率,可以节省ROM空间,高解压速度对Boot速度影响小。因为是外部工具压缩,压缩速度不影响Bootloader的功能。适用于此场景的压缩算法有lzo、lz4hc。
- 追求压缩率,且算力和内存资源充足,并且压缩和解压均不错的算法,选择DEFLATE。
- 有一定的压缩率(50%),追求压缩和解压速度,且算法相对简单,优先LZ4,再选择LZ77,再先LZO.
- 在一定的压缩率(50%)的基础上,追求算法简单,优先LZ77。
4.3. LZ77 vs LZ4
● 如果LZ77的算法复杂度为100,则LZ4的为130。压缩和解压C代码,LZ77在400行左右,LZ4在500行左右。
● 如果LZ77的内存消耗为100,则LZ4的内存消耗为50。LZ77的内存消耗十几K到几十K,LZ4的内存从几百字节到十几K字节。
● 如果LZ77的压缩速度为100,则LZ4的压缩速度为700。
● 如果LZ77的解压速度为100,则LZ4的解压速度为800。
总结,LZ4的综合性能远优于LZ77。这也是LZ4应用于Linux和Android内存压缩的重要原因。
4.3. 代码
代码
相关文章:
适用于嵌入式单片机的压缩算法
1. 简介 因为MCU的内存和算力的限制,那些对内存消耗大或算力需求大的压缩算法就不适合在MCU中使用。适用于MCU的压缩算法主要有:RLE、LZ77、Huffman、LZO、DEFLATE、LZ4。 2. 算法 2.1. RLE RLE(Run Length Encoding),也称为行程编码&…...

软件工程(最简式总结)
目录 第一章:概述 1.软件危机的表现原因 2.常见的软件开发方法包括: 3.软件工程基本原则 4.软件工程三要素 5.设计模式的分类 6.针对变换型数据流设计步骤 7.针对事务型数据流设计步骤 第二章:软件过程 1.软件生命周期 2.软件过程模型 &…...

Docker基础(持续更新中)
# 第1步,去DockerHub查看nginx镜像仓库及相关信息# 第2步,拉取Nginx镜像 docker pull nginx# 第3步,查看镜像 docker images # 结果如下: REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 60…...

Vue工程引入Element-ui
npm 安装ELement-ui npm i element-ui -S 于package.json中发现有“element-ui”版本号即可 引入 Element 在 main.js 中写入以下内容: import element-ui/lib/theme-chalk/index.css; import ElementUI from element-ui;Vue.use(ElementUI);之后根据自己的需求设计…...

算法学习——华为机考题库9(HJ56 - HJ63)
算法学习——华为机考题库9(HJ56 - HJ63) HJ56 完全数计算 描述 完全数(Perfect number),又称完美数或完备数,是一些特殊的自然数。 它所有的真因子(即除了自身以外的约数)的和&…...

Maven安装,学习笔记,详细整理maven的一些配置
Maven 1. 初识Maven 2. Maven概述 Maven模型介绍 Maven仓库介绍 Maven安装与配置 3. IDEA集成Maven 4. 依赖管理 01. Maven课程介绍 1.1 课程安排 学习完前端Web开发技术后,我们即将开始学习后端Web开发技术。做为一名Java开发工程师,后端 Web开发技术…...

STM32--USART串口(2)串口外设
一、USART简介 可配置数据位:不需要校验就是8位,需要校验就选9位; 停止位:决定了帧的间隔; STM32F103C8T6USART:USART1挂载在APB2总线上,USART2和USART3挂载在APB1总线上; 二、USART框图 TXE…...

Unity之做一个最简单的FPS游戏demo
目录 😋FPS游戏Demo 💤1.新建FPS模板项目 ⚒️2.装备枪 💣3.设置射击功能 📺4.制造一个子弹预制体 🎮5.发射子弹 说起来小编学Unity差不多一个月了,都是利用上班摸鱼时间学的(doge.jpg&…...
【Springboot】单元测试Junit5应用
JUnit 5是一个功能强大的测试框架,常用于编写和执行这些单元测试。以下是一些JUnit 5中的常用注解、断言、前置条件、嵌套测试和参数化测试的例子: 1.环境启动 SpringBootTest 注解: classes SmartApplication.class:这个属性…...
【INTEL(ALTERA)】内部错误:子系统:PTI,文件:/quartus/tsm/pti/pti_delay_annotator.cpp
说明 由于英特尔 Quartus Prime Pro Edition 软件 23.2 及更早版本存在问题,因此在编译设计的 Retime 期间可能会出现此错误。 解决方法 此问题已在英特尔 Quartus Prime Pro Edition 软件 v23.3 中修复。 要在版本 23.2 中解决此问题,请通过以下相应链…...

大数据 - Spark系列《二》- 关于Spark在Idea中的一些常用配置
上一篇: 大数据 - Spark系列《一》- 从Hadoop到Spark:大数据计算引擎的演进-CSDN博客 目录 1. 🥙Idea中配置Live Templates来快速生成代码片段 2. 🥙Idea中配置文件模板自定义初始代码 3.🥙设置spark-submit提交程…...
android 设置未知来源等 AppOpsManager 权限的设置接口
开始客户让我们执行下面的CMD 代码 adb shell appops set com.android.chrome REQUEST_INSTALL_PACKAGES allow 后来 GTP 告诉我有 Setmode的方法,后面在设置里面找到了 OP_REQUEST_INSTALL_PACKAGES 这个,里面有个方法mAppOpsManager.setMode(AppOp…...
使用GPT实现一个简单的网站
背景 In this exciting tutorial video, you’ll discover how to use 文心一言, a powerful language model developed by 百度, to generate ReactJS code for a simple blog website. With 文心一言’s help, you can quickly create a blog website that’s easy to custom…...

回归预测 | Matlab实现CPO-CNN-LSTM-Attention冠豪猪优化卷积长短期记忆神经网络注意力机制多变量回归预测(SE注意力机制)
回归预测 | Matlab实现CPO-CNN-LSTM-Attention冠豪猪优化卷积长短期记忆神经网络注意力机制多变量回归预测(SE注意力机制) 目录 回归预测 | Matlab实现CPO-CNN-LSTM-Attention冠豪猪优化卷积长短期记忆神经网络注意力机制多变量回归预测(SE注…...
11:Servlet中初始化参数的获取与应用-Java Web
目录 11.1 Servlet初始化参数简介11.2 如何在Servlet中获取初始化参数11.3 基于注解的初始化参数(Servlet 3.0)11.4 区别总结11.5 应用场景总结 在构建Java Web应用程序时,Servlet是核心组件之一,它负责处理HTTP请求并生成响应。而…...
STM32的ADC采集传感器的模拟量数据
1、 由于项目上使用传感器采集数据,传感器可以输出模拟电压信号,但是模拟电压信号的输出范围是1-5V,而STM32的ADC采集电压范围是0-3.3V,此时可以用一个简单的分压电路将1-5V的电压将至0.5V到2.5V的范围。 2、电阻分压电路可以使用…...

opencvb 十七 使用cmake配置opencv c++项目
1、cmake简介 1.1 cmake是什么 CMake是一个开源、跨平台的编译(Build)工具,是用来构建、测试和打包软件的。它能够用简单的语句来描述所有平台的编译过程。它能够输出各种各样的makefile或者project文件,能测试编译器所支持的C特…...

Java8 中文指南(一)
Java8 中文指南(一) 文章目录 Java8 中文指南(一)《Java8 指南》中文翻译接口的默认方法(Default Methods for Interfaces)Lambda 表达式(Lambda expressions)函数式接口(Functional Interfaces)方法和构造函数引用(Method and Co…...

引流技术-通过文件中增加联系方式并传播
文章目录 前言文档增加联系方式扩散网盘扩散自建网站借力 注意 前言 很多人在找资料的时候可能都遇到过下图情况: 1、文档最后面留一个自己的联系方式; 2、找的一堆文件中都有相同的情况; 3、一段时间全网搜到的很多相同文件也有这个联系方式…...

分布式搜索引擎_学习笔记_2
分布式搜索引擎_学习笔记_2 在昨天的学习中,我们已经导入了大量数据到elasticsearch中,实现了elasticsearch的数据存储功能。但elasticsearch最擅长的还是搜索和数据分析。 所以今天,我们研究下elasticsearch的数据搜索功能。我们会分别使用…...

【学习笔记】树上差分总结(点差分/边差分)
一.树上差分的基本概念 1.树上差分的定义 树上差分,顾名思义,意思就是在树上做差分。 至于什么是差分呢?如果不会的同学,可以先看看我的这篇博客:一维,二维差分の详解(简单易懂)_一维差分-CSDN博客 2.树…...

Vue.js设计与实现(霍春阳)
Vue.js设计与实现 (霍春阳) 电子版获取链接:Vue.js设计与实现(霍春阳) 编辑推荐 适读人群 :1.对Vue.js 2/3具有上手经验,且希望进一步理解Vue.js框架设计原理的开发人员; 2.没有使用过Vue.js,但对Vue.js框架设计感兴趣…...

go消息队列RabbitMQ - 订阅模式-fanout
1、发布订阅 订阅模式,消息被路由投递给多个队列,一个消息被多个消费者获取。 1) 可以有多个消费者 2) 每个消费者有自己的queue(队列) 3) 每个队列都要绑定到Exchange(交换机&…...
科普类——5G远程实时操控技术在国内港口应用简介(十三)
在中国,5G远程实时操控技术已经在多个港口得到应用,并且应用规模不断扩大,展现出良好的发展前景。以下是一些具体的应用案例: 上港集团洋山港:上港集团与华为合作,在全球港口首次将F5G技术应用于超远程控制…...

整理:汉诺塔简析
大体上,要解决一个汉诺塔问题,就需要解决两个更简单的汉诺塔问题 以盘子数量 3 的汉诺塔问题为例 要将 3 个盘子从 A 移动到 C,就要: 将两个盘子从 A 移动到 B(子问题 1) 为了解决子问题 1,就…...
Android 8.1 设置--声音中增加通话音量
Android 8.1 设置--声音中增加通话音量 近来收到项目需求,想要在设置--声音中增加一项通话音量调节,具体修改参照如下: /vendor/mediatek/proprietary/packages/apps/MtkSettings/res/values/strings.xml <!-- Sound: Title for the opt…...

C#中使用OpenCvSharp4绘制直线、矩形、圆、文本
C#中使用OpenCvSharp4绘制直线、矩形、圆、文本 继之前的Python中使用Opencv-python库绘制直线、矩形、圆、文本和VC中使用OpenCV绘制直线、矩形、圆和文字,将之前的Python和C示例代码翻译成C#语言,很简单,还是借用OpenCvSharp4库中的Line、…...

Qt程序设计-自定义控件(提升法)
本文讲解如何使用提升法自定义控件,控件有界面。 实现自定义一个开关控件,控件上显示当前的状态。实现过程如下: 1、在创建的项目上,添加qt设计界面类。 2、选择widget 3、更改名称为MySwitchButton 4、添加两个图标资源文件,用来显示开关状态 5、添加两个label,一个…...
计算机网络基础知识笔记
1 HOST和PORT Claude-2-100k: 我来用简单的语言解释一下HOST和PORT这两个网络术语: HOST就是设备的IP地址,比如"127.0.0.1"就是我们本机的IP地址; PORT就是端口号,可以把它简单理解为设备上的门牌号。 举个类比,我们要给某个人发信件,需要知道…...

【iOS ARKit】2D肢体动作捕捉
人体肢体动作捕捉在动漫影视制作、游戏CG 动画、实时模型驱动中有着广泛的应用,利用 ARKit,无须额外的硬件设备即可实现 2D和3D人体一系列关节和骨骼的动态捕捉,由于移动AR 的便携性及低成本,必将促进相关产业的发展。 ARBody Tr…...