From ed643334103597cb7234f088e377ffc5bd8b3b47 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Mon, 1 May 2023 22:47:45 -0700 Subject: [PATCH] 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. --- tests/pngsuite/ref_results.csv | 259 +++++++++++++++++++++++++++++++++ tests/test_png_regress.c | 75 ++++++++++ 2 files changed, 334 insertions(+) create mode 100644 tests/pngsuite/ref_results.csv create mode 100644 tests/test_png_regress.c diff --git a/tests/pngsuite/ref_results.csv b/tests/pngsuite/ref_results.csv new file mode 100644 index 0000000..74dc2e6 --- /dev/null +++ b/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 diff --git a/tests/test_png_regress.c b/tests/test_png_regress.c new file mode 100644 index 0000000..5ba6796 --- /dev/null +++ b/tests/test_png_regress.c @@ -0,0 +1,75 @@ +#include +#include + +#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); +}