1 ! Copyright (C) 2009 Doug Coleman.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors combinators io kernel math namespaces
4 prettyprint sequences vectors ;
5 QUALIFIED-WITH: bitstreams bs
19 end-of-information-code ;
21 TUPLE: tiff-lzw < lzw ;
22 TUPLE: gif-lzw < lzw ;
24 : initial-uncompress-table ( -- seq )
25 current-lzw get end-of-information-code>> 1 +
26 iota [ 1vector ] V{ } map-as ;
28 : reset-lzw-uncompress ( lzw -- lzw )
29 initial-uncompress-table >>table
30 dup initial-code-size>> >>code-size ;
32 : <lzw-uncompress> ( input code-size class -- obj )
35 dup code-size>> >>initial-code-size
36 dup code-size>> 1 - 2^ >>clear-code
37 dup clear-code>> 1 + >>end-of-information-code
39 BV{ } clone >>output ;
41 ERROR: not-in-table value ;
43 : lookup-old-code ( lzw -- vector )
44 [ old-code>> ] [ table>> ] bi nth ;
46 : lookup-code ( lzw -- vector )
47 [ code>> ] [ table>> ] bi nth ;
49 : code-in-table? ( lzw -- ? )
50 [ code>> ] [ table>> length ] bi < ;
52 : code>old-code ( lzw -- lzw )
53 dup code>> >>old-code ;
55 : write-code ( lzw -- )
56 [ lookup-code ] [ output>> ] bi push-all ;
58 GENERIC: code-space-full? ( lzw -- ? )
60 M: tiff-lzw code-space-full?
61 [ table>> length ] [ code-size>> 2^ 1 - ] bi = ;
63 M: gif-lzw code-space-full?
64 [ table>> length ] [ code-size>> 2^ ] bi = ;
66 : maybe-increment-code-size ( lzw -- lzw )
67 dup code-space-full? [ [ 1 + ] change-code-size ] when ;
69 : add-to-table ( seq lzw -- )
71 [ maybe-increment-code-size 2drop ] 2bi ;
73 : lzw-read ( lzw -- lzw n )
74 [ ] [ code-size>> ] [ input>> ] tri bs:read ;
76 DEFER: lzw-uncompress-char
77 : handle-clear-code ( lzw -- )
79 lzw-read dup current-lzw get end-of-information-code>> = [
88 : handle-uncompress-code ( lzw -- lzw )
94 [ lookup-code first ] bi suffix
96 ] [ code>old-code ] tri
99 [ lookup-old-code dup first suffix ] keep
100 [ output>> push-all ] [ add-to-table ] 2bi
101 ] [ code>old-code ] bi
104 : lzw-uncompress-char ( lzw -- )
107 dup code>> current-lzw get end-of-information-code>> = [
110 dup code>> current-lzw get clear-code>> = [
113 handle-uncompress-code
121 : lzw-uncompress ( bitstream code-size class -- byte-array )
122 <lzw-uncompress> dup current-lzw [
123 [ reset-lzw-uncompress drop ] [ lzw-uncompress-char ] [ output>> ] tri
126 : tiff-lzw-uncompress ( seq -- byte-array )
127 bs:<msb0-bit-reader> 9 tiff-lzw lzw-uncompress ;
129 : gif-lzw-uncompress ( seq code-size -- byte-array )
130 [ bs:<lsb0-bit-reader> ] dip gif-lzw lzw-uncompress ;