X-Git-Url: http://git.shiar.nl/sheet.git/blobdiff_plain/9918b9a0fe4c8ddb0a78cc4639959b2463c1f4dd..e1c15e98e78002475bc637d1a5848b45414b9e41:/codec-image.inc.pl diff --git a/codec-image.inc.pl b/codec-image.inc.pl new file mode 100644 index 0000000..92e17d5 --- /dev/null +++ b/codec-image.inc.pl @@ -0,0 +1,504 @@ +use utf8; ++{ +codec => { + jpeg => { + name => 'JPEG', + available => 1992, + }, + gif => { + name => 'GIF', + available => 1987, + }, + png => { + name => 'PNG', + available => 1996, + }, + jp2k => { + name => 'JPEG 2000', + available => 2000, + }, + webp => { + name => 'WebP', + available => 2010, + }, + heic => { + name => 'HEIC', + available => 2015, + }, + avif => { + name => 'AVIF', + available => 2019, + }, + jxl => { + name => 'JPEG XL', + available => 2021, + }, + pnm => { + name => 'PNM', + available => 1988, + }, +}, +feature => { + default => { + children => [qw( quality_photo quality_art speed limits features royalties overhead support )], + }, + quality_photo => { + name => 'compression (photo)', + score => { + jpeg => 3, + pnm => 'n', + gif => 1, + png => 1, + jp2k => 4, + webp => 3, + heic => 5, + avif => 5, + jxl => 5, + }, + children => [qw( quality_photo_1 quality_photo_2 quality_photo_3 quality_photo_ll )], + }, + quality_photo_1 => { + parent => 'quality_photo', + name => 'thumbnails', + score => { + jpeg => 2, + pnm => 1, + gif => 1, + png => 1, + jp2k => 3, + webp => 4, + heic => 5, + avif => 5, + jxl => 3, + }, + }, + quality_photo_2 => { + parent => 'quality_photo', + name => 'medium fidelity', + score => { + jpeg => 3, + pnm => 1, + gif => 1, + png => 1, + jp2k => 4, + webp => 3, + heic => 4, + avif => 5, + jxl => 5, + }, + }, + quality_photo_3 => { + parent => 'quality_photo', + name => 'high fidelity', + score => { + jpeg => 3, + pnm => 1, + gif => 1, + png => 2, + jp2k => 4, + webp => 2, + heic => 3, + avif => 4, + jxl => 5, + }, + }, + quality_photo_ll => { + parent => 'quality_photo', + name => 'lossless', + score => { + jpeg => 1, + pnm => 1, + gif => 1, + png => 2, + jp2k => 4, + webp => 3, + heic => 3, + avif => 3, + jxl => 5, + }, + }, + quality_art => { + name => 'compression (other images)', + score => { + jpeg => 2, + pnm => 'n', + gif => 1, + png => 3, + jp2k => 2, + webp => 4, + heic => 3, + avif => 4.5, + jxl => 5, + }, + children => [qw( quality_art_2 quality_art_ll quality_art_mixed )], + }, + quality_art_2 => { + name => 'lossy non-photographic', + score => { + jpeg => 2, + pnm => 1, + gif => 2, + png => 3, + jp2k => 2, + webp => 4, + heic => 3, + avif => 5, + jxl => 5, + }, + }, + quality_art_ll => { + name => 'lossless non-photographic', + score => { + jpeg => 1, + pnm => 1, + gif => 1, + png => 4, + jp2k => 2, + webp => 5, + heic => 2, + avif => 3, + jxl => 5, + }, + }, + quality_art_mixed => { + name => 'mixed photo/nonphoto', + score => { + jpeg => 2, + pnm => 1, + gif => 1, + png => 2, + jp2k => 2, + webp => 3, + heic => 3, + avif => 5, + jxl => 5, + }, + }, + speed => { + score => { + jpeg => 5, + pnm => 5, + gif => 4, + png => 4, + jp2k => 3, + webp => 4, + heic => 3, + avif => 3, + jxl => 5, + }, + children => [qw( speed_encode speed_decode speed_parallel )], + }, + speed_encode => { + parent => 'speed', + name => 'single-core encode', + score => { + jpeg => 5, + pnm => 0, + gif => 3, # palette conversion + png => 3, + jp2k => 4, + webp => 4, + heic => 3, + avif => 2, + jxl => 5, + }, + }, + speed_decode => { + parent => 'speed', + name => 'single-core decode', + score => { + jpeg => 5, + pnm => 0, + gif => 5, + png => 5, + jp2k => 4, + webp => 5, + heic => 3, + avif => 3, + jxl => 5, + }, + }, + speed_parallel => { + parent => 'speed', + name => 'pararellizable', + score => { + jpeg => 2, + pnm => 0, + gif => 2, + png => 2, + jp2k => 4, + webp => 2, + heic => 4, + avif => 4, + jxl => 5, + }, + }, + limits => { + score => { + jpeg => 3, + pnm => 3, + gif => 2, + png => 4, + jp2k => 5, + webp => 2, + heic => 4, + avif => 4.5, + jxl => 5, + }, + children => [qw( max_dimensions max_bitdepth color_444 hdr max_channels )], + }, + max_dimensions => { + parent => 'limits', + name => 'maximum image dimensions', + score => { + jpeg => [3, '65k²'], # 2**16 + pnm => [5, '∞'], + gif => [3, '65k²'], # 2**16 + png => [4, '2G²'], # 2**31 + jp2k => [4, '4G²'], # 2**32 + webp => [1, '16k²'], # 2**14 + heic => [2,'8k×4k+', 'tilable, only 512×512 on Apple'], # 8193x4320 + avif => [3, '65k²+', 'tilable, 7680×4320 with Advanced profile'], # 2**16 + jxl => [4, '1G²'], # 2**30 + }, + }, + max_bitdepth => { + parent => 'limits', + name => 'precision (max. bit depth)', + score => { + jpeg => [2, 8], + pnm => [2, 8, 'unofficial PFM extension for 32-bit'], + gif => [1, 8, '256 colour palette per frame'], + png => [4, 16], + jp2k => [5, 38], + webp => [2, 8], + heic => [3, 10], #TODO 16? + avif => [3, 12, '8, 10, 12 bit'], + jxl => [5, 32, '24-bit integer or 32-bit float'], + }, + }, + color_444 => { + parent => 'limits', + name => 'chroma subsampling', + score => { + jpeg => ['y', undef, '4:2:0, 4:2:2, 4:4:4'], + pnm => [4, '✘'], + gif => [4, '✘'], + png => [4, '✘'], + jp2k => 'y', + webp => [1, '4:2:0'], + heic => [1, '4:2:0'], + avif => ['y', undef, '4:2:0, 4:2:2, 4:4:4'], + jxl => ['y', undef, 'for JPEG compatibility'], + }, + }, + hdr => { + parent => 'limits', + name => 'wide gamut/HDR', + score => { + jpeg => 'n', + pnm => 'n', + gif => 'n', + png => 'y', + jp2k => 'y', + webp => 'n', + heic => 'y', + avif => 'y', + jxl => 'y', + }, + }, + max_channels => { + parent => 'limits', + name => 'maximum number of channels', + score => { + jpeg => [3, 4, 'RGB or CMYK'], + pnm => [3, 3, 'RGB'], + gif => [3, 3, 'RGB palette'], + png => [3, 4, 'RGBA'], + jp2k => [5, 2**15], + webp => [3, 4, 'RGBA'], + heic => [3, 3, 'RGB, separate alpha and depth'], + avif => [3, 3, 'RGB, separate alpha and depth'], + jxl => [4, 4099, 'native XYB'], + }, + }, + features => { + score => { + jpeg => 2, + pnm => [2, undef, 'great for simplicity and ASCII storage'], + gif => 2, + png => 3, + jp2k => 4, + webp => 2, + heic => 4, + avif => 4, + jxl => 5, + }, + children => [qw( animation progressive alpha depthmap overlays authoring reencode compat_jpeg )], + }, + animation => { + parent => 'features', + name => 'supports animation', + score => { + jpeg => [2, 'MJPEG'], + pnm => 'n', + gif => 'y', + png => [4, 'APNG', 'later backwards-compatible extension'], + jp2k => [2, 'MJP2'], + webp => 'y', + heic => 'y', + avif => 'y', + jxl => 'y', + }, + }, + progressive => { + parent => 'features', + name => 'progressive decoding', + score => { + jpeg => 4, + pnm => 'n', + gif => 2, + png => 2, + jp2k => 5, + webp => 'n', + heic => 'n', + avif => 'n', + jxl => 5, + }, + }, + alpha => { + parent => 'features', + name => 'alpha transparency', + score => { + jpeg => 'n', + pnm => ['n', undef, 'PAM extension'], + gif => [3, '1 bit'], + png => 'y', + jp2k => 'y', + webp => 'y', + heic => 'y', + avif => 'y', + jxl => 'y', + }, + }, + depthmap => { + parent => 'features', + name => 'depth map', + score => { + jpeg => 'n', + pnm => 'n', + gif => 'n', + png => 'n', + jp2k => 'n', + webp => 'n', + heic => 'y', + avif => 'y', + jxl => 'y', + }, + }, + overlays => { + parent => 'features', + name => 'overlays (layers)', + score => { + jpeg => 'n', + pnm => 'n', + gif => 'y', + png => 'n', + jp2k => 'n', + webp => 'n', + heic => 'y', + avif => 'y', + jxl => 'y', + }, + }, + authoring => { + parent => 'features', + name => 'authoring workflow suitability', + score => { + jpeg => 2, + pnm => 2, + gif => 2, + png => 3, + jp2k => 3, + webp => 2, + heic => 2, + avif => 2, + jxl => 5, + }, + }, + reencode => { + parent => 'features', + name => 'generation loss resilience', + score => { + jpeg => 4, + pnm => 0, + png => 0, + gif => 0, + jp2k => 3, + webp => 2, + heic => 3, + avif => 3, + jxl => 4, + }, + }, + compat_jpeg => { + parent => 'features', + name => 'lossless JPEG recompression', + score => { + jpeg => 0, + pnm => 'n', + gif => 'n', + png => 'n', + jp2k => 'n', + webp => 'n', + heic => 'n', + avif => 'n', + jxl => 'y', + }, + }, + royalties => { + name => 'royalty-free', + score => { + jpeg => 5, + pnm => 5, + gif => [5, undef, 'patented before 2003'], + png => 5, + jp2k => [3, undef, 'ISO specification not freely available'], + webp => [4, undef, 'free format, low remaining risk of patent trolls'], + heic => ['n', undef, 'heavily patented'], + avif => [4, undef, 'free format, risk of patent trolls'], + jxl => [4, undef, 'free format, risk of patent trolls'], + }, + children => [], + }, + support => { + score => { + jpeg => 5, + pnm => [2, undef], + gif => 5, + png => 5, + jp2k => [2, undef, 'Apple only'], + webp => [4, undef, 'modern browsers'], + heic => [1, undef, 'stored by latest cameras, no browser support'], + avif => [3, undef, 'all modern browsers except Safari and Edge'], + jxl => [2, undef, 'upcoming in most browsers'], + }, + }, + overhead => { + name => 'container overhead (file size)', + score => { + png => [3, 67, 'upto 70 bytes for specific RGBA'], + jpeg => [2, 160, '159 bytes minimum for gray, 288 for specific colours'], + gif => [4, 35, '43 bytes for transparent'], + webp => [4, 34, 'black or transparent lossless; 44-92 bytes lossy'], + bpg => [4, 31, 'lossy 29-62 bytes, lossless 37-160'], + flif => [5, 14, 'black or transparent; 20 bytes for specific RGBA'], + pnm => [5, 8, 'monochrome text PBM; 12 bytes PPM; 69 bytes PAM'], + jxl => [5, 12, '512×256 black pixels'], + avif => [1, 282, 'container overhead; 457 bytes with alpha'], + jp2k => [2, 123, 'experimental results, likely not optimal'], + heic => [1, 386], + }, + }, +}, +}