]> gitweb.factorcode.org Git - factor.git/blob - basis/compression/lzw/lzw.factor
factor: trim using lists
[factor.git] / basis / compression / lzw / lzw.factor
1 ! Copyright (C) 2009 Doug Coleman.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors combinators kernel math math.order
4 sequences vectors ;
5 QUALIFIED-WITH: bitstreams bs
6 IN: compression.lzw
7
8 TUPLE: lzw
9 input
10 output
11 table
12 code
13 old-code
14 initial-code-size
15 code-size
16 clear-code
17 end-of-information-code ;
18
19 TUPLE: tiff-lzw < lzw ;
20 TUPLE: gif-lzw < lzw ;
21
22 : initial-uncompress-table ( size -- seq )
23     <iota> [ 1vector ] V{ } map-as ;
24
25 : reset-lzw-uncompress ( lzw -- lzw )
26     dup end-of-information-code>> 1 + initial-uncompress-table >>table
27     dup initial-code-size>> >>code-size ;
28
29 ERROR: code-size-zero ;
30
31 : <lzw-uncompress> ( input code-size class -- obj )
32     new
33         swap [ code-size-zero ] when-zero >>code-size
34         dup code-size>> >>initial-code-size
35         dup code-size>> 1 - 2^ >>clear-code
36         dup clear-code>> 1 + >>end-of-information-code
37         swap >>input
38         BV{ } clone >>output
39         reset-lzw-uncompress ;
40
41 : lookup-old-code ( lzw -- vector )
42     [ old-code>> ] [ table>> ] bi nth ;
43
44 : lookup-code ( lzw -- vector )
45     [ code>> ] [ table>> ] bi nth ;
46
47 : code-in-table? ( lzw -- ? )
48     [ code>> ] [ table>> length ] bi < ;
49
50 : code>old-code ( lzw -- lzw )
51     dup code>> >>old-code ;
52
53 : write-code ( lzw -- )
54     [ lookup-code ] [ output>> ] bi push-all ;
55
56 GENERIC: code-space-full? ( lzw -- ? )
57
58 : size-and-limit ( lzw -- m n ) [ table>> length ] [ code-size>> 2^ ] bi ;
59
60 M: tiff-lzw code-space-full? size-and-limit 1 - = ;
61 M: gif-lzw code-space-full? size-and-limit = ;
62
63 GENERIC: increment-code-size ( lzw -- lzw )
64
65 M: lzw increment-code-size [ 1 + ] change-code-size ;
66 M: gif-lzw increment-code-size [ 1 + 12 min ] change-code-size ;
67
68 : maybe-increment-code-size ( lzw -- lzw )
69     dup code-space-full? [ increment-code-size ] when ;
70
71 : add-to-table ( seq lzw -- )
72     [ table>> push ]
73     [ maybe-increment-code-size 2drop ] 2bi ;
74
75 : lzw-read ( lzw -- lzw n )
76     [ ] [ code-size>> ] [ input>> ] tri bs:read ;
77
78 : end-of-information? ( lzw code -- ? ) swap end-of-information-code>> = ;
79 : clear-code? ( lzw code -- ? ) swap clear-code>> = ;
80
81 DEFER: handle-clear-code
82 : lzw-process-next-code ( lzw quot: ( lzw code -- ) -- )
83     [ lzw-read ] dip {
84         { [ 2over end-of-information? ] [ 3drop ] }
85         { [ 2over clear-code? ] [ 2drop handle-clear-code ] }
86         [ call( lzw code -- ) ]
87     } cond ; inline
88
89 DEFER: lzw-uncompress-char
90 : handle-clear-code ( lzw -- )
91     reset-lzw-uncompress
92     [
93         >>code
94         [ write-code ]
95         [ code>old-code ] bi
96         lzw-uncompress-char
97     ] lzw-process-next-code ;
98
99 : handle-uncompress-code ( lzw -- lzw )
100     dup code-in-table? [
101         [ write-code ]
102         [
103             [
104                 [ lookup-old-code ]
105                 [ lookup-code first ] bi suffix
106             ] [ add-to-table ] bi
107         ] [ code>old-code ] tri
108     ] [
109         [
110             [ lookup-old-code dup first suffix ] keep
111             [ output>> push-all ] [ add-to-table ] 2bi
112         ] [ code>old-code ] bi
113     ] if ;
114
115 : lzw-uncompress-char ( lzw -- )
116     [ >>code handle-uncompress-code lzw-uncompress-char ]
117     lzw-process-next-code ;
118
119 : lzw-uncompress ( bitstream code-size class -- byte-array )
120     <lzw-uncompress>
121     [ lzw-uncompress-char ] [ output>> ] bi ;
122
123 : tiff-lzw-uncompress ( seq -- byte-array )
124     bs:<msb0-bit-reader> 9 tiff-lzw lzw-uncompress ;
125
126 : gif-lzw-uncompress ( seq code-size -- byte-array )
127     [ bs:<lsb0-bit-reader> ] dip gif-lzw lzw-uncompress ;