LZW
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.
1. 개요
LZW는 1984년에 발표된 무손실 데이터 압축 알고리즘으로, 1980년대에 널리 사용되었다. 이 알고리즘은 사전을 기반으로 입력 데이터를 압축하며, 인코딩 및 디코딩 과정을 통해 데이터를 압축하고 복원한다. LZW는 GIF, TIFF, PDF 등 다양한 파일 형식에 사용되었으며, 초기에는 텍스트 파일 압축에 널리 사용되었으나, 특허 문제와 DEFLATE 알고리즘의 등장으로 사용이 감소했다. LZW에는 LZMW, LZAP, LZWL 등의 변형이 존재하며, 가변 폭 코드와 패킹 순서와 같은 기술을 사용한다.
더 읽어볼만한 페이지
- 아카이브 포맷 - ARJ
ARJ는 다양한 소프트웨어 유틸리티에서 압축 해제가 가능한 파일 포맷으로, macOS에서는 독립 실행형 유틸리티를 통해 압축을 해제할 수 있다. - 아카이브 포맷 - JAR (파일 포맷)
JAR (Java ARchive)는 자바 런타임 환경에서 애플리케이션 배포를 위해 사용되는 ZIP 기반의 파일 포맷으로, 자바 클래스 파일과 매니페스트 파일을 포함하여 메타데이터와 실행 정보를 관리하며, 압축 및 전자 서명을 지원하고 실행 가능한 JAR 파일을 통해 애플리케이션을 간편하게 실행할 수 있게 한다. - 무손실 압축 알고리즘 - VP9
VP9는 구글이 개발한 오픈 소스 비디오 코덱으로, VP8보다 압축 효율을 높이고 HEVC보다 나은 성능을 목표로 개발되었으며, WebM 형식으로 사용되고 주요 웹 브라우저와 넷플릭스, 유튜브 등에서 지원했으나 AV1의 등장으로 개발이 중단되었다. - 무손실 압축 알고리즘 - FLAC
FLAC은 조시 콜슨이 개발한 무손실 오디오 코덱으로, 원본 음질을 유지하면서 파일 크기를 줄이기 위해 오디오 데이터를 압축하며, 4~32비트 샘플 크기, 최대 8 채널을 지원하고, 미국 국립 문서 기록 관리청에서 디지털 오디오에 선호되는 형식으로 지정되었다.
| LZW | |
|---|---|
| 알고리즘 정보 | |
| 이름 | 렘펠-지브-웰치 (LZW) |
| 유형 | 무손실 데이터 압축 알고리즘 |
| 개발자 | 테리 웰치 |
| 개발 연도 | 1984년 |
| 기반 알고리즘 | 렘펠-지브 알고리즘 |
| 특징 | 가변 길이 코드워드 사용 딕셔너리 기반 압축 특허 만료 (2004년) |
| 기술 세부 사항 | |
| 압축 방식 | 딕셔너리 기반, 가변 길이 코드워드 |
| 복원 방식 | 딕셔너리 기반 |
| 적용 분야 | GIF 이미지 포맷 TIFF 이미지 포맷 PDF 문서 포맷 유닉스 compress 명령어 |
| 특허 정보 | |
| 특허 번호 (미국) | US4558302A |
| 특허 만료일 | 2004년 |
| 관련 표준 | |
| IEEE 표준 | 1594 |
2. 알고리즘
## 인코딩
LZW 인코딩 알고리즘은 초기 사전을 기반으로 입력 데이터를 순차적으로 처리하며 압축을 수행한다. 알고리즘의 작동 방식은 다음과 같다.[2]
1. 길이가 1인 모든 가능한 문자열을 포함하도록 사전을 초기화한다.
2. 입력 데이터에서 현재까지의 문자열(w)과 일치하는 가장 긴 문자열을 사전에서 찾는다.
3. w에 해당하는 사전 코드를 출력한다.
4. w에 다음 문자(c)를 추가한 문자열(w+c)이 사전에 존재하지 않으면, w+c를 사전에 추가한다.
5. 다음 문자를 새로운 w로 설정하고 2단계부터 반복한다.
초기 사전에는 모든 단일 문자가 포함되어 있으며, 알고리즘은 입력 문자열을 스캔하면서 사전에 없는 가장 긴 부분 문자열을 찾는다. 이 문자열이 발견되면, 마지막 문자를 제외한 문자열의 인덱스를 출력하고, 새 문자열(마지막 문자 포함)을 사전에 추가한다. 이 과정에서 점차 더 긴 문자열이 사전에 등록되어 단일 출력 값으로 인코딩될 수 있다.
예를 들어, "TOBEORNOTTOBEORTOBEORNOT#" 문자열을 인코딩하는 과정은 다음과 같다.
| 현재 시퀀스 | 다음 문자 | 출력 코드 | 출력 비트 | 확장된 사전 | 설명 |
|---|---|---|---|---|---|
| NULL | T | ||||
| T | O | 20 | 10100 | 27: TO | 27은 0부터 26까지의 숫자 이후 사용 가능한 첫 번째 코드 |
| O | B | 15 | 01111 | 28: OB | |
| B | E | 2 | 00010 | 29: BE | |
| E | O | 5 | 00101 | 30: EO | |
| O | R | 15 | 01111 | 31: OR | |
| R | N | 18 | 10010 | 32: RN | 32는 6비트가 필요하므로, 다음 출력에 6비트를 사용 |
| N | O | 14 | 001110 | 33: NO | |
| O | T | 15 | 001111 | 34: OT | |
| T | T | 20 | 010100 | 35: TT | |
| TO | B | 27 | 011011 | 36: TOB | |
| BE | O | 29 | 011101 | 37: BEO | |
| OR | T | 31 | 011111 | 38: ORT | |
| TOB | E | 36 | 100100 | 39: TOBE | |
| EO | R | 30 | 011110 | 40: EOR | |
| RN | O | 32 | 100000 | 41: RNO | |
| OT | # | 34 | 100010 | #은 알고리즘을 중지; 현재 시퀀스 전송 | |
| 0 | 000000 | 그리고 중지 코드 |
위 예시에서 볼 수 있듯이, LZW 알고리즘은 반복되는 패턴을 효율적으로 압축한다. 초기에는 압축률이 낮지만, 메시지가 길어질수록 사전의 항목이 텍스트의 더 긴 부분을 나타내게 되어 압축률이 점근적으로 최대값에 접근한다.[2]
## 디코딩
LZW 디코딩 알고리즘은 인코딩된 데이터를 입력받아 원래의 문자열로 복원하는 과정이다. 이 과정은 인코딩 과정에서 생성된 사전을 기반으로 이루어지며, 사전에 없는 코드가 나타나는 특수한 경우에도 대응할 수 있도록 설계되어 있다.
디코딩 알고리즘의 작동 방식은 다음과 같다.
1. 사전 초기화: 모든 단일 문자를 포함하는 사전으로 초기화한다. 이 사전은 인코딩 과정에서 사용된 초기 사전과 동일해야 한다.
2. 코드 읽기 및 문자열 출력: 입력된 코드에 해당하는 문자열을 사전에서 찾아 출력한다.
3. 사전 갱신: 현재 출력된 문자열에 다음 코드에 해당하는 문자열의 첫 글자를 연결하여 사전에 추가한다.
- 다음 코드가 사전에 존재하는 경우, 해당 코드에 해당하는 문자열의 첫 글자를 사용한다.
- 다음 코드가 사전에 존재하지 않는 경우(예외 상황), 현재 출력된 문자열의 첫 글자를 사용한다.
예외 상황은 인코더가 `cScSc` 형태의 입력을 만났을 때 발생한다. 여기서 `c`는 단일 문자, `S`는 문자열이며, `cS`는 사전에 있지만 `cSc`는 사전에 없는 경우이다. 이 경우, 인코더는 `cS`에 대한 코드를 출력하고 `cSc`에 대한 새 코드를 사전에 추가한다. 디코더는 인코더보다 한 단계 늦게 사전을 갱신하므로, 인코더가 방금 추가한 새 코드를 바로 디코딩해야 하는 상황이 발생할 수 있다. 이 때, 디코더는 현재 출력된 문자열(`cS`)의 첫 글자(`c`)를 사용하여 `cSc`를 추론하고 사전에 추가한다.
디코딩 과정은 입력 스트림이 끝날 때까지 반복된다. LZW 압축 해제 프로그램은 사용된 초기 사전을 미리 알아야 하지만, 추가 항목은 이전 항목의 연결이므로 재구성할 수 있다.
다음은 "TOBEORNOTTOBEORTOBEORNOT#" 문자열을 디코딩하는 예시이다.
| 입력 | 출력 시퀀스 | 새 사전 항목 | 설명 | ||||
|---|---|---|---|---|---|---|---|
| 비트 | 코드 | 전체 | 추측 | ||||
| 10100 | 20 | T | style="border-right: none;" | | style="border-left: none;" | | 27: | T? | |
| 01111 | 15 | O | 27: | TO | 28: | O? | |
| 00010 | 2 | B | 28: | OB | 29: | B? | |
| 00101 | 5 | E | 29: | BE | 30: | E? | |
| 01111 | 15 | O | 30: | EO | 31: | O? | |
| 10010 | 18 | R | 31: | OR | 32: | R? | 코드 31 생성 (5비트에 맞도록 마지막) |
| 001110 | 14 | N | 32: | RN | 33: | N? | 따라서 6비트에서 입력을 읽기 시작합니다. |
| 001111 | 15 | O | 33: | NO | 34: | O? | |
| 010100 | 20 | T | 34: | OT | 35: | T? | |
| 011011 | 27 | TO | 35: | TT | 36: | TO? | |
| 011101 | 29 | BE | 36: | TOB | 37: | BE? | 36 = TO + 첫 번째 기호 (B) |
| 011111 | 31 | OR | 37: | BEO | 38: | OR? | 수신된 다음 코드 시퀀스 (BE) |
| 100100 | 36 | TOB | 38: | ORT | 39: | TOB? | |
| 011110 | 30 | EO | 39: | TOBE | 40: | EO? | |
| 100000 | 32 | RN | 40: | EOR | 41: | RN? | |
| 100010 | 34 | OT | 41: | RNO | 42: | OT? | |
| 000000 | 0 | # | style="border-right: none;" | | style="border-left: none;" | | style="border-right: none;" | | style="border-left: none;" | | |
## 가변 폭 코드
LZW는 가변 폭 코드를 사용하여 압축 효율을 높인다. 인코딩 및 디코딩 과정에서 코드 폭 변경 시점에 주의해야 한다.
일반적인 버전에서 인코더는 현재 문자열(ω)과 다음 문자(s)의 조합(ω + s)이 사전에 없을 때, 다음에 사용 가능한 코드가 2''p'' (처음으로 ''p''+1 비트가 필요한 코드)가 되는 시점에 코드 폭을 ''p''에서 ''p''+1로 증가시킨다. 인코더는 ω에 대한 코드를 ''p'' 비트로 출력한 후, 코드 폭을 증가시켜 다음에 출력하는 코드가 ''p''+1 비트를 사용하도록 한다.
디코더는 사전을 구축하는 과정이 인코더보다 항상 한 단계 늦기 때문에, ω에 대한 코드를 보고 2''p''-1에 해당하는 항목을 생성하는 시점에 코드 폭을 증가시킨다. 이 시점은 인코더가 코드 폭을 증가시키는 시점과 동일하며, ''p'' 비트로 표현 가능한 가장 큰 코드를 생성하는 지점이다.
초기 구현 중 일부는 코드 폭을 증가시킨 후, 이전 폭이 아닌 새로운 폭으로 ω를 출력하는 경우가 있었다. 이를 "초기 변경(Early Change)"이라고 하며, 디코더에서 코드 폭 변경 시점을 혼동시키는 문제를 야기했다. 이러한 혼란을 방지하기 위해 어도비는 PDF 파일에서 두 가지 버전을 모두 허용하고, 각 LZW 압축 스트림의 헤더에 초기 변경 사용 여부를 나타내는 플래그를 포함하도록 했다. TIFF는 초기 변경을 사용하는 반면, GIF는 사용하지 않는다.
사전이 클리어 코드를 받아 지워지면, 인코더와 디코더는 코드 폭을 초기 코드 폭으로 재설정하고, 클리어 코드 바로 다음 코드부터 다시 시작한다.
## 패킹 순서
LZW 압축에서 코드는 일반적으로 바이트 경계에 맞춰 출력되지 않으므로, 인코더와 디코더는 코드를 바이트로 묶는 방법에 대해 합의해야 한다. 일반적인 두 가지 방법은 ''LSB 우선''("최하위 비트 우선")과 ''MSB 우선''("최상위 비트 우선")이다.
LSB 우선 패킹에서는 첫 번째 코드가 코드의 최하위 비트가 첫 번째 스트림 바이트의 최하위 비트에 맞춰지도록 정렬되며, 코드의 비트 수가 8비트를 초과하는 경우 남은 상위 비트는 다음 바이트의 최하위 비트에 맞춰진다. 추가 코드는 현재 스트림 바이트에서 아직 사용되지 않은 최하위 비트부터 시작하여 필요한 경우 추가 바이트로 진행한다.
MSB 우선 패킹은 첫 번째 코드가 ''최상위'' 비트가 첫 번째 스트림 바이트의 MSB에 맞춰지도록 정렬하며, 오버플로우는 다음 바이트의 MSB에 맞춰진다. 추가 코드는 현재 스트림 바이트에서 아직 사용되지 않은 최상위 비트부터 시작하여 작성된다.
GIF 파일은 LSB 우선 패킹 순서를 사용한다. TIFF 파일 및 PDF 파일은 MSB 우선 패킹 순서를 사용한다.
2. 1. 인코딩
LZW 인코딩 알고리즘은 초기 사전을 기반으로 입력 데이터를 순차적으로 처리하며 압축을 수행한다. 알고리즘의 작동 방식은 다음과 같다.[2]1. 길이가 1인 모든 가능한 문자열을 포함하도록 사전을 초기화한다.
2. 입력 데이터에서 현재까지의 문자열(w)과 일치하는 가장 긴 문자열을 사전에서 찾는다.
3. w에 해당하는 사전 코드를 출력한다.
4. w에 다음 문자(c)를 추가한 문자열(w+c)이 사전에 존재하지 않으면, w+c를 사전에 추가한다.
5. 다음 문자를 새로운 w로 설정하고 2단계부터 반복한다.
초기 사전에는 모든 단일 문자가 포함되어 있으며, 알고리즘은 입력 문자열을 스캔하면서 사전에 없는 가장 긴 부분 문자열을 찾는다. 이 문자열이 발견되면, 마지막 문자를 제외한 문자열의 인덱스를 출력하고, 새 문자열(마지막 문자 포함)을 사전에 추가한다. 이 과정에서 점차 더 긴 문자열이 사전에 등록되어 단일 출력 값으로 인코딩될 수 있다.
예를 들어, "TOBEORNOTTOBEORTOBEORNOT#" 문자열을 인코딩하는 과정은 다음과 같다.
| 현재 시퀀스 | 다음 문자 | 출력 코드 | 출력 비트 | 확장된 사전 | 설명 |
|---|---|---|---|---|---|
| NULL | T | ||||
| T | O | 20 | 10100 | 27: TO | 27은 0부터 26까지의 숫자 이후 사용 가능한 첫 번째 코드 |
| O | B | 15 | 01111 | 28: OB | |
| B | E | 2 | 00010 | 29: BE | |
| E | O | 5 | 00101 | 30: EO | |
| O | R | 15 | 01111 | 31: OR | |
| R | N | 18 | 10010 | 32: RN | 32는 6비트가 필요하므로, 다음 출력에 6비트를 사용 |
| N | O | 14 | 001110 | 33: NO | |
| O | T | 15 | 001111 | 34: OT | |
| T | T | 20 | 010100 | 35: TT | |
| TO | B | 27 | 011011 | 36: TOB | |
| BE | O | 29 | 011101 | 37: BEO | |
| OR | T | 31 | 011111 | 38: ORT | |
| TOB | E | 36 | 100100 | 39: TOBE | |
| EO | R | 30 | 011110 | 40: EOR | |
| RN | O | 32 | 100000 | 41: RNO | |
| OT | # | 34 | 100010 | #은 알고리즘을 중지; 현재 시퀀스 전송 | |
| 0 | 000000 | 그리고 중지 코드 |
위 예시에서 볼 수 있듯이, LZW 알고리즘은 반복되는 패턴을 효율적으로 압축한다. 초기에는 압축률이 낮지만, 메시지가 길어질수록 사전의 항목이 텍스트의 더 긴 부분을 나타내게 되어 압축률이 점근적으로 최대값에 접근한다.[2]
2. 2. 디코딩
LZW 디코딩 알고리즘은 인코딩된 데이터를 입력받아 원래의 문자열로 복원하는 과정이다. 이 과정은 인코딩 과정에서 생성된 사전을 기반으로 이루어지며, 사전에 없는 코드가 나타나는 특수한 경우에도 대응할 수 있도록 설계되어 있다.디코딩 알고리즘의 작동 방식은 다음과 같다.
1. 사전 초기화: 모든 단일 문자를 포함하는 사전으로 초기화한다. 이 사전은 인코딩 과정에서 사용된 초기 사전과 동일해야 한다.
2. 코드 읽기 및 문자열 출력: 입력된 코드에 해당하는 문자열을 사전에서 찾아 출력한다.
3. 사전 갱신: 현재 출력된 문자열에 다음 코드에 해당하는 문자열의 첫 글자를 연결하여 사전에 추가한다.
- 다음 코드가 사전에 존재하는 경우, 해당 코드에 해당하는 문자열의 첫 글자를 사용한다.
- 다음 코드가 사전에 존재하지 않는 경우(예외 상황), 현재 출력된 문자열의 첫 글자를 사용한다.
예외 상황은 인코더가 `cScSc` 형태의 입력을 만났을 때 발생한다. 여기서 `c`는 단일 문자, `S`는 문자열이며, `cS`는 사전에 있지만 `cSc`는 사전에 없는 경우이다. 이 경우, 인코더는 `cS`에 대한 코드를 출력하고 `cSc`에 대한 새 코드를 사전에 추가한다. 디코더는 인코더보다 한 단계 늦게 사전을 갱신하므로, 인코더가 방금 추가한 새 코드를 바로 디코딩해야 하는 상황이 발생할 수 있다. 이 때, 디코더는 현재 출력된 문자열(`cS`)의 첫 글자(`c`)를 사용하여 `cSc`를 추론하고 사전에 추가한다.
디코딩 과정은 입력 스트림이 끝날 때까지 반복된다. LZW 압축 해제 프로그램은 사용된 초기 사전을 미리 알아야 하지만, 추가 항목은 이전 항목의 연결이므로 재구성할 수 있다.
다음은 "TOBEORNOTTOBEORTOBEORNOT#" 문자열을 디코딩하는 예시이다.
| 입력 | 출력 시퀀스 | 새 사전 항목 | 설명 | ||||
|---|---|---|---|---|---|---|---|
| 비트 | 코드 | 전체 | 추측 | ||||
| 10100 | 20 | T | style="border-right: none;" | | style="border-left: none;" | | 27: | T? | |
| 01111 | 15 | O | 27: | TO | 28: | O? | |
| 00010 | 2 | B | 28: | OB | 29: | B? | |
| 00101 | 5 | E | 29: | BE | 30: | E? | |
| 01111 | 15 | O | 30: | EO | 31: | O? | |
| 10010 | 18 | R | 31: | OR | 32: | R? | 코드 31 생성 (5비트에 맞도록 마지막) |
| 001110 | 14 | N | 32: | RN | 33: | N? | 따라서 6비트에서 입력을 읽기 시작합니다. |
| 001111 | 15 | O | 33: | NO | 34: | O? | |
| 010100 | 20 | T | 34: | OT | 35: | T? | |
| 011011 | 27 | TO | 35: | TT | 36: | TO? | |
| 011101 | 29 | BE | 36: | TOB | 37: | BE? | 36 = TO + 첫 번째 기호 (B) |
| 011111 | 31 | OR | 37: | BEO | 38: | OR? | 수신된 다음 코드 시퀀스 (BE) |
| 100100 | 36 | TOB | 38: | ORT | 39: | TOB? | |
| 011110 | 30 | EO | 39: | TOBE | 40: | EO? | |
| 100000 | 32 | RN | 40: | EOR | 41: | RN? | |
| 100010 | 34 | OT | 41: | RNO | 42: | OT? | |
| 000000 | 0 | # | style="border-right: none;" | | style="border-left: none;" | | style="border-right: none;" | | style="border-left: none;" | | |
2. 3. 가변 폭 코드
LZW는 가변 폭 코드를 사용하여 압축 효율을 높인다. 인코딩 및 디코딩 과정에서 코드 폭 변경 시점에 주의해야 한다.일반적인 버전에서 인코더는 현재 문자열(ω)과 다음 문자(s)의 조합(ω + s)이 사전에 없을 때, 다음에 사용 가능한 코드가 2''p'' (처음으로 ''p''+1 비트가 필요한 코드)가 되는 시점에 코드 폭을 ''p''에서 ''p''+1로 증가시킨다. 인코더는 ω에 대한 코드를 ''p'' 비트로 출력한 후, 코드 폭을 증가시켜 다음에 출력하는 코드가 ''p''+1 비트를 사용하도록 한다.
디코더는 사전을 구축하는 과정이 인코더보다 항상 한 단계 늦기 때문에, ω에 대한 코드를 보고 2''p''-1에 해당하는 항목을 생성하는 시점에 코드 폭을 증가시킨다. 이 시점은 인코더가 코드 폭을 증가시키는 시점과 동일하며, ''p'' 비트로 표현 가능한 가장 큰 코드를 생성하는 지점이다.
초기 구현 중 일부는 코드 폭을 증가시킨 후, 이전 폭이 아닌 새로운 폭으로 ω를 출력하는 경우가 있었다. 이를 "초기 변경(Early Change)"이라고 하며, 디코더에서 코드 폭 변경 시점을 혼동시키는 문제를 야기했다. 이러한 혼란을 방지하기 위해 어도비는 PDF 파일에서 두 가지 버전을 모두 허용하고, 각 LZW 압축 스트림의 헤더에 초기 변경 사용 여부를 나타내는 플래그를 포함하도록 했다. TIFF는 초기 변경을 사용하는 반면, GIF는 사용하지 않는다.
사전이 클리어 코드를 받아 지워지면, 인코더와 디코더는 코드 폭을 초기 코드 폭으로 재설정하고, 클리어 코드 바로 다음 코드부터 다시 시작한다.
2. 4. 패킹 순서
LZW 압축에서 코드는 일반적으로 바이트 경계에 맞춰 출력되지 않으므로, 인코더와 디코더는 코드를 바이트로 묶는 방법에 대해 합의해야 한다. 일반적인 두 가지 방법은 ''LSB 우선''("최하위 비트 우선")과 ''MSB 우선''("최상위 비트 우선")이다.LSB 우선 패킹에서는 첫 번째 코드가 코드의 최하위 비트가 첫 번째 스트림 바이트의 최하위 비트에 맞춰지도록 정렬되며, 코드의 비트 수가 8비트를 초과하는 경우 남은 상위 비트는 다음 바이트의 최하위 비트에 맞춰진다. 추가 코드는 현재 스트림 바이트에서 아직 사용되지 않은 최하위 비트부터 시작하여 필요한 경우 추가 바이트로 진행한다.
MSB 우선 패킹은 첫 번째 코드가 ''최상위'' 비트가 첫 번째 스트림 바이트의 MSB에 맞춰지도록 정렬하며, 오버플로우는 다음 바이트의 MSB에 맞춰진다. 추가 코드는 현재 스트림 바이트에서 아직 사용되지 않은 최상위 비트부터 시작하여 작성된다.
GIF 파일은 LSB 우선 패킹 순서를 사용한다. TIFF 파일 및 PDF 파일은 MSB 우선 패킹 순서를 사용한다.
3. 종류
LZMW (1985년, V. 밀러, M. 웨그만)[9]는 입력에서 사전에 이미 있는 가장 긴 문자열(현재 일치하는 문자열)을 검색한다. 이전 일치 문자열과 현재 일치 문자열을 연결하여 사전에 추가한다. (따라서 사전 항목이 더 빠르게 증가하지만, 이 방식은 구현하기가 훨씬 더 복잡하다.) 밀러와 웨그만은 또한 사전이 가득 찼을 때 빈도가 낮은 항목을 사전에서 삭제할 것을 제안했다.
LZAP (1988년, 제임스 스토러)[10] - LZMW의 수정판: 이전 일치 문자열과 현재 일치 문자열을 연결한 것만 사전에 추가하는 대신, 이전 일치 문자열과 현재 일치 문자열의 각 초기 부분 문자열을 연결하여 추가한다("AP"는 "모든 접두사"를 의미한다). 예를 들어, 이전 일치 문자열이 "wiki"이고 현재 일치 문자열이 "pedia"이면 LZAP 인코더는 "wikip", "wikipe", "wikiped", "wikipedi", "wikipedia"의 5개의 새로운 시퀀스를 사전에 추가한다. 여기서 LZMW 인코더는 "wikipedia" 시퀀스 하나만 추가한다. 이는 더 많은 사전 항목을 추가하는 대신 LZMW의 복잡성을 일부 제거한다.
LZWL는 음절 기반의 LZW이다.
3. 1. LZMW
LZMW는 1985년 V. 밀러와 M. 웨그만이 제안한 알고리즘이다.[9] 입력에서 사전에 이미 있는 가장 긴 문자열(현재 일치하는 문자열)을 검색하고, 이전 일치 문자열과 현재 일치 문자열을 연결하여 사전에 추가한다. 이 방식은 사전 항목이 더 빠르게 증가하지만 구현하기가 더 복잡하다. 밀러와 웨그만은 사전이 가득 찼을 때 빈도가 낮은 항목을 사전에서 삭제할 것을 제안했다.3. 2. LZAP
LZAP는 제임스 스토러(James Storer)가 1988년에 개발한 알고리즘으로, LZMW의 수정판이다.[10] LZMW가 이전 일치 문자열과 현재 일치 문자열을 연결하여 사전에 추가하는 반면, LZAP는 이전 일치 문자열과 현재 일치 문자열의 각 초기 부분 문자열을 연결하여 추가한다.[10] 예를 들어, 이전 일치 문자열이 "wiki"이고 현재 일치 문자열이 "pedia"이면 LZAP 인코더는 "wikip", "wikipe", "wikiped", "wikipedi", "wikipedia"의 5개의 새로운 시퀀스를 사전에 추가한다. ("AP"는 "모든 접두사"를 의미한다)[10] 이는 더 많은 사전 항목을 추가하여 LZMW의 복잡성을 일부 제거하는 효과를 가진다.3. 3. LZWL
LZWL은 LZW의 음절 기반 변형이다.[9][10]4. 구현 (Groovy)
다음은 Groovy에서의 구현이다. 먼저, 비트 열을 다루는 스트림을 준비한다.
```groovy
class BitStream {
BitSet bs = new BitSet(); int len = 0, pos = 0;
void write(int v, int bits) {
for (int i in 0..
}
int read(int bits) {
int v = 0; for (int i in 0..
return v
}
String toString() { "length = $len, {" + (0..
}
```
압축은 다음과 같다.
```groovy
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
}
```
압축 해제는 다음과 같다.
```groovy
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[]
}
5. 예제
LZW 알고리즘의 작동 방식을 구체적인 예시를 통해 살펴본다. 아래 예제는 데이터의 인코딩 및 디코딩 과정에서 각 단계별 출력 상태와 사전의 변화를 보여준다.
== 인코딩 예제 ==
다음은 "TOBEORNOTTOBEORTOBEORNOT#" 문자열을 LZW 알고리즘으로 인코딩하는 과정을 나타낸 표이다. 초기 사전은 대문자 A-Z(1-26)와 '#' 문자(0)로 구성되며, 각 문자는 5비트로 표현된다.
인코딩 과정에서는 반복되는 문자열을 사전에 등록하고, 해당 문자열을 코드로 대체하여 출력한다.
| 현재 문자 | 다음 문자 | 출력 코드 | 출력 비트 | 사전에 추가 (십진법) | 사전에 추가 (문자열) | 코멘트 |
|---|---|---|---|---|---|---|
| T | O | 20 | 10100 | 27 | TO | 27은 사용 가능한 첫 번째 코드 |
| 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 | 정지 코드 출력 |
== 디코딩 예제 ==
다음은 위에서 인코딩된 코드(20, 15, 11, 25, 15, 27, 11, 29, 28, 30, 11, 1, 34, 11, 21, 0)를 LZW 알고리즘으로 디코딩하는 과정을 나타낸 표이다. 디코더는 인코더와 동일한 초기 사전을 가지고 시작하며, 인코딩 과정과 유사하게 사전을 갱신하면서 디코딩을 수행한다.
| 입력 코드 | 출력 문자 | 사전에 추가 (완전) | 사전에 추가 (추측) | 코멘트 |
|---|---|---|---|---|
| 20 | T | 27: T? | ||
| 15 | O | 27: TO | 28: O? | |
| 11 | K | 28: OK | 29: K? | |
| 25 | Y | 29: KY | 30: Y? | |
| 15 | O | 30: YO | 31: O? | |
| 27 | TO | 31: OT | 32: TO? | 코드 31을 추가 (5비트로 읽는 마지막 입력) |
| 11 | K | 32: TOK | 33: K? | 6비트로 읽음 |
| 29 | KY | 33: KK | 34: KY? | |
| 28 | OK | 34: KYO | 35: OK? | |
| 30 | YO | 35: OKY | 36: YO? | |
| 11 | K | 36: YOK | 37: K? | |
| 1 | A | 37: KA | 38: A? | |
| 34 | KYO | 38: AK | 39: KYO? | |
| 11 | K | 39: KYOK | 40: K? | |
| 21 | U | 40: KU | 41: U? | |
| 0 | # |
== 특수한 경우의 디코딩 예제 ==
"TANBANANAS#" 문자열을 인코딩/디코딩하는 과정에서 발생하는 특수한 경우를 보여준다.
| 인코딩 | 디코딩 | ||||||
|---|---|---|---|---|---|---|---|
| 현재 문자 | 출력할 코드 | 사전에 추가 | 입력 코드 | 출력할 문자 | 사전에 추가 | ||
| T | 20 | 27: | TA | 20 | T | style="border-right: none;" | | style="border-left: none;" | |
| 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 | ANA | 31: | ANA |
| S | 19 | style="border-right: none;" | | style="border-left: none;" | | 19 | S | style="border-right: none;" | | style="border-left: none;" | |
| # | 0 | style="border-right: none;" | | style="border-left: none;" | | 0 | # | style="border-right: none;" | | style="border-left: none;" | |
위의 예시에서 디코딩 중 입력 코드 31은 사전에 아직 추가되지 않은 상태이다. 이는 인코딩 과정에서 사전에 추가된 직후의 코드가 바로 사용되었기 때문이다. 디코딩에서는 사전에 추가하는 과정이 한 단계 늦기 때문에 발생한다. 이 경우, 코드 31에 해당하는 문자열은 이전 단계에서 디코딩된 문자열(AN)에 코드 31의 첫 글자(A)를 붙인 "ANA"임을 유추할 수 있다.
6. 특허 및 라이선스 문제
LZW에 대한 다양한 특허는 미국 및 기타 국가에서 발급되었다. LZ78은 1981년 8월 10일에 출원되어 렘펠(Lempel), 지브(Ziv), 콘(Cohn), 이스트만(Eastman)에 의해 로 특허를 받았으며, 스페리사(Sperry Corporation), 이후 유니시스사(Unisys Corporation)에 양도되었다. LZW 알고리즘에 대해 두 개의 미국 특허가 발급되었다. 빅터 S. 밀러(Victor S. Miller)와 마크 N. 웨그만(Mark N. Wegman)이 발명하고 IBM에 양도된 은 원래 1983년 6월 1일에 출원되었으며, 웰치(Welch)가 발명하여 스페리사, 이후 유니시스사에 양도된 는 1983년 6월 20일에 출원되었다.
상기 특허 외에도 웰치의 1983년 특허에는 그에 영향을 미친 다른 여러 특허에 대한 인용이 포함되어 있으며, 여기에는 NEC의 쥰 카나츠(Jun Kanatsu)가 발명한 두 개의 1980년 일본 특허([https://patents.google.com/patent/JPS5719857A/en JP9343880A] 및 [https://patents.google.com/patent/JPS57101937A/en JP17790880A]), 존 S. 호어닝(John S. Hoerning)의 (1974), 클라우스 E. 홀츠(Klaus E. Holtz)의 (1977), 카를 에크하르트 하인츠(Karl Eckhart Heinz)의 1981년 독일 특허([https://patents.google.com/patent/DE3118676C2/en DE19813118676])가 포함된다.[3]
1993-94년과 1999년에 유니시스사(Unisys Corporation)는 GIF 이미지에서 LZW에 대한 사용료를 징수하려 시도하면서 광범위한 비난을 받았다. 1993-1994년 유니시스-컴퓨서브(CompuServe) 논란(컴퓨서브(CompuServe)는 GIF 형식의 제작자)은 유즈넷(Usenet) comp.graphics 토론인 ''GIF 대체 파일 형식에 대한 생각''을 촉발시켰고, 이는 결국 1995년 특허에 얽매이지 않는 PNG(Portable Network Graphics) 파일 형식의 생성으로 이어진 이메일 교환을 촉진했다.
LZW 알고리즘에 대한 유니시스사의 미국 특허는 출원 후 20년이 지난 2003년 6월 20일에 만료되었다.[4] 영국, 프랑스, 독일, 이탈리아, 일본 및 캐나다에서 출원된 특허도 마찬가지로 출원 후 20년이 지난 2004년에 만료되었다.[4]
LZW는 1984년에 발표되었다. 처음에는 스페리사가 특허를 보유하고 있었다. 이후 스페리사는 배로우스사와 합병하여 1986년에 유니시스사가 되었고, 이 알고리즘의 특허권도 유니시스사에 승계되었다.
앞서 언급했듯이 GIF 이미지 압축에 사용되었으며, 그 특허료에 대한 유니시스사의 입장이 문제가 되었다. 자세한 내용은 GIF 특허 문제를 참조하십시오.
일본에서는 1984년 6월 20일에 특허가 출원되었고, 2004년 6월 20일에 만료되었다. 다음은 일본 특허청 산업 재산권 정보에서 발췌한 내용이다.
- 발명의 명칭: 압축 장치 및 압축 방법
- 출원일: 1984년 6월 20일
- * 출원 번호: 특허 출원 평7-341868
- 공개일: 1996년 9월 13일
- * 공개 번호: 특허 공개 평8-237138
==== 대한민국에서의 특허 문제 ====
LZW 알고리즘은 1984년에 발표되었으며, 처음에는 스페리사가 특허를 보유하고 있었다. 이후 스페리사는 배로우스사와 합병하여 1986년에 유니시스사가 되었고, 이 알고리즘의 특허권도 유니시스사에 승계되었다.
일본에서는 1984년 6월 20일에 특허가 출원되었고, 2004년 6월 20일에 만료되었다. 일본 특허청 산업 재산권 정보에 따르면, 발명의 명칭은 "압축 장치 및 압축 방법"이며, 출원 번호는 특허 출원 평7-341868, 공개일은 1996년 9월 13일(공개 번호: 특허 공개 평8-237138)이다.
GIF 이미지 압축에 LZW 알고리즘이 사용되면서, 유니시스사의 특허료 정책이 문제가 되기도 하였다. 자세한 내용은 GIF 특허 문제를 참조할 수 있다.
==== GIF, TIFF, PDF 등 파일 형식과의 관계 ====
LZW 압축 알고리즘은 다양한 파일 형식에 사용되었는데, 대표적으로 GIF(Graphics Interchange Format), TIFF, PDF 등이 있다.[4] LZW는 1984년에 발표되었으며, 처음에는 스페리사가 특허를 보유하고 있었다.[4] 이후 스페리사는 배로우스사와 합병하여 1986년에 유니시스사가 되었고, LZW 알고리즘의 특허권도 유니시스사에 승계되었다.[4]
LZW에 대한 특허는 미국 및 기타 국가에서 발급되었다.[3] 1983년 6월 20일에 출원된 웰치(Welch)의 특허(US Patent 4,558,302)를 포함하여 LZW 알고리즘에 대한 여러 특허가 존재하며, 이 특허는 유니시스사에 양도되었다.[3] 유니시스사는 1993-94년과 1999년에 GIF 이미지에서 LZW에 대한 사용료를 징수하려 시도하면서 많은 비난을 받았다.[3] 1993-1994년 유니시스-컴퓨서브 논란은 GIF 형식의 제작자인 컴퓨서브(CompuServe)와 유니시스사 간의 분쟁으로, 유즈넷(Usenet)에서 ''GIF 대체 파일 형식에 대한 생각''이라는 토론을 촉발시켰고, 이는 결국 1995년 특허에 얽매이지 않는 PNG(Portable Network Graphics) 파일 형식의 생성으로 이어졌다.[3]
LZW 알고리즘에 대한 유니시스사의 미국 특허는 2003년 6월 20일에 만료되었고, 영국, 프랑스, 독일, 이탈리아, 일본 및 캐나다에서 출원된 특허도 2004년에 만료되었다.[4] 일본에서는 1984년 6월 20일에 특허가 출원되었고(출원 번호: 특허 출원 평7-341868), 2004년 6월 20일에 만료되었다.[4]
6. 1. 대한민국에서의 특허 문제
LZW 알고리즘은 1984년에 발표되었으며, 처음에는 스페리사가 특허를 보유하고 있었다. 이후 스페리사는 배로우스사와 합병하여 1986년에 유니시스사가 되었고, 이 알고리즘의 특허권도 유니시스사에 승계되었다.일본에서는 1984년 6월 20일에 특허가 출원되었고, 2004년 6월 20일에 만료되었다. 일본 특허청 산업 재산권 정보에 따르면, 발명의 명칭은 "압축 장치 및 압축 방법"이며, 출원 번호는 특허 출원 평7-341868, 공개일은 1996년 9월 13일(공개 번호: 특허 공개 평8-237138)이다.
GIF 이미지 압축에 LZW 알고리즘이 사용되면서, 유니시스사의 특허료 정책이 문제가 되기도 하였다. 자세한 내용은 GIF 특허 문제를 참조할 수 있다.
6. 2. GIF, TIFF, PDF 등 파일 형식과의 관계
LZW 압축 알고리즘은 다양한 파일 형식에 사용되었는데, 대표적으로 GIF(Graphics Interchange Format), TIFF, PDF 등이 있다.[4] LZW는 1984년에 발표되었으며, 처음에는 스페리사가 특허를 보유하고 있었다.[4] 이후 스페리사는 배로우스사와 합병하여 1986년에 유니시스사가 되었고, LZW 알고리즘의 특허권도 유니시스사에 승계되었다.[4]LZW에 대한 특허는 미국 및 기타 국가에서 발급되었다.[3] 1983년 6월 20일에 출원된 웰치(Welch)의 특허(US Patent 4,558,302)를 포함하여 LZW 알고리즘에 대한 여러 특허가 존재하며, 이 특허는 유니시스사에 양도되었다.[3] 유니시스사는 1993-94년과 1999년에 GIF 이미지에서 LZW에 대한 사용료를 징수하려 시도하면서 많은 비난을 받았다.[3] 1993-1994년 유니시스-컴퓨서브 논란은 GIF 형식의 제작자인 컴퓨서브(CompuServe)와 유니시스사 간의 분쟁으로, 유즈넷(Usenet)에서 ''GIF 대체 파일 형식에 대한 생각''이라는 토론을 촉발시켰고, 이는 결국 1995년 특허에 얽매이지 않는 PNG(Portable Network Graphics) 파일 형식의 생성으로 이어졌다.[3]
LZW 알고리즘에 대한 유니시스사의 미국 특허는 2003년 6월 20일에 만료되었고, 영국, 프랑스, 독일, 이탈리아, 일본 및 캐나다에서 출원된 특허도 2004년에 만료되었다.[4] 일본에서는 1984년 6월 20일에 특허가 출원되었고(출원 번호: 특허 출원 평7-341868), 2004년 6월 20일에 만료되었다.[4]
7. 활용
LZW 압축은 초기에 널리 사용된 범용 데이터 압축 방법으로, 큰 영어 텍스트 파일은 원래 크기의 절반 정도로 압축할 수 있었다. 1986년경 유닉스 시스템의 사실상 표준 유틸리티인 compress 프로그램에 사용되었으나, 이후 LZW 특허 침해 문제와 gzip이 DEFLATE 알고리즘을 사용하여 더 나은 압축률을 제공함에 따라 많은 배포판에서 사라졌다. 하지만 2008년 기준으로 FreeBSD는 compress와 uncompress를 배포판의 일부로 포함하고 있다. 다른 여러 인기 있는 압축 유틸리티도 LZW 또는 이와 밀접하게 관련된 방법을 사용했다.
LZW는 1987년 GIF 이미지 형식의 일부가 되면서 널리 사용되었으며, TIFF 및 PDF 파일에서도 선택적으로 사용할 수 있다. Adobe Acrobat 소프트웨어에서도 LZW를 사용할 수 있지만, Acrobat은 기본적으로 PDF 파일의 대부분의 텍스트 및 색상 테이블 기반 이미지 데이터에 DEFLATE를 사용한다.
7. 1. 파일 압축
LZW 압축은 컴퓨터에서 최초로 널리 사용된 범용 데이터 압축 방법이었다. 큰 영어 텍스트 파일은 일반적으로 LZW를 사용하여 원래 크기의 약 절반으로 압축할 수 있다.LZW는 1986년경 유닉스 시스템에서 사실상 표준 유틸리티가 된 공개 도메인 프로그램 compress에 사용되었다. 이후 LZW 특허를 침해하고 gzip이 LZ77 기반 DEFLATE 알고리즘을 사용하여 더 나은 압축률을 생성했기 때문에 많은 배포판에서 사라졌지만, 2008년 기준으로 적어도 FreeBSD는 compress와 uncompress를 배포판의 일부로 포함하고 있다. 다른 여러 인기 있는 압축 유틸리티도 LZW 또는 이와 밀접하게 관련된 방법을 사용했다.
LZW는 1987년 GIF 이미지 형식의 일부가 되면서 매우 널리 사용되었다. 또한 TIFF 및 PDF 파일에서도 (선택적으로) 사용할 수 있다.
7. 2. 이미지 압축
LZW 압축은 초기에 널리 사용된 범용 데이터 압축 방법으로, 큰 영어 텍스트 파일은 원래 크기의 절반 정도로 압축할 수 있었다. 1986년경 유닉스 시스템의 사실상 표준 유틸리티인 compress 프로그램에 사용되었으나, 이후 LZW 특허 침해 문제와 gzip이 DEFLATE 알고리즘을 사용하여 더 나은 압축률을 제공함에 따라 많은 배포판에서 사라졌다. 하지만 2008년 기준으로 FreeBSD는 compress와 uncompress를 배포판의 일부로 포함하고 있다.LZW는 1987년 GIF 이미지 형식의 일부가 되면서 널리 사용되었으며, TIFF 및 PDF 파일에서도 선택적으로 사용할 수 있다. Adobe Acrobat 소프트웨어에서도 LZW를 사용할 수 있지만, Acrobat은 기본적으로 PDF 파일의 대부분의 텍스트 및 색상 테이블 기반 이미지 데이터에 DEFLATE를 사용한다.
참조
[1]
간행물
A Technique for High-Performance Data Compression
https://ieeexplore.i[...]
[2]
간행물
Compression of individual sequences via variable-rate coding
http://www.cs.duke.e[...]
2009-03-03
[3]
특허
[4]
웹사이트
LZW Patent Information
http://www.unisys.co[...]
Unisys
2014-03-06
[5]
서적
Data Compression – The complete reference
[6]
서적
Data Compression – The complete reference
[7]
간행물
A Technique for High-Performance Data Compression
http://www.cs.duke.e[...]
[8]
간행물
Compression of individual sequences via variable-rate coding
http://www.cs.duke.e[...]
[9]
서적
Data Compression - The complete reference
[10]
서적
Data Compression - The complete reference
본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.
문의하기 : help@durumis.com