文章首发于我的个人博客

1. LZW基础概念

之前提到的算术编码、霍夫曼编码等技术集中在消除编码的冗余上,而本文要讲的LZW编码是一种针对空间冗余的无误差压缩方法。

LZW算法o又叫“串表压缩算法”,就是通过建立一个将字符串和其对应的记号构成的表(把已经出现过的字符串映射到记号上),用较短的代码来表示较长的字符串来实现压缩。

需要注意的是,LZW算法中字符串和记号的对应关系是在压缩的过程中动态生成的,并且隐含在压缩数据中,解压的时候也是一步一步还原编码并动态生成字典的过程。

2. LZW算法详解

2.1 LZW编码算法

编码器从字符串中不断地读入新的字符,并且将字符或字符串映射到新的记号,以动态地构建编码字典。在编码过程中,我们维护两个变量,即previous_char(表示目前已有的,但未被编码的字符)和current_char(表示刚刚读入的字符)。编码算法流程如下

  • (1)初始状态,previous_charcurrent_char都是空的。
  • (2)读入新的字符current_char,并于previous合并成新的字符串p_and_c(previous_char+current_car)
  • (3)在编码字典里查找p_and_c,如果:
    • p_and_c在字典里,previous_char = p_and_c
    • p_and_c不在字典里,将previous_char的标记输出;在字典中建立p_and_c的映射;更新previous_char = current_char
  • (4)返回步骤(2),重复直至读完字符串。

2.2 Example

ababcababac

初始状态字典里有三个默认的映射

String Symbol
a 0
b 1
c 2

开始编码

previous_char current_char p_and_c p_and_c in dict Action output
“” a a Y previous_char = a -
a b ab N 添加映射{‘ab’, 3} previous_char = b 0
b a ba N 添加映射{‘ba’, 4} 1
a b ab Y previous_char = ab -
ab c abc N 添加映射{‘abc’, 5} previous_char = c 3
c a ca N 添加映射{‘ca’, 6} previous_char = a 2
a b ab Y previous_char = ab -
ab a aba N 添加映射{‘aba’, 7} previsou_char = a 3
a b ab Y previous_char = ab -
ab a aba Y previous_char = aba -
aba c abac N 添加映射{‘abac’, 8} previous_char = c 7
c - - - - 2

编码结束,输出结果为0132372,编码过程中生成的字典为:

String Symbol
a 0
b 1
c 2
ab 3
ba 4
abc 5
ca 6
aba 7
abac 8

2.2 LZW解码算法

解码器输入的是压缩后的数据。同时,我们将维护两个变量previous_symbol(目前已有的但未被处理的记号),current_symbol(当前读入的记号)。算法流程如下

  • (1)初始状态,previous_symbolcurrent_symbol都为空。
  • (2)读入第一个记号,并赋给current_symbol,并解码直接输出。因为第一个字符为单个字符,一定可以直接解码。
  • (3)赋值,previous_symbol = current_symbol
  • (4)在字典里查找current_symbol,如果:
    • current_symbol在字典里:

      • current_symbol解码的结果输出
      • previous_char = dict.get(previous_symbol), current_char = dict.get(current_symbol)[0] 。注意,这里current_charcurrent_symbol解码的第一个字符。
      • p_and_c添加到新的映射
    • current_symbol不在字典里:
      • previous_char = dict.get(previous_symbol), current_char = dict.get(previous_symbol)[0] 。注意,这里current_charprevious_symbol解码的第一个字符。
      • p_and_c添加到新的映射
      • 输出p_and_c
  • 返回步骤(3),直至读完所有记号。

2.4 Example

0 1 3 2 3 7 2

初始状态字典里有三个默认的映射

Symbol String
0 a
1 b
2 c

开始解码:

首先读取第一个记号,current_symbol = 0,输出解码结果dict.get(current_symbol),即a赋值previous_symbol = current_symbol,然后循环读取之后的记号。

previous_symbol current_symbol current_symbol in dict Action output
0 1 Y previous_char = a current_char = b p_and_c = ‘ab’ 添加映射{3, ‘ab’} b
1 3 Y previous_char = b current_char = a p_and_c = ‘ba’ 添加映射{4. ‘ba’} ab
3 2 Y previous_char = ab current_char = c p_and_c = ‘abc’ 添加映射{5, ‘abc’} c
2 3 Y previous_char = c current_char = a p_and_c = ca 添加映射{6. ‘ca’} ab
3 7 N previous_char = ab current_char = a p_and_c = aba 添加映射{7, ‘aba’} aba
7 2 Y previous_char = aba current_char = c P_and_c = abac 添加映射{8, ‘abac’} c

解码结束,输出结果为ababcababac。解码过程中生成的字典为

Symbol String
0 a
1 b
2 c
3 ab
4 ba
5 abc
6 ca
7 aba
8 abac

2.5 代码实现(python)

def encode_init():k = 0char_num_dict = {}for i in range(97,123):char_num_dict[chr(i)] = kk += 1# print(char_num_dict.items())return char_num_dictdef decode_init():k = 0num_char_dict = {}for i in range(97,123):num_char_dict[str(k)] = chr(i)k += 1# print(char_num_dict.items())return num_char_dictdef LZW_encode(strList, char_num_dict):symbol = 26     # 标记previous_char = ""       # 已有的,但未被编码的字符current_char = ""       # 当前读入的字符p_and_c = ""output = ""          # 输出的编码序列for s in strList:current_char = sp_and_c = previous_char + current_char# print(previous_char, s)if char_num_dict.get(p_and_c) != None:previous_char = p_and_celse:output += str(char_num_dict.get(previous_char)) + '-'char_num_dict[p_and_c] = symbolsymbol += 1 previous_char = current_charoutput += str(char_num_dict[s[-1]])print(char_num_dict.items())return outputdef LZW_decode(output, num_char_dict):output_list = output.split('-')print(output_list)symbol = 26previous_symbol = ""current_symbol = ""previous_char = ""current_char = ""decodeList = ""decodeList += num_char_dict.get(output_list[0])previous_symbol = output_list[0] for o in output_list[1:]:current_symbol = o # print(previous_symbol, current_symbol)if num_char_dict.get(current_symbol) != None:decodeList += num_char_dict.get(current_symbol)previous_char = num_char_dict.get(previous_symbol)current_char = num_char_dict.get(current_symbol)[0]num_char_dict[str(symbol)] = previous_char + current_charsymbol += 1 else:previous_char = num_char_dict.get(previous_symbol)current_char = num_char_dict.get(previous_symbol)[0]num_char_dict[str(symbol)] = previous_char + current_charsymbol += 1decodeList += previous_char + current_charprevious_symbol = current_symbol# print(num_char_dict.items())return decodeListif __name__ == '__main__':strList = input("请输入字符序列:").lower()print('字符序列长度:', len(strList))char_num_dict = encode_init()output = LZW_encode(strList, char_num_dict)print(output)num_char_dict = decode_init()# print(num_char_dict.items())decodeList = LZW_decode(output, num_char_dict)print(decodeList)print("编码长度:", len(output) / 2)

图像压缩——LZW压缩算法相关推荐

  1. LZW压缩算法解码器实现

    本文先给出具体的代码实现,懂一些LZW算法理论,基本上如果静下心来,都能看明白解码器的实现.如果不太清楚LZW,可以查看下以前的一篇帖子:http://www.cnblogs.com/jillzhan ...

  2. 基于xilinx FPGA实现LZW压缩算法

    1 LZW算法简介 数据压缩分为有损压缩和无损压缩.有损压缩是对压缩后的数据进行重构 (解压缩 ) ,重构后的数据与原来的数据有所不同,换来了大的压缩比.无损压缩指对压缩后的数据进行重构 ,重构后的数 ...

  3. 数据压缩课程作业——LZW压缩算法完整仿真代码和分析

    前言 关于数字压缩课程的作业记录,附完整代码 一.算法描述 1.1 算法特点 LZW压缩算法是一种无损数据压缩算法.在众多的压缩技术中,LZW算法是一种通用的.性能优良并得到广泛应用的压缩算法,它是一 ...

  4. lzw压缩 java_java实现的LZW 压缩算法源码 | 学步园

    导读:/* * LZW.java * * Created on 01 Dec 2005 * * Implementation of LZW compression/decompression algo ...

  5. LZW压缩算法原理解析与实现【转载】

    LZW算法原理--Wikipedia相关介绍 一个简单的例子 ZW编码 (Encoding) 的核心思想其实比较简单,就是把出现过的字符串映射到记号上,这样就可能用较短的编码来表示长的字符串,实现压缩 ...

  6. 数字图像处理(八)图像压缩-有损压缩/压缩算法+matlab

    有损压缩/压缩算法实验 1.问题及说明 查阅JPEG编码的有关资料,对图像进行JPEG压缩,算法步骤必须包括如下几个部分:图像分块,离散余弦变换,量化,ac和dc系数的Z字形编排. 在输入灰度图像时直 ...

  7. LZW数据压缩算法的原理分析

    1.LZW的全称是什么?   Lempel-Ziv-Welch (LZW). 2. LZW的简介和压缩原理是什么?   LZW压缩算法是一种新颖的压缩方法,由Lemple-Ziv-Welch 三人共同 ...

  8. lz78算法c语言,LZW数据压缩算法研究

    内容介绍 LZW数据压缩算法研究 46页 3.2万字 摘 要 随着信息化技术的蓬勃发展,日常需要处理或者传输的数据越来越多,数据的压缩也就变得越来越重要了.我们迫切的需要有好的压缩算法来支持我们的数据 ...

  9. 你发表情包全靠他,GIF压缩算法发明者之一获IEEE最高荣誉奖

    点击上方,选择星标或置顶,不定期资源大放送! 阅读大概需要5分钟 Follow小博主,每天更新前沿干货 转载自:量子位 现年90岁的以色列科学家Jacob Ziv,获得了2021年IEEE荣誉奖章(I ...

最新文章

  1. ubuntu16.04安装opencv3.4.1教程
  2. 多帧点云拼接的全局ICP算法【附Matlab代码链接】
  3. 宇宙膨胀背后的故事(卅三):宇宙之有生于无
  4. Unity5 AssetBundle系列——简单的AssetBundleManager
  5. yum安装JAVA centos下使用yum安装jdk
  6. python拼接mysql时遇到unsupported format character ‘?‘ “(0x82f1)“
  7. Codeforces 1025F Disjoint Triangles (计算几何)
  8. Java树形转扁平_js把树形数据转成扁平数据
  9. javascript系列:NaN类型
  10. aop cache再讨论
  11. java歌词解析器_设计模式学习(四):基于Builder模式的歌词解析器
  12. photoshop基础视频教程 [4G]
  13. 低功耗实例——isolation cell及level shifter的选择
  14. 牛逼!这个C++跳棋游戏居然可以让你边玩游戏边学编程!
  15. php 即时通讯插件,四款可以整合到网站的网页版即时通信IM插件系统
  16. 6月 CSDN 创作者之夜:获奖名单公布
  17. 基于pion生态的SFU实时音视频发布服务(一)
  18. 学生信息管理系统python
  19. 智能电话机器人(AI语音机器人)是什么
  20. 96张完整PPT清晰解读全球智能制造趋势!

热门文章

  1. 水库防汛泄洪抢险应急广播系统建设4G无线广播模式分析
  2. linux脚本遍历数组,浅谈shell 遍历数组的几种方法
  3. LayoutTransition关键点分析
  4. Linux下Windows访问DNF,Fedora Linux系统中用Steam play与Proton玩Windows系统下的游戏
  5. 小程序2个页面如何接传值
  6. 微信JS-SDK PHP Demo JS接口安全域名 自定义分享接口 jsapi_ticket
  7. Linux 添加用户组和添加用户
  8. 【Java设计模式】简单工厂
  9. 卓训教育:面对孩子,家长如何管理好自己的情绪?
  10. 移动端的touch事件