搜索
bottom↓
回复: 11

有了解lzo压缩算法的吗?

[复制链接]

出0入0汤圆

发表于 2014-1-13 23:51:09 | 显示全部楼层 |阅读模式
看介绍说它有个8KB RAM等级的压缩算法,但看了好久也没有看到是哪个压缩函数。
它的实例里面也没有找到。

项目用MCU,要传输的数据量比较大,需要压缩一下,苦于内存太小。

暂时还没有找LZO的8KB级别的算法怎么用/配置,现在自己写了差分方式来传输数据,稍微缓解一下资源的紧张。

有了解的吗?请介绍一下。

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2014-1-14 22:11:04 | 显示全部楼层
miniLZO

miniLZO is a lightweight subset of the LZO library.

We've created miniLZO for projects where it is inconvenient to include or require the full LZO source code just because you want to add a little bit of data compression to your application.

miniLZO implements the LZO1X-1 compressor and both the standard and safe LZO1X decompressor. Apart from fast compression it also useful for situations where you want to use pre-compressed data files (which must have been compressed with LZO1X-999).

miniLZO consists of one C source file and three header files. It compiles to less than 5 kB (on an i386), and the sources are about 30 kB when packed - so there's no more excuse that your application doesn't support data compression :-)

出0入0汤圆

 楼主| 发表于 2014-1-14 22:18:14 | 显示全部楼层
bitter 发表于 2014-1-14 22:11
miniLZO

miniLZO is a lightweight subset of the LZO library.

试过了,不是

出0入84汤圆

发表于 2014-1-14 23:39:30 | 显示全部楼层
LZO
编辑

LZO 是致力于解压速度的一种数据压缩算法,LZO 是 Lempel-Ziv-Oberhumer 的缩写。这个算法是无损算法,参考实现程序是线程安全的。 实现它的一个自由软件工具是lzop。最初的库是用 ANSI C 编写、并且遵从 GNU通用公共许可证发布的。现在 LZO 有用于 Perl、Python 以及 Java 的各种版本。代码版权的所有者是 Markus F. X. J. Oberhumer。
目录
1特点
2C语言压缩算法
3C语言解压缩算法
1特点

LZO 库实现了许多有下述特点的算法:
* 解压简单,速度非常快。
* 解压不需要内存。
* 压缩相当地快。
* 压缩需要 64 kB 的内存。
* 允许在压缩部分以损失压缩速度为代价提高压缩率,解压速度不会降低。
* 包括生成预先压缩数据的压缩级别,这样可以得到相当有竞争力的压缩比。
* 另外还有一个只需要 8 kB 内存的压缩级别。
* 算法是线程安全的。
* 算法是无损的。
LZO 支持重复压缩以及原地解压。
LZO 是块压缩算法——压缩解压成块的数据。压缩与解压所用块的大小必须一样。
LZO 将数据块压缩成匹配数据(滑动字典)与非匹配文字的序列。LZO 对于较长的匹配数据以及较长的非匹配文字序列有专门的处理,这样对于高度冗余的数据能够取得很好的效果,并且对于不可压缩的数据也能得到可以接受的效果。
当处理不可压缩数据的时候,LZO 将每个 1024 字节的输入数据块扩展 16 字节。
据报道 LZO 也在 AIX、 ConvexOS、IRIX、Mac OS、Palm OS、 PS1(PlayStation)、Solaris、SunOS、TOS (Atari ST) 以及 VxWorks 上得到实现。
2C语言压缩算法

static unsigned _do_compress (byte *in, unsigned in_len, byte *out, unsigned *out_len)
{
static long wrkmem [16384L];
register byte *ip;
byte *op;
byte *in_end = in + in_len;
byte *ip_end = in + in_len -3;
byte *ii; // 指向开始编码的位置
byte **dict = (byte **)wrkmem;
op = out;
ip = in;
ii = ip;
ip += 4;
for(;;)
{
register byte *m_pos;
unsigned m_off;
unsigned m_len;
unsigned dindex; // hashkey(ip[0], ip[1], ip[2], ip[3])
dindex = ((0x21*(((((((unsigned)(ip[3])<<6)^ip[2])<<5)^ip[1])<<5)^ip[0]))>>5) & 0x3fff;
m_pos = dict [dindex];
if(((unsigned)m_pos < (unsigned)in) ||
(m_off = (unsigned)((unsigned)ip-(unsigned)m_pos) ) <= 0 ||
m_off > 0xbfff) // 0xc000 48kb
goto literal;
if(m_off <= 0x0800 || m_pos[3] == ip[3]) // 回指长度小于2Kb
goto try_match;
dindex = (dindex & 0x7ff ) ^ 0x201f; // 处理冲突,第二次hash
m_pos = dict[dindex];
if((unsigned)(m_pos) < (unsigned)(in) ||
(m_off = (unsigned)( (int)((unsigned)ip-(unsigned)m_pos))) <= 0 ||
m_off > 0xbfff)
goto literal;
if (m_off <= 0x0800 || m_pos[3] == ip[3]) // 回指长度小于2Kb
goto try_match; // 第三个字节相等
goto literal;
try_match: // m_pos[0],m_pos[1],m_pos[2]都匹配成功时,继续比较
if(*(unsigned short*)m_pos == *(unsigned short*)ip && m_pos[2]== ip[2])
goto match;
literal: // 匹配不成功时,或者无记录
dict[dindex] = ip; // 记录字符串为ip[0],ip[1],ip[2],ip[3]的地址
++ip;
if (ip >= ip_end)
break;
continue;
match: // 在得到匹配长度与位置之前,先输出未匹配的字符
dict[dindex] = ip; // 更新,字符匹配时的位置(未编码)
if(ip - ii > 0) // 存在新字符
{
register unsigned t = ip - ii; // t:新字符的数目(未匹配的)
if (t <= 3) // 新字符数目<3时
op[-2] |= (byte)t; // 对两个保留字元赋值
else if(t <= 18) // 新字符数目<18时
*op++ = (byte)(t - 3);
else
{
register unsigned tt = t - 18;
*op++ = 0;
while(tt > 255) // 构建新位元组
{
tt -= 255;
*op++ = 0;
}
*op++ = (byte)tt;
}
do
{
*op++ = *ii++; // ii指向开始匹配的位置(未编码)
}while (--t > 0); // 输出 t个新字符
}
ip += 3; // 跳过与m_pos[0] m_pos[1] m_pos[2]的比较
if(m_pos[3] != *ip++ || m_pos[4] != *ip++ || m_pos[5] != *ip++ ||
m_pos[6] != *ip++ || m_pos[7] != *ip++ || m_pos[8] != *ip++ )
{
--ip;
m_len = ip - ii; // 得到重复长度<=8
if(m_off <= 0x0800 ) // 回指长度小于2kb
{
--m_off; // m_off,与m_len在输出时都减1
// m_off在第一位元组(byte)占三位,m_off&7 小于8
*op++ = (byte)(((m_len - 1) << 5) | ((m_off & 7) << 2));
*op++ = (byte)(m_off >> 3); // 去除已用的低3位
}
else
if (m_off <= 0x4000 ) // 回指长度小于16kb
{
-- m_off;
*op++ = (byte)(32 | (m_len - 2));
goto m3_m4_offset;
}
else // 回指长度大于16时
{
m_off -= 0x4000;
*op++ = (byte)(16 | ((m_off & 0x4000) >> 11) | (m_len - 2));
goto m3_m4_offset;
}
}
else // 重复长度大于8时
{
{
byte *end = in_end;
byte *m = m_pos + 9; // 从m_pos[9]开始比较
while (ip < end && *m == *ip)
m++, ip++;
m_len = (ip - ii);
}
if(m_off <= 0x4000) // 回指长度小于16kb
{
--m_off;
if (m_len <= 33) // 可用5bit表示时
*op++ = (byte)(32 | (m_len - 2));
else
{
m_len -= 33;
*op++ = 32;
goto m3_m4_len;
}
}
else // 回指长度大于16kb ,小于48 kb
{
m_off -= 0x4000;
if(m_len <= 9)
*op++ = (byte)(16|((m_off & 0x4000) >> 11) | (m_len - 2));
else
{
m_len -= 9;
*op++ = (byte)(16 | ((m_off & 0x4000) >> 11));
m3_m4_len:
while (m_len > 255)
{
m_len -= 255;
*op++ = 0;
}
*op++ = (byte)m_len;
}
}
m3_m4_offset:
*op++ = (byte)((m_off & 63) << 2);
*op++ = (byte)(m_off >> 6);
}
ii = ip; // 下次匹配的开始位置
if (ip >= ip_end)
break;
}
*out_len = op - out;
return (unsigned) (in_end - ii);
}
3C语言解压缩算法

int _stdcall compress(byte *in, unsigned in_len, byte *out)
{
byte *op = out;
unsigned t,out_len;
if (in_len <= 13)
t = in_len;
else
{
t = _do_compress (in,in_len,op,&out_len);
op += out_len;
}
if (t > 0) // t: 未编码的字符大小,即新字符的数目
{
byte *ii = (byte*)in + in_len - t; // 未编码的开始地址
if (op == (byte*)out && t <= 238)
*op++ = (byte) ( 17 + t );
else
if (t <= 3) // 新字符数目<3时
op[-2] |= (byte)t ;
else
if (t <= 18) // 新字符数目<18 时
*op++ = (byte)(t-3);
else
{
unsigned tt = t - 18;
*op++ = 0;
while (tt > 255)
{
tt -= 255;
*op++ = 0;
}
*op++ = (byte)tt;
}
do
{
*op++ = *ii++;
}while (--t > 0); // 输出t个新字符
}
*op++ = 17; // 结束编码标志
*op++ = 0;
*op++ = 0;
return (op - (byte*)out); // 返回编码后的长度
}
int _stdcall decompress(byte *in, unsigned in_len, byte *out)
{
register byte *op; // 输出临时缓存区
register byte *ip;
register unsigned t;
register byte *m_pos;
byte *ip_end = (byte*)in + in_len;
op = out;
ip = in;
if(*ip > 17)
{
t = *ip++ - 17;
if (t < 4)
goto match_next;
do *op++ = *ip++; while (--t > 0);
goto first_literal_run;
}
for(;;)
{
t = *ip++; // 得到新字符的数目(t+3)
if (t >= 16) // 新字符数目(t+3) > 18时
goto match;
if (t == 0) // 新字符数目大于18时
{
while (*ip == 0)
{
t += 255;
ip++;
}
t += 15 + *ip++; // 得到具体新字符数目大小(t+3)
}
// 获取t新字符,每次以4个为单位
* (unsigned *) op = * ( unsigned *) ip; // 获取sizeof(unsigned)个新字符
op += 4;
ip += 4;
if (--t > 0) // 新字符数目:t+4-1 = t + 3,已处理了4个
{
if (t >= 4)
{
do
{
// 获取sizeof(unsigned)个新字符,即4个,以4个为单位
* (unsigned * ) op = * ( unsigned * ) ip;
op += 4;
ip += 4;
t -= 4;
} while (t >= 4);
if (t > 0) // 不足一个单位时,且t>0
{
do
{
*op++ = *ip++;
}while (--t > 0);
}
}
else
{
do
{
*op++ = *ip++;
}while (--t > 0);
}
}
first_literal_run:
t = *ip++; // 判断是否是重复字符编码
if (t >= 16) // 是重复字符编码
goto match;
m_pos = op - 0x0801;
m_pos -= t >> 2;
m_pos -= *ip++ << 2;
*op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;
goto match_done;
for(;;)
{
match:
// 根据第一单元组来判断其解压种类
if (t >= 64) // 回指长度小于2Kb
{
// int match_len = (*ip++ << 3) | ((t >> 2) & 7) + 1;
// m_pos= op -match_len; //得到匹配位置
m_pos = op - 1; //
m_pos -= (t >> 2) & 7; // 得到第一个位元组的distance
m_pos -= *ip++ << 3; //得到匹配位置
t = (t >> 5) - 1; // 得到第一个位元组的len - 1
goto copy_match;
}
else if (t >= 32) // 回指长度大于2Kb < 16kb
{
t &= 31;
if (t == 0)
{
while (*ip == 0)
{
t += 255;
ip++;
}
t += 31 + *ip++;
}
m_pos = op - 1;
m_pos -= (* ( unsigned short * ) ip) >> 2;
ip += 2;
}
else if (t >= 16) // 回指长度大于16 Kb,或者结束标志
{
m_pos = op;
m_pos -= (t & 8) << 11; // 获得第一个单元组的distance
t &= 7; // 获取第一个单元组的len
if (t == 0)
{
while (*ip == 0)
{
t += 255;
ip++;
}
t += 7 + *ip++;
}
m_pos -= (* ( unsigned short *) ip) >> 2;
ip += 2;
if (m_pos == op) // 判断是否为结束标志
goto eof_found;
m_pos -= 0x4000;
}
else
{
m_pos = op - 1;
m_pos -= t >> 2;
m_pos -= *ip++ << 2;
*op++ = *m_pos++; *op++ = *m_pos;
goto match_done;
}
if (t >= 6 && (op - m_pos) >= 4)
{
* (unsigned *) op = * ( unsigned *) m_pos;
op += 4;
m_pos += 4;
t -= 2;
do
{
* (unsigned *) op = * ( unsigned *) m_pos;
op += 4;
m_pos += 4;
t -= 4;
}while (t >= 4);
if (t > 0)
do
{
*op++ = *m_pos++;
}while (--t > 0);
}
else
{
copy_match:
*op++ = *m_pos++; // 获得前两个匹配字符
*op++ = *m_pos++;
do
{
*op++ = *m_pos++;
}while (--t > 0); // 获得剩余的匹配字符
}
match_done:
t = ip[-2] & 3; // 获取保留位,当新字符数目<=3时
if (t == 0) // 保留位未使用时,即新字符数目>3
break;
match_next:
do
{
*op++ = *ip++;
}while (--t > 0);
t = *ip++; // 下一个匹配单元
}
}
eof_found:
if (ip != ip_end)
return -1;
return (op - (byte*)out); // 返回解码后的长度
}

出0入0汤圆

发表于 2014-1-15 09:41:56 来自手机 | 显示全部楼层
不错,看看能不能用上

出0入0汤圆

发表于 2014-1-15 10:22:24 | 显示全部楼层
内核压缩可选LZO,一些snapshot image也选择了LZO,如TuxOnIce

出0入0汤圆

发表于 2014-3-10 15:35:36 | 显示全部楼层
正在研究压缩算法,希望有用

出0入0汤圆

发表于 2014-7-14 17:17:13 | 显示全部楼层
mark 正在研究压缩算法

出0入0汤圆

发表于 2015-1-26 14:25:54 | 显示全部楼层

就一个函数这么简单啊,先谢谢了!
这个函数有人测试过吗,能用的吼一声!

出0入12汤圆

发表于 2015-1-26 14:28:20 | 显示全部楼层
也可以试试 lz4

出0入0汤圆

发表于 2019-5-31 18:31:27 | 显示全部楼层

大侠,你公布的这个代码是什么压缩?LZO压缩吗?能直接使用吗?

出0入84汤圆

发表于 2019-5-31 23:38:35 | 显示全部楼层
jintongshuai 发表于 2019-5-31 18:31
大侠,你公布的这个代码是什么压缩?LZO压缩吗?能直接使用吗?

我都忘了,居然被挖出来了,应该是网上找的,没测试过,能不能用自己测试一下
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-27 05:37

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表