Lempel–Ziv–Welch

出典: フリー百科事典『ウィキペディア(Wikipedia)』

LempelZivWelch1984 Lempel-Ziv (LZ78) LempelZivWelchLZW

LZSSDeflateLZHZIPPNG30%GIFTIFFPDFLZWUNIX Compress使

[]


LZ78Welch1984[1]8120255182564095

[2]

使1198016121使1(12)使

()(1)

使LZW使1()使使()LZW

[]




(一)(使)

(二)W

(三)W()W

(四)1sW + s

(五)2

[]




(一)(1)

(二)1

(三)W

(四)W

(五)

(六)sWW + s

(七)2

[]


使W + s2ppp + 1()Wpp + 1

1W2p  1p

W1"Early Change"PDFLZWEarly Change使LZW使TIFFEarly Change使GIF使


[]


2LSB-First("Least Significant Bit First")MSB-First("Most Significant Bit First")

GIFLSB-First使TIFFPDFMSB-First使

[]


Groovy
class BitStream {
  BitSet bs = new BitSet(); int len = 0, pos = 0;
  void write(int v, int bits) {
    for (int i in 0..<bits) { bs[len++] = ((v >>> i) & 1) != 0 }
  }
  int read(int bits) {
    int v = 0; for (int i in 0..<bits) { if (bs[pos++]) { v |= 1 << i } }
    return v
  }
  String toString() { "length = $len, {" + (0..<len).findAll({ bs[it] }).join(", ") + "}" }
}

圧縮は以下の通り。

BitStream compress(byte[] data) {
  BitStream bs = new BitStream(); List str = []; int maxCode = 255, maxCodeBits = 8;
  Map table = [:]; for (int i in 0..maxCode) { table[[(byte) i]] = i }

  for (byte c in data) {
    str << c
    if (!table.containsKey(str)) {
      bs.write(table[str[0..(str.size() - 2)]], maxCodeBits)
      table[str] = ++maxCode
      if (maxCode == (1 << maxCodeBits)) maxCodeBits++
      str = [c]
    }
  }
  bs.write(table[str], maxCodeBits)
  return bs
}

解凍は以下の通り。

byte[] decompress(BitStream bs) {
  List bytes = []; int maxCode = 255, maxCodeBits = 8, prevCode; byte c;
  List table = []; for (byte v in 0..maxCode) { table << [v] }

  bs.pos = 0
  bytes << (c = prevCode = bs.read(maxCodeBits))
  while (bs.pos < bs.len) {
    if (++maxCode == (1 << maxCodeBits)) maxCodeBits++
    int code = bs.read(maxCodeBits)
    List str = (code == maxCode) ? table[prevCode] + c : table[code]
    bytes.addAll(str)
    table << table[prevCode] + (c = str[0])
    prevCode = code
  }
  return bytes as byte[]
}

[編集]

今回圧縮する平文(アルファベットの大文字のみで表される)は

TOKYOTOKKYOKYOKAKYOKU#

である。#は文字列の終端を表す。 この時、使用される文字は27種類(アルファベットおよび#)である。 この例では、1~26の数字をアルファベットに、 0を#に当てはめる(ストップコードが0)。27種類を表すために必要な最小のビット幅は5なので、5ビットから始める。

エンコーディング[編集]

現在の文字 次の文字 出力 辞書への追加 コメント
コード ビット
なし T
T O 20 10100 27: TO 27は0から26の後で最初に使えるコード
O K 15 01111 28: OK
K Y 11 01011 29: KY
Y O 25 11001 30: YO
O T 15 01111 31: OT
TO K 27 11011 32: TOK 32は6ビット必要なため次の出力から6ビットになる
K K 11 001011 33: KK
KY O 29 011101 34: KYO
OK Y 28 011100 35: OKY
YO K 30 011110 36: YOK
K A 11 001011 37: KA
A K 1 000001 38: AK
KYO K 34 100010 39: KYOK
K U 11 001011 40: KU
U # 21 010101 次の文字が#なので辞書への追加はない
# 0 000000 ストップコードを出力する

デコーディング[編集]

デコーダーはアルファベット大文字しか使わず、初期コード幅が5ビットで可変幅エンコーディングであり、ストップコードが0であるという前提を知っていなければならない。

入力 出力する文字 辞書への追加 コメント
ビット コード 完全 推測
10100 20 T 27: T?
01111 15 O 27: TO 28: O?
01011 11 K 28: OK 29: K?
11001 25 Y 29: KY 30: Y?
01111 15 O 30: YO 31: O?
11011 27 TO 31: OT 32: TO? コード31を追加する(5ビットで読み取る最後の入力)
001011 11 K 32: TOK 33: K? 6ビットで読み込む
011101 29 KY 33: KK 34: KY?
011100 28 OK 34: KYO 35: OK?
011110 30 YO 35: OKY 36: YO?
001011 11 K 36: YOK 37: K?
000001 1 A 37: KA 38: A?
100010 34 KYO 38: AK 39: KYO?
001011 11 K 39: KYOK 40: K?
010101 21 U 40: KU 41: U?
000000 0 #

まず入力ビット列から5ビット読み込み、コード20に対応した文字Tを辞書から得る。次の5ビットを読み込み、同様に文字Oを得る。ここで一回前に得られた文字Tと今回得られた文字Oの先頭の文字Oを連結したTOを辞書に追加する。以下同様にやっていき、復号する。

また、

TANBANANAS#

をエンコードしたものを、デコードする際には、

エンコーディング デコーディング
現在の文字 出力するコード 辞書への追加 入力コード 出力する文字 辞書への追加
T 20 27: TA 20 T
A 1 28: AN 1 A 27: TA
N 14 29: NB 14 N 28: AN
B 2 30: BA 2 B 29: NB
AN 28 31: ANA 28 AN 30: BA
ANA 31 32: ANAS 31 ?
S 19 19
# 0 0

入力コード31が出てくるが辞書にはない。これはエンコーディングで辞書に追加したばかりのコードを直後に使っているが、デコーディングでは辞書への追加は1コード分遅れておりまだ追加されていないために起こる。しかし、コード31に対応する文字列がANAであることは原理上明らかである。なぜなら、コード31に対応する文字列は1つ前にデコーディングした文字列ANになんらかの1文字を連結したものである。その1文字はコード31に対応する文字列の先頭の文字である。よってその1文字はANの先頭の文字のAであり、31に対応するのはANにAを連結したANAである。

cは文字で、Sは文字列とし、cSはすでに出現しているが、cScは出現していない状況でcScScと並んだ時に起きる。

特許[編集]

LZWは1984年に発表された。当初スペリー社が特許を保有していた。のちスペリー社はバロース社と合併し1986年ユニシス社となり、本アルゴリズムの特許権もユニシス社に引き継がれた。

前述の通りGIF画像の圧縮に用いられており、その特許料に関するユニシス社の姿勢が問題となった。詳細はGIF特許問題を参照。

日本では1984年6月20日に特許が出願され、2004年6月20日に期限切れとなった。以下、日本の特許庁産業財産権情報より:

  • 発明の名称:圧縮装置および圧縮方法
  • 出願日:1984年6月20日
    • 出願番号:特許出願平7-341868
  • 公開日:1996年9月13日
    • 公開番号:特許公開平8-237138

出典[編集]

  1. ^ Welch, Terry (1984). “A Technique for High-Performance Data Compression”. Computer 17 (6): 8–19. doi:10.1109/MC.1984.1659158. http://www.cs.duke.edu/courses/spring03/cps296.5/papers/welch_1984_technique_for.pdf. 
  2. ^ Ziv, J.; Lempel, A. (1978). “Compression of individual sequences via variable-rate coding”. IEEE Transactions on Information Theory 24 (5): 530. doi:10.1109/TIT.1978.1055934. http://www.cs.duke.edu/courses/spring03/cps296.5/papers/ziv_lempel_1978_variable-rate.pdf.