},
},
feature => {
+ default => {
+ children => [qw( quality_photo quality_art speed limits features royalties )],
+ },
quality_photo => {
name => 'compression (photo)',
score => {
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,
},
},
quality_photo_2 => {
+ parent => 'quality_photo',
name => 'medium fidelity',
score => {
jpeg => 3,
},
},
quality_photo_3 => {
+ parent => 'quality_photo',
name => 'high fidelity',
score => {
jpeg => 3,
},
},
quality_photo_ll => {
+ parent => 'quality_photo',
name => 'lossless',
score => {
jpeg => 1,
avif => 4.5,
jxl => 5,
},
+ children => [qw( quality_art_2 quality_art_ll quality_art_mixed )],
},
quality_art_2 => {
name => 'lossy non-photographic',
avif => 3,
jxl => 5,
},
+ children => [qw( speed_encode speed_decode speed_parallel )],
},
speed_encode => {
+ parent => 'speed',
name => 'single-core encode',
score => {
jpeg => 5,
},
},
speed_decode => {
+ parent => 'speed',
name => 'single-core decode',
score => {
jpeg => 5,
},
},
speed_parallel => {
+ parent => 'speed',
name => 'pararellizable',
score => {
jpeg => 2,
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,
},
},
max_bitdepth => {
+ parent => 'limits',
name => 'precision (max. bit depth)',
score => {
jpeg => 2,
},
},
color_444 => {
+ parent => 'limits',
name => 'can do (lossy) 4:4:4',
score => {
jpeg => 'y',
},
},
hdr => {
+ parent => 'limits',
name => 'wide gamut/HDR',
score => {
jpeg => 'n',
},
},
max_channels => {
+ parent => 'limits',
name => 'maximum number of channels',
score => {
jpeg => 2,
avif => 4,
jxl => 5,
},
+ children => [qw( animation progressive alpha depthmap overlays authoring reencode compat_jpeg )],
},
animation => {
+ parent => 'features',
name => 'supports animation',
score => {
jpeg => 2,
},
},
progressive => {
+ parent => 'features',
name => 'progressive decoding',
score => {
jpeg => 4,
},
},
alpha => {
+ parent => 'features',
name => 'alpha transparency',
score => {
jpeg => 'n',
},
},
depthmap => {
+ parent => 'features',
name => 'depth map',
score => {
jpeg => 'n',
},
},
overlays => {
+ parent => 'features',
name => 'overlays',
score => {
jpeg => 'n',
},
},
authoring => {
+ parent => 'features',
name => 'authoring workflow suitability',
score => {
jpeg => 2,
},
},
reencode => {
+ parent => 'features',
name => 'generation loss resilience',
score => {
jpeg => 4,
},
},
compat_jpeg => {
+ parent => 'features',
name => 'lossless JPEG recompression',
score => {
jpeg => 0,
avif => 4,
jxl => 4,
},
+ children => [],
},
},
}
<(common.inc.plp)><:
+my @feat = split m{/+}, $Request || 'default';
+
Html({
title => 'Codecs',
version => '1.0',
print '<td>', $_->{available} for @{$info->{codec}}{@codecs};
say '</thead>';
-print '<tbody>';
-for my $feat (sort keys %{$info->{feature}}) {
- my $featinfo = $info->{feature}->{$feat};
+while (defined (my $feat = shift @feat)) {
+ my $featinfo = $info->{feature}->{$feat} or next;
+ unshift @feat, @{$_} for $featinfo->{children} // ();
+ $featinfo->{score} or $featinfo->{data} or next;
+ print '<tbody>' if $featinfo->{children};
printf '<tr><th>%s', $featinfo->{name} // $feat;
printf('<td class="l%d">%s',
(map { $_ && $BOOLSCORE{$_} || $_ || 0 } $featinfo->{score}->{$_}),