images.pam: encode and decode support for netpbm's PAM image format

db4
Keith Lazuka 2009-09-29 20:35:21 -04:00
parent f297e88987
commit dc509f111b
1 changed files with 99 additions and 0 deletions

View File

@ -0,0 +1,99 @@
! Copyright (C) 2009 Keith Lazuka.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors arrays combinators fry grouping images
images.loader io io.encodings io.encodings.ascii
io.encodings.binary io.files io.files.temp kernel math
math.parser prettyprint sequences splitting ;
IN: images.pam
SINGLETON: pam-image
"pam" pam-image register-image-class
: output-pam-header ( note num-channels width height -- )
ascii [
"P7" print
"HEIGHT " write pprint nl
"WIDTH " write pprint nl
"MAXVAL 255" print
"DEPTH " write pprint nl
"TUPLTYPE " prepend print
"ENDHDR" print
] with-encoded-output ; inline
: output-pam ( note num-channels width height pixels -- )
[ output-pam-header ] dip write ;
: verify-bitmap-format ( image -- )
[ component-type>> ubyte-components assert= ]
[ component-order>> { RGB RGBA } memq? [
"PAM encode: component-order must be RGB or RGBA!" throw
] unless ] bi ;
GENERIC: TUPLTYPE ( component-order -- str )
M: component-order TUPLTYPE name>> ;
M: RGBA TUPLTYPE drop "RGB_ALPHA" ;
M: pam-image image>stream
drop {
[ verify-bitmap-format ]
[ component-order>> [ TUPLTYPE ] [ component-count ] bi ]
[ dim>> first2 ]
[ bitmap>> ]
} cleave output-pam ;
! PAM Decoder
TUPLE: loading-pam width height depth maxval tupltype bitmap ;
: ?glue ( seq1 seq2 seq3 -- seq )
pick empty? [ drop nip ] [ glue ] if ;
: append-tupltype ( pam tupltype -- pam )
'[ _ " " ?glue ] change-tupltype ;
: read-header-lines ( pam -- pam )
readln " " split unclip swap " " join swap {
{ "ENDHDR" [ drop ] }
{ "HEIGHT" [ string>number >>height read-header-lines ] }
{ "WIDTH" [ string>number >>width read-header-lines ] }
{ "DEPTH" [ string>number >>depth read-header-lines ] }
{ "MAXVAL" [ string>number >>maxval read-header-lines ] }
{ "TUPLTYPE" [ append-tupltype read-header-lines ] }
[ 2drop read-header-lines ]
} case ;
: read-header ( pam -- pam )
ascii [
readln "P7" assert=
read-header-lines
] with-decoded-input ;
: bytes-per-pixel ( pam -- n )
[ depth>> ] [ maxval>> 256 < 1 2 ? ] bi * ;
: bitmap-length ( pam -- num-bytes )
[ width>> ] [ height>> ] [ bytes-per-pixel ] tri * * ;
: read-bitmap ( pam -- pam )
dup bitmap-length read >>bitmap ;
: load-pam ( stream -- pam )
[ loading-pam new read-header read-bitmap ] with-input-stream ;
: tupltype>component-order ( pam -- component-order )
tupltype>> dup {
{ "RGB_ALPHA" [ drop RGBA ] }
{ "RGBA" [ drop RGBA ] }
{ "RGB" [ drop RGB ] }
[ "Cannot determine component-order from TUPLTYPE " prepend throw ]
} case ;
: pam>image ( pam -- image )
[ <image> ] dip {
[ [ width>> ] [ height>> ] bi 2array >>dim ]
[ tupltype>component-order >>component-order ]
[ drop ubyte-components >>component-type ]
[ bitmap>> >>bitmap ]
} cleave ;
M: pam-image stream>image drop load-pam pam>image ;