2009-02-12 18:44:04 -05:00
|
|
|
! Copyright (C) 2009 Doug Coleman.
|
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
2011-01-27 00:06:43 -05:00
|
|
|
USING: accessors combinators io kernel math math.order
|
|
|
|
namespaces sequences vectors ;
|
2009-05-14 16:44:57 -04:00
|
|
|
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 16:51:47 -04:00
|
|
|
TUPLE: lzw
|
|
|
|
input
|
|
|
|
output
|
|
|
|
table
|
|
|
|
code
|
|
|
|
old-code
|
|
|
|
initial-code-size
|
|
|
|
code-size
|
|
|
|
clear-code
|
|
|
|
end-of-information-code ;
|
|
|
|
|
|
|
|
TUPLE: tiff-lzw < lzw ;
|
|
|
|
TUPLE: gif-lzw < lzw ;
|
2009-02-12 18:44:04 -05:00
|
|
|
|
2009-09-26 13:09:12 -04:00
|
|
|
: initial-uncompress-table ( size -- seq )
|
2009-09-25 16:51:47 -04:00
|
|
|
iota [ 1vector ] V{ } map-as ;
|
2009-02-12 18:44:04 -05:00
|
|
|
|
|
|
|
: reset-lzw-uncompress ( lzw -- lzw )
|
2009-09-26 13:09:12 -04:00
|
|
|
dup end-of-information-code>> 1 + initial-uncompress-table >>table
|
2009-09-25 15:12:44 -04:00
|
|
|
dup initial-code-size>> >>code-size ;
|
2009-02-12 18:44:04 -05:00
|
|
|
|
2010-01-31 17:29:20 -05:00
|
|
|
ERROR: code-size-zero ;
|
|
|
|
|
2009-09-25 16:51:47 -04:00
|
|
|
: <lzw-uncompress> ( input code-size class -- obj )
|
|
|
|
new
|
2015-08-13 19:13:05 -04:00
|
|
|
swap [ code-size-zero ] when-zero >>code-size
|
2009-09-25 16:51:47 -04:00
|
|
|
dup code-size>> >>initial-code-size
|
|
|
|
dup code-size>> 1 - 2^ >>clear-code
|
|
|
|
dup clear-code>> 1 + >>end-of-information-code
|
2009-02-12 18:44:04 -05:00
|
|
|
swap >>input
|
2009-09-26 13:09:12 -04:00
|
|
|
BV{ } clone >>output
|
|
|
|
reset-lzw-uncompress ;
|
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 16:51:47 -04:00
|
|
|
GENERIC: code-space-full? ( lzw -- ? )
|
|
|
|
|
2009-09-26 22:09:58 -04:00
|
|
|
: size-and-limit ( lzw -- m n ) [ table>> length ] [ code-size>> 2^ ] bi ;
|
2009-09-25 16:51:47 -04:00
|
|
|
|
2009-09-26 22:09:58 -04:00
|
|
|
M: tiff-lzw code-space-full? size-and-limit 1 - = ;
|
|
|
|
M: gif-lzw code-space-full? size-and-limit = ;
|
2009-09-25 15:12:44 -04:00
|
|
|
|
2011-01-27 00:06:43 -05:00
|
|
|
GENERIC: increment-code-size ( lzw -- lzw )
|
|
|
|
|
|
|
|
M: lzw increment-code-size [ 1 + ] change-code-size ;
|
|
|
|
M: gif-lzw increment-code-size [ 1 + 12 min ] change-code-size ;
|
|
|
|
|
2009-09-25 15:12:44 -04:00
|
|
|
: maybe-increment-code-size ( lzw -- lzw )
|
2011-01-27 00:06:43 -05:00
|
|
|
dup code-space-full? [ increment-code-size ] when ;
|
2009-09-25 15:12:44 -04:00
|
|
|
|
|
|
|
: 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
|
|
|
|
2009-09-26 13:09:12 -04:00
|
|
|
: end-of-information? ( lzw code -- ? ) swap end-of-information-code>> = ;
|
|
|
|
: clear-code? ( lzw code -- ? ) swap clear-code>> = ;
|
|
|
|
|
|
|
|
DEFER: handle-clear-code
|
2009-09-26 15:17:52 -04:00
|
|
|
: lzw-process-next-code ( lzw quot: ( lzw code -- ) -- )
|
2009-09-26 13:09:12 -04:00
|
|
|
[ lzw-read ] dip {
|
2012-10-22 23:45:15 -04:00
|
|
|
{ [ 2over end-of-information? ] [ 3drop ] }
|
|
|
|
{ [ 2over clear-code? ] [ 2drop handle-clear-code ] }
|
2009-09-26 13:09:12 -04:00
|
|
|
[ call( lzw code -- ) ]
|
|
|
|
} cond ; inline
|
|
|
|
|
2009-02-12 18:44:04 -05:00
|
|
|
DEFER: lzw-uncompress-char
|
|
|
|
: handle-clear-code ( lzw -- )
|
|
|
|
reset-lzw-uncompress
|
2009-09-26 13:09:12 -04:00
|
|
|
[
|
2009-02-12 18:44:04 -05:00
|
|
|
>>code
|
|
|
|
[ write-code ]
|
|
|
|
[ code>old-code ] bi
|
|
|
|
lzw-uncompress-char
|
2009-09-26 15:17:52 -04:00
|
|
|
] lzw-process-next-code ;
|
2009-02-12 18:44:04 -05:00
|
|
|
|
|
|
|
: 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 ;
|
2011-01-27 00:06:43 -05:00
|
|
|
|
2009-02-12 18:44:04 -05:00
|
|
|
: lzw-uncompress-char ( lzw -- )
|
2009-09-26 15:17:52 -04:00
|
|
|
[ >>code handle-uncompress-code lzw-uncompress-char ]
|
|
|
|
lzw-process-next-code ;
|
2009-02-12 18:44:04 -05:00
|
|
|
|
2009-09-25 16:51:47 -04:00
|
|
|
: lzw-uncompress ( bitstream code-size class -- byte-array )
|
2009-09-26 13:09:12 -04:00
|
|
|
<lzw-uncompress>
|
|
|
|
[ lzw-uncompress-char ] [ output>> ] bi ;
|
2009-09-25 15:12:44 -04:00
|
|
|
|
2009-09-25 16:51:47 -04:00
|
|
|
: tiff-lzw-uncompress ( seq -- byte-array )
|
|
|
|
bs:<msb0-bit-reader> 9 tiff-lzw lzw-uncompress ;
|
2009-09-25 15:12:44 -04:00
|
|
|
|
2009-09-25 16:51:47 -04:00
|
|
|
: gif-lzw-uncompress ( seq code-size -- byte-array )
|
|
|
|
[ bs:<lsb0-bit-reader> ] dip gif-lzw lzw-uncompress ;
|