home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / comp / compress / 4256 < prev    next >
Encoding:
Text File  |  1992-12-28  |  16.7 KB  |  284 lines

  1. Newsgroups: comp.compression
  2. Path: sparky!uunet!think.com!ames!sgi!wdl1!master!jerry
  3. From: jerry@lds-az.loral.com (J Barbera)
  4. Subject: Re: lzw and arc specs.
  5. Message-ID: <1992Dec28.112116.4089@lds-az.loral.com>
  6. Organization: Loral Defense Systems Arizona
  7. References: <27DEC92.21033227.0012@SEMOVM.SEMO.EDU>
  8. Date: Mon, 28 Dec 1992 11:21:16 GMT
  9. Lines: 273
  10.  
  11.  
  12. In article <27DEC92.21033227.0012@SEMOVM.SEMO.EDU> A261CCR@SEMOVM.SEMO.EDU (A261CCR) writes:
  13. >I am working on a GIF reader programming project and need some
  14. >info on the data compression used in GIF files. Could anyone
  15. >supply me with the specs. or algorithoms for LZW or ARC compression
  16. >formats? I deperately need these algorithoms to complete my project.
  17. >Thanks in advance for any help.
  18. >
  19. >Mark Tenholder
  20. >a261ccr@semovm.semo.edu
  21.  
  22.                    LZW and GIF explained----Steve Blackstock
  23.  
  24.  
  25.       I hope this little document will help enlighten those of you out there
  26. who want to know more about the Lempel-Ziv Welch compression algorithm, and,
  27. specifically, the implementation that GIF uses.
  28.      Before we start, here's a little terminology, for the purposes of this
  29. document:
  30.  
  31.       "character": a fundamental data element. In normal text files, this is
  32. just a single byte. In raster images, which is what we're interested in, it's
  33. an index that specifies the color of a given pixel. I'll refer to an arbitray
  34. character as "K".
  35.       "charstream": a stream of characters, as in a data file.
  36.       "string": a number of continuous characters, anywhere from one to very
  37. many characters in length. I can specify an arbitrary string as "[...]K".
  38.       "prefix": almost the same as a string, but with the implication that a
  39. prefix immediately precedes a character, and a prefix can have a length of
  40. zero. So, a prefix and a character make up a string. I will refer to an
  41. arbitrary prefix as "[...]".
  42.       "root": a single-character string. For most purposes, this is a
  43. character, but we may occasionally make a distinction. It is [...]K, where
  44. [...] is empty.
  45.       "code": a number, specified by a known number of bits, which maps to a
  46. string.
  47.       "codestream": the output stream of codes, as in the "raster data"
  48.       "entry": a code and its string.
  49.       "string table": a list of entries; usually, but not necessarily, unique.
  50.       That should be enough of that.
  51.  
  52.      LZW is a way of compressing data that takes advantage of repetition of
  53. strings in the data. Since raster data usually contains a lot of this
  54. repetition, LZW is a good way of compressing and decompressing it.
  55.      For the moment, lets consider normal LZW encoding and decoding. GIF's
  56. variation on the concept is just an extension from there.
  57.      LZW manipulates three objects in both compression and decompression: the
  58. charstream, the codestream, and the string table. In compression, the
  59. charstream is the input and the codestream is the output. In decompression,
  60. the codestream is the input and the charstream is the output. The string table
  61. is a product of both compression and decompression, but is never passed from
  62. one to the other.
  63.      The first thing we do in LZW compression is initialize our string table.
  64. To do this, we need to choose a code size (how many bits) and know how many
  65. values our characters can possibly take. Let's say our code size is 12 bits,
  66. meaning we can store 0->FFF, or 4096 entries in our string table. Lets also
  67. say that we have 32 possible different characters. (This corresponds to, say,
  68. a picture in which there are 32 different colors possible for each pixel.) To
  69. initialize the table, we set code#0 to character#0, code #1 to character#1,
  70. and so on, until code#31 to character#31. Actually, we are specifying that
  71. each code from 0 to 31 maps to a root. There will be no more entries in the
  72. table that have this property.
  73.      Now we start compressing data. Let's first define something called the
  74. "current prefix". It's just a prefix that we'll store things in and compare
  75. things to now and then. I will refer to it as "[.c.]". Initially, the current
  76. prefix has nothing in it. Let's also define a "current string", which will be
  77. the current prefix plus the next character in the charstream. I will refer to
  78. the current string as "[.c.]K", where K is some character. OK, look at the
  79. first character in the charstream. Call it P. Make [.c.]P the current string.
  80. (At this point, of course, it's just the root P.) Now search through the
  81. string table to see if [.c.]P appears in it. Of course, it does now, because
  82. our string table is initialized to have all roots. So we don't do anything.
  83. Now make [.c.]P the current prefix. Look at the next character in the
  84. charstream. Call it Q. Add it to the current prefix to form [.c.]Q, the
  85. current string. Now search through the string table to see if [.c.]Q appears
  86. in it. In this case, of course, it doesn't. Aha! Now we get to do something.
  87. Add [.c.]Q (which is PQ in this case) to the string table for code#32, and
  88. output the code for [.c.] to the codestream. Now start over again with the
  89. current prefix being just the root P. Keep adding characters to [.c.] to form
  90. [.c.]K, until you can't find [.c.]K in the string table. Then output the code
  91. for [.c.] and add [.c.]K to the string table. In pseudo-code, the algorithm
  92. goes something like this:
  93.  
  94.      [1] Initialize string table;
  95.      [2] [.c.] <- empty;
  96.      [3] K <- next character in charstream;
  97.      [4] Is [.c.]K in string table?
  98.       (yes: [.c.] <- [.c.]K;
  99.             go to [3];
  100.       )
  101.       (no: add [.c.]K to the string table;
  102.            output the code for [.c.] to the codestream;
  103.            [.c.] <- K;
  104.            go to [3];
  105.       )
  106.  
  107.        It's as simple as that! Of course, when you get to step [3] and there
  108. aren't any more characters left, you just output the code for [.c.] and throw
  109. the table away. You're done.
  110.       Wanna do an example? Let's pretend we have a four-character alphabet:
  111. A,B,C,D. The charstream looks like ABACABA. Let's compress it. First, we
  112. initialize our string table to: #0=A, #1=B, #2=C, #3=D. The first character is
  113. A, which is in the string table, so [.c.] becomes A. Next we get AB, which is
  114. not in the table, so we output code #0 (for [.c.]),
  115.      and add AB to the string table as code #4. [.c.] becomes B. Next we get
  116. [.c.]A = BA, which is not in the string table, so output code #1, and add BA
  117. to the string table as code #5. [.c.] becomes A. Next we get AC, which is not
  118. in the string table. Output code #0, and add AC to the string table as code
  119. #6. Now [.c.] becomes C. Next we get [.c.]A = CA, which is not in the table.
  120. Output #2 for C, and add CA to table as code#7. Now [.c.] becomes A. Next we
  121. get AB, which IS in the string table, so [.c.] gets AB, and we look at ABA,
  122. which is not in the string table, so output the code for AB, which is #4, and
  123. add ABA to the string table as code #8. [.c.] becomes A. We can't get any more
  124. characters, so we just output #0 for the code for A, and we're done. So, the
  125. codestream is #0#1#0#2#4#0.
  126.       A few words (four) should be said here about efficiency: use a hashing
  127. strategy. The search through the string table can be computationally
  128. intensive, and some hashing is well worth the effort. Also, note that
  129. "straight LZW" compression runs the risk of overflowing the string table -
  130. getting to a code which can't be represented in the number of bits you've set
  131. aside for codes. There are several ways of dealing with this problem, and GIF
  132. implements a very clever one, but we'll get to that.
  133.       An important thing to notice is that, at any point during the
  134. compression, if [...]K is in the string table, [...] is there also. This fact
  135. suggests an efficient method for storing strings in the table. Rather than
  136. store the entire string of K's in the table, realize that any string can be
  137. expressed as a prefix plus a character: [...]K. If we're about to store [...]K
  138. in the table, we know that [...] is already there, so we can just store the
  139. code for [...] plus the final character K.
  140.       Ok, that takes care of compression. Decompression is perhaps more
  141. difficult conceptually, but it is really easier to program.
  142.       Here's how it goes: We again have to start with an initialized string
  143. table. This table comes from what knowledge we have about the charstream that
  144. we will eventually get, like what possible values the characters can take. In
  145. GIF files, this information is in the header as the number of possible pixel
  146. values. The beauty of LZW, though, is that this is all we need to know. We
  147. will build the rest of the string table as we decompress the codestream. The
  148. compression is done in such a way that we will never encounter a code in the
  149. codestream that we can't translate into a string.
  150.       We need to define something called a "current code", which I will refer
  151. to as "<code>", and an "old-code", which I will refer to as "<old>". To start
  152. things off, look at the first code. This is now <code>. This code will be in
  153. the intialized string table as the code for a root. Output the root to the
  154. charstream. Make this code the old-code <old>. *Now look at the next code, and
  155. make it <code>. It is possible that this code will not be in the string table,
  156. but let's assume for now that it is. Output the string corresponding to <code>
  157. to the codestream. Now find the first character in the string you just
  158. translated. Call this K. Add this to the prefix [...] generated by <old> to
  159. form a new string [...]K. Add this string [...]K to the string table, and set
  160. the old-code <old> to the current code <code>. Repeat from where I typed the
  161. asterisk, and you're all set. Read this paragraph again if you just skimmed
  162. it!!!  Now let's consider the possibility that <code> is not in the string
  163. table. Think back to compression, and try to understand what happens when you
  164. have a string like P[...]P[...]PQ appear in the charstream. Suppose P[...] is
  165. already in the string table, but P[...]P is not. The compressor will parse out
  166. P[...], and find that P[...]P is not in the string table. It will output the
  167. code for P[...], and add P[...]P to the string table. Then it will get up to
  168. P[...]P for the next string, and find that P[...]P is in the table, as
  169.      the code just added. So it will output the code for P[...]P if it finds
  170. that P[...]PQ is not in the table. The decompressor is always "one step
  171. behind" the compressor. When the decompressor sees the code for P[...]P, it
  172. will not have added that code to it's string table yet because it needed the
  173. beginning character of P[...]P to add to the string for the last code, P[...],
  174. to form the code for P[...]P. However, when a decompressor finds a code that
  175. it doesn't know yet, it will always be the very next one to be added to the
  176. string table. So it can guess at what the string for the code should be, and,
  177. in fact, it will always be correct. If I am a decompressor, and I see
  178. code#124, and yet my string table has entries only up to code#123, I can
  179. figure out what code#124 must be, add it to my string table, and output the
  180. string. If code#123 generated the string, which I will refer to here as a
  181. prefix, [...], then code#124, in this special case, will be [...] plus the
  182. first character of [...]. So just add the first character of [...] to the end
  183. of itself. Not too bad.  As an example (and a very common one) of this special
  184. case, let's assume we have a raster image in which the first three pixels have
  185. the same color value. That is, my charstream looks like: QQQ.... For the sake
  186. of argument, let's say we have 32 colors, and Q is the color#12. The
  187. compressor will generate the code sequence 12,32,.... (if you don't know why,
  188. take a minute to understand it.) Remember that #32 is not in the initial
  189. table, which goes from #0 to #31. The decompressor will see #12 and translate
  190. it just fine as color Q. Then it will see #32 and not yet know what that
  191. means. But if it thinks about it long enough, it can figure out that QQ should
  192. be entry#32 in the table and QQ should be the next string output.  So the
  193. decompression pseudo-code goes something like:
  194.  
  195.       [1] Initialize string table;
  196.      [2] get first code: <code>;
  197.      [3] output the string for <code> to the charstream;
  198.      [4] <old> = <code>;
  199.      [5] <code> <- next code in codestream;
  200.      [6] does <code> exist in the string table?
  201.       (yes: output the string for <code> to the charstream;
  202.             [...] <- translation for <old>;
  203.             K <- first character of translation for <code>;
  204.             add [...]K to the string table;        <old> <- <code>;  )
  205.       (no: [...] <- translation for <old>;
  206.            K <- first character of [...];
  207.            output [...]K to charstream and add it to string table;
  208.            <old> <- <code>
  209.       )
  210.      [7] go to [5];
  211.  
  212.       Again, when you get to step [5] and there are no more codes, you're
  213. finished.  Outputting of strings, and finding of initial characters in strings
  214. are efficiency problems all to themselves, but I'm not going to suggest ways
  215. to do them here. Half the fun of programming is figuring these things out!
  216.       ---
  217.       Now for the GIF variations on the theme. In part of the header of a GIF
  218. file, there is a field, in the Raster Data stream, called "code size". This is
  219. a very misleading name for the field, but we have to live with it. What it is
  220. really is the "root size". The actual size, in bits, of the compression codes
  221. actually changes during compression/decompression, and I will refer to that
  222. size here as the "compression size". The initial table is just the codes for
  223. all the roots, as usual, but two special codes are added on top of those.
  224. Suppose you have a "code size", which is usually the number of bits per pixel
  225. in the image, of N. If the number of bits/pixel is one, then N must be 2: the
  226. roots take up slots #0 and #1 in the initial table, and the two special codes
  227. will take up slots #4 and #5. In any other case, N is the number of bits per
  228. pixel, and the roots take up slots #0 through #(2**N-1), and the special codes
  229. are (2**N) and (2**N + 1). The initial compression size will be N+1 bits per
  230. code. If you're encoding, you output the codes (N+1) bits at a time to start
  231. with, and if you're decoding, you grab (N+1) bits from the codestream at a
  232. time.  As for the special codes: <CC> or the clear code, is (2**N), and <EOI>,
  233. or end-of-information, is (2**N + 1). <CC> tells the compressor to re-
  234. initialize the string table, and to reset the compression size to (N+1). <EOI>
  235. means there's no more in the codestream.  If you're encoding or decoding, you
  236. should start adding things to the string table at <CC> + 2. If you're
  237. encoding, you should output <CC> as the very first code, and then whenever
  238. after that you reach code #4095 (hex FFF), because GIF does not allow
  239. compression sizes to be greater than 12 bits. If you're decoding, you should
  240. reinitialize your string table when you observe <CC>.  The variable
  241. compression sizes are really no big deal. If you're encoding, you start with a
  242. compression size of (N+1) bits, and, whenever you output the code
  243. (2**(compression size)-1), you bump the compression size up one bit. So the
  244. next code you output will be one bit longer. Remember that the largest
  245. compression size is 12 bits, corresponding to a code of 4095. If you get that
  246. far, you must output <CC> as the next code, and start over.  If you're
  247. decoding, you must increase your compression size AS SOON AS YOU write entry
  248. #(2**(compression size) - 1) to the string table. The next code you READ will
  249. be one bit longer. Don't make the mistake of waiting until you need to add the
  250. code (2**compression size) to the table. You'll have already missed a bit from
  251. the last code.  The packaging of codes into a bitsream for the raster data is
  252. also a potential stumbling block for the novice encoder or decoder. The lowest
  253. order bit in the code should coincide with the lowest available bit in the
  254. first available byte in the codestream. For example, if you're starting with
  255. 5-bit compression codes, and your first three codes are, say, <abcde>,
  256. <fghij>, <klmno>, where e, j, and o are bit#0, then your codestream will start
  257. off like:
  258.  
  259.        byte#0: hijabcde
  260.        byte#1: .klmnofg
  261.  
  262.       So the differences between straight LZW and GIF LZW are: two additional
  263. special codes and variable compression sizes. If you understand LZW, and you
  264. understand those variations, you understand it all!
  265.       Just as sort of a P.S., you may have noticed that a compressor has a
  266. little bit of flexibility at compression time. I specified a "greedy" approach
  267. to the compression, grabbing as many characters as possible before outputting
  268. codes. This is, in fact, the standard LZW way of doing things, and it will
  269. yield the best compression ratio. But there's no rule saying you can't stop
  270. anywhere along the line and just output the code for the current prefix,
  271. whether it's already in the table or not, and add that string plus the next
  272. character to the string table. There are various reasons for wanting to do
  273. this, especially if the strings get extremely long and make hashing difficult.
  274. If you need to, do it.
  275.       Hope this helps out.----steve blackstock
  276.  
  277.  
  278.  
  279.  
  280.  
  281.  
  282.  
  283.  
  284.