PNG library should reverse filter on entire bytes

Add word to test that some pngs fail to load
db4
Doug Coleman 2011-09-13 09:35:12 -05:00
parent 218cdcbe0b
commit 5ea02f4798
3 changed files with 217 additions and 182 deletions

View File

@ -75,164 +75,188 @@ IN: images.png.tests
"z09n2c08.png" decode-test "z09n2c08.png" decode-test
] with-directory ] with-directory
! The current PNG decoder implementation is very limited, ! Test pngsuite
! so the entire test suite is not currently enabled. "vocab:images/testing/png/suite" [
! "vocab:images/testing/png/suite" [ "PngSuite.png" decode-test
! "basi0g01.png" decode-test "basi0g01.png" decode-test
! "basi0g02.png" decode-test "basi0g02.png" decode-test
! "basi0g04.png" decode-test "basi0g04.png" decode-test
! "basi0g08.png" decode-test "basi0g08.png" decode-test
! "basi0g16.png" decode-test "basi0g16.png" decode-test
! "basi2c08.png" decode-test "basi2c08.png" decode-test
! "basi2c16.png" decode-test "basi2c16.png" decode-test
! "basi3p01.png" decode-test "basi3p01.png" decode-test
! "basi3p02.png" decode-test "basi3p02.png" decode-test
! "basi3p04.png" decode-test "basi3p04.png" decode-test
! "basi3p08.png" decode-test "basi3p08.png" decode-test
! "basi4a08.png" decode-test "basi4a08.png" decode-test
! "basi4a16.png" decode-test "basi4a16.png" decode-test
! "basi6a08.png" decode-test "basi6a08.png" decode-test
! "basi6a16.png" decode-test "basi6a16.png" decode-test
! "basn0g01.png" decode-test "basn0g01.png" decode-test
! "basn0g02.png" decode-test "basn0g02.png" decode-test
! "basn0g04.png" decode-test "basn0g04.png" decode-test
! "basn0g08.png" decode-test "basn0g08.png" decode-test
! "basn0g16.png" decode-test "basn0g16.png" decode-test
! "basn2c08.png" decode-test "basn2c08.png" decode-test
! "basn2c16.png" decode-test "basn2c16.png" decode-test
! "basn3p01.png" decode-test "basn3p01.png" decode-test
! "basn3p02.png" decode-test "basn3p02.png" decode-test
! "basn3p04.png" decode-test "basn3p04.png" decode-test
! "basn3p08.png" decode-test "basn3p08.png" decode-test
! "basn4a08.png" decode-test "basn4a08.png" decode-test
! "basn4a16.png" decode-test "basn4a16.png" decode-test
! "basn6a08.png" decode-test "basn6a08.png" decode-test
! "basn6a16.png" decode-test "basn6a16.png" decode-test
! "bgai4a08.png" decode-test "bgai4a08.png" decode-test
! "bgai4a16.png" decode-test "bgai4a16.png" decode-test
! "bgan6a08.png" decode-test "bgan6a08.png" decode-test
! "bgan6a16.png" decode-test "bgan6a16.png" decode-test
! "bgbn4a08.png" decode-test "bgbn4a08.png" decode-test
! "bggn4a16.png" decode-test "bggn4a16.png" decode-test
! "bgwn6a08.png" decode-test "bgwn6a08.png" decode-test
! "bgyn6a16.png" decode-test "bgyn6a16.png" decode-test
! "ccwn2c08.png" decode-test "ccwn2c08.png" decode-test
! "ccwn3p08.png" decode-test "ccwn3p08.png" decode-test
! "cdfn2c08.png" decode-test "cdfn2c08.png" decode-test
! "cdhn2c08.png" decode-test "cdhn2c08.png" decode-test
! "cdsn2c08.png" decode-test "cdsn2c08.png" decode-test
! "cdun2c08.png" decode-test "cdun2c08.png" decode-test
! "ch1n3p04.png" decode-test "ch1n3p04.png" decode-test
! "ch2n3p08.png" decode-test "ch2n3p08.png" decode-test
! "cm0n0g04.png" decode-test "cm0n0g04.png" decode-test
! "cm7n0g04.png" decode-test "cm7n0g04.png" decode-test
! "cm9n0g04.png" decode-test "cm9n0g04.png" decode-test
! "cs3n2c16.png" decode-test "cs3n2c16.png" decode-test
! "cs3n3p08.png" decode-test "cs3n3p08.png" decode-test
! "cs5n2c08.png" decode-test "cs5n2c08.png" decode-test
! "cs5n3p08.png" decode-test "cs5n3p08.png" decode-test
! "cs8n2c08.png" decode-test "cs8n2c08.png" decode-test
! "cs8n3p08.png" decode-test "cs8n3p08.png" decode-test
! "ct0n0g04.png" decode-test "ct0n0g04.png" decode-test
! "ct1n0g04.png" decode-test "ct1n0g04.png" decode-test
! "ctzn0g04.png" decode-test "cten0g04.png" decode-test
! "f00n0g08.png" decode-test "ctfn0g04.png" decode-test
! "f00n2c08.png" decode-test "ctgn0g04.png" decode-test
! "f01n0g08.png" decode-test "cthn0g04.png" decode-test
! "f01n2c08.png" decode-test "ctjn0g04.png" decode-test
! "f02n0g08.png" decode-test "ctzn0g04.png" decode-test
! "f02n2c08.png" decode-test "f00n0g08.png" decode-test
! "f03n0g08.png" decode-test "f00n2c08.png" decode-test
! "f03n2c08.png" decode-test "f01n0g08.png" decode-test
! "f04n0g08.png" decode-test "f01n2c08.png" decode-test
! "f04n2c08.png" decode-test "f02n0g08.png" decode-test
! "g03n0g16.png" decode-test "f02n2c08.png" decode-test
! "g03n2c08.png" decode-test "f03n0g08.png" decode-test
! "g03n3p04.png" decode-test "f03n2c08.png" decode-test
! "g04n0g16.png" decode-test "f04n0g08.png" decode-test
! "g04n2c08.png" decode-test "f04n2c08.png" decode-test
! "g04n3p04.png" decode-test "f99n0g04.png" decode-test
! "g05n0g16.png" decode-test "g03n0g16.png" decode-test
! "g05n2c08.png" decode-test "g03n2c08.png" decode-test
! "g05n3p04.png" decode-test "g03n3p04.png" decode-test
! "g07n0g16.png" decode-test "g04n0g16.png" decode-test
! "g07n2c08.png" decode-test "g04n2c08.png" decode-test
! "g07n3p04.png" decode-test "g04n3p04.png" decode-test
! "g10n0g16.png" decode-test "g05n0g16.png" decode-test
! "g10n2c08.png" decode-test "g05n2c08.png" decode-test
! "g10n3p04.png" decode-test "g05n3p04.png" decode-test
! "g25n0g16.png" decode-test "g07n0g16.png" decode-test
! "g25n2c08.png" decode-test "g07n2c08.png" decode-test
! "g25n3p04.png" decode-test "g07n3p04.png" decode-test
! "oi1n0g16.png" decode-test "g10n0g16.png" decode-test
! "oi1n2c16.png" decode-test "g10n2c08.png" decode-test
! "oi2n0g16.png" decode-test "g10n3p04.png" decode-test
! "oi2n2c16.png" decode-test "g25n0g16.png" decode-test
! "oi4n0g16.png" decode-test "g25n2c08.png" decode-test
! "oi4n2c16.png" decode-test "g25n3p04.png" decode-test
! "oi9n0g16.png" decode-test "oi1n0g16.png" decode-test
! "oi9n2c16.png" decode-test "oi1n2c16.png" decode-test
! "pngsuite_logo.png" decode-test "oi2n0g16.png" decode-test
! "pp0n2c16.png" decode-test "oi2n2c16.png" decode-test
! "pp0n6a08.png" decode-test "oi4n0g16.png" decode-test
! "ps1n0g08.png" decode-test "oi4n2c16.png" decode-test
! "ps1n2c16.png" decode-test "oi9n0g16.png" decode-test
! "ps2n0g08.png" decode-test "oi9n2c16.png" decode-test
! "ps2n2c16.png" decode-test "pngsuite_logo.png" decode-test
! "s01i3p01.png" decode-test "pp0n2c16.png" decode-test
! "s01n3p01.png" decode-test "pp0n6a08.png" decode-test
! "s02i3p01.png" decode-test "ps1n0g08.png" decode-test
! "s02n3p01.png" decode-test "ps1n2c16.png" decode-test
! "s03i3p01.png" decode-test "ps2n0g08.png" decode-test
! "s03n3p01.png" decode-test "ps2n2c16.png" decode-test
! "s04i3p01.png" decode-test "s01i3p01.png" decode-test
! "s04n3p01.png" decode-test "s01n3p01.png" decode-test
! "s05i3p02.png" decode-test "s02i3p01.png" decode-test
! "s05n3p02.png" decode-test "s02n3p01.png" decode-test
! "s06i3p02.png" decode-test "s03i3p01.png" decode-test
! "s06n3p02.png" decode-test "s03n3p01.png" decode-test
! "s07i3p02.png" decode-test "s04i3p01.png" decode-test
! "s07n3p02.png" decode-test "s04n3p01.png" decode-test
! "s08i3p02.png" decode-test "s05i3p02.png" decode-test
! "s08n3p02.png" decode-test "s05n3p02.png" decode-test
! "s09i3p02.png" decode-test "s06i3p02.png" decode-test
! "s09n3p02.png" decode-test "s06n3p02.png" decode-test
! "s32i3p04.png" decode-test "s07i3p02.png" decode-test
! "s32n3p04.png" decode-test "s07n3p02.png" decode-test
! "s33i3p04.png" decode-test "s08i3p02.png" decode-test
! "s33n3p04.png" decode-test "s08n3p02.png" decode-test
! "s34i3p04.png" decode-test "s09i3p02.png" decode-test
! "s34n3p04.png" decode-test "s09n3p02.png" decode-test
! "s35i3p04.png" decode-test "s32i3p04.png" decode-test
! "s35n3p04.png" decode-test "s32n3p04.png" decode-test
! "s36i3p04.png" decode-test "s33i3p04.png" decode-test
! "s36n3p04.png" decode-test "s33n3p04.png" decode-test
! "s37i3p04.png" decode-test "s34i3p04.png" decode-test
! "s37n3p04.png" decode-test "s34n3p04.png" decode-test
! "s38i3p04.png" decode-test "s35i3p04.png" decode-test
! "s38n3p04.png" decode-test "s35n3p04.png" decode-test
! "s39i3p04.png" decode-test "s36i3p04.png" decode-test
! "s39n3p04.png" decode-test "s36n3p04.png" decode-test
! "s40i3p04.png" decode-test "s37i3p04.png" decode-test
! "s40n3p04.png" decode-test "s37n3p04.png" decode-test
! "tbbn1g04.png" decode-test "s38i3p04.png" decode-test
! "tbbn2c16.png" decode-test "s38n3p04.png" decode-test
! "tbbn3p08.png" decode-test "s39i3p04.png" decode-test
! "tbgn2c16.png" decode-test "s39n3p04.png" decode-test
! "tbgn3p08.png" decode-test "s40i3p04.png" decode-test
! "tbrn2c08.png" decode-test "s40n3p04.png" decode-test
! "tbwn1g16.png" decode-test "tbbn0g04.png" decode-test
! "tbwn3p08.png" decode-test "tbbn1g04.png" decode-test
! "tbyn3p08.png" decode-test "tbbn2c16.png" decode-test
! "tp0n1g08.png" decode-test "tbbn3p08.png" decode-test
! "tp0n2c08.png" decode-test "tbgn2c16.png" decode-test
! "tp0n3p08.png" decode-test "tbgn3p08.png" decode-test
! "tp1n3p08.png" decode-test "tbrn2c08.png" decode-test
! "x00n0g01.png" decode-test "tbwn0g16.png" decode-test
! "xcrn0g04.png" decode-test "tbwn1g16.png" decode-test
! "xlfn0g04.png" decode-test "tbwn3p08.png" decode-test
! "z00n2c08.png" decode-test "tbyn3p08.png" decode-test
! "z03n2c08.png" decode-test "tp0n0g08.png" decode-test
! "z06n2c08.png" decode-test "tp0n1g08.png" decode-test
! "z09n2c08.png" decode-test "tp0n2c08.png" decode-test
! ] with-directory "tp0n3p08.png" decode-test
"tp1n3p08.png" decode-test
"z00n2c08.png" decode-test
"z03n2c08.png" decode-test
"z06n2c08.png" decode-test
"z09n2c08.png" decode-test
] with-directory
"vocab:images/testing/png/suite/bads" [
"x00n0g01.png" image-load-must-fail
"xcsn0g01.png" image-load-must-fail
"xd0n2c08.png" image-load-must-fail
"xd3n2c08.png" image-load-must-fail
"xd9n2c08.png" image-load-must-fail
"xdtn0g01.png" image-load-must-fail
"xcrn0g04.png" image-load-must-fail
"xc1n0g08.png" image-load-must-fail
"xc9n2c08.png" image-load-must-fail
"xlfn0g04.png" image-load-must-fail
"xhdn0g08.png" image-load-must-fail
"xs1n0g01.png" image-load-must-fail
"xs2n0g01.png" image-load-must-fail
"xs4n0g01.png" image-load-must-fail
"xs7n0g01.png" image-load-must-fail
] with-directory

View File

@ -1,10 +1,11 @@
! Copyright (C) 2009 Doug Coleman. ! Copyright (C) 2009 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors arrays checksums checksums.crc32 combinators USING: accessors arrays assocs byte-arrays checksums
compression.inflate fry grouping images images.loader io checksums.crc32 combinators compression.inflate fry grouping
io.binary io.encodings.ascii io.encodings.string kernel locals images images.loader io io.binary io.encodings.ascii
math math.bitwise math.ranges sequences sorting assocs io.encodings.binary io.encodings.string io.streams.byte-array
math.functions math.order byte-arrays io.streams.throwing ; io.streams.throwing kernel locals math math.bitwise
math.functions math.order math.ranges sequences sorting ;
QUALIFIED-WITH: bitstreams bs QUALIFIED-WITH: bitstreams bs
IN: images.png IN: images.png
@ -115,6 +116,8 @@ ERROR: unimplemented-color-type image ;
a b + c - { a b c } [ [ - abs ] keep 2array ] with map a b + c - { a b c } [ [ - abs ] keep 2array ] with map
sort-keys first second ; sort-keys first second ;
ERROR: bad-filter n ;
:: png-unfilter-line ( width prev curr filter -- curr' ) :: png-unfilter-line ( width prev curr filter -- curr' )
prev :> c prev :> c
prev width tail-slice :> b prev width tail-slice :> b
@ -127,6 +130,7 @@ ERROR: unimplemented-color-type image ;
{ filter-up [ [| n | n x nth n b nth + 256 wrap n x set-nth ] each ] } { filter-up [ [| n | n x nth n b nth + 256 wrap n x set-nth ] each ] }
{ filter-average [ [| n | n x nth n a nth n b nth + 2/ + 256 wrap n x set-nth ] each ] } { filter-average [ [| n | n x nth n a nth n b nth + 2/ + 256 wrap n x set-nth ] each ] }
{ filter-paeth [ [| n | n x nth n a nth n b nth n c nth paeth + 256 wrap n x set-nth ] each ] } { filter-paeth [ [| n | n x nth n a nth n b nth n c nth paeth + 256 wrap n x set-nth ] each ] }
[ bad-filter ]
} case } case
curr width tail ; curr width tail ;
@ -145,32 +149,36 @@ ERROR: unimplemented-color-type image ;
row image nth :> irow row image nth :> irow
pixel col irow set-nth ; pixel col irow set-nth ;
ERROR: bad-filter n ; :: read-scanlines ( byte-reader loading-png width height -- array )
:: read-scanlines ( bit-reader loading-png width height -- array )
loading-png png-components-per-pixel :> #components loading-png png-components-per-pixel :> #components
loading-png bit-depth>> :> bit-depth loading-png bit-depth>> :> bit-depth
bit-depth :> depth! bit-depth :> depth!
#components width * :> count! #components width * :> count!
#components bit-depth * width * 8 math:align 8 /i :> stride
height [
stride 1 + byte-reader stream-read
] replicate
#components bit-depth 16 = [ 2 * ] when reverse-png-filter
! Only read up to 8 bits at a time ! Only read up to 8 bits at a time
bit-depth 16 = [ bit-depth 16 = [
8 depth! 8 depth!
count 2 * count! count 2 * count!
] when ] when
bs:<msb0-bit-reader> :> br
height [ height [
8 bit-reader bs:read dup 0 4 between? [ bad-filter ] unless count [ depth br bs:read ] B{ } replicate-as
count [ depth bit-reader bs:read ] replicate swap prefix 8 br bs:align
8 bit-reader bs:align ] replicate concat ;
] replicate
#components bit-depth 16 = [ 2 * ] when reverse-png-filter ;
:: reverse-interlace-none ( byte-array loading-png -- array ) :: reverse-interlace-none ( bytes loading-png -- array )
byte-array bs:<msb0-bit-reader> :> bs bytes binary <byte-reader> :> br
loading-png width>> :> width loading-png width>> :> width
loading-png height>> :> height loading-png height>> :> height
bs loading-png width height read-scanlines ; br loading-png width height read-scanlines ;
:: adam7-subimage-height ( png-height pass -- subimage-height ) :: adam7-subimage-height ( png-height pass -- subimage-height )
pass starting-row nth png-height >= [ pass starting-row nth png-height >= [
@ -190,18 +198,18 @@ ERROR: bad-filter n ;
pass col-increment nth /i pass col-increment nth /i
] if ; ] if ;
:: read-adam7-subimage ( bit-reader loading-png pass -- lines ) :: read-adam7-subimage ( byte-reader loading-png pass -- lines )
loading-png height>> pass adam7-subimage-height :> height loading-png height>> pass adam7-subimage-height :> height
loading-png width>> pass adam7-subimage-width :> width loading-png width>> pass adam7-subimage-width :> width
height width * zero? [ height width * zero? [
B{ } clone B{ } clone
] [ ] [
bit-reader loading-png width height read-scanlines byte-reader loading-png width height read-scanlines
] if ; ] if ;
:: reverse-interlace-adam7 ( byte-array loading-png -- byte-array ) :: reverse-interlace-adam7 ( byte-array loading-png -- byte-array )
byte-array bs:<msb0-bit-reader> :> bs byte-array binary <byte-reader> :> ba
loading-png height>> :> height loading-png height>> :> height
loading-png width>> :> width loading-png width>> :> width
loading-png bit-depth>> :> bit-depth loading-png bit-depth>> :> bit-depth
@ -217,7 +225,7 @@ ERROR: bad-filter n ;
0 :> pass! 0 :> pass!
[ pass 7 < ] [ [ pass 7 < ] [
bs loading-png pass read-adam7-subimage ba loading-png pass read-adam7-subimage
#bytes <sliced-groups> #bytes <sliced-groups>

View File

@ -60,4 +60,7 @@ PRIVATE>
ubyte-components >>component-type ; inline ubyte-components >>component-type ; inline
: randomize-image ( image -- image ) : randomize-image ( image -- image )
dup bytes-per-image random-bytes >>bitmap ; dup bytes-per-image random-bytes >>bitmap ;
: image-load-must-fail ( path -- )
'[ _ load-image ] must-fail ;