factor/basis/compression/lzw/lzw.factor

127 lines
3.2 KiB
Factor
Raw Normal View History

2009-02-12 18:44:04 -05:00
! Copyright (C) 2009 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
2009-09-25 15:12:44 -04:00
USING: accessors combinators io kernel math namespaces
prettyprint sequences vectors ;
QUALIFIED-WITH: bitstreams bs
2009-09-25 15:12:44 -04:00
IN: compression.lzw
2009-02-12 18:44:04 -05:00
2009-09-25 15:12:44 -04:00
SYMBOL: clear-code
4 clear-code set-global
2009-02-12 18:44:04 -05:00
2009-09-25 15:12:44 -04:00
SYMBOL: end-of-information
5 end-of-information set-global
2009-02-12 18:44:04 -05:00
2009-09-25 15:12:44 -04:00
TUPLE: lzw input output table code old-code initial-code-size code-size ;
2009-02-12 18:44:04 -05:00
: initial-uncompress-table ( -- seq )
2009-09-25 15:12:44 -04:00
end-of-information get 1 + iota [ 1vector ] V{ } map-as ;
2009-02-12 18:44:04 -05:00
: reset-lzw-uncompress ( lzw -- lzw )
2009-09-25 15:12:44 -04:00
initial-uncompress-table >>table
dup initial-code-size>> >>code-size ;
2009-02-12 18:44:04 -05:00
2009-09-25 15:12:44 -04:00
: <lzw-uncompress> ( input code-size -- obj )
2009-02-12 18:44:04 -05:00
lzw new
2009-09-25 15:12:44 -04:00
swap >>initial-code-size
dup initial-code-size>> >>code-size
2009-02-12 18:44:04 -05:00
swap >>input
BV{ } clone >>output
reset-lzw-uncompress ;
2009-02-22 18:29:27 -05:00
ERROR: not-in-table value ;
2009-02-12 18:44:04 -05:00
: lookup-old-code ( lzw -- vector )
[ old-code>> ] [ table>> ] bi nth ;
: lookup-code ( lzw -- vector )
[ code>> ] [ table>> ] bi nth ;
: code-in-table? ( lzw -- ? )
[ code>> ] [ table>> length ] bi < ;
: code>old-code ( lzw -- lzw )
dup code>> >>old-code ;
: write-code ( lzw -- )
[ lookup-code ] [ output>> ] bi push-all ;
2009-09-25 15:12:44 -04:00
: kdebug ( lzw -- lzw )
dup "TIFF: incrementing code size " write
[ code-size>> pprint ]
[ " table length " write table>> length pprint ] bi
nl ;
: maybe-increment-code-size ( lzw -- lzw )
dup [ table>> length ] [ code-size>> 2^ 1 - ] bi =
[ kdebug [ 1 + ] change-code-size ] when ;
: add-to-table ( seq lzw -- )
[ table>> push ]
[ maybe-increment-code-size 2drop ] 2bi ;
2009-02-12 18:44:04 -05:00
: lzw-read ( lzw -- lzw n )
2009-09-25 15:12:44 -04:00
[ ] [ code-size>> ] [ input>> ] tri bs:read ;
2009-02-12 18:44:04 -05:00
DEFER: lzw-uncompress-char
: handle-clear-code ( lzw -- )
2009-09-25 15:12:44 -04:00
"CLEAR CODE" print
2009-02-12 18:44:04 -05:00
reset-lzw-uncompress
2009-09-25 15:12:44 -04:00
lzw-read dup end-of-information get = [
2009-02-12 18:44:04 -05:00
2drop
] [
>>code
[ write-code ]
[ code>old-code ] bi
lzw-uncompress-char
] if ;
: handle-uncompress-code ( lzw -- lzw )
dup code-in-table? [
[ write-code ]
[
[
[ lookup-old-code ]
[ lookup-code first ] bi suffix
] [ add-to-table ] bi
] [ code>old-code ] tri
] [
[
[ lookup-old-code dup first suffix ] keep
[ output>> push-all ] [ add-to-table ] 2bi
] [ code>old-code ] bi
] if ;
: lzw-uncompress-char ( lzw -- )
lzw-read [
>>code
2009-09-25 15:12:44 -04:00
dup code>> end-of-information get = [
2009-02-12 18:44:04 -05:00
drop
] [
2009-09-25 15:12:44 -04:00
dup code>> clear-code get = [
2009-02-12 18:44:04 -05:00
handle-clear-code
] [
handle-uncompress-code
lzw-uncompress-char
] if
] if
] [
drop
] if* ;
2009-09-25 15:12:44 -04:00
: register-special-codes ( first-code-size -- first-code-size )
[
1 - 2^ dup clear-code set
1 + end-of-information set
] keep ;
: lzw-uncompress ( bitstream code-size -- byte-array )
register-special-codes
<lzw-uncompress>
[ lzw-uncompress-char ] [ output>> ] bi ;
2009-09-25 15:12:44 -04:00
: lzw-uncompress-msb0 ( seq code-size -- byte-array )
[ bs:<msb0-bit-reader> ] dip lzw-uncompress ;
: lzw-uncompress-lsb0 ( seq code-size -- byte-array )
[ bs:<lsb0-bit-reader> ] dip lzw-uncompress ;