use utf8;
+{
codec => {
	jpeg => {
		name => '<abbr title="Joint Photographic Experts Group">JPEG</abbr>',
		available => 1992,
	},
	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,
	},
},
feature => {
	default => {
		children => [qw( quality_photo quality_art speed limits features royalties )],
	},
	quality_photo => {
		name => 'compression (photo)',
		score => {
			jpeg => 3,
			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 => 'low fidelity',
		score => {
			jpeg => 2,
			png  => 1,
			jp2k => 3,
			webp => 3,
			heic => 5,
			avif => 5,
			jxl  => 4,
		},
	},
	quality_photo_2 => {
		parent => 'quality_photo',
		name => 'medium fidelity',
		score => {
			jpeg => 3,
			png  => 1,
			jp2k => 4,
			webp => 3,
			heic => 4,
			avif => 5,
			jxl  => 5,
		},
	},
	quality_photo_3 => {
		parent => 'quality_photo',
		name => 'high fidelity',
		score => {
			jpeg => 3,
			png  => 2,
			jp2k => 4,
			webp => 2,
			heic => 3,
			avif => 4,
			jxl  => 5,
		},
	},
	quality_photo_ll => {
		parent => 'quality_photo',
		name => 'lossless',
		score => {
			jpeg => 1,
			png  => 2,
			jp2k => 4,
			webp => 3,
			heic => 3,
			avif => 3,
			jxl  => 5,
		},
	},
	quality_art => {
		name => 'compression (other images)',
		score => {
			jpeg => 2,
			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,
			png  => 3,
			jp2k => 2,
			webp => 4,
			heic => 3,
			avif => 5,
			jxl  => 5,
		},
	},
	quality_art_ll => {
		name => 'lossless non-photographic',
		score => {
			jpeg => 1,
			png  => 4,
			jp2k => 2,
			webp => 5,
			heic => 2,
			avif => 3,
			jxl  => 5,
		},
	},
	quality_art_mixed => {
		name => 'mixed photo/nonphoto',
		score => {
			jpeg => 2,
			png  => 2,
			jp2k => 2,
			webp => 3,
			heic => 3,
			avif => 5,
			jxl  => 5,
		},
	},
	speed => {
		score => {
			jpeg => 5,
			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,
			png  => 3,
			jp2k => 4,
			webp => 4,
			heic => 3,
			avif => 2,
			jxl  => 5,
		},
	},
	speed_decode => {
		parent => 'speed',
		name => 'single-core decode',
		score => {
			jpeg => 5,
			png  => 5,
			jp2k => 4,
			webp => 5,
			heic => 3,
			avif => 3,
			jxl  => 5,
		},
	},
	speed_parallel => {
		parent => 'speed',
		name => 'pararellizable',
		score => {
			jpeg => 2,
			png  => 2,
			jp2k => 4,
			webp => 2,
			heic => 4,
			avif => 4,
			jxl  => 5,
		},
	},
	limits => {
		score => {
			jpeg => 3,
			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,
			png  => 4,
			jp2k => 5,
			webp => 1,
			heic => 2,
			avif => 3,
			jxl  => 4,
		},
		data => {
			jpeg => '65k²',  # 2**16
			png  => '2G²',   # 2**31
			jp2k => '4G²',   # 2**32
			webp => '16k²',  # 2**14
			heic => '8k×4k+', # 8193x4320
			avif => '65k²+',  # 2**16, 8193x4320 with profile
			jxl  => '1G²',   # 2**30
		},
	},
	max_bitdepth => {
		parent => 'limits',
		name => 'precision (max. bit depth)',
		score => {
			jpeg => 2,
			png  => 4,
			jp2k => 5,
			webp => 2,
			heic => 3,
			avif => 3,
			jxl  => 5,
		},
		data => {
			jpeg => 8,
			png  => 16,
			jp2k => 38,
			webp => 8,
			heic => 10,
			avif => 10,
			jxl  => 32,
		},
	},
	color_444 => {
		parent => 'limits',
		name => 'can do (lossy) 4:4:4',
		score => {
			jpeg => 'y',
			png  => 'y',
			jp2k => 'y',
			webp => 'n',
			heic => 'n',
			avif => 'y',
			jxl  => 'y',
		},
	},
	hdr => {
		parent => 'limits',
		name => 'wide gamut/HDR',
		score => {
			jpeg => 'n',
			png  => 'y',
			jp2k => 'y',
			webp => 'n',
			heic => 'y',
			avif => 'y',
			jxl  => 'y',
		},
	},
	max_channels => {
		parent => 'limits',
		name => 'maximum number of channels',
		score => {
			jpeg => 2,
			png  => 2,
			jp2k => 5,
			webp => 2,
			heic => 3,
			avif => 3,
			jxl  => 4,
		},
		data => {
			jpeg => 4, # cmyk
			png  => 4, # cmyk
			jp2k => 2**15,
			webp => 4,
			heic => 5,
			avif => 5,
			jxl  => 4099,
		},
	},
	features => {
		score => {
			jpeg => 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,
			png  => 4,
			jp2k => 2,
			webp => 'y',
			heic => 'y',
			avif => 'y',
			jxl  => 'y',
		},
		data => {
			jpeg => 'MJPEG',
			png  => 'APNG',
			jp2k => 'MJP2',
		},
	},
	progressive => {
		parent => 'features',
		name => 'progressive decoding',
		score => {
			jpeg => 4,
			png  => 2,
			jp2k => 5,
			webp => 'n',
			heic => 'n',
			avif => 'n',
			jxl  => 5,
		},
	},
	alpha => {
		parent => 'features',
		name => 'alpha transparency',
		score => {
			jpeg => 'n',
			png  => 'y',
			jp2k => 'y',
			webp => 'y',
			heic => 'y',
			avif => 'y',
			jxl  => 'y',
		},
	},
	depthmap => {
		parent => 'features',
		name => 'depth map',
		score => {
			jpeg => 'n',
			png  => 'n',
			jp2k => 'n',
			webp => 'n',
			heic => 'y',
			avif => 'y',
			jxl  => 'y',
		},
	},
	overlays => {
		parent => 'features',
		name => 'overlays',
		score => {
			jpeg => 'n',
			png  => 'n',
			jp2k => 'n',
			webp => 'n',
			heic => 'y',
			avif => 'y',
			jxl  => 'y',
		},
	},
	authoring => {
		parent => 'features',
		name => 'authoring workflow suitability',
		score => {
			jpeg => 2,
			png  => 3,
			jp2k => 3,
			webp => 2,
			heic => 2,
			avif => 2,
			jxl  => 5,
		},
	},
	reencode => {
		parent => 'features',
		name => 'generation loss resilience',
		score => {
			jpeg => 4,
			png  => 'n/a',
			jp2k => 3,
			webp => 2,
			heic => 3,
			avif => 3,
			jxl  => 4,
		},
		data => {
			png  => 'n/a',
		},
	},
	compat_jpeg => {
		parent => 'features',
		name => 'lossless JPEG recompression',
		score => {
			jpeg => 0,
			png  => 'n',
			jp2k => 'n',
			webp => 'n',
			heic => 'n',
			avif => 'n',
			jxl  => 'y',
		},
		data => {
			jpeg => 'n/a',
		},
	},
	royalties => {
		name => 'royalty-free',
		score => {
			jpeg => 5,
			png  => 5,
			gif  => 5, # patents expired
			jp2k => 3, # specs not freely available
			webp => 4, # submarine risk
			heic => 'n', # patents enforced
			avif => 4,
			jxl  => 4,
		},
		children => [],
	},
},
}
