硬汉嵌入式论坛

 找回密码
 立即注册
查看: 3404|回复: 7
收起左侧

[客户分享] 移植LZMA压缩算法到STM32

  [复制链接]

1

主题

35

回帖

43

积分

新手上路

积分
43
发表于 2022-2-1 12:45:14 | 显示全部楼层 |阅读模式
①准备一个简单的Demo例程,这里以STM32F407为例,需要有外扩内存至少有1M的外扩RAM大小;
②去7Zip官网下载源码解压如下:
③将源码添加到准备好的工程中,截图如下:
④使用的压缩测试代码如下:
static void *SzAlloc(void *p, size_t size) { (void)p; return MyAlloc(size); }
static void SzFree(void *p, void *address) { (void)p; MyFree(address); }
static ISzAlloc stAllocator = { (void *(*)(ISzAllocPtr, size_t))SzAlloc, (void (*)(ISzAllocPtr, void *))SzFree };


#define COMP_BUFLEN 1000
#define UNCOMP_BUFLEN 5000

char* pTestData = "DEADBEEF|askjd9827x34bnzkjaskjd9827x34bnzkjaskjd9827x34bnzkjaskjd9827x34bnzkjaskjd9827x34bnzkj#%wioeruxo3b84nxijlhwqdzhwerzu39b87r#_3b9p78bznor83y4frAAAABBBBBBCCCCCDDDDDDFFFF";
unsigned char pCompBuf[1000]; /* Compressed data */
unsigned char pUnCompBuf[5000]; /* Unompressed data - at the end its contents */


int LZMA_Compress(uint8_t *dst, size_t *dst_len, uint8_t *src, size_t src_len)
{
    CLzmaEncProps stProps;
    SRes rc;
    size_t nPropsBufLen = LZMA_PROPS_SIZE;

    LzmaEncProps_Init(&stProps);

    stProps.level = 9;
    stProps.lc = 0;
    stProps.lp = 0;
    stProps.dictSize = 1 << 12;
    stProps.numThreads = 1;

//    PRINT_APP_INFO("dst_len: %d, src_len: %d, prop_len:%d\r\n", *dst_len, src_len, nPropsBufLen);

    rc = LzmaEncode(dst + LZMA_PROPS_SIZE, dst_len, src, src_len, &stProps, dst, &nPropsBufLen, 0, NULL, &stAllocator, &stAllocator);
    if(rc != SZ_OK)
    {
        PRINT_APP_INFO("LZMA compression failed (rc = %d)\r\n", rc);
        return -1;
    }
    else
    {
        PRINT_APP_INFO(RTT_CTRL_BG_CYAN"压缩: %8d-->%-8d"RTT_CTRL_RESET, src_len, *dst_len);
                PRINT_APP_INFO("\r\n");
        return 0;
    }
}

int LZMA_DeCompress(uint8_t *dst, size_t *dst_len, uint8_t *src, size_t src_len)
{
    ELzmaStatus nStatus;

    SRes rc = LzmaDecode(dst, dst_len, src + LZMA_PROPS_SIZE, &src_len, src, LZMA_PROPS_SIZE, LZMA_FINISH_ANY, &nStatus, &stAllocator);
    if ( rc != SZ_OK )
    {
        PRINT_APP_INFO("LZMA decompression failed (rc = %d, status = %d)\r\n", rc, nStatus);
        return -1;
    }
    else
    {
        PRINT_APP_INFO(RTT_CTRL_BG_CYAN"解压: %8d-->%-8d"RTT_CTRL_RESET, src_len, *dst_len);
                PRINT_APP_INFO("\r\n");
        return 0;
    }
}


void LZMA_Test(void)
{
    size_t nTestDataLen = strlen(pTestData);
    size_t nCompBufLen = COMP_BUFLEN;
    size_t nUnCompBufLen = UNCOMP_BUFLEN;

    PRINT_APP_INFO("LZMA: %s, %s\r\n", MY_VERSION, MY_CPU_NAME);

    memset(pCompBuf, 0, COMP_BUFLEN);
    memset(pUnCompBuf, 0, UNCOMP_BUFLEN);
       
        PRINT_APP_INFO(RTT_CTRL_TEXT_BRIGHT_RED"分配/释放 编号\t内存分配/释放大小\t地址\t内存总占用\r\n"RTT_CTRL_RESET);

    if(LZMA_Compress(pCompBuf, &nCompBufLen, (uint8_t *)pTestData, nTestDataLen) != SZ_OK)
    {
        PRINT_APP_INFO("LZMA_Compress ERR...%u...\r\n", __LINE__);
        while(1);
    }

    nUnCompBufLen = nTestDataLen;
    if(LZMA_DeCompress(pUnCompBuf, &nUnCompBufLen, pCompBuf, nCompBufLen) != SZ_OK)
    {
        PRINT_APP_INFO("LZMA_DeCompress ERR...%u...\r\n", __LINE__);
        while(1);
    }

    if ((nUnCompBufLen != nTestDataLen) || memcmp(pTestData, pUnCompBuf, nTestDataLen) )
    {
        PRINT_APP_INFO("Compression and/or decompression failed!\r\n");
        PRINT_APP_INFO("Input data length [nTestDataLen] : %d\r\n", nTestDataLen);
        PRINT_APP_INFO("Compressed data length [nCompBufLen] : \r%d\n", nCompBufLen);
        PRINT_APP_INFO("Uncompressed data length [nUnCompBufLen]: %d\r\n", nUnCompBufLen);

        if (memcmp(pTestData, pUnCompBuf, nTestDataLen) )
        {
            PRINT_APP_INFO("pTestData and pUnCompBuf contain different data!\r\n");
        }
        else
        {
            PRINT_APP_INFO("dst_len:%d\r\n,dst_data:%s\r\n,src_len:%d\r\n,src_data:%s\r\n\r\n",nUnCompBufLen, pUnCompBuf, nTestDataLen, pTestData);
        }
    }
}

⑤测试结果如下:
⑥工程源码:


7zip压缩算法源码

7zip压缩算法源码

将LZMA源码添加到工程中

将LZMA源码添加到工程中

LAMA压缩算法测试结果

LAMA压缩算法测试结果

F407_LZMA_20220201.7z

1.07 MB, 下载次数: 85

移植LZMA压缩算法到STM32平台

评分

参与人数 1金币 +100 收起 理由
eric2013 + 100 很给力!

查看全部评分

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106746
QQ
发表于 2022-2-1 15:19:05 | 显示全部楼层
谢谢楼主分享
回复

使用道具 举报

5

主题

201

回帖

216

积分

高级会员

积分
216
发表于 2022-2-2 11:29:23 | 显示全部楼层
很好的研究哦,在一些应用中可以尝试使用。
回复

使用道具 举报

0

主题

3

回帖

3

积分

新手上路

积分
3
发表于 2023-7-10 10:12:12 | 显示全部楼层
感谢楼主分享!楼主能不能对 C LZMA 压缩后的文件格式做一个详细的解释,另外就是对于一份比较大的压缩文件(存储在外置dataflash里),解压缩流程该如何处理?谢谢~
回复

使用道具 举报

0

主题

3

回帖

3

积分

新手上路

积分
3
发表于 2023-7-10 10:18:35 | 显示全部楼层
您好,看了你分享的能应用在嵌入式里的LZMA压缩算法,很感兴趣。该算法我也在qt平台上验证过了,压缩解压缩都没问题。但是呢我对 C LZMA 压缩出的数据格式有疑问,貌似跟标准的7z格式不一致, 楼主能不能详细解答一下 C LZMA 压缩数据格式。另外对于要解压缩的文件比较大(比如压缩后的升级文件,保存在外置dataflash里),那么解压缩流程该如何处理?
回复

使用道具 举报

1

主题

35

回帖

43

积分

新手上路

积分
43
 楼主| 发表于 2023-7-11 17:24:10 | 显示全部楼层
这里移植的主要是核心的算法,是针对bu原始f数据的,针对提到的对于文件压缩格式问题,是针对文件或者文件系统的,压缩的时候,是需要很多属性的,你可以想象自己使用7z桌面软件压缩一个文件夹的时候,里边既有文件,也有文件夹的时候,文件夹下面一级,还有很多,这些归档的格式具体可以重点参考官方的文档7z format.txt

关于这个压缩算法,一般是在桌面级PC的应用,嵌入式的应用很少,需要消耗较大的资源,也比较慢,关于外部Flash存储较大的压缩文件需要解压时,这个时候是否可以考虑分段压缩,或者考虑使用适用于嵌入式的压缩的压缩算法FastLZ、minilzo、heatshrink等

7z SDK说明文档

7z  SDK说明文档
回复

使用道具 举报

0

主题

3

回帖

3

积分

新手上路

积分
3
发表于 2023-7-14 10:41:48 | 显示全部楼层
好的,了解,感谢楼主解答
回复

使用道具 举报

2

主题

2

回帖

8

积分

新手上路

积分
8
发表于 2023-11-4 09:59:15 | 显示全部楼层
大家有没有在stm32上生成压缩文件,然后上传上位机,在pc上解压过?我把文件头都添加上了,但是还是在pc上解不出来。大家有遇到过这问题吗
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-3 16:15 , Processed in 0.353816 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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