Standard Compression Scheme for Unicode
# Standard Compression Scheme for Unicode

Das Standard Compression Scheme for Unicode (SCSU, englisch für Standard-Kompressions-Schema für Unicode) ist eine Zeichenkodierung für Texte aus Unicode-Zeichen, das im Gegensatz zu den meisten anderen Kodierungen darauf ausgerichtet ist, möglichst wenig Speicherplatz zu benötigen.

## Geschichte

Die Kodierung wurde ursprünglich von Reuters entwickelt. Autoren des im technischen Standard UTS #6 beschriebenen Verfahrens sind Misha Wolf, Ken Whistler, Charles Wicksteed, Mark Davis, Asmus Freytag und Markus Scherer. Die erste Veröffentlichung erfolgte im Mai 1997, seit Mai 2005 liegt der Standard unverändert in der Revision 4 vor.

## Idee

Traditionelle Zeichensätze vor Unicode, etwa die ISO-8859-Zeichensätze, benötigten nur ein Byte pro Zeichen, Zeichensätze für ostasiatische Schriften zwei Byte. Bei der Verwendung von Unicode steigt der Speicherbedarf meist an: Bei UTF-32 auf vier Byte pro Zeichen, bei UTF-16 sind es zwei oder vier Byte pro Zeichen, bei UTF-8 zwischen ein und vier Byte pro Zeichen. Dabei nutzen gewöhnliche Texte nur einen sehr kleinen Teil aller in Unicode verfügbaren Zeichen. Die meisten verwendeten Zeichen liegen dabei zum einen im ASCII-Bereich (insbesondere Satzzeichen), zum anderen in einem kleinen zusammenhängenden Bereich, der häufig einem Unicodeblock entspricht. Der Algorithmus verwendet ein dynamisch positioniertes Fenster, das 128 aufeinander folgende Zeichen umfasst. Zeichen in diesem Fenster werden durch ein Byte im Bereich von 0x80 bis 0xFF kodiert, Zeichen im ASCII-Bereich (mit Ausnahme der meisten Steuerzeichen) durch ein Byte aus dem Bereich von 0x20 bis 0x7F. Die restlichen Byte werden als Befehle verwendet, um dieses Fenster neu zu positionierten oder in den unkomprimierten Modus umzuschalten, in dem die folgenden Byte als UTF-16 interpretiert werden. Dieser Modus ist besonders dann zweckmäßig, wenn der Text viele Zeichen aus einem Bereich von mehr als 128 aufeinander folgenden Zeichen verwendet, etwa im Chinesischen.

## Algorithmus

Diese Idee wird mit dem folgenden Verfahren umgesetzt. Definiert wird dabei die Methode, mit der aus einem SCSU-Bytestrom wieder ein Text aus Unicode-Zeichen gewonnen werden kann. Zur Kodierung können verschiedene Algorithmen verwendet werden, die zu einem Ergebnis führen, das korrekt dekodiert werden kann. Wie ein solcher Algorithmus gestaltet wird, hängt unter anderem davon ab, ob mehr Gewicht auf eine schnelle Kodierung oder auf eine gute Kompression gelegt wird.

### Fenster

Der Algorithmus kennt zwei Arten von Fenstern: Statische Fenster, die im Algorithmus fest vordefiniert sind, und dynamische Fenster, deren Position bei Bedarf geändert werden kann. Von jeder Sorte gibt es acht Stück, nummeriert von 0 bis 7. Die Lage eines Fensters kann durch den Codepunkt des ersten Zeichens in diesem Fenster angegeben werden.

#### Statische Fenster

Die acht statischen Fenster sind folgendermaßen definiert:
| Fensternummer | Start | enthaltene Zeichen |
| 0 | U+0000 | Basis-Lateinisch |
| 1 | U+0080 | Lateinisch-1, Ergänzung |
| 2 | U+0100 | Lateinisch, erweitert-A |
| 3 | U+0300 | Kombinierende diakritische Zeichen |
| 4 | U+2000 | Allgemeine Interpunktion und Hochgestellte Zeichen |
| 5 | U+2080 | Tiefgestellte Zeichen, Währungszeichen und Kombinierende diakritische Zeichen für Symbole |
| 6 | U+2100 | Buchstabenähnliche Symbole und Zahlzeichen |
| 7 | U+3000 | CJK-Symbole und -Interpunktion |

#### Dynamische Fenster

Die Anfangspositionen der acht dynamischen Fenster sind die folgenden:
| Fensternummer | Start | enthaltene Zeichen |
| 0 | U+0080 | Lateinisch-1, Ergänzung |
| 1 | U+00C0 | Teile von Lateinisch-1, Ergänzung und Lateinisch, erweitert-A |
| 2 | U+0400 | Kyrillisch |
| 3 | U+0600 | Arabisch |
| 4 | U+0900 | Devanagari |
| 5 | U+3040 | Hiragana |
| 6 | U+30A0 | Katakana |
| 7 | U+FF00 | Vollbreite Formen |
Das dynamische Fenster 0 ist dabei zu Beginn aktiv.
Um die Position eines dynamischen Fensters zu verändern, stehen verschiedene Befehle zur Verfügung. Die beiden einfachen Befehle (SDn und UDn) zur Definition bestimmen die neue Lage des Fensters durch ein Byte nach der folgenden Tabelle:
| Byte (hex) | Start | Anmerkung |
| 00 | reserviert | reserviert zur internen Verwendung |
| 01–67 | U+0080–U+3380 | das Byte wird mit 0x80 multipliziert |
| 68–A7 | U+E000–U+FF80 | das Byte wird mit 0x80 multipliziert, dazu wird 0xAC00 addiert |
| A8–F8 | reserviert | reserviert für zukünftige Verwendung |
| F9 | U+00C0 | Teile von Lateinisch-1, Ergänzung und Lateinisch, erweitert-A |
| FA | U+0250 | IPA-Erweiterungen |
| FB | U+0370 | Griechisch |
| FC | U+0530 | Armenisch |
| FD | U+3040 | Hiragana |
| FE | U+30A0 | Katakana |
| FF | U+FF60 | Halbbreite Katakana |
Die beiden erweiterten Befehle (SDX und UDX) zur Fensterdefinition verwenden zwei Byte. Die obersten drei Bit geben die Nummer des Fensters an, zu den restlichen 13 Bit wird 0x10000 addiert und das Ergebnis als erstes Zeichen des Fensters genommen.

### Modi

Der Algorithmus verwendet zwei verschiedene Modi. Anfangs befindet er sich im Ein-Byte-Modus, in dem Zeichen durch ein einzelnes Byte kodiert werden. Bytewerte im Bereich 0x20 bis 0x7F sowie 0x00 (NUL), 0x09 (horizontales Tabulatorzeichen), 0x0A (LF) und 0x0D (CR) werden als Zeichen im statischen Fenster 0 interpretiert, Werte im Bereich 0x80 bis 0xFF als Zeichen im aktiven dynamischen Fenster. Alle anderen Byte werden als Befehle interpretiert.
Der andere Modus ist ein Zwei-Byte-Modus. Bis auf einige Ausnahmen werden hier alle Bytepaare als UTF-16BE-kodierte Zeichen interpretiert, nur einige wenige Bytes stellen Befehle dar.

### Befehle

Im Ein-Byte-Modus stellen folgende Bytewerte Befehle dar:
| Byte (hex) | Name | Bedeutung |
| 01–08 | SQ0–SQ7 | wechselt für das folgende Byte die Fenster: 0x00 bis 0x7F werden als Zeichen im statischen Fenster n interpretiert, 0x80 bis 0xFF im dynamischen Fenster n |
| 0B | SDX | verwendet die beiden folgenden Bytes zur erweiterten Definition eines dynamischen Fensters, dieses Fenster ist danach aktiv |
| 0C | reserviert | reserviert für zukünftige Verwendung |
| 0E | SQU | interpretiert die beiden folgenden Byte als ein UTF-16-kodiertes Zeichen |
| 0F | SCU | wechselt in den Zwei-Byte-Modus |
| 10–17 | SC0–SC7 | macht das dynamische Fenster n zum aktiven Fenster |
| 18–1F | SD0–SD7 | verwendet das folgende Byte als einfache Definition für das dynamische Fenster n, dieses Fenster ist danach aktiv |
Soll ein Steuerzeichen kodiert werden, das durch ein Byte repräsentiert wird, das einen Befehl darstellt, kann der Befehl SQ0 verwendet werden.
Im Zwei-Byte-Modus stellen folgende Bytewerte Befehle dar, sofern sie an erster Position in einem möglichen Bytepaar auftreten:
| Byte (hex) | Name | Bedeutung |
| E0–E7 | UC0–UC7 | wechselt in den Ein-Byte-Modus und aktiviert das dynamische Fenster n |
| E8–EF | UD0–UD7 | verwendet das folgende Byte als einfache Definition für das dynamische Fenster n, aktiviert dieses Fenster und wechselt in den Ein-Byte-Modus |
| F0 | UQU | interpretiert die beiden folgenden Byte als ein UTF-16-kodiertes Zeichen |
| F1 | UDX | verwendet die beiden folgenden Byte zur erweiterten Definition eines dynamischen Fensters, aktiviert dieses Fenster und wechselt in den Ein-Byte-Modus |
| F2 | reserviert | reserviert für zukünftige Verwendung |
Soll ein Zeichen (aus dem Bereich zur privaten Nutzung) kodiert werden, das mit einem von einem Befehl besetzten Byte beginnt, kann der Befehl UQU verwendet werden.

## Eigenschaften

Das Verfahren besitzt einige Eigenschaften, die bewusst gewählt wurden:
* Für Texte, die ausschließlich aus Latin-1-Zeichen ohne Steuerzeichen bestehen, ergibt sich keine Änderung.
* Für Texte ohne Zeichen aus dem Bereich zur privaten Nutzung kann immer mit einem zusätzlichen Byte in den Zwei-Byte-Modus umgeschaltet werden, sodass der Speicherbedarf in diesem Fall dem von UTF-16 entspricht.
* Selbst im schlechtesten Fall ist der Speicherbedarf nur um einen Faktor 1,5 größer als UTF-16.
* Bei optimaler Kodierung werden normale Texte kompakter als in UTF-8 oder UTF-16 gespeichert. Wie groß diese Einsparung ist, hängt von der Sprache ab: Während bei englischen und französischen Texten SCSU genauso viel Platz benötigt wie UTF-8, reduziert sich dieser bei Koreanisch auf 85 %, bei Chinesisch auf 70 %, bei Griechisch, Russisch, Arabisch, Hebräisch und Japanisch auf 55 %, bei Hindi sogar auf 40 %.
Folgende Eigenschaften können in einigen Anwendungen problematisch sein:
* Im komprimierten Bytestrom können Null-Byte vorkommen, unter anderem deswegen ist die Kodierung nicht MIME-kompatibel. Hier kann stattdessen BOCU-1 verwendet werden.
* Der gleiche Text kann auf unterschiedliche Art kodiert werden.
* Texte mit wenigen verschiedenen Zeichen, die aber auf mehrere unzusammenhängende Bereiche verteilt sind, können nicht gut komprimiert werden. Dies ist etwa im Vietnamesischen der Fall.

## Mögliche Kodierungen

Folgen von Zeichen aus dem ASCII-Bereich und den vordefinierten dynamischen Fenstern werden am effizientesten im Ein-Byte-Modus kodiert. Gibt es kein geeignetes vordefiniertes Fenster, so kann ein nicht benötigtes dynamisches Fenster umdefiniert werden. Von den chinesischen und koreanischen Schriftzeichen abgesehen, können die meisten Bereiche als dynamisches Fenster gewählt werden.
Für Folgen von Zeichen außerhalb kleiner Bereiche sollte in den Zwei-Byte-Modus umgeschaltet werden.
Einzelne Zeichen, die in einem Fenster liegen, das gerade nicht aktiv ist, können über den Befehl SQn kodiert werden, Einzelzeichen außerhalb der möglichen Fenster über den Befehl SQU.

## Beispiele
### Deutsch

Um den Text „Wikipedia – die freie Enzyklopädie“ (mit typographischem Gedankenstrich) mit SCSU zu kodieren, reichen alle vordefinierten Fenster aus: nur der Gedankenstrich und das ä liegen nicht im ASCII-Bereich. Das ä befindet sich im aktiven dynamischen Fenster, der Gedankenstrich im statischen Fenster 4. Es ergibt sich also folgende hexadezimale Bytefolge:
Bis auf den Gedankenstrich stimmt die Kodierung mit ISO 8859-1 überein.

### Griechisch

Alle Zeichen des griechischen Wortes für Wikipedia „Βικιπαίδεια“ liegen im Unicodeblock für Griechisch. Es lässt sich daher kodieren, indem erst dieser Block durch ein dynamisches Fenster abgedeckt wird, mit dessen Hilfe dann die Buchstaben kodiert werden.
Die Kodierung braucht nur zwei Byte mehr als ISO 8859-7, ist aber gegenüber dieser um 0x20 verschoben.

### Japanisch

Der japanische Wikipedia-Artikel über Wikipedia beginnt folgendermaßen:
   „ウィキペディア（英: Wikipedia）は、ウィキメディア財団が運営するインターネット百科事典である。“
Es werden dabei verschiedene Schriften verwendet:
* Lateinische Buchstaben und Satzzeichen, die im statischen Fenster 0 liegen
* Katakana aus dem dynamischen Fenster 6
* vereinzelt Hiragana aus dem dynamischen Fenster 5
* CJK-Zeichen, die in keinem möglichen Fenster liegen
* Vollbreite Satzzeichen aus dem dynamischen Fenster 7
* CJK-Interpunktion aus dem statischen Fenster 7
Eine von vielen möglichen Kodierungen stellen die folgenden Tabellen dar: Die meiste Zeit wird mit dem dynamischen Fenster 6 (Katakana) gearbeitet. Einzelne Zeichen aus anderen Bereichen werden ohne einen dauerhaften Wechsel kodiert. Für längere Folgen von CJK-Zeichen wird dabei in den Zwei-Byte-Modus gewechselt, erst wenn wieder längere Folgen von Hiragana oder Katakana kodiert werden müssen, wird in den Ein-Byte-Modus zurückgeschaltet.
| Byte | 16 | 86 | 83 | 8D | BA | A7 | 83 | 82 | 08 | 88 | 0E | 82 | F1 | 3A | 20 | 57 | 69 | 6B | 69 | 70 | 65 | 64 | 69 | 61 | 08 | 89 |
| Zeichen Befehl | SC6 | ウ | ィ | キ | ペ | デ | ィ | ア | SQ7 | （ | SQU | 英 | 英 | : | | W | i | k | i | p | e | d | i | a | SQ7 | ） |
| Codepunkt (U+) | | 30A6 | 30A3 | 30AD | 30DA | 30C7 | 30A3 | 30A2 | | FF08 | | 82F1 | 82F1 | 003A | 0020 | 0057 | 0069 | 006B | 0069 | 0070 | 0065 | 0064 | 0069 | 0061 | | FF09 |
| Byte | 06 | AF | 08 | 01 | 86 | 83 | 8D | C1 | A7 | 83 | 82 | 0F | 8C | A1 | 56 | E3 | 30 | 4C | 90 | 4B | 55 | B6 |
| Zeichen Befehl | SQ5 | は | SQ7 | 、 | ウ | ィ | キ | メ | デ | ィ | ア | SCU | 財 | 財 | 団 | 団 | が | が | 運 | 運 | 営 | 営 |
| Codepunkt (U+) | | 306F | | 3001 | 30A6 | 30A3 | 30AD | 30E1 | 30C7 | 30A3 | 30A2 | | 8CA1 | 8CA1 | 56E3 | 56E3 | 304C | 304C | 904B | 904B | 55B6 | 55B6 |
| Byte | E5 | 99 | CB | 16 | 84 | D3 | 9F | DC | AC | A3 | A8 | 0F | 76 | 7E | 79 | D1 | 4E | 8B | 51 | 78 | E5 | A7 | 82 | CB | 08 | 02 |
| Zeichen Befehl | UC5 | す | る | SC6 | イ | ン | タ | ー | ネ | ッ | ト | SCU | 百 | 百 | 科 | 科 | 事 | 事 | 典 | 典 | UC5 | で | あ | る | SQ7 | 。 |
| Codepunkt (U+) | | 3059 | 308B | | 30A4 | 30F3 | 30BF | 30FC | 30CD | 30C3 | 30C8 | | 767E | 767E | 79D1 | 79D1 | 4E8B | 4E8B | 5178 | 5178 | | 3067 | 3042 | 308B | | 3002 |

## Verwendung

In der Praxis konnte sich SCSU nie durchsetzen. Nur einige wenige Programme verwenden diese Kodierung, darunter Microsoft SQL Server und Symbian.
Eines der Hauptprobleme des Verfahrens ist es, einen guten Algorithmus zum Komprimieren zu finden und diesen auszuführen. Da es meist effizienter ist Rechenzeit zu sparen als Speicherplatz, lohnt sich der Aufwand einer Komprimierung mit SCSU für die meisten Anwendungen nicht gegenüber UTF-8 oder UTF-16. Zudem führte die fehlende Unterstützung von SCSU in Anwendungsprogrammen dazu, dass SCSU kaum genutzt wurde, was wiederum dazu führte, dass die Kodierung auch weiterhin nicht unterstützt wurde. Da eine Fehlinterpretation durch Programme, die SCSU nicht unterstützen, zu unerwartetem Verhalten und sogar zu Sicherheitsproblemen führen kann, ist eine Verwendung von SCSU in HTML5 ausdrücklich ausgeschlossen.

## Quellen

* Asmus Freytag u. a.: Unicode Technical Standard #6: A Standard Compression Scheme For Unicode. (online)
* Doug Ewell: Unicode Technical Note #14: A Survey of Unicode Compression. (online)