factor/basis/images/bitmap/bitmap.factor

215 lines
5.9 KiB
Factor
Raw Normal View History

! Copyright (C) 2007, 2009 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors alien alien.c-types arrays byte-arrays columns
2009-06-03 00:29:04 -04:00
combinators compression.run-length endian fry grouping images
images.loader io io.binary io.encodings.binary io.files kernel
locals macros math math.bitwise math.functions namespaces
sequences strings summary ;
IN: images.bitmap
2009-03-14 16:17:51 -04:00
: assert-sequence= ( a b -- )
2dup sequence= [ 2drop ] [ assert ] if ;
: read2 ( -- n ) 2 read le> ;
: read4 ( -- n ) 4 read le> ;
2009-03-14 16:31:59 -04:00
: write2 ( n -- ) 2 >le write ;
: write4 ( n -- ) 4 >le write ;
2009-03-14 16:17:51 -04:00
TUPLE: bitmap-image < image ;
! Used to construct the final bitmap-image
2009-03-14 16:08:50 -04:00
TUPLE: loading-bitmap
2009-03-14 16:52:04 -04:00
size reserved offset header-length width
2009-03-02 20:38:28 -05:00
height planes bit-count compression size-image
2009-06-03 00:20:07 -04:00
x-pels y-pels color-used color-important color-palette color-index
uncompressed-bytes ;
2009-03-02 20:38:28 -05:00
ERROR: bitmap-magic magic ;
M: bitmap-magic summary
drop "First two bytes of bitmap stream must be 'BM'" ;
<PRIVATE
: 8bit>buffer ( bitmap -- array )
2009-06-03 00:20:07 -04:00
[ color-palette>> 4 <sliced-groups> [ 3 head-slice ] map ]
[ color-index>> >array ] bi [ swap nth ] with map concat ;
ERROR: bmp-not-supported n ;
2009-03-14 16:31:59 -04:00
: reverse-lines ( byte-array width -- byte-array )
2009-04-08 19:42:01 -04:00
<sliced-groups> <reversed> concat ; inline
2009-03-14 16:31:59 -04:00
2009-06-03 00:20:07 -04:00
: bitmap>bytes ( loading-bitmap -- array )
dup bit-count>>
{
{ 32 [ color-index>> ] }
2009-04-08 19:42:01 -04:00
{ 24 [ [ color-index>> ] [ width>> 3 * ] bi reverse-lines ] }
{ 8 [ [ 8bit>buffer ] [ width>> 3 * ] bi reverse-lines ] }
2009-03-14 16:17:51 -04:00
[ bmp-not-supported ]
} case >byte-array ;
2009-06-03 00:20:07 -04:00
ERROR: unsupported-bitmap-compression compression ;
: uncompress-bitmap ( loading-bitmap -- loading-bitmap' )
dup compression>> {
{ 0 [ ] }
2009-06-03 00:29:04 -04:00
{ 1 [ [ run-length-uncompress8 ] change-color-index ] }
2009-06-03 00:20:07 -04:00
{ 2 [ "run-length encoding 4" unsupported-bitmap-compression ] }
{ 3 [ "bitfields" unsupported-bitmap-compression ] }
{ 4 [ "jpeg" unsupported-bitmap-compression ] }
{ 5 [ "png" unsupported-bitmap-compression ] }
} case ;
: loading-bitmap>bytes ( loading-bitmap -- byte-array )
uncompress-bitmap bitmap>bytes ;
2009-03-14 16:31:59 -04:00
: parse-file-header ( loading-bitmap -- loading-bitmap )
2009-03-14 16:17:51 -04:00
2 read "BM" assert-sequence=
read4 >>size
read4 >>reserved
read4 >>offset ;
2009-03-14 16:31:59 -04:00
: parse-bitmap-header ( loading-bitmap -- loading-bitmap )
read4 >>header-length
read4 >>width
read4 32 >signed >>height
read2 >>planes
read2 >>bit-count
read4 >>compression
read4 >>size-image
read4 >>x-pels
read4 >>y-pels
read4 >>color-used
read4 >>color-important ;
2009-06-03 00:20:07 -04:00
: color-palette-length ( loading-bitmap -- n )
[ offset>> 14 - ] [ header-length>> ] bi - ;
2009-03-14 16:08:50 -04:00
: color-index-length ( loading-bitmap -- n )
{
[ width>> ]
[ planes>> * ]
[ bit-count>> * 31 + 32 /i 4 * ]
[ height>> abs * ]
} cleave ;
: image-size ( loading-bitmap -- n )
[ [ width>> ] [ height>> ] bi * ] [ bit-count>> 8 /i ] bi * abs ;
2009-04-08 19:42:01 -04:00
: bitmap-padding ( width -- n )
3 * 4 mod 4 swap - 4 mod ; inline
:: fixup-color-index ( loading-bitmap -- loading-bitmap )
loading-bitmap width>> :> width
2009-03-16 08:08:35 -04:00
width 3 * :> width*3
2009-04-08 19:42:01 -04:00
loading-bitmap width>> bitmap-padding :> padding
loading-bitmap [ color-index>> length ] [ height>> abs ] bi /i :> stride
loading-bitmap
2009-03-16 08:08:35 -04:00
padding 0 > [
2009-04-08 19:42:01 -04:00
[
2009-03-16 08:08:35 -04:00
stride <sliced-groups>
[ width*3 head-slice ] map concat
] change-color-index
2009-04-08 19:42:01 -04:00
] when ;
2009-03-14 16:17:51 -04:00
: parse-bitmap ( loading-bitmap -- loading-bitmap )
2009-06-03 00:20:07 -04:00
dup color-palette-length read >>color-palette
dup color-index-length read >>color-index
fixup-color-index ;
2009-06-03 00:20:07 -04:00
: load-bitmap ( path -- loading-bitmap )
2009-04-08 19:42:01 -04:00
binary [
loading-bitmap new
parse-file-header parse-bitmap-header parse-bitmap
] with-file-reader ;
2009-02-10 18:17:36 -05:00
ERROR: unknown-component-order bitmap ;
2009-03-14 16:31:59 -04:00
: bitmap>component-order ( loading-bitmap -- object )
2009-02-10 18:17:36 -05:00
bit-count>> {
{ 32 [ BGRA ] }
{ 24 [ BGR ] }
{ 8 [ BGR ] }
[ unknown-component-order ]
} case ;
2009-04-08 19:42:01 -04:00
: loading-bitmap>bitmap-image ( bitmap-image loading-bitmap -- bitmap-image )
2009-03-14 16:08:50 -04:00
{
2009-06-03 00:20:07 -04:00
[ loading-bitmap>bytes >>bitmap ]
[ [ width>> ] [ height>> abs ] bi 2array >>dim ]
[ height>> 0 < [ t >>upside-down? ] when ]
2009-03-02 20:38:28 -05:00
[ bitmap>component-order >>component-order ]
} cleave ;
2009-03-14 16:08:50 -04:00
M: bitmap-image load-image* ( path loading-bitmap -- bitmap )
2009-06-03 00:20:07 -04:00
swap load-bitmap loading-bitmap>bitmap-image ;
"bmp" bitmap-image register-image-class
2009-03-02 20:38:28 -05:00
PRIVATE>
2009-04-08 19:42:01 -04:00
: bitmap>color-index ( bitmap -- byte-array )
[
bitmap>>
4 <sliced-groups>
[ 3 head-slice <reversed> ] map
B{ } join
] [
dim>> first dup bitmap-padding dup 0 > [
[ 3 * group ] dip '[ _ <byte-array> append ] map
B{ } join
] [
2drop
] if
] bi ;
: save-bitmap ( image path -- )
binary [
B{ CHAR: B CHAR: M } write
[
2009-04-08 19:42:01 -04:00
bitmap>color-index length 14 + 40 + write4
0 write4
54 write4
40 write4
] [
{
2009-03-14 16:08:50 -04:00
! width height
[ dim>> first2 [ write4 ] bi@ ]
2009-03-14 16:08:50 -04:00
! planes
[ drop 1 write2 ]
2009-03-14 16:08:50 -04:00
! bit-count
[ drop 24 write2 ]
2009-03-14 16:08:50 -04:00
! compression
[ drop 0 write4 ]
2009-03-14 16:08:50 -04:00
! size-image
2009-04-08 19:42:01 -04:00
[ bitmap>color-index length write4 ]
2009-03-14 16:08:50 -04:00
! x-pels
[ drop 0 write4 ]
2009-03-14 16:08:50 -04:00
! y-pels
[ drop 0 write4 ]
2009-03-14 16:08:50 -04:00
! color-used
[ drop 0 write4 ]
2009-03-14 16:08:50 -04:00
! color-important
[ drop 0 write4 ]
2009-03-14 16:08:50 -04:00
2009-06-03 00:20:07 -04:00
! color-palette
2009-03-14 16:31:59 -04:00
[
2009-04-08 19:42:01 -04:00
[ bitmap>color-index ]
[ dim>> first 3 * ]
[ dim>> first bitmap-padding + ] tri
2009-03-14 16:31:59 -04:00
reverse-lines write
]
} cleave
] bi
] with-file-writer ;