+++ /dev/null
-use utf8;
-+{
-codec => {
- jpeg => {
- name => '<abbr title="Joint Photographic Experts Group">JPEG</abbr>',
- available => 1992,
- },
- gif => {
- name => '<abbr title="Graphics Interchange Format">GIF</abbr>',
- available => 1987,
- },
- png => {
- name => '<abbr title="Portable Network Graphics">PNG</abbr>',
- available => 1996,
- },
- jp2k => {
- name => 'JPEG 2000',
- available => 2000,
- },
- webp => {
- name => 'WebP',
- available => 2010,
- },
- heic => {
- name => '<abbr title="High Efficiency Image Container (HEVC in HEIF)">HEIC</abbr>',
- available => 2015,
- },
- avif => {
- name => '<abbr title="AV1 Image File Format">AVIF</abbr>',
- available => 2019,
- },
- jxl => {
- name => 'JPEG XL',
- available => 2021,
- },
- pnm => {
- name => '<abbr title="Portable aNyMap">PNM</abbr>',
- 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],
- },
- },
-},
-}