基于LZO算法的编解码器

1. LZO算法介绍

LZO 是一个用 ANSI C 语言编写的无损压缩库。他能够提供非常快速的压缩和解压功能。解压并不需要内存的支持。即使使用非常大的压缩比例进行缓慢压缩出的数据,依然能够非常快速的解压。LZO 遵循 GNU 的 GPL 使用许可。

LZO 非常适合进行数据的实时压缩解压处理,这就是说他更关心操作速度,而不是压缩比例。

LZO 使用 ANSI C 语言编写,并且压缩后的数据也被设计为可以跨平台使用的格式。

LZO 拥有如下的特点:

  • 解压速度很快,并且很简单;
  • 解压时不需要内存支持;
  • 压缩的速度还不错;
  • 压缩时只需要 64 KiB 的内存支持;
  • 压缩比例可以根据需要调节,而这并不影响解压的效率,提高压缩比例自然会降低压缩速度;
  • 压缩包含了很多的压缩级别,提供很多选择;
  • 提供只需要 8 KiB 内存支持的压缩级别;
  • 提供线程安全;
  • 提供无损压缩;

LZO提供多重压缩,和复原解压;

设计标准

LZO 以处理速度为原则设计。解压速度要快于压缩速度。能够提供给任何程序实时解压的功能。LZO1X的解压是按照 i386 编码优化的。

事实上,是通过解压算法定义的压缩数据结构,最后采用手工测试数据验证了这个结构。

效果

在古老的 Pentium 133 的设备上,我们运行了 Calgary Corpus 的测试数据。数据采用了 256 KiB的大小。

LZOxx-N 定义了使用的算法名称,N代表压缩级别。1-9 级别使用 64 KiB 内存,他主要提供更快的压缩速度。99 级别使用 256 KiB 内存,提供更大的压缩比例,但是速度依然很快。999 级别是按照压缩比例优化的算法,他的压缩速度很慢,并且使用大量的内存,这种级别一般用于生成预压缩数据。

C 语言版本的 LZO1X-1 算法要比最快的 ZLIB 压缩级别,快4-5倍的速度。当然他也在压缩比例、压缩时间、解压时间方便优于 LZRW1-A 和 LZV 这些算法。

简单文档

LZO 是块压缩算法,他压缩和解压一个块数据。压缩和解压的块大小必须一样。

LZO 将块数据压缩成匹配数据(滑动字典)和非匹配的文字序列。LZO 对于长匹配和长文字序列有专门的处理,这样对于高冗余的数据能够获得很好的效果,这样对于不可压缩的数据,也能得到较好的结果。

在处理不可压缩数据时,LZO 将扩展输入数据,每1024个字节最大增加 64 个字节。

我已经通过类似于 valgrind 这样的内存检查工具验证过 LZO 程序,并且也使用了超过千兆字节的数据,进行各种参数调整,检查过各种潜在的问题。LZO 目前不存在任何已知 BUG。


2. 关键实现代码

(1)选择待压缩

void CcompressDlg::OnBnClickedButton3()  
{  
    // TODO: 在此添加控件通知处理程序代码  
    CString strFile = _T("");  
  
    CFileDialog    dlgFile(TRUE, NULL, NULL, OFN_HIDEREADONLY, _T("Describe Files (*.cfg)|*.cfg|All Files (*.*)|*.*||"), NULL);  
  
    if (dlgFile.DoModal())  
    {  
        strFile = dlgFile.GetPathName();  
    }  
  
    UpdateData(true);          // 获取数据  
    path = strFile;  
    UpdateData(false);         // 更新数据  
}  


(2)选择解压缩文件

void CcompressDlg::OnBnClickedButton4()  
{  
    // TODO: 在此添加控件通知处理程序代码  
    CString strFile = _T("");  
  
    CFileDialog    dlgFile(TRUE, NULL, NULL, OFN_HIDEREADONLY, _T("Describe Files (*.cfg)|*.cfg|All Files (*.*)|*.*||"), NULL);  
  
    if (dlgFile.DoModal())  
    {  
        strFile = dlgFile.GetPathName();  
    }  
  
    UpdateData(true);          // 获取数据  
    path_decompress = strFile;  
    UpdateData(false);         // 更新数据  
}  



(3) 压缩

void CcompressDlg::OnBnClickedButton1()  
{  
    // TODO: 在此添加控件通知处理程序代码  
#ifdef _UNICODE  
    LONG len1;  
    len1 = WideCharToMultiByte(CP_ACP, 0, path, -1, NULL, 0, NULL, NULL);  
    char *textPath = (char *)malloc(sizeof(char)*(len1 + 1));  
    memset(textPath, 0, len1 + 1);  
    WideCharToMultiByte(CP_ACP, 0, path, -1, textPath, len1 + 1, NULL, NULL);  
#else  
    ptr = new char[str.GetAllocLength() + 1];  
#endif  
    err = fopen_s(&ifp, textPath, "rb");  
    if (err == 0)  
    {  
        printf("Thefile'crt_fopen_s.c'wasopened\n");  
    }  
    fseek(ifp, 0, SEEK_END);  
    unsigned long len = ftell(ifp);  
    myInLen = len;  
    fseek(ifp, 0, SEEK_SET);  
    cpTemp = (char*)malloc(len * sizeof(char));  
    fread(cpTemp, sizeof(char), len, ifp);  
    char *in = cpTemp;  
    char *out = (char*)malloc((len + len / 16 + 64 + 3) * sizeof(char));  
      
    if (lzo_init() != LZO_E_OK)  
    {  
        printf("internal error - lzo_init() failed !!!\n");  
        printf("(this usually indicates a compiler bug - try recompiling\nwithout optimizations, and enable '-DLZO_DEBUG' for diagnostics)\n");  
          
    }  
      
    lzo_uint in_len;  
    in_len = len;  
    lzo_memset(in, 0, in_len);  
    lzo_uint out_len;  
  
    int r;  
      
    r = lzo1x_1_compress((unsigned char*)in, in_len, (unsigned char*)out, &out_len, wrkmem);  
    char mess[256];  
  
    if (r == LZO_E_OK)  
    {  
        sprintf_s(mess, sizeof(mess),  "压缩成功!\n\n原文件大小:%lu bytes\n压缩后大小:%lu bytes\n\n解压得到的文件“compress.txt”保存于工程目录下",  
            (unsigned long)in_len, (unsigned long)out_len);  
        MessageBox(CString(mess));  
      
    }  
    else  
    {  
        /* this should NEVER happen */  
        sprintf_s(mess, sizeof(mess), "压缩失败!\n %d\n", r);  
        MessageBox(CString(mess));  
    }  
    /* check for an incompressible block */  
    if (out_len >= in_len)  
    {  
        sprintf_s(mess, sizeof(mess), "未压缩!\n");  
        MessageBox(CString(mess));  
    }  
  
    err = fopen_s(&ofp, ".\\compress.txt", "wb");  
    fwrite(out, sizeof(char), out_len, ofp);  
      
    fclose(ifp);  
    fclose(ofp);  
    free(cpTemp);  
    free(out);  
    free(textPath);  
  
}  


(4)
void CcompressDlg::OnBnClickedButton2()  
{  
    // TODO: 在此添加控件通知处理程序代码  
#ifdef _UNICODE  
    LONG len1;  
    len1 = WideCharToMultiByte(CP_ACP, 0, path_decompress, -1, NULL, 0, NULL, NULL);  
    char *textPath = (char *)malloc(sizeof(char)*(len1 + 1));  
    memset(textPath, 0, len1 + 1);  
    WideCharToMultiByte(CP_ACP, 0, path_decompress, -1, textPath, len1 + 1, NULL, NULL);  
#else  
    ptr = new char[str.GetAllocLength() + 1];  
#endif  
    err = fopen_s(&ifp, textPath, "rb");  
    if (err == 0)  
    {  
        printf("Thefile'crt_fopen_s.c'was opened\n");  
    }  
    fseek(ifp, 0, SEEK_END);  
    unsigned long len = ftell(ifp);  
    fseek(ifp, 0, SEEK_SET);  
    cpTemp = (char*)malloc(len * sizeof(char));  
    fread(cpTemp, sizeof(char), len, ifp);  
    char *in = cpTemp;  
    char *out = (char *)malloc(len*100* sizeof(char));  
    memset(out, 0, len * 100 * sizeof(char));  
      
    int r;  
    lzo_uint new_len;  
    r = lzo1x_decompress((unsigned char*)in, len, (unsigned char*)out, &new_len, NULL);  
  
    char mess[256];  
    if (r == LZO_E_OK && new_len == myInLen)  
    {  
        sprintf_s(mess, sizeof(mess), "解压成功!\n\n待解压文件大小: %lu bytes\n解压后文件大小: %lu bytes\n\n解压得到的文件“decompress.txt”保存于工程目录下",  
            (unsigned long)len, (unsigned long)new_len);  
        MessageBox(CString(mess));  
    }  
    else  
    {  
        /* this should NEVER happen */  
        sprintf_s(mess, sizeof(mess), "解压失败! %d\n", r);  
        MessageBox(CString(mess));  
    }  
    err = fopen_s(&ofp, ".\\decompress.txt", "wt+");  
    fwrite(out, sizeof(char), new_len, ofp);  
  
    fclose(ifp);  
    fclose(ofp);  
    free(cpTemp);  
    free(textPath);  
    free(out);  
}  


3. 实验结果

(1)压缩结果

基于LZO算法的编解码器_第1张图片

(2)解压缩结果

基于LZO算法的编解码器_第2张图片

你可能感兴趣的:(基于LZO算法的编解码器)