1 ! Copyright (C) 2009 Doug Coleman.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors images io io.binary io.encodings.ascii
4 io.encodings.binary io.encodings.string io.files io.files.info kernel
5 sequences io.streams.limited fry combinators arrays math checksums
6 checksums.crc32 compression.inflate grouping byte-arrays images.loader ;
10 "png" png-image register-image-class
14 width height bit-depth color-type compression-method
15 filter-method interlace-method uncompressed ;
17 : <loading-png> ( -- image )
21 TUPLE: png-chunk length type data ;
23 : <png-chunk> ( -- png-chunk )
24 png-chunk new ; inline
27 B{ HEX: 89 HEX: 50 HEX: 4e HEX: 47 HEX: 0d HEX: 0a HEX: 1a HEX: 0a }
29 ERROR: bad-png-header header ;
31 : read-png-header ( -- )
32 8 read dup png-header sequence= [
38 : read-png-chunks ( loading-png -- loading-png )
40 4 read be> [ >>length ] [ 4 + ] bi
41 read dup crc32 checksum-bytes
42 4 read = [ bad-checksum ] unless
44 [ ascii decode >>type ] [ B{ } like >>data ] bi*
45 [ over chunks>> push ]
46 [ type>> ] bi "IEND" =
47 [ read-png-chunks ] unless ;
49 : find-chunk ( loading-png string -- chunk )
50 [ chunks>> ] dip '[ type>> _ = ] find nip ;
52 : parse-ihdr-chunk ( loading-png -- loading-png )
53 dup "IHDR" find-chunk data>> {
54 [ [ 0 4 ] dip subseq be> >>width ]
55 [ [ 4 8 ] dip subseq be> >>height ]
56 [ [ 8 ] dip nth >>bit-depth ]
57 [ [ 9 ] dip nth >>color-type ]
58 [ [ 10 ] dip nth >>compression-method ]
59 [ [ 11 ] dip nth >>filter-method ]
60 [ [ 12 ] dip nth >>interlace-method ]
63 : find-compressed-bytes ( loading-png -- bytes )
64 chunks>> [ type>> "IDAT" = ] filter
65 [ data>> ] map concat ;
68 : zlib-data ( loading-png -- bytes )
69 chunks>> [ type>> "IDAT" = ] find nip data>> ;
71 ERROR: unknown-color-type n ;
72 ERROR: unimplemented-color-type image ;
74 : inflate-data ( loading-png -- bytes )
75 zlib-data zlib-inflate ;
77 : decode-greyscale ( loading-png -- loading-png )
78 unimplemented-color-type ;
80 : png-image-bytes ( loading-png -- byte-array )
81 [ inflate-data ] [ width>> 3 * 1 + ] bi group
84 : decode-truecolor ( loading-png -- loading-png )
86 [ png-image-bytes >>bitmap ]
87 [ [ width>> ] [ height>> ] bi 2array >>dim ]
88 [ drop RGB >>component-order ubyte-components >>component-type ]
91 : decode-indexed-color ( loading-png -- loading-png )
92 unimplemented-color-type ;
94 : decode-greyscale-alpha ( loading-png -- loading-png )
95 unimplemented-color-type ;
97 : decode-truecolor-alpha ( loading-png -- loading-png )
99 [ png-image-bytes >>bitmap ]
100 [ [ width>> ] [ height>> ] bi 2array >>dim ]
101 [ drop RGBA >>component-order ubyte-components >>component-type ]
104 : decode-png ( loading-png -- loading-png )
106 { 0 [ decode-greyscale ] }
107 { 2 [ decode-truecolor ] }
108 { 3 [ decode-indexed-color ] }
109 { 4 [ decode-greyscale-alpha ] }
110 { 6 [ decode-truecolor-alpha ] }
111 [ unknown-color-type ]
114 M: png-image stream>image
121 ] with-input-stream ;