LZW
出典: フリー百科事典『ウィキペディア(Wikipedia)』
LZWは、辞書式圧縮である Lempel-Ziv法 (LZ78) を、スペリー社のテリー・ウェルチが改良したアルゴリズム。
開発者の Lempel、Ziv、Welch の頭文字を取ってLZWと呼ばれる。
圧縮効率と高速化の両面を追求している為、LZSSとハフマン符号化を組み合わせたDeflateアルゴリズム(LZHやZIPなどが採用)と比べると30%ほど圧縮効率が悪い。GIFやTIFFなどの圧縮で利用されている。UNIX Compressで使える。
実装
以下、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[]
}
特許
LZWは1984年に発表された。当初スペリー社が特許を保有していた。のちスペリー社はバロース社と合併し1986年にユニシス社となり、本アルゴリズムの特許権もユニシス社に引き継がれた。
前述の通りGIF画像の圧縮に用いられており、その特許料に関するユニシス社の姿勢が問題となった。詳細はGIF特許問題を参照。
日本では1984年6月20日に特許が出願され、2004年6月20日に期限切れとなった。以下、日本の特許庁産業財産権情報より: