Bladeren bron

tests: test_png_regress

I want to make some changes to the PNG loader, this is to get some
test coverage at least to make it easier not to break anything.

The two ref_results files that are "corrupt" files that stb_image
nevertheless loads without error are checksum failures; this is
by design, since stb_image does not verify checksums.
Fabian Giesen 2 jaren geleden
bovenliggende
commit
ed64333410
2 gewijzigde bestanden met toevoegingen van 334 en 0 verwijderingen
  1. 259 0
      tests/pngsuite/ref_results.csv
  2. 75 0
      tests/test_png_regress.c

+ 259 - 0
tests/pngsuite/ref_results.csv

@@ -0,0 +1,259 @@
+filename,width,height,ncomp,error,hash
+pngsuite/16bit/basi0g16.png,32,32,1,,0xfc8f2f99
+pngsuite/16bit/basi2c16.png,32,32,3,,0x65567ed5
+pngsuite/16bit/basi4a16.png,32,32,2,,0x198cf245
+pngsuite/16bit/basi6a16.png,32,32,4,,0x3016e9b5
+pngsuite/16bit/basn0g16.png,32,32,1,,0xfc8f2f99
+pngsuite/16bit/basn2c16.png,32,32,3,,0x65567ed5
+pngsuite/16bit/basn4a16.png,32,32,2,,0x198cf245
+pngsuite/16bit/basn6a16.png,32,32,4,,0x3016e9b5
+pngsuite/16bit/bgai4a16.png,32,32,2,,0x198cf245
+pngsuite/16bit/bgan6a16.png,32,32,4,,0x3016e9b5
+pngsuite/16bit/bggn4a16.png,32,32,2,,0x198cf245
+pngsuite/16bit/bgyn6a16.png,32,32,4,,0x3016e9b5
+pngsuite/16bit/oi1n0g16.png,32,32,1,,0xfc8f2f99
+pngsuite/16bit/oi1n2c16.png,32,32,3,,0x65567ed5
+pngsuite/16bit/oi2n0g16.png,32,32,1,,0xfc8f2f99
+pngsuite/16bit/oi2n2c16.png,32,32,3,,0x65567ed5
+pngsuite/16bit/oi4n0g16.png,32,32,1,,0xfc8f2f99
+pngsuite/16bit/oi4n2c16.png,32,32,3,,0x65567ed5
+pngsuite/16bit/oi9n0g16.png,32,32,1,,0xfc8f2f99
+pngsuite/16bit/oi9n2c16.png,32,32,3,,0x65567ed5
+pngsuite/16bit/tbbn2c16.png,32,32,4,,0xaa9bfe44
+pngsuite/16bit/tbgn2c16.png,32,32,4,,0xaa9bfe44
+pngsuite/16bit/tbwn0g16.png,32,32,2,,0x075e519a
+pngsuite/corrupt/xc1n0g08.png,32,32,2,bad ctype,0x00000000
+pngsuite/corrupt/xc9n2c08.png,32,32,2,bad ctype,0x00000000
+pngsuite/corrupt/xcrn0g04.png,32,32,2,unknown image type,0x00000000
+pngsuite/corrupt/xcsn0g01.png,32,32,1,,0x43b9891f
+pngsuite/corrupt/xd0n2c08.png,32,32,1,1/2/4/8/16-bit only,0x00000000
+pngsuite/corrupt/xd3n2c08.png,32,32,1,1/2/4/8/16-bit only,0x00000000
+pngsuite/corrupt/xd9n2c08.png,32,32,1,1/2/4/8/16-bit only,0x00000000
+pngsuite/corrupt/xdtn0g01.png,32,32,1,no IDAT,0x00000000
+pngsuite/corrupt/xhdn0g08.png,32,32,1,,0x414f1ca9
+pngsuite/corrupt/xlfn0g04.png,32,32,1,unknown image type,0x00000000
+pngsuite/corrupt/xs1n0g01.png,32,32,1,unknown image type,0x00000000
+pngsuite/corrupt/xs2n0g01.png,32,32,1,unknown image type,0x00000000
+pngsuite/corrupt/xs4n0g01.png,32,32,1,unknown image type,0x00000000
+pngsuite/corrupt/xs7n0g01.png,32,32,1,unknown image type,0x00000000
+pngsuite/iphone/iphone_basi0g01.png,32,32,4,,0x5fb33cfd
+pngsuite/iphone/iphone_basi0g02.png,32,32,4,,0x5bbe95c5
+pngsuite/iphone/iphone_basi3p02.png,32,32,4,,0x50ba29c5
+pngsuite/iphone/iphone_bgwn6a08.png,32,32,4,,0x45d8548a
+pngsuite/iphone/iphone_bgyn6a16.png,32,32,4,,0x4b2b7545
+pngsuite/iphone/iphone_tbyn3p08.png,32,32,4,,0x8ea9aaaf
+pngsuite/iphone/iphone_z06n2c08.png,32,32,4,,0xb5dd034b
+pngsuite/primary/basi0g01.png,32,32,1,,0x43b9891f
+pngsuite/primary/basi0g02.png,32,32,1,,0xaf0bb3c5
+pngsuite/primary/basi0g04.png,32,32,1,,0x6fbaeb45
+pngsuite/primary/basi0g08.png,32,32,1,,0x414f1ca9
+pngsuite/primary/basi2c08.png,32,32,3,,0x522345c5
+pngsuite/primary/basi3p01.png,32,32,3,,0x9c5b75c5
+pngsuite/primary/basi3p02.png,32,32,3,,0x46f26ec5
+pngsuite/primary/basi3p04.png,32,32,3,,0x35b2e4a5
+pngsuite/primary/basi3p08.png,32,32,3,,0xfe066865
+pngsuite/primary/basi4a08.png,32,32,2,,0x77cbbfa5
+pngsuite/primary/basi6a08.png,32,32,4,,0xb472197d
+pngsuite/primary/basn0g01.png,32,32,1,,0x43b9891f
+pngsuite/primary/basn0g02.png,32,32,1,,0xaf0bb3c5
+pngsuite/primary/basn0g04.png,32,32,1,,0x6fbaeb45
+pngsuite/primary/basn0g08.png,32,32,1,,0x414f1ca9
+pngsuite/primary/basn2c08.png,32,32,3,,0x522345c5
+pngsuite/primary/basn3p01.png,32,32,3,,0x9c5b75c5
+pngsuite/primary/basn3p02.png,32,32,3,,0x46f26ec5
+pngsuite/primary/basn3p04.png,32,32,3,,0x35b2e4a5
+pngsuite/primary/basn3p08.png,32,32,3,,0xfe066865
+pngsuite/primary/basn4a08.png,32,32,2,,0x77cbbfa5
+pngsuite/primary/basn6a08.png,32,32,4,,0xb472197d
+pngsuite/primary/bgai4a08.png,32,32,2,,0x77cbbfa5
+pngsuite/primary/bgan6a08.png,32,32,4,,0xb472197d
+pngsuite/primary/bgbn4a08.png,32,32,2,,0x77cbbfa5
+pngsuite/primary/bgwn6a08.png,32,32,4,,0xb472197d
+pngsuite/primary/s01i3p01.png,1,1,3,,0xafb003b6
+pngsuite/primary/s01n3p01.png,1,1,3,,0xafb003b6
+pngsuite/primary/s02i3p01.png,2,2,3,,0x96f3dd85
+pngsuite/primary/s02n3p01.png,2,2,3,,0x96f3dd85
+pngsuite/primary/s03i3p01.png,3,3,3,,0xb0cf1241
+pngsuite/primary/s03n3p01.png,3,3,3,,0xb0cf1241
+pngsuite/primary/s04i3p01.png,4,4,3,,0xbfcedd75
+pngsuite/primary/s04n3p01.png,4,4,3,,0xbfcedd75
+pngsuite/primary/s05i3p02.png,5,5,3,,0xc322cedd
+pngsuite/primary/s05n3p02.png,5,5,3,,0xc322cedd
+pngsuite/primary/s06i3p02.png,6,6,3,,0x46916799
+pngsuite/primary/s06n3p02.png,6,6,3,,0x46916799
+pngsuite/primary/s07i3p02.png,7,7,3,,0xfdabc297
+pngsuite/primary/s07n3p02.png,7,7,3,,0xfdabc297
+pngsuite/primary/s08i3p02.png,8,8,3,,0x8f036d09
+pngsuite/primary/s08n3p02.png,8,8,3,,0x8f036d09
+pngsuite/primary/s09i3p02.png,9,9,3,,0x16a46830
+pngsuite/primary/s09n3p02.png,9,9,3,,0x16a46830
+pngsuite/primary/s32i3p04.png,32,32,3,,0x4bd4fbd3
+pngsuite/primary/s32n3p04.png,32,32,3,,0x4bd4fbd3
+pngsuite/primary/s33i3p04.png,33,33,3,,0x51aa005e
+pngsuite/primary/s33n3p04.png,33,33,3,,0x51aa005e
+pngsuite/primary/s34i3p04.png,34,34,3,,0x84818775
+pngsuite/primary/s34n3p04.png,34,34,3,,0x84818775
+pngsuite/primary/s35i3p04.png,35,35,3,,0x6359ec75
+pngsuite/primary/s35n3p04.png,35,35,3,,0x6359ec75
+pngsuite/primary/s36i3p04.png,36,36,3,,0xe4878065
+pngsuite/primary/s36n3p04.png,36,36,3,,0xe4878065
+pngsuite/primary/s37i3p04.png,37,37,3,,0x3cefc423
+pngsuite/primary/s37n3p04.png,37,37,3,,0x3cefc423
+pngsuite/primary/s38i3p04.png,38,38,3,,0xffc55a2b
+pngsuite/primary/s38n3p04.png,38,38,3,,0xffc55a2b
+pngsuite/primary/s39i3p04.png,39,39,3,,0x0c790240
+pngsuite/primary/s39n3p04.png,39,39,3,,0x0c790240
+pngsuite/primary/s40i3p04.png,40,40,3,,0x951a316d
+pngsuite/primary/s40n3p04.png,40,40,3,,0x951a316d
+pngsuite/primary/tbbn0g04.png,32,32,2,,0x9c8410ea
+pngsuite/primary/tbbn3p08.png,32,32,4,,0x82bf9a57
+pngsuite/primary/tbgn3p08.png,32,32,4,,0x82bf9a57
+pngsuite/primary/tbrn2c08.png,32,32,4,,0xaa9bfe44
+pngsuite/primary/tbwn3p08.png,32,32,4,,0x82bf9a57
+pngsuite/primary/tbyn3p08.png,32,32,4,,0x82bf9a57
+pngsuite/primary/tm3n3p02.png,32,32,4,,0xf59745c5
+pngsuite/primary/tp0n0g08.png,32,32,1,,0xbac0864c
+pngsuite/primary/tp0n2c08.png,32,32,3,,0x82687c37
+pngsuite/primary/tp0n3p08.png,32,32,3,,0x61f54e37
+pngsuite/primary/tp1n3p08.png,32,32,4,,0x82bf9a57
+pngsuite/primary/z00n2c08.png,32,32,3,,0x65b4a72f
+pngsuite/primary/z03n2c08.png,32,32,3,,0x65b4a72f
+pngsuite/primary/z06n2c08.png,32,32,3,,0x65b4a72f
+pngsuite/primary/z09n2c08.png,32,32,3,,0x65b4a72f
+pngsuite/primary_check/basi0g01.png,32,32,4,,0x5fb33cfd
+pngsuite/primary_check/basi0g02.png,32,32,4,,0x5bbe95c5
+pngsuite/primary_check/basi0g04.png,32,32,4,,0x3468b9c5
+pngsuite/primary_check/basi0g08.png,32,32,4,,0x262ef46d
+pngsuite/primary_check/basi2c08.png,32,32,4,,0x1fc92bc5
+pngsuite/primary_check/basi3p01.png,32,32,4,,0x28a3e1c5
+pngsuite/primary_check/basi3p02.png,32,32,4,,0x803be5c5
+pngsuite/primary_check/basi3p04.png,32,32,4,,0xf3fc60e5
+pngsuite/primary_check/basi3p08.png,32,32,4,,0x30ef4f45
+pngsuite/primary_check/basi4a08.png,32,32,4,,0x23c8536d
+pngsuite/primary_check/basi6a08.png,32,32,4,,0xb472197d
+pngsuite/primary_check/basn0g01.png,32,32,4,,0x5fb33cfd
+pngsuite/primary_check/basn0g02.png,32,32,4,,0x5bbe95c5
+pngsuite/primary_check/basn0g04.png,32,32,4,,0x3468b9c5
+pngsuite/primary_check/basn0g08.png,32,32,4,,0x262ef46d
+pngsuite/primary_check/basn2c08.png,32,32,4,,0x1fc92bc5
+pngsuite/primary_check/basn3p01.png,32,32,4,,0x28a3e1c5
+pngsuite/primary_check/basn3p02.png,32,32,4,,0x803be5c5
+pngsuite/primary_check/basn3p04.png,32,32,4,,0xf3fc60e5
+pngsuite/primary_check/basn3p08.png,32,32,4,,0x30ef4f45
+pngsuite/primary_check/basn4a08.png,32,32,4,,0x23c8536d
+pngsuite/primary_check/basn6a08.png,32,32,4,,0xb472197d
+pngsuite/primary_check/bgai4a08.png,32,32,4,,0x23c8536d
+pngsuite/primary_check/bgan6a08.png,32,32,4,,0xb472197d
+pngsuite/primary_check/bgbn4a08.png,32,32,4,,0x23c8536d
+pngsuite/primary_check/bgwn6a08.png,32,32,4,,0xb472197d
+pngsuite/primary_check/s01i3p01.png,1,1,4,,0xdb152beb
+pngsuite/primary_check/s01n3p01.png,1,1,4,,0xdb152beb
+pngsuite/primary_check/s02i3p01.png,2,2,4,,0xa344a3a5
+pngsuite/primary_check/s02n3p01.png,2,2,4,,0xa344a3a5
+pngsuite/primary_check/s03i3p01.png,3,3,4,,0x594d3bfa
+pngsuite/primary_check/s03n3p01.png,3,3,4,,0x594d3bfa
+pngsuite/primary_check/s04i3p01.png,4,4,4,,0xd59d4605
+pngsuite/primary_check/s04n3p01.png,4,4,4,,0xd59d4605
+pngsuite/primary_check/s05i3p02.png,5,5,4,,0x41e58366
+pngsuite/primary_check/s05n3p02.png,5,5,4,,0x41e58366
+pngsuite/primary_check/s06i3p02.png,6,6,4,,0xcad1a885
+pngsuite/primary_check/s06n3p02.png,6,6,4,,0xcad1a885
+pngsuite/primary_check/s07i3p02.png,7,7,4,,0x09184108
+pngsuite/primary_check/s07n3p02.png,7,7,4,,0x09184108
+pngsuite/primary_check/s08i3p02.png,8,8,4,,0x4fd11cad
+pngsuite/primary_check/s08n3p02.png,8,8,4,,0x4fd11cad
+pngsuite/primary_check/s09i3p02.png,9,9,4,,0xc50dbecd
+pngsuite/primary_check/s09n3p02.png,9,9,4,,0xc50dbecd
+pngsuite/primary_check/s32i3p04.png,32,32,4,,0x95cbb1d3
+pngsuite/primary_check/s32n3p04.png,32,32,4,,0x95cbb1d3
+pngsuite/primary_check/s33i3p04.png,33,33,4,,0x6649fc5b
+pngsuite/primary_check/s33n3p04.png,33,33,4,,0x6649fc5b
+pngsuite/primary_check/s34i3p04.png,34,34,4,,0x35b98e15
+pngsuite/primary_check/s34n3p04.png,34,34,4,,0x35b98e15
+pngsuite/primary_check/s35i3p04.png,35,35,4,,0xc9ddf938
+pngsuite/primary_check/s35n3p04.png,35,35,4,,0xc9ddf938
+pngsuite/primary_check/s36i3p04.png,36,36,4,,0x7bb4e1cd
+pngsuite/primary_check/s36n3p04.png,36,36,4,,0x7bb4e1cd
+pngsuite/primary_check/s37i3p04.png,37,37,4,,0xee50001c
+pngsuite/primary_check/s37n3p04.png,37,37,4,,0xee50001c
+pngsuite/primary_check/s38i3p04.png,38,38,4,,0x51b76813
+pngsuite/primary_check/s38n3p04.png,38,38,4,,0x51b76813
+pngsuite/primary_check/s39i3p04.png,39,39,4,,0x42f23327
+pngsuite/primary_check/s39n3p04.png,39,39,4,,0x42f23327
+pngsuite/primary_check/s40i3p04.png,40,40,4,,0xf91b6a7d
+pngsuite/primary_check/s40n3p04.png,40,40,4,,0xf91b6a7d
+pngsuite/primary_check/tbbn0g04.png,32,32,4,,0x8a0117a4
+pngsuite/primary_check/tbbn3p08.png,32,32,4,,0x82bf9a57
+pngsuite/primary_check/tbgn3p08.png,32,32,4,,0x82bf9a57
+pngsuite/primary_check/tbrn2c08.png,32,32,4,,0xaa9bfe44
+pngsuite/primary_check/tbwn3p08.png,32,32,4,,0x82bf9a57
+pngsuite/primary_check/tbyn3p08.png,32,32,4,,0x82bf9a57
+pngsuite/primary_check/tm3n3p02.png,32,32,4,,0xf59745c5
+pngsuite/primary_check/tp0n0g08.png,32,32,4,,0xd405ad2e
+pngsuite/primary_check/tp0n2c08.png,32,32,4,,0x5a66ca09
+pngsuite/primary_check/tp0n3p08.png,32,32,4,,0x06e81adf
+pngsuite/primary_check/tp1n3p08.png,32,32,4,,0x82bf9a57
+pngsuite/primary_check/z00n2c08.png,32,32,4,,0xaa698493
+pngsuite/primary_check/z03n2c08.png,32,32,4,,0xaa698493
+pngsuite/primary_check/z06n2c08.png,32,32,4,,0xaa698493
+pngsuite/primary_check/z09n2c08.png,32,32,4,,0xaa698493
+pngsuite/unused/ccwn2c08.png,32,32,3,,0xbb576418
+pngsuite/unused/ccwn3p08.png,32,32,3,,0x5c4df060
+pngsuite/unused/cdfn2c08.png,8,32,3,,0xe30ed48f
+pngsuite/unused/cdhn2c08.png,32,8,3,,0x999321f5
+pngsuite/unused/cdsn2c08.png,8,8,3,,0x7f63fa01
+pngsuite/unused/cdun2c08.png,32,32,3,,0xbd325d71
+pngsuite/unused/ch1n3p04.png,32,32,3,,0x35b2e4a5
+pngsuite/unused/ch2n3p08.png,32,32,3,,0xfe066865
+pngsuite/unused/cm0n0g04.png,32,32,1,,0xe9f53e6c
+pngsuite/unused/cm7n0g04.png,32,32,1,,0xe9f53e6c
+pngsuite/unused/cm9n0g04.png,32,32,1,,0xe9f53e6c
+pngsuite/unused/cs3n2c16.png,32,32,3,,0x7f0fa2c5
+pngsuite/unused/cs3n3p08.png,32,32,3,,0x5533bac5
+pngsuite/unused/cs5n2c08.png,32,32,3,,0x8a80f8c5
+pngsuite/unused/cs5n3p08.png,32,32,3,,0x8a80f8c5
+pngsuite/unused/cs8n2c08.png,32,32,3,,0x7f0fa2c5
+pngsuite/unused/cs8n3p08.png,32,32,3,,0x7f0fa2c5
+pngsuite/unused/ct0n0g04.png,32,32,1,,0xe9f53e6c
+pngsuite/unused/ct1n0g04.png,32,32,1,,0xe9f53e6c
+pngsuite/unused/cten0g04.png,32,32,1,,0x1c073b45
+pngsuite/unused/ctfn0g04.png,32,32,1,,0xfa9fd205
+pngsuite/unused/ctgn0g04.png,32,32,1,,0xf28c8085
+pngsuite/unused/cthn0g04.png,32,32,1,,0x7c039595
+pngsuite/unused/ctjn0g04.png,32,32,1,,0xc520f455
+pngsuite/unused/ctzn0g04.png,32,32,1,,0xe9f53e6c
+pngsuite/unused/f00n0g08.png,32,32,1,,0x21db411b
+pngsuite/unused/f00n2c08.png,32,32,3,,0x1f25ded0
+pngsuite/unused/f01n0g08.png,32,32,1,,0x7437b32a
+pngsuite/unused/f01n2c08.png,32,32,3,,0x0d4507ae
+pngsuite/unused/f02n0g08.png,32,32,1,,0x6b633c7c
+pngsuite/unused/f02n2c08.png,32,32,3,,0x4b278986
+pngsuite/unused/f03n0g08.png,32,32,1,,0x2f31c08e
+pngsuite/unused/f03n2c08.png,32,32,3,,0x843ecc7e
+pngsuite/unused/f04n0g08.png,32,32,1,,0xfd3a0b73
+pngsuite/unused/f04n2c08.png,32,32,3,,0x557174bc
+pngsuite/unused/f99n0g04.png,32,32,1,,0xb79aa6e1
+pngsuite/unused/g03n0g16.png,32,32,1,,0xecd13817
+pngsuite/unused/g03n2c08.png,32,32,3,,0x242407a8
+pngsuite/unused/g03n3p04.png,32,32,3,,0xe801ecc8
+pngsuite/unused/g04n0g16.png,32,32,1,,0xc11bc972
+pngsuite/unused/g04n2c08.png,32,32,3,,0xdf843cc4
+pngsuite/unused/g04n3p04.png,32,32,3,,0x60e41f3b
+pngsuite/unused/g05n0g16.png,32,32,1,,0xbe6615a5
+pngsuite/unused/g05n2c08.png,32,32,3,,0x5c312116
+pngsuite/unused/g05n3p04.png,32,32,3,,0x2e0fbf86
+pngsuite/unused/g07n0g16.png,32,32,1,,0x2b54a398
+pngsuite/unused/g07n2c08.png,32,32,3,,0xf765fb10
+pngsuite/unused/g07n3p04.png,32,32,3,,0x9a8c3338
+pngsuite/unused/g10n0g16.png,32,32,1,,0xb08a92e1
+pngsuite/unused/g10n2c08.png,32,32,3,,0xa43f2291
+pngsuite/unused/g10n3p04.png,32,32,3,,0xb733194c
+pngsuite/unused/g25n0g16.png,32,32,1,,0xa6b1f5dd
+pngsuite/unused/g25n2c08.png,32,32,3,,0x767aee0c
+pngsuite/unused/g25n3p04.png,32,32,3,,0x4cf349a8
+pngsuite/unused/pp0n2c16.png,32,32,3,,0x65567ed5
+pngsuite/unused/pp0n6a08.png,32,32,4,,0x3188c645
+pngsuite/unused/ps1n0g08.png,32,32,1,,0x414f1ca9
+pngsuite/unused/ps1n2c16.png,32,32,3,,0x65567ed5
+pngsuite/unused/ps2n0g08.png,32,32,1,,0x414f1ca9
+pngsuite/unused/ps2n2c16.png,32,32,3,,0x65567ed5

+ 75 - 0
tests/test_png_regress.c

@@ -0,0 +1,75 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#define STBI_WINDOWS_UTF8
+
+#ifdef _WIN32
+#define WIN32 // what stb.h checks
+#pragma comment(lib, "advapi32.lib")
+#endif
+
+#define STB_IMAGE_IMPLEMENTATION
+#include "stb_image.h"
+
+#define STB_DEFINE
+#include "deprecated/stb.h"
+
+static unsigned int fnv1a_hash32(const stbi_uc *bytes, size_t len)
+{
+   unsigned int hash = 0x811c9dc5;
+   unsigned int mul = 0x01000193;
+   size_t i;
+
+   for (i = 0; i < len; ++i)
+      hash = (hash ^ bytes[i]) * mul;
+
+   return hash;
+}
+
+// The idea for this test is to leave pngsuite/ref_results.csv checked in,
+// and then you can run this test after making PNG loader changes. If the
+// ref results change (as per git diff), confirm that the change was
+// intentional. If so, commit them as well; if not, undo.
+int main()
+{
+   char **files;
+   FILE *csv_file;
+   int i;
+
+   files = stb_readdir_recursive("pngsuite", "*.png");
+   if (!files) {
+      fprintf(stderr, "pngsuite files not found!\n");
+      return 1;
+   }
+
+   // sort files by name
+   qsort(files, stb_arr_len(files), sizeof(char*), stb_qsort_strcmp(0));
+
+   csv_file = fopen("pngsuite/ref_results.csv", "w");
+   if (!csv_file) {
+      fprintf(stderr, "error opening ref results for writing!\n");
+      stb_readdir_free(files);
+      return 1;
+   }
+
+   fprintf(csv_file, "filename,width,height,ncomp,error,hash\n");
+   for (i = 0; i < stb_arr_len(files); ++i) {
+      char *filename = files[i];
+      int width, height, ncomp;
+      stbi_uc *pixels = stbi_load(filename, &width, &height, &ncomp, 0);
+      const char *error = "";
+      unsigned int hash = 0;
+
+      if (!pixels)
+         error = stbi_failure_reason();
+      else {
+         hash = fnv1a_hash32(pixels, width * height * ncomp);
+         stbi_image_free(pixels);
+      }
+
+      fprintf(csv_file, "%s,%d,%d,%d,%s,0x%08x\n", filename, width, height, ncomp, error, hash);
+   }
+
+   fclose(csv_file);
+   stb_readdir_free(files);
+}