RFC 1950
ZLIB Compressed Data Format Specification version 3.3
okay bestie, this one is RFC 1950 π and it's called ZLIB Compressed Data Format Specification version 3.3 β¨. It came out of the Network Working Group in May 1996 and it's classed as Informational πΈ. The authors are P. Deutsch from Aladdin Enterprises and J-L. Gailly from Info-ZIP π. It doesn't list anything it obsoletes or updates, so no drama there π¦.
Status of This Memo πΈ
this memo gives information to the Internet community π. it does not specify an Internet standard of any kind π and distribution of it is unlimited π.
IESG Note π
the IESG takes no position on whether any Intellectual Property Rights statements in this document are valid π«Ά.
Notices π
Copyright (c) 1996 L. Peter Deutsch and Jean-Loup Gailly π
you're allowed to copy and distribute this document for any purpose and without charge, including translating it into other languages and putting it into compilations π. the only conditions are that the copyright notice and this notice stay intact, and that any substantive changes or deletions from the original are clearly marked βοΈ.
a pointer to the latest version of this doc and related stuff in HTML format lives at the URL <ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html> π.
Abstract β¨
okay so this spec defines a lossless compressed data format π₯. the data can be produced or consumed even for an arbitrarily long, sequentially presented input stream, and you only need an a priori bounded amount of intermediate storage to do it π§ . right now it uses the DEFLATE compression method, but it can easily be extended to use other compression methods π§©. it can also be implemented readily in a way that isn't covered by patents ποΈ.
this spec also defines the ADLER-32 checksum, which is an extension and improvement of the Fletcher checksum π¦. it's used for detecting data corruption, and the spec gives an algorithm for computing it π.
Table of Contents π
1. Introduction ................................................... 2
1.1. Purpose ................................................... 2
1.2. Intended audience ......................................... 3
1.3. Scope ..................................................... 3
1.4. Compliance ................................................ 3
1.5. Definitions of terms and conventions used ................ 3
1.6. Changes from previous versions ............................ 3
2. Detailed specification ......................................... 3
2.1. Overall conventions ....................................... 3
2.2. Data format ............................................... 4
2.3. Compliance ................................................ 7
3. References ..................................................... 7
4. Source code .................................................... 8
5. Security Considerations ........................................ 8
6. Acknowledgements ............................................... 8
7. Authors' Addresses ............................................. 8
8. Appendix: Rationale ............................................ 9
9. Appendix: Sample code ..........................................10
1. Introduction β¨
1.1. Purpose π―
the whole point of this spec is to define a lossless compressed data format that:
- is independent of CPU type, operating system, file system, and character set, so it can be used for interchange π;
- can be produced or consumed even for an arbitrarily long sequentially presented input data stream, using only an a priori bounded amount of intermediate storage, so it can be used in data communications or similar structures such as Unix filters π‘;
- can use a number of different compression methods π§°;
- can be implemented readily in a way not covered by patents, so it can be practiced freely π.
also, the data format defined here does not try to allow random access to compressed data π ββοΈ.
1.2. Intended audience π§βπ»
this spec is for implementors of software that compresses data into zlib format and/or decompresses data from zlib format π». the text assumes you've got a basic background in programming at the level of bits and other primitive data representations π§ .
1.3. Scope π
the spec describes a compressed data format that can be used for in-memory compression of a sequence of arbitrary bytes πΎ.
1.4. Compliance π
unless otherwise indicated below, a compliant decompressor must be able to accept and decompress any data set that conforms to all the specifications presented here π₯. a compliant compressor must produce data sets that conform to all the specifications presented here π€. no skipping steps, bestie π€.
1.5. Definitions of terms and conventions used π
byte: 8 bits stored or transmitted as a unit (same as an octet) π§©. for this spec, a byte is exactly 8 bits, even on machines that store a character on a number of bits different from 8 π€. the numbering of bits within a byte is explained below π.
1.6. Changes from previous versions π°οΈ
the glow-up timeline π: version 3.1 was the first public release of this spec π±. in version 3.2, some terminology got changed and the Adler-32 sample code was rewritten for clarity β¨. then in version 3.3, support for a preset dictionary was introduced, and the spec got converted to RFC style π iconic.
2. Detailed specification β¨
2.1. Overall conventions π
Okay bestie, the diagrams in this section look like a lot, but they're actually simple. Here's the deal π
A box like this is one byte:
+---+
| | <-- the vertical bars might be missing
+---+
And a box like this is a variable number of bytes:
+==============+
| |
+==============+
Bytes stored inside a computer don't have a "bit order" π¦, since they're always treated as a unit. BUT, a byte treated as an integer between 0 and 255 does have a most- and least-significant bit. We write numbers with the most-significant digit on the left, so we write bytes with the most-significant bit on the left too. In the diagrams below, bit 0 is the least-significant bit, so the bits are numbered like this:
+--------+
|76543210|
+--------+
A number can take up multiple bytes inside a computer. All multi-byte numbers in this format are stored with the MOST-significant byte first (at the lower memory address). For example, the decimal number 520 is stored like this πΈ:
0 1
+--------+--------+
|00000010|00001000|
+--------+--------+
^ ^
| |
| + less significant byte = 8
+ more significant byte = 2 x 256
2.2. Data format π
A zlib stream has the following structure β¨:
0 1
+---+---+
|CMF|FLG| (more-->)
+---+---+
(if FLG.FDICT set)
0 1 2 3
+---+---+---+---+
| DICTID | (more-->)
+---+---+---+---+
+=====================+---+---+---+---+
|...compressed data...| ADLER32 |
+=====================+---+---+---+---+
Anything that shows up after ADLER32 is NOT part of the zlib stream π ββοΈ. Nothing after it counts.
CMF (Compression Method and flags): this byte is split into a 4-bit compression method and a 4-bit information field, and what the info field means depends on the compression method π§
bits 0 to 3 CM Compression method
bits 4 to 7 CINFO Compression info
CM (Compression method): this tells you which compression method was used in the file. CM = 8 means the "deflate" compression method with a window size up to 32K. This is the method gzip and PNG use (check references [1] and [2] in Chapter 3, below, for the reference documents). CM = 15 is reserved π. It might get used in a future version of this spec to say there's an extra field before the compressed data.
CINFO (Compression info): for CM = 8, CINFO is the base-2 logarithm of the LZ77 window size, minus eight. CINFO=7 means a 32K window. CINFO values above 7 are not allowed in this version of the spec. CINFO isn't defined in this spec for any CM that isn't 8 π.
FLG (FLaGs): this flag byte breaks down like this π:
bits 0 to 4 FCHECK (check bits for CMF and FLG)
bit 5 FDICT (preset dictionary)
bits 6 to 7 FLEVEL (compression level)
The FCHECK value has to be set so that CMF and FLG, read together as a 16-bit unsigned integer stored in MSB order (CMF*256 + FLG), is a multiple of 31 π’.
FDICT (Preset dictionary): if FDICT is set, a DICT dictionary identifier shows up right after the FLG byte. The dictionary is a sequence of bytes that gets fed to the compressor first, without making any compressed output. DICT is the Adler-32 checksum of that byte sequence (see the ADLER32 definition below). The decompressor can use this identifier to figure out which dictionary the compressor used π΅οΈββοΈ.
FLEVEL (Compression level): these flags are there for specific compression methods to use. The "deflate" method (CM = 8) sets them like this:
0 - compressor used fastest algorithm
1 - compressor used fast algorithm
2 - compressor used default algorithm
3 - compressor used maximum compression, slowest algorithm
FLEVEL isn't needed for decompression at all. It's just there to hint whether recompressing might be worth it π .
compressed data: for compression method 8, the compressed data is stored in the deflate compressed data format, as described in the document "DEFLATE Compressed Data Format Specification" by L. Peter Deutsch (see reference [3] in Chapter 3, below). Other compressed data formats aren't specified in this version of the zlib spec π«.
ADLER32 (Adler-32 checksum): this holds a checksum value of the uncompressed data (excluding any dictionary data), computed with the Adler-32 algorithm. Adler-32 is a 32-bit extension and improvement of the Fletcher algorithm, which is used in the ITU-T X.224 / ISO 8073 standard. (See references [4] and [5] in Chapter 3, below.) π¦
Adler-32 is made of two sums that get accumulated per byte. s1 is the sum of all the bytes, and s2 is the sum of all the s1 values. Both sums are done modulo 65521. s1 starts at 1, and s2 starts at zero. The Adler-32 checksum gets stored as s2*65536 + s1, most-significant-byte first (network) order π.
2.3. Compliance π«Ά
A compliant compressor must produce streams with correct CMF, FLG and ADLER32 values, but it doesn't need to support preset dictionaries. When the zlib data format is used as part of another standard data format, the compressor may use only the preset dictionaries that this other data format specifies. If that other format doesn't use the preset dictionary feature, the compressor must not set the FDICT flag β οΈ.
A compliant decompressor must check CMF, FLG and ADLER32, and it must give an error indication if any of them have incorrect values π¨. A compliant decompressor must also give an error indication if CM isn't one of the values this spec defines (only the value 8 is allowed in this version). The reason is that another value could mean new features are present, and then the following data would be read wrong π±. A compliant decompressor must give an error indication if FDICT is set and DICTID isn't the identifier of a known preset dictionary. A decompressor may ignore FLEVEL and still be compliant. When the zlib data format is used as part of another standard format, a compliant decompressor must support all the preset dictionaries that the other format specifies. When the other format doesn't use the preset dictionary feature, a compliant decompressor must reject any stream where the FDICT flag is set π ββοΈ.
3. References π
[1] Deutsch, L.P.,"GZIP Compressed Data Format Specification", available in ftp://ftp.uu.net/pub/archiving/zip/doc/
[2] Thomas Boutell, "PNG (Portable Network Graphics) specification", available in ftp://ftp.uu.net/graphics/png/documents/
[3] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification", available in ftp://ftp.uu.net/pub/archiving/zip/doc/
[4] Fletcher, J. G., "An Arithmetic Checksum for Serial Transmissions," IEEE Transactions on Communications, Vol. COM-30, No. 1, January 1982, pp. 247-252.
[5] ITU-T Recommendation X.224, Annex D, "Checksum Algorithms," November, 1993, pp. 144, 145. (Available from gopher://info.itu.ch). ITU-T X.244 is also the same as ISO 8073.
4. Source code π»
Source code for a C language implementation of a "zlib" compliant library is available at ftp://ftp.uu.net/pub/archiving/zip/zlib/ π.
5. Security Considerations π
A decoder that fails to check the ADLER32 checksum value may be subject to undetected data corruption. This is serious, bestie ππ¨. Skipping that check means corrupted data can slip right through without anyone noticing π.
6. Acknowledgements π«Ά
Trademarks cited in this document are the property of their respective owners π.
Jean-Loup Gailly and Mark Adler designed the zlib format and wrote the related software described in this specification π. Glenn Randers-Pehrson converted this document to RFC and HTML format πΈ.
7. Authors' Addresses βοΈ
L. Peter Deutsch
Aladdin Enterprises
203 Santa Margarita Ave.
Menlo Park, CA 94025
Phone: (415) 322-0103 (AM only)
FAX: (415) 322-1734
EMail: <ghost@aladdin.com>
Jean-Loup Gailly
EMail: <gzip@prep.ai.mit.edu>
Questions about the technical content of this specification can be sent by email to Jean-Loup Gailly <gzip@prep.ai.mit.edu> and Mark Adler <madler@alumni.caltech.edu> π§ .
Editorial comments on this specification can be sent by email to L. Peter Deutsch <ghost@aladdin.com> and Glenn Randers-Pehrson <randeg@alumni.rpi.edu> π.
8. Appendix: Rationale π§
8.1. Preset dictionaries π
A preset dictionary is especially useful for compressing short input sequences π. The compressor can use the dictionary context to encode the input in a more compact way. The decompressor can be set up with the right context by virtually decompressing a compressed version of the dictionary, without producing any output. For certain compression algorithms, such as deflate, this can be done without actually performing any decompression π€―.
The compressor and the decompressor must use exactly the same dictionary. The dictionary may be fixed, or it may be picked from a certain number of predefined dictionaries, depending on the kind of input data. The decompressor can figure out which dictionary the compressor picked by checking the dictionary identifier. This document doesn't specify the contents of predefined dictionaries, since the best dictionaries are application specific. Standard data formats that use this feature of the zlib spec must precisely define the allowed dictionaries π.
8.2. The Adler-32 algorithm π¦
The Adler-32 algorithm is much faster than the CRC32 algorithm, and it still gives an extremely low probability of undetected errors π₯.
The modulo on unsigned long accumulators can be delayed for 5552 bytes, so the modulo operation time is negligible π. If the bytes are a, b, c, the second sum is 3a + 2b + c + 3. That makes it sensitive to position and order, unlike the first sum, which is just a checksum π. That 65521 is prime matters, because it avoids a possible large class of two-byte errors that would leave the check unchanged π§. (The Fletcher checksum uses 255, which isn't prime, and which also makes the Fletcher check insensitive to single byte changes 0 <-> 255 π.)
The sum s1 starts at 1 instead of zero, so the length of the sequence becomes part of s2. That way the length doesn't have to be checked separately π . (Any sequence of zeroes has a Fletcher checksum of zero π.)
9. Appendix: Sample code β¨
okay so this is the sample code π It computes the Adler-32 checksum of a data buffer. It's written for clarity, not speed, so it's not trying to be fast, it's trying to be readable π§ It's ANSI C. If you're not a C girlie, here are some hints π
&is the bitwise AND operator.>>is the bitwise right shift operator. When it's applied to an unsigned quantity, like here, right shift inserts zero bit(s) at the left.<<is the bitwise left shift operator. Left shift inserts zero bit(s) at the right.++meansn++increments the variable n.%is the modulo operator.a % bis the remainder of a divided by b.
#define BASE 65521 /* largest prime smaller than 65536 */
/*
Update a running Adler-32 checksum with the bytes buf[0..len-1]
and return the updated checksum. The Adler-32 checksum should be
initialized to 1.
Usage example:
unsigned long adler = 1L;
while (read_buffer(buffer, length) != EOF) {
adler = update_adler32(adler, buffer, length);
}
if (adler != original_adler) error();
*/
unsigned long update_adler32(unsigned long adler,
unsigned char *buf, int len)
{
unsigned long s1 = adler & 0xffff;
unsigned long s2 = (adler >> 16) & 0xffff;
int n;
for (n = 0; n < len; n++) {
s1 = (s1 + buf[n]) % BASE;
s2 = (s2 + s1) % BASE;
}
return (s2 << 16) + s1;
}
/* Return the adler32 of the bytes buf[0..len-1] */
unsigned long adler32(unsigned char *buf, int len)
{
return update_adler32(1L, buf, len);
}
π¦ where this page comes from
- ietf: rfc1950 1996-05
- π girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms