diff --git a/Cargo.toml b/Cargo.toml index a03073eddf..fad0a4fe50 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,6 +72,8 @@ quickcheck = "1" criterion = "0.5.0" libtest-mimic = "0.8.1" walkdir = "2.5.0" +oxipng = { version = "10.1.0", default-features = false, features = ["parallel", "zopfli"] } +toml = "1.0.3" [features] default = ["rayon", "default-formats"] diff --git a/tests/hashes.toml b/tests/hashes.toml new file mode 100644 index 0000000000..219ddfb4ef --- /dev/null +++ b/tests/hashes.toml @@ -0,0 +1,223 @@ +"bmp/images/Core_1_Bit.bmp" = "a38b54e9" +"bmp/images/Core_4_Bit.bmp" = "b8054352" +"bmp/images/Core_8_Bit.bmp" = "4d23f82" +"bmp/images/Info_1_Bit.bmp" = "e17c1696" +"bmp/images/Info_1_Bit_Top_Down.bmp" = "e17c1696" +"bmp/images/Info_4_Bit.bmp" = "58b65b8d" +"bmp/images/Info_4_Bit_Top_Down.bmp" = "58b65b8d" +"bmp/images/Info_8_Bit.bmp" = "58b65b8d" +"bmp/images/Info_8_Bit_Top_Down.bmp" = "58b65b8d" +"bmp/images/Info_A8_R8_G8_B8.bmp" = "58b65b8d" +"bmp/images/Info_A8_R8_G8_B8_Top_Down.bmp" = "58b65b8d" +"bmp/images/Info_R8_G8_B8.bmp" = "58b65b8d" +"bmp/images/Info_R8_G8_B8_Top_Down.bmp" = "58b65b8d" +"bmp/images/Info_X1_R5_G5_B5.bmp" = "58b65b8d" +"bmp/images/Info_X1_R5_G5_B5_Top_Down.bmp" = "58b65b8d" +"bmp/images/V3_A1_R5_G5_B5.bmp" = "dcd94d7c" +"bmp/images/V3_A1_R5_G5_B5_Top_Down.bmp" = "dcd94d7c" +"bmp/images/V3_A4_R4_G4_B4.bmp" = "dcd94d7c" +"bmp/images/V3_A4_R4_G4_B4_Top_Down.bmp" = "dcd94d7c" +"bmp/images/V3_R5_G6_B5.bmp" = "58b65b8d" +"bmp/images/V3_R5_G6_B5_Top_Down.bmp" = "58b65b8d" +"bmp/images/V3_X4_R4_G4_B4.bmp" = "58b65b8d" +"bmp/images/V3_X4_R4_G4_B4_Top_Down.bmp" = "58b65b8d" +"bmp/images/V3_X8_R8_G8_B8.bmp" = "58b65b8d" +"bmp/images/V3_X8_R8_G8_B8_Top_Down.bmp" = "58b65b8d" +"bmp/images/V4_24_Bit.bmp" = "4210721a" +"bmp/images/V4_A8_R8_G8_B8.bmp" = "ee3c0d72" +"bmp/images/V4_R5_G6_B5.bmp" = "8a9ba1e" +"bmp/images/V5_24_Bit.bmp" = "4210721a" +"bmp/images/V5_A1_R5_G5_B5.bmp" = "c1945420" +"bmp/images/imagemagick_invalid_run_length_issue_2321.bmp" = "97349b40" +"bmp/images/lenient/badpalettesize.bmp" = "38454155" +"bmp/images/lenient/badplanes.bmp" = "3ce81fae" +"bmp/images/lenient/pal8oversizepal.bmp" = "38454155" +"bmp/images/lenient/rgb16-880.bmp" = "f1c20c73" +"bmp/images/lenient/rletopdown.bmp" = "38454155" +"bmp/images/pal2.bmp" = "da27594" +"bmp/images/pal2color.bmp" = "f0d8c5d6" +"bmp/images/pal4rle.bmp" = "288e4371" +"bmp/images/pal4rlecut.bmp" = "473fbc7d" +"bmp/images/pal4rletrns.bmp" = "eed4e744" +"bmp/images/pal8badindex.bmp" = "4500d02" +"bmp/images/pal8os2-hs.bmp" = "38454155" +"bmp/images/pal8os2-sz.bmp" = "38454155" +"bmp/images/pal8os2sp.bmp" = "38454155" +"bmp/images/pal8rle.bmp" = "38454155" +"bmp/images/pal8v4.bmp" = "38454155" +"bmp/images/pal8v5.bmp" = "38454155" +"bmp/images/rgb16-231.bmp" = "3e2d81cf" +"bmp/images/rgb16-565.bmp" = "80839b35" +"bmp/images/rgb16.bmp" = "46dd68ad" +"bmp/images/rgb24.bmp" = "25bba0a" +"bmp/images/rgb24prof.bmp" = "25bba0a" +"bmp/images/rgb24prof2.bmp" = "cbef96a5" +"bmp/images/rgb24rle24.bmp" = "38454155" +"bmp/images/rgb32-111110.bmp" = "5d640669" +"bmp/images/rgb32.bmp" = "25bba0a" +"bmp/images/rgb32bf.bmp" = "25bba0a" +"bmp/images/rgba16-1924.bmp" = "8e9a585c" +"bmp/images/rgba32-61754.bmp" = "462df9cd" +"bmp/images/rgba32.bmp" = "e041b498" +"bmp/images/rgba32abf.bmp" = "e041b498" +"exr/cropping - data window differs display window.exr" = "cd2c1859" +"exr/cropping - uncropped original.exr" = "cd2c1859" +"exr/overexposed gradient - data window equals display window.exr" = "e96b6b86" +"exr/overexposed gradient.hdr" = "68886b3" +"farbfeld/transparency/acid2.ff" = "f9137306" +"farbfeld/transparency/tbbn0g04.ff" = "d5e59b7a" +"farbfeld/transparency/tbbn3p08.ff" = "a5312e47" +"farbfeld/transparency/tbgn3p08.ff" = "a5312e47" +"farbfeld/transparency/tbrn2c08.ff" = "96d7c541" +"farbfeld/transparency/tbwn3p08.ff" = "a5312e47" +"farbfeld/transparency/tbyn3p08.ff" = "a5312e47" +"farbfeld/transparency/tm3n3p02.ff" = "cc5790a7" +"farbfeld/transparency/tp0n0g08.ff" = "628aa052" +"farbfeld/transparency/tp0n2c08.ff" = "d538e05b" +"farbfeld/transparency/tp0n3p08.ff" = "b9303e4f" +"farbfeld/transparency/tp1n3p08.ff" = "a5312e47" +"gif/anim/any-disposal.gif" = "ace8cccc" +"gif/anim/any-disposal.gif.01" = "ace8cccc" +"gif/anim/any-disposal.gif.02" = "bbea5b89" +"gif/anim/any-disposal.gif.03" = "434ba962" +"gif/anim/any-disposal.gif.04" = "3aab6d2b" +"gif/anim/any-disposal.gif.05" = "61214b59" +"gif/anim/border_touching_layers.gif" = "d3fd29b8" +"gif/anim/border_touching_layers.gif.01" = "d3fd29b8" +"gif/anim/border_touching_layers.gif.02" = "1d319f0e" +"gif/anim/interlaced.gif" = "ad3a4823" +"gif/anim/issue_1455_undersized.gif" = "78e9e0e9" +"gif/anim/issue_1455_undersized.gif.01" = "78e9e0e9" +"gif/anim/issue_1455_undersized.gif.02" = "f5d9a825" +"gif/anim/large-gif-anim-combine.gif" = "33ca873" +"gif/anim/large-gif-anim-combine.gif.01" = "33ca873" +"gif/anim/large-gif-anim-combine.gif.02" = "7b0fc4a4" +"gif/anim/large-gif-anim-full-frame-replace.gif" = "b2b6e438" +"gif/anim/large-gif-anim-full-frame-replace.gif.01" = "b2b6e438" +"gif/anim/large-gif-anim-full-frame-replace.gif.02" = "8129b05d" +"gif/anim/mixed-disposal.gif" = "ace8cccc" +"gif/anim/mixed-disposal.gif.01" = "ace8cccc" +"gif/anim/mixed-disposal.gif.02" = "bbea5b89" +"gif/anim/mixed-disposal.gif.03" = "decc7304" +"gif/anim/mixed-disposal.gif.04" = "14ae66bc" +"gif/anim/mixed-disposal.gif.05" = "ea912dbc" +"gif/anim/oob.gif" = "da695a00" +"gif/simple/alpha_gif_a.gif" = "e6c86941" +"gif/simple/issue_1455_oversized.gif" = "d3942570" +"gif/simple/sample_1.gif" = "c33b036b" +"hdr/images/image1.hdr" = "cd489dff" +"hdr/images/old-rle.hdr" = "34096238" +"hdr/images/rgbr4x4.hdr" = "cf021a95" +"hdr/images/scale.hdr" = "e79c5305" +"ico/images/bmp-24bpp-mask.ico" = "5c8eaf83" +"ico/images/bmp-32bpp-alpha.ico" = "5c8eaf83" +"ico/images/bmp_v5_with_icc.ico" = "b9cca945" +"ico/images/multiple_entries_with_different_bit_depth.ico" = "369021e9" +"ico/images/png-32bpp-alpha.ico" = "5c8eaf83" +"ico/images/smile.ico" = "291e3bb0" +"ico/images/two-entry-order-test.ico" = "b59f783a" +"jpg/exif-xmp-metadata.jpg" = "b6174a58" +"jpg/iptc.jpg" = "2b592a62" +"jpg/portrait_2.jpg" = "295c0394" +"jpg/progressive/3.jpg" = "56223be9" +"jpg/progressive/cat.jpg" = "3c4113c0" +"jpg/progressive/test.jpg" = "d86d3f63" +"pbm/images/issue-794.pbm" = "80cbc790" +"pbm/images/narrow.pbm" = "2ba1a727" +"png/16bpc/basi0g16.png" = "2ab15133" +"png/16bpc/basn2c16.png" = "8ec6de79" +"png/16bpc/basn6a16.png" = "87be531" +"png/apng/ball.png" = "1c840a9" +"png/apng/ball.png.01" = "1c840a9" +"png/apng/ball.png.02" = "a5cb4cc1" +"png/apng/ball.png.03" = "cc6d71d9" +"png/apng/ball.png.04" = "26897da3" +"png/apng/ball.png.05" = "123fe3c5" +"png/apng/ball.png.06" = "69c299ea" +"png/apng/ball.png.07" = "765d3648" +"png/apng/ball.png.08" = "e44a80f7" +"png/apng/ball.png.09" = "dd6883db" +"png/apng/ball.png.10" = "3b68b97b" +"png/apng/ball.png.11" = "c42e2a3f" +"png/apng/ball.png.12" = "796c12e" +"png/apng/ball.png.13" = "bf335902" +"png/apng/ball.png.14" = "ee765a97" +"png/apng/ball.png.15" = "56f89914" +"png/apng/ball.png.16" = "cd899432" +"png/apng/ball.png.17" = "c3b039a" +"png/apng/ball.png.18" = "611a8f5d" +"png/apng/ball.png.19" = "d7316ce1" +"png/apng/ball.png.20" = "1e8b755f" +"png/bugfixes/debug_triangle_corners_widescreen.png" = "50664ae3" +"png/bugfixes/issue#2026.png" = "d202ef8d" +"png/bugfixes/issue#403.png" = "b0818cef" +"png/interlaced/basi2c08.png" = "7855b9bf" +"png/iptc.png" = "fbb9084e" +"png/transparency/acid2.png" = "8de8ca3f" +"png/transparency/tbbn0g04.png" = "8d94cbac" +"png/transparency/tbbn3p08.png" = "9d56cd67" +"png/transparency/tbgn3p08.png" = "9d56cd67" +"png/transparency/tbrn2c08.png" = "370ef89" +"png/transparency/tbwn3p08.png" = "9d56cd67" +"png/transparency/tbyn3p08.png" = "9d56cd67" +"png/transparency/tm3n3p02.png" = "e7daa7f5" +"png/transparency/tp0n0g08.png" = "c3dda42e" +"png/transparency/tp0n2c08.png" = "b426b350" +"png/transparency/tp0n3p08.png" = "15493236" +"png/transparency/tp1n3p08.png" = "9d56cd67" +"png/transparency/tp1n3p08_xmp.png" = "9d56cd67" +"qoi/basic-test.qoi" = "ff1dc025" +"tga/encoding/black_white.tga" = "34c05f7f" +"tga/testsuite/b5-attrib.tga" = "283e5700" +"tga/testsuite/b5-cmap.tga" = "283e5700" +"tga/testsuite/b5-noattrib.tga" = "283e5700" +"tga/testsuite/b5-unused-cmap.tga" = "283e5700" +"tga/testsuite/bottom_left.tga" = "391a5b46" +"tga/testsuite/bottom_right.tga" = "a6b4aab1" +"tga/testsuite/cbw8.tga" = "3f8a9b3c" +"tga/testsuite/ccm8.tga" = "b7096b3" +"tga/testsuite/cmap_offset.tga" = "1ebb7ae9" +"tga/testsuite/ctc24.tga" = "b7096b3" +"tga/testsuite/top_left.tga" = "a7f3521c" +"tga/testsuite/top_right.tga" = "2519b547" +"tga/testsuite/ubw8.tga" = "3f8a9b3c" +"tga/testsuite/ucm8.tga" = "b7096b3" +"tga/testsuite/utc16.tga" = "b7096b3" +"tga/testsuite/utc24.tga" = "b7096b3" +"tga/testsuite/utc32.tga" = "134a83ba" +"tiff/testsuite/fax4.tiff" = "aba6a268" +"tiff/testsuite/hpredict.tiff" = "dc00a927" +"tiff/testsuite/hpredict_packbits.tiff" = "82ca6aa0" +"tiff/testsuite/l1.tiff" = "5079e13c" +"tiff/testsuite/l1_xmp.tiff" = "5079e13c" +"tiff/testsuite/mandrill.tiff" = "99549da9" +"tiff/testsuite/planar.tiff" = "dac8e568" +"tiff/testsuite/rgb-3c-16b.tiff" = "531c087a" +"tiff/testsuite/rgb32f_bw.tiff" = "f90a5776" +"tiff/testsuite/rgb32f_color.tiff" = "2d565c20" +"webp/extended_images/advertises_rgba_but_frames_are_rgb.webp" = "4dd87800" +"webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.01" = "4dd87800" +"webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.02" = "c48c6f8b" +"webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.03" = "b702a85f" +"webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.04" = "ef32efb8" +"webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.05" = "5176abe5" +"webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.06" = "2c0011ef" +"webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.07" = "e2c8fb51" +"webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.08" = "8ce389c4" +"webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.09" = "d461aee8" +"webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.10" = "9f86db3e" +"webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.11" = "f2e10a06" +"webp/extended_images/anim.webp" = "f595c678" +"webp/extended_images/anim.webp.01" = "f595c678" +"webp/extended_images/anim.webp.02" = "3cfd026e" +"webp/extended_images/anim.webp.03" = "5691a653" +"webp/extended_images/anim.webp.04" = "b3691330" +"webp/extended_images/anim.webp.05" = "94ecb933" +"webp/extended_images/anim.webp.06" = "8de2a84" +"webp/extended_images/lossy_alpha.webp" = "99fb5348" +"webp/lossless_images/2-color.webp" = "1c59922a" +"webp/lossless_images/multi-color.webp" = "aeee944f" +"webp/lossless_images/simple.webp" = "3d047de8" +"webp/lossless_images/simple_xmp.webp" = "3d047de8" +"webp/lossy_images/simple-gray.webp" = "a2524735" +"webp/lossy_images/simple-rgb.webp" = "adea0613" diff --git a/tests/reference/.gitignore b/tests/reference/.gitignore new file mode 100644 index 0000000000..59ed417b90 --- /dev/null +++ b/tests/reference/.gitignore @@ -0,0 +1 @@ +png/iptc.png.png diff --git a/tests/reference/bmp/images/Core_1_Bit.bmp.a38b54e9.png b/tests/reference/bmp/images/Core_1_Bit.bmp.png similarity index 100% rename from tests/reference/bmp/images/Core_1_Bit.bmp.a38b54e9.png rename to tests/reference/bmp/images/Core_1_Bit.bmp.png diff --git a/tests/reference/bmp/images/Core_4_Bit.bmp.b8054352.png b/tests/reference/bmp/images/Core_4_Bit.bmp.png similarity index 100% rename from tests/reference/bmp/images/Core_4_Bit.bmp.b8054352.png rename to tests/reference/bmp/images/Core_4_Bit.bmp.png diff --git a/tests/reference/bmp/images/Core_8_Bit.bmp.4d23f82.png b/tests/reference/bmp/images/Core_8_Bit.bmp.png similarity index 100% rename from tests/reference/bmp/images/Core_8_Bit.bmp.4d23f82.png rename to tests/reference/bmp/images/Core_8_Bit.bmp.png diff --git a/tests/reference/bmp/images/Info_1_Bit.bmp.e17c1696.png b/tests/reference/bmp/images/Info_1_Bit.bmp.png similarity index 100% rename from tests/reference/bmp/images/Info_1_Bit.bmp.e17c1696.png rename to tests/reference/bmp/images/Info_1_Bit.bmp.png diff --git a/tests/reference/bmp/images/Info_1_Bit_Top_Down.bmp.e17c1696.png b/tests/reference/bmp/images/Info_1_Bit_Top_Down.bmp.png similarity index 100% rename from tests/reference/bmp/images/Info_1_Bit_Top_Down.bmp.e17c1696.png rename to tests/reference/bmp/images/Info_1_Bit_Top_Down.bmp.png diff --git a/tests/reference/bmp/images/Info_4_Bit.bmp.58b65b8d.png b/tests/reference/bmp/images/Info_4_Bit.bmp.png similarity index 100% rename from tests/reference/bmp/images/Info_4_Bit.bmp.58b65b8d.png rename to tests/reference/bmp/images/Info_4_Bit.bmp.png diff --git a/tests/reference/bmp/images/Info_4_Bit_Top_Down.bmp.58b65b8d.png b/tests/reference/bmp/images/Info_4_Bit_Top_Down.bmp.png similarity index 100% rename from tests/reference/bmp/images/Info_4_Bit_Top_Down.bmp.58b65b8d.png rename to tests/reference/bmp/images/Info_4_Bit_Top_Down.bmp.png diff --git a/tests/reference/bmp/images/Info_8_Bit.bmp.58b65b8d.png b/tests/reference/bmp/images/Info_8_Bit.bmp.png similarity index 100% rename from tests/reference/bmp/images/Info_8_Bit.bmp.58b65b8d.png rename to tests/reference/bmp/images/Info_8_Bit.bmp.png diff --git a/tests/reference/bmp/images/Info_8_Bit_Top_Down.bmp.58b65b8d.png b/tests/reference/bmp/images/Info_8_Bit_Top_Down.bmp.png similarity index 100% rename from tests/reference/bmp/images/Info_8_Bit_Top_Down.bmp.58b65b8d.png rename to tests/reference/bmp/images/Info_8_Bit_Top_Down.bmp.png diff --git a/tests/reference/bmp/images/Info_A8_R8_G8_B8.bmp.58b65b8d.png b/tests/reference/bmp/images/Info_A8_R8_G8_B8.bmp.png similarity index 100% rename from tests/reference/bmp/images/Info_A8_R8_G8_B8.bmp.58b65b8d.png rename to tests/reference/bmp/images/Info_A8_R8_G8_B8.bmp.png diff --git a/tests/reference/bmp/images/Info_A8_R8_G8_B8_Top_Down.bmp.58b65b8d.png b/tests/reference/bmp/images/Info_A8_R8_G8_B8_Top_Down.bmp.png similarity index 100% rename from tests/reference/bmp/images/Info_A8_R8_G8_B8_Top_Down.bmp.58b65b8d.png rename to tests/reference/bmp/images/Info_A8_R8_G8_B8_Top_Down.bmp.png diff --git a/tests/reference/bmp/images/Info_R8_G8_B8.bmp.58b65b8d.png b/tests/reference/bmp/images/Info_R8_G8_B8.bmp.png similarity index 100% rename from tests/reference/bmp/images/Info_R8_G8_B8.bmp.58b65b8d.png rename to tests/reference/bmp/images/Info_R8_G8_B8.bmp.png diff --git a/tests/reference/bmp/images/Info_R8_G8_B8_Top_Down.bmp.58b65b8d.png b/tests/reference/bmp/images/Info_R8_G8_B8_Top_Down.bmp.png similarity index 100% rename from tests/reference/bmp/images/Info_R8_G8_B8_Top_Down.bmp.58b65b8d.png rename to tests/reference/bmp/images/Info_R8_G8_B8_Top_Down.bmp.png diff --git a/tests/reference/bmp/images/Info_X1_R5_G5_B5.bmp.58b65b8d.png b/tests/reference/bmp/images/Info_X1_R5_G5_B5.bmp.png similarity index 100% rename from tests/reference/bmp/images/Info_X1_R5_G5_B5.bmp.58b65b8d.png rename to tests/reference/bmp/images/Info_X1_R5_G5_B5.bmp.png diff --git a/tests/reference/bmp/images/Info_X1_R5_G5_B5_Top_Down.bmp.58b65b8d.png b/tests/reference/bmp/images/Info_X1_R5_G5_B5_Top_Down.bmp.png similarity index 100% rename from tests/reference/bmp/images/Info_X1_R5_G5_B5_Top_Down.bmp.58b65b8d.png rename to tests/reference/bmp/images/Info_X1_R5_G5_B5_Top_Down.bmp.png diff --git a/tests/reference/bmp/images/V3_A1_R5_G5_B5.bmp.dcd94d7c.png b/tests/reference/bmp/images/V3_A1_R5_G5_B5.bmp.png similarity index 100% rename from tests/reference/bmp/images/V3_A1_R5_G5_B5.bmp.dcd94d7c.png rename to tests/reference/bmp/images/V3_A1_R5_G5_B5.bmp.png diff --git a/tests/reference/bmp/images/V3_A1_R5_G5_B5_Top_Down.bmp.dcd94d7c.png b/tests/reference/bmp/images/V3_A1_R5_G5_B5_Top_Down.bmp.png similarity index 100% rename from tests/reference/bmp/images/V3_A1_R5_G5_B5_Top_Down.bmp.dcd94d7c.png rename to tests/reference/bmp/images/V3_A1_R5_G5_B5_Top_Down.bmp.png diff --git a/tests/reference/bmp/images/V3_A4_R4_G4_B4.bmp.dcd94d7c.png b/tests/reference/bmp/images/V3_A4_R4_G4_B4.bmp.png similarity index 100% rename from tests/reference/bmp/images/V3_A4_R4_G4_B4.bmp.dcd94d7c.png rename to tests/reference/bmp/images/V3_A4_R4_G4_B4.bmp.png diff --git a/tests/reference/bmp/images/V3_A4_R4_G4_B4_Top_Down.bmp.dcd94d7c.png b/tests/reference/bmp/images/V3_A4_R4_G4_B4_Top_Down.bmp.png similarity index 100% rename from tests/reference/bmp/images/V3_A4_R4_G4_B4_Top_Down.bmp.dcd94d7c.png rename to tests/reference/bmp/images/V3_A4_R4_G4_B4_Top_Down.bmp.png diff --git a/tests/reference/bmp/images/V3_R5_G6_B5.bmp.58b65b8d.png b/tests/reference/bmp/images/V3_R5_G6_B5.bmp.png similarity index 100% rename from tests/reference/bmp/images/V3_R5_G6_B5.bmp.58b65b8d.png rename to tests/reference/bmp/images/V3_R5_G6_B5.bmp.png diff --git a/tests/reference/bmp/images/V3_R5_G6_B5_Top_Down.bmp.58b65b8d.png b/tests/reference/bmp/images/V3_R5_G6_B5_Top_Down.bmp.png similarity index 100% rename from tests/reference/bmp/images/V3_R5_G6_B5_Top_Down.bmp.58b65b8d.png rename to tests/reference/bmp/images/V3_R5_G6_B5_Top_Down.bmp.png diff --git a/tests/reference/bmp/images/V3_X4_R4_G4_B4.bmp.58b65b8d.png b/tests/reference/bmp/images/V3_X4_R4_G4_B4.bmp.png similarity index 100% rename from tests/reference/bmp/images/V3_X4_R4_G4_B4.bmp.58b65b8d.png rename to tests/reference/bmp/images/V3_X4_R4_G4_B4.bmp.png diff --git a/tests/reference/bmp/images/V3_X4_R4_G4_B4_Top_Down.bmp.58b65b8d.png b/tests/reference/bmp/images/V3_X4_R4_G4_B4_Top_Down.bmp.png similarity index 100% rename from tests/reference/bmp/images/V3_X4_R4_G4_B4_Top_Down.bmp.58b65b8d.png rename to tests/reference/bmp/images/V3_X4_R4_G4_B4_Top_Down.bmp.png diff --git a/tests/reference/bmp/images/V3_X8_R8_G8_B8.bmp.58b65b8d.png b/tests/reference/bmp/images/V3_X8_R8_G8_B8.bmp.png similarity index 100% rename from tests/reference/bmp/images/V3_X8_R8_G8_B8.bmp.58b65b8d.png rename to tests/reference/bmp/images/V3_X8_R8_G8_B8.bmp.png diff --git a/tests/reference/bmp/images/V3_X8_R8_G8_B8_Top_Down.bmp.58b65b8d.png b/tests/reference/bmp/images/V3_X8_R8_G8_B8_Top_Down.bmp.png similarity index 100% rename from tests/reference/bmp/images/V3_X8_R8_G8_B8_Top_Down.bmp.58b65b8d.png rename to tests/reference/bmp/images/V3_X8_R8_G8_B8_Top_Down.bmp.png diff --git a/tests/reference/bmp/images/V4_24_Bit.bmp.4210721a.png b/tests/reference/bmp/images/V4_24_Bit.bmp.png similarity index 100% rename from tests/reference/bmp/images/V4_24_Bit.bmp.4210721a.png rename to tests/reference/bmp/images/V4_24_Bit.bmp.png diff --git a/tests/reference/bmp/images/V4_A8_R8_G8_B8.bmp.ee3c0d72.png b/tests/reference/bmp/images/V4_A8_R8_G8_B8.bmp.png similarity index 100% rename from tests/reference/bmp/images/V4_A8_R8_G8_B8.bmp.ee3c0d72.png rename to tests/reference/bmp/images/V4_A8_R8_G8_B8.bmp.png diff --git a/tests/reference/bmp/images/V4_R5_G6_B5.bmp.8a9ba1e.png b/tests/reference/bmp/images/V4_R5_G6_B5.bmp.png similarity index 100% rename from tests/reference/bmp/images/V4_R5_G6_B5.bmp.8a9ba1e.png rename to tests/reference/bmp/images/V4_R5_G6_B5.bmp.png diff --git a/tests/reference/bmp/images/V5_24_Bit.bmp.4210721a.png b/tests/reference/bmp/images/V5_24_Bit.bmp.png similarity index 100% rename from tests/reference/bmp/images/V5_24_Bit.bmp.4210721a.png rename to tests/reference/bmp/images/V5_24_Bit.bmp.png diff --git a/tests/reference/bmp/images/V5_A1_R5_G5_B5.bmp.c1945420.png b/tests/reference/bmp/images/V5_A1_R5_G5_B5.bmp.png similarity index 100% rename from tests/reference/bmp/images/V5_A1_R5_G5_B5.bmp.c1945420.png rename to tests/reference/bmp/images/V5_A1_R5_G5_B5.bmp.png diff --git a/tests/reference/bmp/images/imagemagick_invalid_run_length_issue_2321.bmp.png b/tests/reference/bmp/images/imagemagick_invalid_run_length_issue_2321.bmp.png new file mode 100644 index 0000000000..b3a2c683f0 Binary files /dev/null and b/tests/reference/bmp/images/imagemagick_invalid_run_length_issue_2321.bmp.png differ diff --git a/tests/reference/bmp/images/lenient/badpalettesize.bmp.png b/tests/reference/bmp/images/lenient/badpalettesize.bmp.png new file mode 100644 index 0000000000..e3c8c08f46 Binary files /dev/null and b/tests/reference/bmp/images/lenient/badpalettesize.bmp.png differ diff --git a/tests/reference/bmp/images/lenient/badplanes.bmp.png b/tests/reference/bmp/images/lenient/badplanes.bmp.png new file mode 100644 index 0000000000..72736aaf97 Binary files /dev/null and b/tests/reference/bmp/images/lenient/badplanes.bmp.png differ diff --git a/tests/reference/bmp/images/lenient/pal8oversizepal.bmp.png b/tests/reference/bmp/images/lenient/pal8oversizepal.bmp.png new file mode 100644 index 0000000000..e3c8c08f46 Binary files /dev/null and b/tests/reference/bmp/images/lenient/pal8oversizepal.bmp.png differ diff --git a/tests/reference/bmp/images/lenient/rgb16-880.bmp.png b/tests/reference/bmp/images/lenient/rgb16-880.bmp.png new file mode 100644 index 0000000000..e1481b398b Binary files /dev/null and b/tests/reference/bmp/images/lenient/rgb16-880.bmp.png differ diff --git a/tests/reference/bmp/images/lenient/rletopdown.bmp.png b/tests/reference/bmp/images/lenient/rletopdown.bmp.png new file mode 100644 index 0000000000..e3c8c08f46 Binary files /dev/null and b/tests/reference/bmp/images/lenient/rletopdown.bmp.png differ diff --git a/tests/reference/bmp/images/pal2.bmp.da27594.png b/tests/reference/bmp/images/pal2.bmp.png similarity index 100% rename from tests/reference/bmp/images/pal2.bmp.da27594.png rename to tests/reference/bmp/images/pal2.bmp.png diff --git a/tests/reference/bmp/images/pal2color.bmp.f0d8c5d6.png b/tests/reference/bmp/images/pal2color.bmp.png similarity index 100% rename from tests/reference/bmp/images/pal2color.bmp.f0d8c5d6.png rename to tests/reference/bmp/images/pal2color.bmp.png diff --git a/tests/reference/bmp/images/pal4rle.bmp.288e4371.png b/tests/reference/bmp/images/pal4rle.bmp.png similarity index 100% rename from tests/reference/bmp/images/pal4rle.bmp.288e4371.png rename to tests/reference/bmp/images/pal4rle.bmp.png diff --git a/tests/reference/bmp/images/pal4rlecut.bmp.473fbc7d.png b/tests/reference/bmp/images/pal4rlecut.bmp.png similarity index 100% rename from tests/reference/bmp/images/pal4rlecut.bmp.473fbc7d.png rename to tests/reference/bmp/images/pal4rlecut.bmp.png diff --git a/tests/reference/bmp/images/pal4rletrns.bmp.eed4e744.png b/tests/reference/bmp/images/pal4rletrns.bmp.png similarity index 100% rename from tests/reference/bmp/images/pal4rletrns.bmp.eed4e744.png rename to tests/reference/bmp/images/pal4rletrns.bmp.png diff --git a/tests/reference/bmp/images/pal8badindex.bmp.4500d02.png b/tests/reference/bmp/images/pal8badindex.bmp.png similarity index 100% rename from tests/reference/bmp/images/pal8badindex.bmp.4500d02.png rename to tests/reference/bmp/images/pal8badindex.bmp.png diff --git a/tests/reference/bmp/images/pal8os2-hs.bmp.38454155.png b/tests/reference/bmp/images/pal8os2-hs.bmp.png similarity index 100% rename from tests/reference/bmp/images/pal8os2-hs.bmp.38454155.png rename to tests/reference/bmp/images/pal8os2-hs.bmp.png diff --git a/tests/reference/bmp/images/pal8os2-sz.bmp.38454155.png b/tests/reference/bmp/images/pal8os2-sz.bmp.png similarity index 100% rename from tests/reference/bmp/images/pal8os2-sz.bmp.38454155.png rename to tests/reference/bmp/images/pal8os2-sz.bmp.png diff --git a/tests/reference/bmp/images/pal8os2sp.bmp.38454155.png b/tests/reference/bmp/images/pal8os2sp.bmp.png similarity index 100% rename from tests/reference/bmp/images/pal8os2sp.bmp.38454155.png rename to tests/reference/bmp/images/pal8os2sp.bmp.png diff --git a/tests/reference/bmp/images/pal8rle.bmp.38454155.png b/tests/reference/bmp/images/pal8rle.bmp.png similarity index 100% rename from tests/reference/bmp/images/pal8rle.bmp.38454155.png rename to tests/reference/bmp/images/pal8rle.bmp.png diff --git a/tests/reference/bmp/images/pal8v4.bmp.38454155.png b/tests/reference/bmp/images/pal8v4.bmp.png similarity index 100% rename from tests/reference/bmp/images/pal8v4.bmp.38454155.png rename to tests/reference/bmp/images/pal8v4.bmp.png diff --git a/tests/reference/bmp/images/pal8v5.bmp.38454155.png b/tests/reference/bmp/images/pal8v5.bmp.png similarity index 100% rename from tests/reference/bmp/images/pal8v5.bmp.38454155.png rename to tests/reference/bmp/images/pal8v5.bmp.png diff --git a/tests/reference/bmp/images/rgb16-231.bmp.3e2d81cf.png b/tests/reference/bmp/images/rgb16-231.bmp.png similarity index 100% rename from tests/reference/bmp/images/rgb16-231.bmp.3e2d81cf.png rename to tests/reference/bmp/images/rgb16-231.bmp.png diff --git a/tests/reference/bmp/images/rgb16-565.bmp.80839b35.png b/tests/reference/bmp/images/rgb16-565.bmp.png similarity index 100% rename from tests/reference/bmp/images/rgb16-565.bmp.80839b35.png rename to tests/reference/bmp/images/rgb16-565.bmp.png diff --git a/tests/reference/bmp/images/rgb16.bmp.46dd68ad.png b/tests/reference/bmp/images/rgb16.bmp.png similarity index 100% rename from tests/reference/bmp/images/rgb16.bmp.46dd68ad.png rename to tests/reference/bmp/images/rgb16.bmp.png diff --git a/tests/reference/bmp/images/rgb24.bmp.25bba0a.png b/tests/reference/bmp/images/rgb24.bmp.png similarity index 100% rename from tests/reference/bmp/images/rgb24.bmp.25bba0a.png rename to tests/reference/bmp/images/rgb24.bmp.png diff --git a/tests/reference/bmp/images/rgb24prof.bmp.25bba0a.png b/tests/reference/bmp/images/rgb24prof.bmp.png similarity index 100% rename from tests/reference/bmp/images/rgb24prof.bmp.25bba0a.png rename to tests/reference/bmp/images/rgb24prof.bmp.png diff --git a/tests/reference/bmp/images/rgb24prof2.bmp.cbef96a5.png b/tests/reference/bmp/images/rgb24prof2.bmp.png similarity index 100% rename from tests/reference/bmp/images/rgb24prof2.bmp.cbef96a5.png rename to tests/reference/bmp/images/rgb24prof2.bmp.png diff --git a/tests/reference/bmp/images/rgb24rle24.bmp.38454155.png b/tests/reference/bmp/images/rgb24rle24.bmp.png similarity index 100% rename from tests/reference/bmp/images/rgb24rle24.bmp.38454155.png rename to tests/reference/bmp/images/rgb24rle24.bmp.png diff --git a/tests/reference/bmp/images/rgb32-111110.bmp.5d640669.png b/tests/reference/bmp/images/rgb32-111110.bmp.png similarity index 100% rename from tests/reference/bmp/images/rgb32-111110.bmp.5d640669.png rename to tests/reference/bmp/images/rgb32-111110.bmp.png diff --git a/tests/reference/bmp/images/rgb32.bmp.25bba0a.png b/tests/reference/bmp/images/rgb32.bmp.png similarity index 100% rename from tests/reference/bmp/images/rgb32.bmp.25bba0a.png rename to tests/reference/bmp/images/rgb32.bmp.png diff --git a/tests/reference/bmp/images/rgb32bf.bmp.25bba0a.png b/tests/reference/bmp/images/rgb32bf.bmp.png similarity index 100% rename from tests/reference/bmp/images/rgb32bf.bmp.25bba0a.png rename to tests/reference/bmp/images/rgb32bf.bmp.png diff --git a/tests/reference/bmp/images/rgba16-1924.bmp.8e9a585c.png b/tests/reference/bmp/images/rgba16-1924.bmp.png similarity index 100% rename from tests/reference/bmp/images/rgba16-1924.bmp.8e9a585c.png rename to tests/reference/bmp/images/rgba16-1924.bmp.png diff --git a/tests/reference/bmp/images/rgba32-61754.bmp.462df9cd.png b/tests/reference/bmp/images/rgba32-61754.bmp.png similarity index 100% rename from tests/reference/bmp/images/rgba32-61754.bmp.462df9cd.png rename to tests/reference/bmp/images/rgba32-61754.bmp.png diff --git a/tests/reference/bmp/images/rgba32.bmp.e041b498.png b/tests/reference/bmp/images/rgba32.bmp.png similarity index 100% rename from tests/reference/bmp/images/rgba32.bmp.e041b498.png rename to tests/reference/bmp/images/rgba32.bmp.png diff --git a/tests/reference/bmp/images/rgba32abf.bmp.e041b498.png b/tests/reference/bmp/images/rgba32abf.bmp.png similarity index 100% rename from tests/reference/bmp/images/rgba32abf.bmp.e041b498.png rename to tests/reference/bmp/images/rgba32abf.bmp.png diff --git a/tests/reference/exr/cropping - data window differs display window.exr.tiff b/tests/reference/exr/cropping - data window differs display window.exr.tiff new file mode 100644 index 0000000000..d7ff479ce8 Binary files /dev/null and b/tests/reference/exr/cropping - data window differs display window.exr.tiff differ diff --git a/tests/reference/exr/cropping - uncropped original.exr.tiff b/tests/reference/exr/cropping - uncropped original.exr.tiff new file mode 100644 index 0000000000..d7ff479ce8 Binary files /dev/null and b/tests/reference/exr/cropping - uncropped original.exr.tiff differ diff --git a/tests/reference/exr/overexposed gradient - data window equals display window.exr.tiff b/tests/reference/exr/overexposed gradient - data window equals display window.exr.tiff new file mode 100644 index 0000000000..da684f0f0a Binary files /dev/null and b/tests/reference/exr/overexposed gradient - data window equals display window.exr.tiff differ diff --git a/tests/reference/exr/overexposed gradient.hdr.tiff b/tests/reference/exr/overexposed gradient.hdr.tiff new file mode 100644 index 0000000000..a9f9f57c24 Binary files /dev/null and b/tests/reference/exr/overexposed gradient.hdr.tiff differ diff --git a/tests/reference/farbfeld/transparency/acid2.ff.png b/tests/reference/farbfeld/transparency/acid2.ff.png new file mode 100644 index 0000000000..9841f130b6 Binary files /dev/null and b/tests/reference/farbfeld/transparency/acid2.ff.png differ diff --git a/tests/reference/farbfeld/transparency/tbbn0g04.ff.png b/tests/reference/farbfeld/transparency/tbbn0g04.ff.png new file mode 100644 index 0000000000..02d0dcaa9a Binary files /dev/null and b/tests/reference/farbfeld/transparency/tbbn0g04.ff.png differ diff --git a/tests/reference/farbfeld/transparency/tbbn3p08.ff.png b/tests/reference/farbfeld/transparency/tbbn3p08.ff.png new file mode 100644 index 0000000000..950636fc94 Binary files /dev/null and b/tests/reference/farbfeld/transparency/tbbn3p08.ff.png differ diff --git a/tests/reference/farbfeld/transparency/tbgn3p08.ff.png b/tests/reference/farbfeld/transparency/tbgn3p08.ff.png new file mode 100644 index 0000000000..950636fc94 Binary files /dev/null and b/tests/reference/farbfeld/transparency/tbgn3p08.ff.png differ diff --git a/tests/reference/farbfeld/transparency/tbrn2c08.ff.png b/tests/reference/farbfeld/transparency/tbrn2c08.ff.png new file mode 100644 index 0000000000..6aee6e280c Binary files /dev/null and b/tests/reference/farbfeld/transparency/tbrn2c08.ff.png differ diff --git a/tests/reference/farbfeld/transparency/tbwn3p08.ff.png b/tests/reference/farbfeld/transparency/tbwn3p08.ff.png new file mode 100644 index 0000000000..950636fc94 Binary files /dev/null and b/tests/reference/farbfeld/transparency/tbwn3p08.ff.png differ diff --git a/tests/reference/farbfeld/transparency/tbyn3p08.ff.png b/tests/reference/farbfeld/transparency/tbyn3p08.ff.png new file mode 100644 index 0000000000..950636fc94 Binary files /dev/null and b/tests/reference/farbfeld/transparency/tbyn3p08.ff.png differ diff --git a/tests/reference/farbfeld/transparency/tm3n3p02.ff.png b/tests/reference/farbfeld/transparency/tm3n3p02.ff.png new file mode 100644 index 0000000000..8a5930fc5d Binary files /dev/null and b/tests/reference/farbfeld/transparency/tm3n3p02.ff.png differ diff --git a/tests/reference/farbfeld/transparency/tp0n0g08.ff.png b/tests/reference/farbfeld/transparency/tp0n0g08.ff.png new file mode 100644 index 0000000000..1b60a47533 Binary files /dev/null and b/tests/reference/farbfeld/transparency/tp0n0g08.ff.png differ diff --git a/tests/reference/farbfeld/transparency/tp0n2c08.ff.png b/tests/reference/farbfeld/transparency/tp0n2c08.ff.png new file mode 100644 index 0000000000..cf42eeea8f Binary files /dev/null and b/tests/reference/farbfeld/transparency/tp0n2c08.ff.png differ diff --git a/tests/reference/farbfeld/transparency/tp0n3p08.ff.png b/tests/reference/farbfeld/transparency/tp0n3p08.ff.png new file mode 100644 index 0000000000..71ec8dc769 Binary files /dev/null and b/tests/reference/farbfeld/transparency/tp0n3p08.ff.png differ diff --git a/tests/reference/farbfeld/transparency/tp1n3p08.ff.png b/tests/reference/farbfeld/transparency/tp1n3p08.ff.png new file mode 100644 index 0000000000..950636fc94 Binary files /dev/null and b/tests/reference/farbfeld/transparency/tp1n3p08.ff.png differ diff --git a/tests/reference/gif/anim/any-disposal.gif.01.png b/tests/reference/gif/anim/any-disposal.gif.01.png new file mode 100644 index 0000000000..8588453aef Binary files /dev/null and b/tests/reference/gif/anim/any-disposal.gif.01.png differ diff --git a/tests/reference/gif/anim/any-disposal.gif.02.png b/tests/reference/gif/anim/any-disposal.gif.02.png new file mode 100644 index 0000000000..4021e6967c Binary files /dev/null and b/tests/reference/gif/anim/any-disposal.gif.02.png differ diff --git a/tests/reference/gif/anim/any-disposal.gif.03.png b/tests/reference/gif/anim/any-disposal.gif.03.png new file mode 100644 index 0000000000..c67d8fc6ac Binary files /dev/null and b/tests/reference/gif/anim/any-disposal.gif.03.png differ diff --git a/tests/reference/gif/anim/any-disposal.gif.04.png b/tests/reference/gif/anim/any-disposal.gif.04.png new file mode 100644 index 0000000000..5b38404094 Binary files /dev/null and b/tests/reference/gif/anim/any-disposal.gif.04.png differ diff --git a/tests/reference/gif/anim/any-disposal.gif.05.png b/tests/reference/gif/anim/any-disposal.gif.05.png new file mode 100644 index 0000000000..ecd1834007 Binary files /dev/null and b/tests/reference/gif/anim/any-disposal.gif.05.png differ diff --git a/tests/reference/gif/anim/any-disposal.gif.ace8cccc.png b/tests/reference/gif/anim/any-disposal.gif.png similarity index 100% rename from tests/reference/gif/anim/any-disposal.gif.ace8cccc.png rename to tests/reference/gif/anim/any-disposal.gif.png diff --git a/tests/reference/gif/anim/border_touching_layers.gif.01.png b/tests/reference/gif/anim/border_touching_layers.gif.01.png new file mode 100644 index 0000000000..6efbd8ecd8 Binary files /dev/null and b/tests/reference/gif/anim/border_touching_layers.gif.01.png differ diff --git a/tests/reference/gif/anim/border_touching_layers.gif.02.png b/tests/reference/gif/anim/border_touching_layers.gif.02.png new file mode 100644 index 0000000000..7c258b5189 Binary files /dev/null and b/tests/reference/gif/anim/border_touching_layers.gif.02.png differ diff --git a/tests/reference/gif/anim/border_touching_layers.gif.d3fd29b8.png b/tests/reference/gif/anim/border_touching_layers.gif.png similarity index 100% rename from tests/reference/gif/anim/border_touching_layers.gif.d3fd29b8.png rename to tests/reference/gif/anim/border_touching_layers.gif.png diff --git a/tests/reference/gif/anim/interlaced.gif.ad3a4823.png b/tests/reference/gif/anim/interlaced.gif.png similarity index 100% rename from tests/reference/gif/anim/interlaced.gif.ad3a4823.png rename to tests/reference/gif/anim/interlaced.gif.png diff --git a/tests/reference/gif/anim/issue_1455_undersized.gif.01.png b/tests/reference/gif/anim/issue_1455_undersized.gif.01.png new file mode 100644 index 0000000000..0e10a0b86e Binary files /dev/null and b/tests/reference/gif/anim/issue_1455_undersized.gif.01.png differ diff --git a/tests/reference/gif/anim/issue_1455_undersized.gif.02.png b/tests/reference/gif/anim/issue_1455_undersized.gif.02.png new file mode 100644 index 0000000000..be087a83a5 Binary files /dev/null and b/tests/reference/gif/anim/issue_1455_undersized.gif.02.png differ diff --git a/tests/reference/gif/anim/issue_1455_undersized.gif.78e9e0e9.png b/tests/reference/gif/anim/issue_1455_undersized.gif.png similarity index 100% rename from tests/reference/gif/anim/issue_1455_undersized.gif.78e9e0e9.png rename to tests/reference/gif/anim/issue_1455_undersized.gif.png diff --git a/tests/reference/gif/anim/large-gif-anim-combine.gif.01.png b/tests/reference/gif/anim/large-gif-anim-combine.gif.01.png new file mode 100644 index 0000000000..0e6bf8b3ea Binary files /dev/null and b/tests/reference/gif/anim/large-gif-anim-combine.gif.01.png differ diff --git a/tests/reference/gif/anim/large-gif-anim-combine.gif.02.png b/tests/reference/gif/anim/large-gif-anim-combine.gif.02.png new file mode 100644 index 0000000000..64a9233883 Binary files /dev/null and b/tests/reference/gif/anim/large-gif-anim-combine.gif.02.png differ diff --git a/tests/reference/gif/anim/large-gif-anim-combine.gif.png b/tests/reference/gif/anim/large-gif-anim-combine.gif.png new file mode 100644 index 0000000000..0e6bf8b3ea Binary files /dev/null and b/tests/reference/gif/anim/large-gif-anim-combine.gif.png differ diff --git a/tests/reference/gif/anim/large-gif-anim-full-frame-replace.gif.01.png b/tests/reference/gif/anim/large-gif-anim-full-frame-replace.gif.01.png new file mode 100644 index 0000000000..0c0030fdde Binary files /dev/null and b/tests/reference/gif/anim/large-gif-anim-full-frame-replace.gif.01.png differ diff --git a/tests/reference/gif/anim/large-gif-anim-full-frame-replace.gif.02.png b/tests/reference/gif/anim/large-gif-anim-full-frame-replace.gif.02.png new file mode 100644 index 0000000000..7eff762568 Binary files /dev/null and b/tests/reference/gif/anim/large-gif-anim-full-frame-replace.gif.02.png differ diff --git a/tests/reference/gif/anim/large-gif-anim-full-frame-replace.gif.png b/tests/reference/gif/anim/large-gif-anim-full-frame-replace.gif.png new file mode 100644 index 0000000000..0c0030fdde Binary files /dev/null and b/tests/reference/gif/anim/large-gif-anim-full-frame-replace.gif.png differ diff --git a/tests/reference/gif/anim/mixed-disposal.gif.01.png b/tests/reference/gif/anim/mixed-disposal.gif.01.png new file mode 100644 index 0000000000..8588453aef Binary files /dev/null and b/tests/reference/gif/anim/mixed-disposal.gif.01.png differ diff --git a/tests/reference/gif/anim/mixed-disposal.gif.02.png b/tests/reference/gif/anim/mixed-disposal.gif.02.png new file mode 100644 index 0000000000..4021e6967c Binary files /dev/null and b/tests/reference/gif/anim/mixed-disposal.gif.02.png differ diff --git a/tests/reference/gif/anim/mixed-disposal.gif.03.png b/tests/reference/gif/anim/mixed-disposal.gif.03.png new file mode 100644 index 0000000000..4bd688bffc Binary files /dev/null and b/tests/reference/gif/anim/mixed-disposal.gif.03.png differ diff --git a/tests/reference/gif/anim/mixed-disposal.gif.04.png b/tests/reference/gif/anim/mixed-disposal.gif.04.png new file mode 100644 index 0000000000..617cd1129a Binary files /dev/null and b/tests/reference/gif/anim/mixed-disposal.gif.04.png differ diff --git a/tests/reference/gif/anim/mixed-disposal.gif.05.png b/tests/reference/gif/anim/mixed-disposal.gif.05.png new file mode 100644 index 0000000000..83e310271e Binary files /dev/null and b/tests/reference/gif/anim/mixed-disposal.gif.05.png differ diff --git a/tests/reference/gif/anim/mixed-disposal.gif.ace8cccc.png b/tests/reference/gif/anim/mixed-disposal.gif.png similarity index 100% rename from tests/reference/gif/anim/mixed-disposal.gif.ace8cccc.png rename to tests/reference/gif/anim/mixed-disposal.gif.png diff --git a/tests/reference/gif/anim/oob.gif.da695a00.png b/tests/reference/gif/anim/oob.gif.png similarity index 100% rename from tests/reference/gif/anim/oob.gif.da695a00.png rename to tests/reference/gif/anim/oob.gif.png diff --git a/tests/reference/gif/simple/alpha_gif_a.gif.e6c86941.png b/tests/reference/gif/simple/alpha_gif_a.gif.png similarity index 100% rename from tests/reference/gif/simple/alpha_gif_a.gif.e6c86941.png rename to tests/reference/gif/simple/alpha_gif_a.gif.png diff --git a/tests/reference/gif/simple/issue_1455_oversized.gif.d3942570.png b/tests/reference/gif/simple/issue_1455_oversized.gif.png similarity index 100% rename from tests/reference/gif/simple/issue_1455_oversized.gif.d3942570.png rename to tests/reference/gif/simple/issue_1455_oversized.gif.png diff --git a/tests/reference/gif/simple/sample_1.gif.c33b036b.png b/tests/reference/gif/simple/sample_1.gif.png similarity index 100% rename from tests/reference/gif/simple/sample_1.gif.c33b036b.png rename to tests/reference/gif/simple/sample_1.gif.png diff --git a/tests/reference/hdr/images/image1.hdr.cd489dff.tiff b/tests/reference/hdr/images/image1.hdr.tiff similarity index 100% rename from tests/reference/hdr/images/image1.hdr.cd489dff.tiff rename to tests/reference/hdr/images/image1.hdr.tiff diff --git a/tests/reference/hdr/images/old-rle.hdr.34096238.tiff b/tests/reference/hdr/images/old-rle.hdr.tiff similarity index 100% rename from tests/reference/hdr/images/old-rle.hdr.34096238.tiff rename to tests/reference/hdr/images/old-rle.hdr.tiff diff --git a/tests/reference/hdr/images/rgbr4x4.hdr.cf021a95.tiff b/tests/reference/hdr/images/rgbr4x4.hdr.tiff similarity index 100% rename from tests/reference/hdr/images/rgbr4x4.hdr.cf021a95.tiff rename to tests/reference/hdr/images/rgbr4x4.hdr.tiff diff --git a/tests/reference/hdr/images/scale.hdr.e79c5305.tiff b/tests/reference/hdr/images/scale.hdr.tiff similarity index 100% rename from tests/reference/hdr/images/scale.hdr.e79c5305.tiff rename to tests/reference/hdr/images/scale.hdr.tiff diff --git a/tests/reference/ico/images/bmp-24bpp-mask.ico.5c8eaf83.png b/tests/reference/ico/images/bmp-24bpp-mask.ico.png similarity index 100% rename from tests/reference/ico/images/bmp-24bpp-mask.ico.5c8eaf83.png rename to tests/reference/ico/images/bmp-24bpp-mask.ico.png diff --git a/tests/reference/ico/images/bmp-32bpp-alpha.ico.5c8eaf83.png b/tests/reference/ico/images/bmp-32bpp-alpha.ico.png similarity index 100% rename from tests/reference/ico/images/bmp-32bpp-alpha.ico.5c8eaf83.png rename to tests/reference/ico/images/bmp-32bpp-alpha.ico.png diff --git a/tests/reference/ico/images/bmp_v5_with_icc.ico.png b/tests/reference/ico/images/bmp_v5_with_icc.ico.png new file mode 100644 index 0000000000..b3c5da7cef Binary files /dev/null and b/tests/reference/ico/images/bmp_v5_with_icc.ico.png differ diff --git a/tests/reference/ico/images/multiple_entries_with_different_bit_depth.ico.369021e9.png b/tests/reference/ico/images/multiple_entries_with_different_bit_depth.ico.png similarity index 100% rename from tests/reference/ico/images/multiple_entries_with_different_bit_depth.ico.369021e9.png rename to tests/reference/ico/images/multiple_entries_with_different_bit_depth.ico.png diff --git a/tests/reference/ico/images/png-32bpp-alpha.ico.5c8eaf83.png b/tests/reference/ico/images/png-32bpp-alpha.ico.png similarity index 100% rename from tests/reference/ico/images/png-32bpp-alpha.ico.5c8eaf83.png rename to tests/reference/ico/images/png-32bpp-alpha.ico.png diff --git a/tests/reference/ico/images/smile.ico.291e3bb0.png b/tests/reference/ico/images/smile.ico.png similarity index 100% rename from tests/reference/ico/images/smile.ico.291e3bb0.png rename to tests/reference/ico/images/smile.ico.png diff --git a/tests/reference/ico/images/two-entry-order-test.ico.b59f783a.png b/tests/reference/ico/images/two-entry-order-test.ico.png similarity index 100% rename from tests/reference/ico/images/two-entry-order-test.ico.b59f783a.png rename to tests/reference/ico/images/two-entry-order-test.ico.png diff --git a/tests/reference/jpg/exif-xmp-metadata.jpg.png b/tests/reference/jpg/exif-xmp-metadata.jpg.png new file mode 100644 index 0000000000..febc72526c Binary files /dev/null and b/tests/reference/jpg/exif-xmp-metadata.jpg.png differ diff --git a/tests/reference/jpg/iptc.jpg.png b/tests/reference/jpg/iptc.jpg.png new file mode 100644 index 0000000000..0a54af5b5a Binary files /dev/null and b/tests/reference/jpg/iptc.jpg.png differ diff --git a/tests/reference/jpg/portrait_2.jpg.png b/tests/reference/jpg/portrait_2.jpg.png new file mode 100644 index 0000000000..16118de07e Binary files /dev/null and b/tests/reference/jpg/portrait_2.jpg.png differ diff --git a/tests/reference/jpg/progressive/3.jpg.56223be9.png b/tests/reference/jpg/progressive/3.jpg.png similarity index 100% rename from tests/reference/jpg/progressive/3.jpg.56223be9.png rename to tests/reference/jpg/progressive/3.jpg.png diff --git a/tests/reference/jpg/progressive/cat.jpg.3c4113c0.png b/tests/reference/jpg/progressive/cat.jpg.png similarity index 100% rename from tests/reference/jpg/progressive/cat.jpg.3c4113c0.png rename to tests/reference/jpg/progressive/cat.jpg.png diff --git a/tests/reference/jpg/progressive/test.jpg.d86d3f63.png b/tests/reference/jpg/progressive/test.jpg.png similarity index 100% rename from tests/reference/jpg/progressive/test.jpg.d86d3f63.png rename to tests/reference/jpg/progressive/test.jpg.png diff --git a/tests/reference/pbm/images/issue-794.pbm.80cbc790.png b/tests/reference/pbm/images/issue-794.pbm.png similarity index 100% rename from tests/reference/pbm/images/issue-794.pbm.80cbc790.png rename to tests/reference/pbm/images/issue-794.pbm.png diff --git a/tests/reference/pbm/images/narrow.pbm.2ba1a727.png b/tests/reference/pbm/images/narrow.pbm.png similarity index 100% rename from tests/reference/pbm/images/narrow.pbm.2ba1a727.png rename to tests/reference/pbm/images/narrow.pbm.png diff --git a/tests/reference/png/16bpc/basi0g16.png.png b/tests/reference/png/16bpc/basi0g16.png.png new file mode 100644 index 0000000000..3d70f66243 Binary files /dev/null and b/tests/reference/png/16bpc/basi0g16.png.png differ diff --git a/tests/reference/png/16bpc/basn2c16.png.png b/tests/reference/png/16bpc/basn2c16.png.png new file mode 100644 index 0000000000..dcfff04034 Binary files /dev/null and b/tests/reference/png/16bpc/basn2c16.png.png differ diff --git a/tests/reference/png/16bpc/basn6a16.png.87be531.png b/tests/reference/png/16bpc/basn6a16.png.png similarity index 100% rename from tests/reference/png/16bpc/basn6a16.png.87be531.png rename to tests/reference/png/16bpc/basn6a16.png.png diff --git a/tests/reference/png/apng/ball.png.anim_01_01c840a9.png b/tests/reference/png/apng/ball.png.01.png similarity index 100% rename from tests/reference/png/apng/ball.png.anim_01_01c840a9.png rename to tests/reference/png/apng/ball.png.01.png diff --git a/tests/reference/png/apng/ball.png.anim_02_a5cb4cc1.png b/tests/reference/png/apng/ball.png.02.png similarity index 100% rename from tests/reference/png/apng/ball.png.anim_02_a5cb4cc1.png rename to tests/reference/png/apng/ball.png.02.png diff --git a/tests/reference/png/apng/ball.png.anim_03_cc6d71d9.png b/tests/reference/png/apng/ball.png.03.png similarity index 100% rename from tests/reference/png/apng/ball.png.anim_03_cc6d71d9.png rename to tests/reference/png/apng/ball.png.03.png diff --git a/tests/reference/png/apng/ball.png.anim_04_26897da3.png b/tests/reference/png/apng/ball.png.04.png similarity index 100% rename from tests/reference/png/apng/ball.png.anim_04_26897da3.png rename to tests/reference/png/apng/ball.png.04.png diff --git a/tests/reference/png/apng/ball.png.anim_05_123fe3c5.png b/tests/reference/png/apng/ball.png.05.png similarity index 100% rename from tests/reference/png/apng/ball.png.anim_05_123fe3c5.png rename to tests/reference/png/apng/ball.png.05.png diff --git a/tests/reference/png/apng/ball.png.anim_06_69c299ea.png b/tests/reference/png/apng/ball.png.06.png similarity index 100% rename from tests/reference/png/apng/ball.png.anim_06_69c299ea.png rename to tests/reference/png/apng/ball.png.06.png diff --git a/tests/reference/png/apng/ball.png.anim_07_765d3648.png b/tests/reference/png/apng/ball.png.07.png similarity index 100% rename from tests/reference/png/apng/ball.png.anim_07_765d3648.png rename to tests/reference/png/apng/ball.png.07.png diff --git a/tests/reference/png/apng/ball.png.anim_08_e44a80f7.png b/tests/reference/png/apng/ball.png.08.png similarity index 100% rename from tests/reference/png/apng/ball.png.anim_08_e44a80f7.png rename to tests/reference/png/apng/ball.png.08.png diff --git a/tests/reference/png/apng/ball.png.anim_09_dd6883db.png b/tests/reference/png/apng/ball.png.09.png similarity index 100% rename from tests/reference/png/apng/ball.png.anim_09_dd6883db.png rename to tests/reference/png/apng/ball.png.09.png diff --git a/tests/reference/png/apng/ball.png.anim_10_3b68b97b.png b/tests/reference/png/apng/ball.png.10.png similarity index 100% rename from tests/reference/png/apng/ball.png.anim_10_3b68b97b.png rename to tests/reference/png/apng/ball.png.10.png diff --git a/tests/reference/png/apng/ball.png.anim_11_c42e2a3f.png b/tests/reference/png/apng/ball.png.11.png similarity index 100% rename from tests/reference/png/apng/ball.png.anim_11_c42e2a3f.png rename to tests/reference/png/apng/ball.png.11.png diff --git a/tests/reference/png/apng/ball.png.anim_12_0796c12e.png b/tests/reference/png/apng/ball.png.12.png similarity index 100% rename from tests/reference/png/apng/ball.png.anim_12_0796c12e.png rename to tests/reference/png/apng/ball.png.12.png diff --git a/tests/reference/png/apng/ball.png.anim_13_bf335902.png b/tests/reference/png/apng/ball.png.13.png similarity index 100% rename from tests/reference/png/apng/ball.png.anim_13_bf335902.png rename to tests/reference/png/apng/ball.png.13.png diff --git a/tests/reference/png/apng/ball.png.anim_14_ee765a97.png b/tests/reference/png/apng/ball.png.14.png similarity index 100% rename from tests/reference/png/apng/ball.png.anim_14_ee765a97.png rename to tests/reference/png/apng/ball.png.14.png diff --git a/tests/reference/png/apng/ball.png.anim_15_56f89914.png b/tests/reference/png/apng/ball.png.15.png similarity index 100% rename from tests/reference/png/apng/ball.png.anim_15_56f89914.png rename to tests/reference/png/apng/ball.png.15.png diff --git a/tests/reference/png/apng/ball.png.anim_16_cd899432.png b/tests/reference/png/apng/ball.png.16.png similarity index 100% rename from tests/reference/png/apng/ball.png.anim_16_cd899432.png rename to tests/reference/png/apng/ball.png.16.png diff --git a/tests/reference/png/apng/ball.png.anim_17_0c3b039a.png b/tests/reference/png/apng/ball.png.17.png similarity index 100% rename from tests/reference/png/apng/ball.png.anim_17_0c3b039a.png rename to tests/reference/png/apng/ball.png.17.png diff --git a/tests/reference/png/apng/ball.png.anim_18_611a8f5d.png b/tests/reference/png/apng/ball.png.18.png similarity index 100% rename from tests/reference/png/apng/ball.png.anim_18_611a8f5d.png rename to tests/reference/png/apng/ball.png.18.png diff --git a/tests/reference/png/apng/ball.png.anim_19_d7316ce1.png b/tests/reference/png/apng/ball.png.19.png similarity index 100% rename from tests/reference/png/apng/ball.png.anim_19_d7316ce1.png rename to tests/reference/png/apng/ball.png.19.png diff --git a/tests/reference/png/apng/ball.png.anim_20_1e8b755f.png b/tests/reference/png/apng/ball.png.20.png similarity index 100% rename from tests/reference/png/apng/ball.png.anim_20_1e8b755f.png rename to tests/reference/png/apng/ball.png.20.png diff --git a/tests/reference/png/apng/ball.png.1c840a9.png b/tests/reference/png/apng/ball.png.png similarity index 100% rename from tests/reference/png/apng/ball.png.1c840a9.png rename to tests/reference/png/apng/ball.png.png diff --git a/tests/reference/png/bugfixes/debug_triangle_corners_widescreen.png.50664ae3.png b/tests/reference/png/bugfixes/debug_triangle_corners_widescreen.png.png similarity index 100% rename from tests/reference/png/bugfixes/debug_triangle_corners_widescreen.png.50664ae3.png rename to tests/reference/png/bugfixes/debug_triangle_corners_widescreen.png.png diff --git a/tests/reference/png/bugfixes/issue#2026.png.png b/tests/reference/png/bugfixes/issue#2026.png.png new file mode 100644 index 0000000000..155ae74613 Binary files /dev/null and b/tests/reference/png/bugfixes/issue#2026.png.png differ diff --git a/tests/reference/png/bugfixes/issue#403.png.b0818cef.png b/tests/reference/png/bugfixes/issue#403.png.png similarity index 100% rename from tests/reference/png/bugfixes/issue#403.png.b0818cef.png rename to tests/reference/png/bugfixes/issue#403.png.png diff --git a/tests/reference/png/interlaced/basi2c08.png.7855b9bf.png b/tests/reference/png/interlaced/basi2c08.png.png similarity index 100% rename from tests/reference/png/interlaced/basi2c08.png.7855b9bf.png rename to tests/reference/png/interlaced/basi2c08.png.png diff --git a/tests/reference/png/transparency/acid2.png.8de8ca3f.png b/tests/reference/png/transparency/acid2.png.png similarity index 100% rename from tests/reference/png/transparency/acid2.png.8de8ca3f.png rename to tests/reference/png/transparency/acid2.png.png diff --git a/tests/reference/png/transparency/tbbn0g04.png.8d94cbac.png b/tests/reference/png/transparency/tbbn0g04.png.png similarity index 100% rename from tests/reference/png/transparency/tbbn0g04.png.8d94cbac.png rename to tests/reference/png/transparency/tbbn0g04.png.png diff --git a/tests/reference/png/transparency/tbbn3p08.png.9d56cd67.png b/tests/reference/png/transparency/tbbn3p08.png.png similarity index 100% rename from tests/reference/png/transparency/tbbn3p08.png.9d56cd67.png rename to tests/reference/png/transparency/tbbn3p08.png.png diff --git a/tests/reference/png/transparency/tbgn3p08.png.9d56cd67.png b/tests/reference/png/transparency/tbgn3p08.png.png similarity index 100% rename from tests/reference/png/transparency/tbgn3p08.png.9d56cd67.png rename to tests/reference/png/transparency/tbgn3p08.png.png diff --git a/tests/reference/png/transparency/tbrn2c08.png.370ef89.png b/tests/reference/png/transparency/tbrn2c08.png.png similarity index 100% rename from tests/reference/png/transparency/tbrn2c08.png.370ef89.png rename to tests/reference/png/transparency/tbrn2c08.png.png diff --git a/tests/reference/png/transparency/tbwn3p08.png.9d56cd67.png b/tests/reference/png/transparency/tbwn3p08.png.png similarity index 100% rename from tests/reference/png/transparency/tbwn3p08.png.9d56cd67.png rename to tests/reference/png/transparency/tbwn3p08.png.png diff --git a/tests/reference/png/transparency/tbyn3p08.png.9d56cd67.png b/tests/reference/png/transparency/tbyn3p08.png.png similarity index 100% rename from tests/reference/png/transparency/tbyn3p08.png.9d56cd67.png rename to tests/reference/png/transparency/tbyn3p08.png.png diff --git a/tests/reference/png/transparency/tm3n3p02.png.e7daa7f5.png b/tests/reference/png/transparency/tm3n3p02.png.png similarity index 100% rename from tests/reference/png/transparency/tm3n3p02.png.e7daa7f5.png rename to tests/reference/png/transparency/tm3n3p02.png.png diff --git a/tests/reference/png/transparency/tp0n0g08.png.c3dda42e.png b/tests/reference/png/transparency/tp0n0g08.png.png similarity index 100% rename from tests/reference/png/transparency/tp0n0g08.png.c3dda42e.png rename to tests/reference/png/transparency/tp0n0g08.png.png diff --git a/tests/reference/png/transparency/tp0n2c08.png.b426b350.png b/tests/reference/png/transparency/tp0n2c08.png.png similarity index 100% rename from tests/reference/png/transparency/tp0n2c08.png.b426b350.png rename to tests/reference/png/transparency/tp0n2c08.png.png diff --git a/tests/reference/png/transparency/tp0n3p08.png.15493236.png b/tests/reference/png/transparency/tp0n3p08.png.png similarity index 100% rename from tests/reference/png/transparency/tp0n3p08.png.15493236.png rename to tests/reference/png/transparency/tp0n3p08.png.png diff --git a/tests/reference/png/transparency/tp1n3p08.png.9d56cd67.png b/tests/reference/png/transparency/tp1n3p08.png.png similarity index 100% rename from tests/reference/png/transparency/tp1n3p08.png.9d56cd67.png rename to tests/reference/png/transparency/tp1n3p08.png.png diff --git a/tests/reference/png/transparency/tp1n3p08_xmp.png.png b/tests/reference/png/transparency/tp1n3p08_xmp.png.png new file mode 100644 index 0000000000..950636fc94 Binary files /dev/null and b/tests/reference/png/transparency/tp1n3p08_xmp.png.png differ diff --git a/tests/reference/qoi/basic-test.qoi.png b/tests/reference/qoi/basic-test.qoi.png new file mode 100644 index 0000000000..c46b53be0d Binary files /dev/null and b/tests/reference/qoi/basic-test.qoi.png differ diff --git a/tests/reference/tga/encoding/black_white.tga.png b/tests/reference/tga/encoding/black_white.tga.png new file mode 100644 index 0000000000..0ca87b2ac4 Binary files /dev/null and b/tests/reference/tga/encoding/black_white.tga.png differ diff --git a/tests/reference/tga/testsuite/b5-attrib.tga.283e5700.png b/tests/reference/tga/testsuite/b5-attrib.tga.png similarity index 100% rename from tests/reference/tga/testsuite/b5-attrib.tga.283e5700.png rename to tests/reference/tga/testsuite/b5-attrib.tga.png diff --git a/tests/reference/tga/testsuite/b5-cmap.tga.283e5700.png b/tests/reference/tga/testsuite/b5-cmap.tga.png similarity index 100% rename from tests/reference/tga/testsuite/b5-cmap.tga.283e5700.png rename to tests/reference/tga/testsuite/b5-cmap.tga.png diff --git a/tests/reference/tga/testsuite/b5-noattrib.tga.283e5700.png b/tests/reference/tga/testsuite/b5-noattrib.tga.png similarity index 100% rename from tests/reference/tga/testsuite/b5-noattrib.tga.283e5700.png rename to tests/reference/tga/testsuite/b5-noattrib.tga.png diff --git a/tests/reference/tga/testsuite/b5-unused-cmap.tga.283e5700.png b/tests/reference/tga/testsuite/b5-unused-cmap.tga.png similarity index 100% rename from tests/reference/tga/testsuite/b5-unused-cmap.tga.283e5700.png rename to tests/reference/tga/testsuite/b5-unused-cmap.tga.png diff --git a/tests/reference/tga/testsuite/bottom_left.tga.391a5b46.png b/tests/reference/tga/testsuite/bottom_left.tga.png similarity index 100% rename from tests/reference/tga/testsuite/bottom_left.tga.391a5b46.png rename to tests/reference/tga/testsuite/bottom_left.tga.png diff --git a/tests/reference/tga/testsuite/bottom_right.tga.a6b4aab1.png b/tests/reference/tga/testsuite/bottom_right.tga.png similarity index 100% rename from tests/reference/tga/testsuite/bottom_right.tga.a6b4aab1.png rename to tests/reference/tga/testsuite/bottom_right.tga.png diff --git a/tests/reference/tga/testsuite/cbw8.tga.3f8a9b3c.png b/tests/reference/tga/testsuite/cbw8.tga.png similarity index 100% rename from tests/reference/tga/testsuite/cbw8.tga.3f8a9b3c.png rename to tests/reference/tga/testsuite/cbw8.tga.png diff --git a/tests/reference/tga/testsuite/ccm8.tga.png b/tests/reference/tga/testsuite/ccm8.tga.png new file mode 100644 index 0000000000..f57a66409d Binary files /dev/null and b/tests/reference/tga/testsuite/ccm8.tga.png differ diff --git a/tests/reference/tga/testsuite/cmap_offset.tga.1ebb7ae9.png b/tests/reference/tga/testsuite/cmap_offset.tga.png similarity index 100% rename from tests/reference/tga/testsuite/cmap_offset.tga.1ebb7ae9.png rename to tests/reference/tga/testsuite/cmap_offset.tga.png diff --git a/tests/reference/tga/testsuite/ctc24.tga.b7096b3.png b/tests/reference/tga/testsuite/ctc24.tga.png similarity index 100% rename from tests/reference/tga/testsuite/ctc24.tga.b7096b3.png rename to tests/reference/tga/testsuite/ctc24.tga.png diff --git a/tests/reference/tga/testsuite/top_left.tga.a7f3521c.png b/tests/reference/tga/testsuite/top_left.tga.png similarity index 100% rename from tests/reference/tga/testsuite/top_left.tga.a7f3521c.png rename to tests/reference/tga/testsuite/top_left.tga.png diff --git a/tests/reference/tga/testsuite/top_right.tga.2519b547.png b/tests/reference/tga/testsuite/top_right.tga.png similarity index 100% rename from tests/reference/tga/testsuite/top_right.tga.2519b547.png rename to tests/reference/tga/testsuite/top_right.tga.png diff --git a/tests/reference/tga/testsuite/ubw8.tga.3f8a9b3c.png b/tests/reference/tga/testsuite/ubw8.tga.png similarity index 100% rename from tests/reference/tga/testsuite/ubw8.tga.3f8a9b3c.png rename to tests/reference/tga/testsuite/ubw8.tga.png diff --git a/tests/reference/tga/testsuite/ucm8.tga.png b/tests/reference/tga/testsuite/ucm8.tga.png new file mode 100644 index 0000000000..f57a66409d Binary files /dev/null and b/tests/reference/tga/testsuite/ucm8.tga.png differ diff --git a/tests/reference/tga/testsuite/utc16.tga.png b/tests/reference/tga/testsuite/utc16.tga.png new file mode 100644 index 0000000000..f57a66409d Binary files /dev/null and b/tests/reference/tga/testsuite/utc16.tga.png differ diff --git a/tests/reference/tga/testsuite/utc24.tga.b7096b3.png b/tests/reference/tga/testsuite/utc24.tga.png similarity index 100% rename from tests/reference/tga/testsuite/utc24.tga.b7096b3.png rename to tests/reference/tga/testsuite/utc24.tga.png diff --git a/tests/reference/tga/testsuite/utc32.tga.134a83ba.png b/tests/reference/tga/testsuite/utc32.tga.png similarity index 100% rename from tests/reference/tga/testsuite/utc32.tga.134a83ba.png rename to tests/reference/tga/testsuite/utc32.tga.png diff --git a/tests/reference/tiff/testsuite/fax4.tiff.aba6a268.png b/tests/reference/tiff/testsuite/fax4.tiff.png similarity index 100% rename from tests/reference/tiff/testsuite/fax4.tiff.aba6a268.png rename to tests/reference/tiff/testsuite/fax4.tiff.png diff --git a/tests/reference/tiff/testsuite/hpredict.tiff.dc00a927.png b/tests/reference/tiff/testsuite/hpredict.tiff.png similarity index 100% rename from tests/reference/tiff/testsuite/hpredict.tiff.dc00a927.png rename to tests/reference/tiff/testsuite/hpredict.tiff.png diff --git a/tests/reference/tiff/testsuite/hpredict_packbits.tiff.82ca6aa0.png b/tests/reference/tiff/testsuite/hpredict_packbits.tiff.png similarity index 100% rename from tests/reference/tiff/testsuite/hpredict_packbits.tiff.82ca6aa0.png rename to tests/reference/tiff/testsuite/hpredict_packbits.tiff.png diff --git a/tests/reference/tiff/testsuite/l1.tiff.5079e13c.png b/tests/reference/tiff/testsuite/l1.tiff.png similarity index 100% rename from tests/reference/tiff/testsuite/l1.tiff.5079e13c.png rename to tests/reference/tiff/testsuite/l1.tiff.png diff --git a/tests/reference/tiff/testsuite/l1_xmp.tiff.png b/tests/reference/tiff/testsuite/l1_xmp.tiff.png new file mode 100644 index 0000000000..e1d033c5bf Binary files /dev/null and b/tests/reference/tiff/testsuite/l1_xmp.tiff.png differ diff --git a/tests/reference/tiff/testsuite/mandrill.tiff.99549da9.png b/tests/reference/tiff/testsuite/mandrill.tiff.png similarity index 100% rename from tests/reference/tiff/testsuite/mandrill.tiff.99549da9.png rename to tests/reference/tiff/testsuite/mandrill.tiff.png diff --git a/tests/reference/tiff/testsuite/planar.tiff.dac8e568.png b/tests/reference/tiff/testsuite/planar.tiff.png similarity index 100% rename from tests/reference/tiff/testsuite/planar.tiff.dac8e568.png rename to tests/reference/tiff/testsuite/planar.tiff.png diff --git a/tests/reference/tiff/testsuite/rgb-3c-16b.tiff.531c087a.png b/tests/reference/tiff/testsuite/rgb-3c-16b.tiff.png similarity index 100% rename from tests/reference/tiff/testsuite/rgb-3c-16b.tiff.531c087a.png rename to tests/reference/tiff/testsuite/rgb-3c-16b.tiff.png diff --git a/tests/reference/tiff/testsuite/rgb32f_bw.tiff.f90a5776.png b/tests/reference/tiff/testsuite/rgb32f_bw.tiff.f90a5776.png deleted file mode 100644 index 478ed75a6a..0000000000 Binary files a/tests/reference/tiff/testsuite/rgb32f_bw.tiff.f90a5776.png and /dev/null differ diff --git a/tests/reference/tiff/testsuite/rgb32f_bw.tiff.tiff b/tests/reference/tiff/testsuite/rgb32f_bw.tiff.tiff new file mode 100644 index 0000000000..0523ce0295 Binary files /dev/null and b/tests/reference/tiff/testsuite/rgb32f_bw.tiff.tiff differ diff --git a/tests/reference/tiff/testsuite/rgb32f_color.tiff.2d565c20.png b/tests/reference/tiff/testsuite/rgb32f_color.tiff.2d565c20.png deleted file mode 100644 index 6029a728fb..0000000000 Binary files a/tests/reference/tiff/testsuite/rgb32f_color.tiff.2d565c20.png and /dev/null differ diff --git a/tests/reference/tiff/testsuite/rgb32f_color.tiff.tiff b/tests/reference/tiff/testsuite/rgb32f_color.tiff.tiff new file mode 100644 index 0000000000..07f82ba058 Binary files /dev/null and b/tests/reference/tiff/testsuite/rgb32f_color.tiff.tiff differ diff --git a/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.01.png b/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.01.png new file mode 100644 index 0000000000..35ab5a96cc Binary files /dev/null and b/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.01.png differ diff --git a/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.02.png b/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.02.png new file mode 100644 index 0000000000..7a8f79c6cc Binary files /dev/null and b/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.02.png differ diff --git a/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.03.png b/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.03.png new file mode 100644 index 0000000000..950076aed3 Binary files /dev/null and b/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.03.png differ diff --git a/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.04.png b/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.04.png new file mode 100644 index 0000000000..4da0bb5175 Binary files /dev/null and b/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.04.png differ diff --git a/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.05.png b/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.05.png new file mode 100644 index 0000000000..f35330205e Binary files /dev/null and b/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.05.png differ diff --git a/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.06.png b/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.06.png new file mode 100644 index 0000000000..fb89f6b7fc Binary files /dev/null and b/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.06.png differ diff --git a/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.07.png b/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.07.png new file mode 100644 index 0000000000..016ddd4f27 Binary files /dev/null and b/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.07.png differ diff --git a/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.08.png b/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.08.png new file mode 100644 index 0000000000..532cdf466a Binary files /dev/null and b/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.08.png differ diff --git a/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.09.png b/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.09.png new file mode 100644 index 0000000000..8a9479de99 Binary files /dev/null and b/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.09.png differ diff --git a/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.10.png b/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.10.png new file mode 100644 index 0000000000..1cfe6108a8 Binary files /dev/null and b/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.10.png differ diff --git a/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.11.png b/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.11.png new file mode 100644 index 0000000000..a338e17506 Binary files /dev/null and b/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.11.png differ diff --git a/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.4dd87800.png b/tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.png similarity index 100% rename from tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.4dd87800.png rename to tests/reference/webp/extended_images/advertises_rgba_but_frames_are_rgb.webp.png diff --git a/tests/reference/webp/extended_images/anim.webp.01.png b/tests/reference/webp/extended_images/anim.webp.01.png new file mode 100644 index 0000000000..82865620f5 Binary files /dev/null and b/tests/reference/webp/extended_images/anim.webp.01.png differ diff --git a/tests/reference/webp/extended_images/anim.webp.02.png b/tests/reference/webp/extended_images/anim.webp.02.png new file mode 100644 index 0000000000..b29348691c Binary files /dev/null and b/tests/reference/webp/extended_images/anim.webp.02.png differ diff --git a/tests/reference/webp/extended_images/anim.webp.03.png b/tests/reference/webp/extended_images/anim.webp.03.png new file mode 100644 index 0000000000..d94edf46e7 Binary files /dev/null and b/tests/reference/webp/extended_images/anim.webp.03.png differ diff --git a/tests/reference/webp/extended_images/anim.webp.04.png b/tests/reference/webp/extended_images/anim.webp.04.png new file mode 100644 index 0000000000..8ff42bda30 Binary files /dev/null and b/tests/reference/webp/extended_images/anim.webp.04.png differ diff --git a/tests/reference/webp/extended_images/anim.webp.05.png b/tests/reference/webp/extended_images/anim.webp.05.png new file mode 100644 index 0000000000..420fa07ca5 Binary files /dev/null and b/tests/reference/webp/extended_images/anim.webp.05.png differ diff --git a/tests/reference/webp/extended_images/anim.webp.06.png b/tests/reference/webp/extended_images/anim.webp.06.png new file mode 100644 index 0000000000..7871ba70a7 Binary files /dev/null and b/tests/reference/webp/extended_images/anim.webp.06.png differ diff --git a/tests/reference/webp/extended_images/anim.webp.f595c678.png b/tests/reference/webp/extended_images/anim.webp.png similarity index 100% rename from tests/reference/webp/extended_images/anim.webp.f595c678.png rename to tests/reference/webp/extended_images/anim.webp.png diff --git a/tests/reference/webp/extended_images/lossy_alpha.webp.99fb5348.png b/tests/reference/webp/extended_images/lossy_alpha.webp.png similarity index 100% rename from tests/reference/webp/extended_images/lossy_alpha.webp.99fb5348.png rename to tests/reference/webp/extended_images/lossy_alpha.webp.png diff --git a/tests/reference/webp/lossless_images/2-color.webp.1c59922a.png b/tests/reference/webp/lossless_images/2-color.webp.png similarity index 100% rename from tests/reference/webp/lossless_images/2-color.webp.1c59922a.png rename to tests/reference/webp/lossless_images/2-color.webp.png diff --git a/tests/reference/webp/lossless_images/multi-color.webp.aeee944f.png b/tests/reference/webp/lossless_images/multi-color.webp.png similarity index 100% rename from tests/reference/webp/lossless_images/multi-color.webp.aeee944f.png rename to tests/reference/webp/lossless_images/multi-color.webp.png diff --git a/tests/reference/webp/lossless_images/simple.webp.3d047de8.png b/tests/reference/webp/lossless_images/simple.webp.png similarity index 100% rename from tests/reference/webp/lossless_images/simple.webp.3d047de8.png rename to tests/reference/webp/lossless_images/simple.webp.png diff --git a/tests/reference/webp/lossless_images/simple_xmp.webp.png b/tests/reference/webp/lossless_images/simple_xmp.webp.png new file mode 100644 index 0000000000..34a4ca4e64 Binary files /dev/null and b/tests/reference/webp/lossless_images/simple_xmp.webp.png differ diff --git a/tests/reference/webp/lossy_images/simple-gray.webp.a2524735.png b/tests/reference/webp/lossy_images/simple-gray.webp.png similarity index 100% rename from tests/reference/webp/lossy_images/simple-gray.webp.a2524735.png rename to tests/reference/webp/lossy_images/simple-gray.webp.png diff --git a/tests/reference/webp/lossy_images/simple-rgb.webp.adea0613.png b/tests/reference/webp/lossy_images/simple-rgb.webp.png similarity index 100% rename from tests/reference/webp/lossy_images/simple-rgb.webp.adea0613.png rename to tests/reference/webp/lossy_images/simple-rgb.webp.png diff --git a/tests/reference_images.rs b/tests/reference_images.rs index f869e3c974..fa939cf79d 100644 --- a/tests/reference_images.rs +++ b/tests/reference_images.rs @@ -1,293 +1,334 @@ -//! Compares the decoding results with reference renderings. -//! -//! This test harness automatically detects all reference images in -//! `tests/reference/...` and compares them to the associated file in -//! `tests/images/...`. - +use std::collections::BTreeMap; +use std::error::Error; use std::fs; -use std::fs::File; -use std::io::{self, BufWriter}; -use std::path::Path; -use std::str::FromStr; - -use crc32fast::Hasher as Crc32; -use image::ColorType; -use image::{DynamicImage, ImageFormat}; -use libtest_mimic::{Arguments, Failed, Trial}; +use std::path::{Path, PathBuf}; +use std::sync::{LazyLock, Mutex}; + +use image::{AnimationDecoder, ColorType, ImageFormat, RgbaImage}; +use image::{DynamicImage, GenericImageView}; +use libtest_mimic::{Arguments, Trial}; use walkdir::WalkDir; +static BLESSED: LazyLock = LazyLock::new(|| std::env::var("BLESS").is_ok()); + +static TEST_DIR: LazyLock = + LazyLock::new(|| Path::new(env!("CARGO_MANIFEST_DIR")).join("tests")); +static IMAGE_DIR: LazyLock = LazyLock::new(|| TEST_DIR.join("images")); +static REFERENCE_DIR: LazyLock = LazyLock::new(|| TEST_DIR.join("reference")); + +static HASH_PATH: LazyLock = LazyLock::new(|| TEST_DIR.join("hashes.toml")); +static HASHES: LazyLock = LazyLock::new(|| HashFile::open(&HASH_PATH).unwrap()); + +/// Test decoding of all test images in `tests/images/` against their hashes in +/// `hashes.toml` and reference images (either PNG or TIFF) in `tests/reference/`. +/// +/// ## Bless mode +/// +/// If the `BLESS` environment variable is set, the test will create/update all +/// missing/mismatching hashes and reference images. +/// +/// To add a new test image, simply add it to `tests/images/` and run the +/// following command: +/// +/// ```sh +/// BLESS=1 cargo test +/// ``` +/// ```powershell +/// $env:BLESS=1; cargo test; $env:BLESS=$null +/// ``` fn main() { let mut trials = Vec::new(); - let image_dir = Path::new(env!("CARGO_MANIFEST_DIR")) - .join("tests") - .join("images"); - let reference_dir = Path::new(env!("CARGO_MANIFEST_DIR")) - .join("tests") - .join("reference"); - let output_dir = Path::new(env!("CARGO_MANIFEST_DIR")) - .join("tests") - .join("output"); - - for entry in WalkDir::new(&reference_dir) { - let entry = entry.unwrap(); - if !entry.file_type().is_file() || entry.path().extension() == Some("txt".as_ref()) { + for image_path in image_paths_in(&IMAGE_DIR) { + let test_name = format!( + "reference {}", + image_path.strip_prefix(&*TEST_DIR).unwrap().display() + ); + + // we need both PNG and TIFF to be able to run reference tests, since + // reference images are stored in those formats. + if !ImageFormat::Png.reading_enabled() || !ImageFormat::Tiff.reading_enabled() { + trials.push(Trial::test(test_name, || Ok(())).with_ignored_flag(true)); continue; } - let relative_path = entry - .path() - .strip_prefix(&reference_dir) - .unwrap() - .to_path_buf(); - let Ok(case) = ReferenceTestCase::from_str(entry.file_name().to_str().unwrap()) else { + // fail if the test image is of an unknown format + let Ok(format) = ImageFormat::from_path(&image_path) else { trials.push(Trial::test( - format!("reference_images {}", relative_path.display()), - || Err("Malformed reference image filename".into()), + test_name, + || Err("Unknown image format".into()), )); continue; }; - let path = entry.into_path(); - - let original_relative_path = relative_path.parent().unwrap().join(&case.orig_filename); - let img_path = image_dir.join(&original_relative_path); - - let test_name = match case.kind { - ReferenceTestKind::AnimatedFrame { frame } => format!( - "reference tests/images/{}[{}]", - original_relative_path.display(), - frame + 1 - ), - ReferenceTestKind::SingleImage => { - format!( - "reference tests/images/{}", - original_relative_path.display() - ) - } - }; - let image_format = img_path.extension().and_then(ImageFormat::from_extension); - let reference_format = relative_path - .extension() - .and_then(ImageFormat::from_extension) - .expect("reference image with unknown extension"); - - if image_format.is_none() { - trials.push(Trial::test( - test_name, - || Err("Unknown image format".into()), - )); + // skip if the format of the test image isn't enabled + if !format.reading_enabled() { + trials.push(Trial::test(test_name, || Ok(())).with_ignored_flag(true)); continue; } - if !image_format.unwrap().reading_enabled() || !reference_format.reading_enabled() { + // QOI is currently broken on BE architectures, so we have to skip. + // See https://github.com/image-rs/image/issues/2808 for details. + // TODO: Remove this stupid hack once QOI is fixed. + if format == ImageFormat::Qoi && cfg!(target_endian = "big") { trials.push(Trial::test(test_name, || Ok(())).with_ignored_flag(true)); continue; } - let output_dir = output_dir.clone(); - trials.push(Trial::test(test_name, move || -> Result<(), Failed> { - // Load the test image - let mut test_img = match case.kind { - ReferenceTestKind::SingleImage => { - // Read the input file as a single image - image::open(&img_path)? - } - ReferenceTestKind::AnimatedFrame { frame: frame_num } => { - // TODO: Once there's a generic API for animated images, switch to that instead. - match image_format { - #[cfg(feature = "gif")] - Some(image::ImageFormat::Gif) => { - // Interpret the input file as an animation file - use image::AnimationDecoder; - let stream = io::BufReader::new(fs::File::open(&img_path).unwrap()); - let decoder = image::codecs::gif::GifDecoder::new(stream)?; - let mut frames = decoder.into_frames().collect_frames()?; - - // Select a single frame - let frame = frames.drain(frame_num..).next().unwrap(); - - // Convert the frame to a`RgbaImage` - DynamicImage::from(frame.into_buffer()) - } - - #[cfg(feature = "png")] - Some(image::ImageFormat::Png) => { - // Interpret the input file as an animation file - use image::AnimationDecoder; - let stream = io::BufReader::new(fs::File::open(&img_path).unwrap()); - let decoder = image::codecs::png::PngDecoder::new(stream)?.apng()?; - let mut frames = decoder.into_frames().collect_frames()?; - - // Select a single frame - let frame = frames.drain(frame_num..).next().unwrap(); - - // Convert the frame to a`RgbaImage` - DynamicImage::from(frame.into_buffer()) - } - _ => unreachable!( - "Format is unspported or disabled. Should have been detected earlier" - ), - } - } - }; - - let test_crc_actual = { - let mut hasher = Crc32::new(); - match test_img { - DynamicImage::ImageLuma8(_) - | DynamicImage::ImageLumaA8(_) - | DynamicImage::ImageRgb8(_) - | DynamicImage::ImageRgba8(_) => hasher.update(test_img.as_bytes()), - DynamicImage::ImageLuma16(_) - | DynamicImage::ImageLumaA16(_) - | DynamicImage::ImageRgb16(_) - | DynamicImage::ImageRgba16(_) => { - for v in test_img.as_bytes().chunks(2) { - hasher.update(&u16::from_ne_bytes(v.try_into().unwrap()).to_le_bytes()); - } - } - DynamicImage::ImageRgb32F(_) | DynamicImage::ImageRgba32F(_) => { - for v in test_img.as_bytes().chunks(4) { - hasher.update(&f32::from_ne_bytes(v.try_into().unwrap()).to_le_bytes()); - } - } - _ => panic!("Unsupported image format"), - } - hasher.finalize() - }; - - if reference_format == ImageFormat::Png && image_format == Some(ImageFormat::Tiff) { - match test_img { - DynamicImage::ImageRgb32F(_) => { - test_img = test_img.to_rgb16().into(); - } - DynamicImage::ImageRgba32F(_) => { - test_img = test_img.to_rgba16().into(); - } - _ => {} - } - } + trials.push(Trial::test(test_name, move || { + // load image and check against reference + let image = + image::open(&image_path).map_err(|e| format!("Failed to open image: {}", e))?; - let mut error = if test_crc_actual != case.crc { - format!( - "The decoded image's hash does not match (expected = {:08x}, actual = {:08x})", - case.crc, test_crc_actual - ) - } else if image::open(&path)?.as_bytes() != test_img.as_bytes() { - "Reference rendering does not match".into() - } else { - // The image exactly matches the reference. Success! - return Ok(()); - }; - - // The image doesn't match the reference. Save the decoded version to the - // output directory for inspection. - let ext = match test_img.color() { - ColorType::Rgb32F | ColorType::Rgba32F => "tiff", - _ => "png", - }; - let output_filename = format!("{}.{test_crc_actual:08x}.{ext}", case.orig_filename); - let output_path = output_dir.join(output_filename); - fs::create_dir_all(output_dir).unwrap(); - - let ret = match test_img.color() { - ColorType::Rgb32F | ColorType::Rgba32F => test_img.save(&output_path), - #[cfg(feature = "png")] - _ => { - use image::codecs::png::{CompressionType, FilterType, PngEncoder}; - test_img.write_with_encoder(PngEncoder::new_with_quality( - BufWriter::new(File::create(&output_path).unwrap()), - CompressionType::Best, - FilterType::Adaptive, - )) + let reference_path = get_reference_path(&image_path, None, &image); + check_image_reference(&reference_path, image)?; + + // if the image is an animation, check each frame against its reference as well + if let Some(frames) = decode_animation_frames(&image_path)? { + for (index, frame) in frames.into_iter().enumerate() { + let frame_num = index + 1; + let frame = DynamicImage::from(frame); + + let reference_path = get_reference_path(&image_path, Some(frame_num), &frame); + check_image_reference(&reference_path, frame) + .map_err(|e| format!("Frame {frame_num}: {e}"))?; } - #[cfg(not(feature = "png"))] - _ => unreachable!(), - }; - - match ret { - Ok(()) => error.push_str(&format!( - "\n\n New reference saved to: {}", - output_path.display() - )), - Err(e) => error.push_str(&format!("\n\n Failed to save new reference: {e}")), } - Err(error.into()) - })); + + Ok(()) + })) } let args = Arguments::from_args(); libtest_mimic::run(&args, trials).exit(); } -/// Describes a single test case of `check_references`. -struct ReferenceTestCase { - orig_filename: String, - crc: u32, - kind: ReferenceTestKind, +fn check_image_reference(reference_path: &Path, image: DynamicImage) -> Result<(), Box> { + let hash_key = reference_path + .strip_prefix(&*REFERENCE_DIR) + .unwrap() + .with_extension("") // remove reference image extension + .to_string_lossy() + .replace(std::path::MAIN_SEPARATOR, "/"); // use UNIX separators + + // check hash + let hash = HASHES.get(&hash_key); + let image_hash = format!("{:x}", crc32fast::hash(image.as_bytes())); + if hash != Some(&image_hash) { + if !*BLESSED { + return Err( + "Decoded image changed!\nMissing or mismatching pixel data hash. Try running tests in blessed mode.".into(), + ); + } + edit_image_hash(&hash_key, &image)?; + } + + // check reference image + if !reference_path.exists() { + // missing reference images are probably just ignored via .gitignore. + // so just create them in blessed mode + if *BLESSED { + return save_image(&image, reference_path, true); + } + return Ok(()); + } + + // load reference + let reference = + image::open(reference_path).map_err(|e| format!("Failed to open reference image: {e}"))?; + + // compare to reference + let cmp_result = compare_to_reference(&image, &reference); + if cmp_result.is_err() && *BLESSED { + // update reference in bless mode + return save_image(&image, reference_path, true); + } + cmp_result?; + + Ok(()) +} + +fn save_image(image: &DynamicImage, path: &Path, optimize: bool) -> Result<(), Box> { + fs::create_dir_all(path.parent().unwrap())?; + image.save(path)?; + + // optimize PNGs with oxipng to reduce the size of reference images in the repo + if optimize && path.extension().is_some_and(|ext| ext == "png") { + oxipng::optimize( + &oxipng::InFile::Path(path.to_path_buf()), + &oxipng::OutFile::from_path(path.to_path_buf()), + &oxipng::Options::from_preset(4), + )?; + } + + Ok(()) +} + +fn get_save_format(image: &DynamicImage) -> ImageFormat { + match image.color() { + ColorType::Rgb32F | ColorType::Rgba32F => ImageFormat::Tiff, + _ => ImageFormat::Png, + } +} + +fn get_reference_path( + image_path: &Path, + frame_num: Option, + image: &DynamicImage, +) -> PathBuf { + // TODO: Use PathBuf::add_extension once MSRV is 1.91.0 + fn add_extension(path: &mut PathBuf, extension: &str) { + path.set_file_name( + path.file_name().unwrap().to_string_lossy().to_string() + "." + extension, + ); + } + + let relative_path = image_path.strip_prefix(&*IMAGE_DIR).unwrap(); + let mut reference_path = REFERENCE_DIR.join(relative_path); + + if let Some(frame_num) = frame_num { + add_extension(&mut reference_path, &format!("{frame_num:02}")); + } + add_extension( + &mut reference_path, + get_save_format(image).extensions_str()[0], + ); + + reference_path +} + +fn image_paths_in(dir: &Path) -> impl Iterator { + WalkDir::new(dir) + .into_iter() + .filter_map(|e| e.ok()) + .filter(|e| e.file_type().is_file()) + .map(|e| e.into_path()) + .filter(|p| p.extension().is_some_and(|ext| ext != "txt" && ext != "md")) } -enum ReferenceTestKind { - /// The test image is loaded using `image::open`, and the result is compared - /// against the reference image. - SingleImage, - - /// From the test image file, a single frame is extracted using a fitting animation decoder and - /// the result is compared against the reference image. - AnimatedFrame { - /// A zero-based frame number. - frame: usize, - }, +fn compare_to_reference(image: &DynamicImage, reference: &DynamicImage) -> Result<(), String> { + if image.dimensions() != reference.dimensions() { + return Err(format!( + "Reference dimension mismatch: image is {:?}, reference is {:?}", + image.dimensions(), + reference.dimensions() + )); + } + + // fast path + if image.color() == reference.color() && image.as_bytes() == reference.as_bytes() { + return Ok(()); + } + + // convert to a common color type + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] + enum Precision { + U8, + U16, + F32, + } + impl Precision { + fn of(color: ColorType) -> Self { + match color { + ColorType::L8 | ColorType::La8 | ColorType::Rgb8 | ColorType::Rgba8 => Self::U8, + ColorType::L16 | ColorType::La16 | ColorType::Rgb16 | ColorType::Rgba16 => { + Self::U16 + } + ColorType::Rgb32F | ColorType::Rgba32F | _ => Self::F32, + } + } + } + fn to_rgba_precision(image: &DynamicImage, precision: Precision) -> DynamicImage { + match precision { + Precision::U8 => image.to_rgba8().into(), + Precision::U16 => image.to_rgba16().into(), + Precision::F32 => image.to_rgba32f().into(), + } + } + + let image_precision = Precision::of(image.color()); + let reference_precision = Precision::of(reference.color()); + let common_precision = image_precision.max(reference_precision); + + let image = to_rgba_precision(image, common_precision); + let reference = to_rgba_precision(reference, common_precision); + assert_eq!(image.color(), reference.color()); + + if image.as_bytes() == reference.as_bytes() { + Ok(()) + } else { + Err("Mismatching pixel data".into()) + } } -impl std::str::FromStr for ReferenceTestCase { - type Err = &'static str; - - /// Construct `ReferenceTestCase` from the file name of a reference - /// image. - fn from_str(filename: &str) -> Result { - let mut filename_parts = filename.rsplitn(3, '.'); - - // Ignore the file extension - filename_parts.next().unwrap(); - - // The penultimate part of `filename_parts` represents the metadata, - // describing the test type and other details. - let meta_str = filename_parts.next().ok_or("missing metadata part")?; - let meta = meta_str.split('_').collect::>(); - let (crc, kind); - - if meta.len() == 1 { - // `CRC` - crc = parse_crc(meta[0]).ok_or("malformed CRC")?; - kind = ReferenceTestKind::SingleImage; - } else if meta.len() == 3 && meta[0] == "anim" { - // `anim_FRAME_CRC` - crc = parse_crc(meta[2]).ok_or("malformed CRC")?; - let frame: usize = meta[1].parse().map_err(|_| "malformed frame number")?; - kind = ReferenceTestKind::AnimatedFrame { - frame: frame.checked_sub(1).ok_or("frame number must be 1-based")?, - }; - } else { - return Err("unrecognized reference image metadata format"); +fn decode_animation_frames(path: &Path) -> Result>, Box> { + let format = ImageFormat::from_path(path)?; + if !format.reading_enabled() { + return Ok(None); // nothing we can do if the feature isn't enabled. + } + + let reader = std::io::BufReader::new(std::fs::File::open(path)?); + let frames: image::Frames<'_> = match format { + #[cfg(feature = "gif")] + ImageFormat::Gif => image::codecs::gif::GifDecoder::new(reader)?.into_frames(), + #[cfg(feature = "png")] + ImageFormat::Png => { + let decoder = image::codecs::png::PngDecoder::new(reader)?; + if !decoder.is_apng()? { + return Ok(None); + } + decoder.apng()?.into_frames() + } + #[cfg(feature = "webp")] + ImageFormat::WebP => { + let decoder = image::codecs::webp::WebPDecoder::new(reader)?; + if !decoder.has_animation() { + return Ok(None); + } + decoder.into_frames() } + _ => { + return Ok(None); // format doesn't support animations + } + }; + let frames = frames.collect_frames()?; + if frames.len() < 2 { + return Ok(None); // not actually animated + } + Ok(Some(frames.into_iter().map(|f| f.into_buffer()).collect())) +} + +struct HashFile { + data: BTreeMap, +} +impl HashFile { + fn open(path: &Path) -> Result> { + let contents = fs::read_to_string(path)?; + let data = toml::from_str(&contents)?; + Ok(Self { data }) + } + fn save(&self, path: &Path) -> Result<(), Box> { + let contents = toml::to_string(&self.data)?; + fs::write(path, contents)?; + Ok(()) + } + + fn get(&self, key: &str) -> Option<&String> { + self.data.get(key) + } - // The remaining part represents the original file name - let orig_filename = filename_parts - .next() - .ok_or("missing original file name")? - .to_owned(); - - Ok(Self { - orig_filename, - crc, - kind, - }) + fn set(&mut self, key: String, value: String) { + self.data.insert(key, value); } } -/// Parse the given string as a hexadecimal CRC hash, used by `check_references`. -fn parse_crc(src: &str) -> Option { - u32::from_str_radix(src, 16).ok() +static HASH_WRITE_LOCK: Mutex<()> = Mutex::new(()); +fn edit_image_hash(key: &str, image: &DynamicImage) -> Result<(), Box> { + let hash = format!("{:x}", crc32fast::hash(image.as_bytes())); + let guard = HASH_WRITE_LOCK.lock().unwrap(); + let mut hash_file = HashFile::open(&HASH_PATH)?; + hash_file.set(key.to_string(), hash); + hash_file.save(&HASH_PATH)?; + std::mem::drop(guard); + Ok(()) } diff --git a/tests/regression.rs b/tests/regression.rs index c57415195e..e477748f7c 100644 --- a/tests/regression.rs +++ b/tests/regression.rs @@ -78,28 +78,6 @@ fn check_webp_frames_regressions() { } } -/// Regression test for ICO files containing BMP V5 images with embedded ICC profiles. -/// The ICC profile offset in BITMAPV5HEADER is relative to the DIB header start, so it -/// should work correctly when embedded in ICO files (which don't have a BITMAPFILEHEADER). -/// This test verifies the image can be fully decoded without errors. -#[cfg(feature = "ico")] -#[test] -fn ico_bmp_v5_with_icc_profile() { - let path = BASE_PATH - .iter() - .collect::() - .join(IMAGE_DIR) - .join("ico/images") - .join("bmp_v5_with_icc.ico"); - - // Verify the image can be opened and decoded without errors - let img = image::open(&path).expect("Failed to open ICO with BMP V5 ICC profile"); - - // Verify the image has expected dimensions (127x64 from rgb24prof.bmp) - assert_eq!(img.width(), 127); - assert_eq!(img.height(), 64); -} - // Test that BMP bitmaps with extra `BI_BITFIELD` values are parsed correctly. // // The test data comes from a `CF_DIBV5` bitmap on the Windows clipboard. It is a screenshot