parent => 'limits',
name => 'maximum image dimensions',
score => {
- jpeg => 3,
- gif => 3,
- png => 4,
- jp2k => 5,
- webp => 1,
- heic => 2,
- avif => 3,
- jxl => 4,
- },
- data => {
- jpeg => '65k²', # 2**16
- gif => '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
+ jpeg => [3, '65k²'], # 2**16
+ gif => [3, '65k²'], # 2**16
+ png => [4, '2G²'], # 2**31
+ jp2k => [5, '4G²'], # 2**32
+ webp => [1, '16k²'], # 2**14
+ heic => [2, '8k×4k+'], # 8193x4320
+ avif => [3, '65k²+'], # 2**16, 8193x4320 with profile
+ jxl => [4, '1G²'], # 2**30
},
},
max_bitdepth => {
parent => 'limits',
name => 'precision (max. bit depth)',
score => {
- jpeg => 2,
- gif => 2,
- png => 4,
- jp2k => 5,
- webp => 2,
- heic => 3,
- avif => 3,
- jxl => 5,
- },
- data => {
- jpeg => 8,
- gif => 8,
- png => 16,
- jp2k => 38,
- webp => 8,
- heic => 10,
- avif => 10,
- jxl => 32,
+ jpeg => [2, 8],
+ gif => [2, 8],
+ png => [4, 16],
+ jp2k => [5, 38],
+ webp => [2, 8],
+ heic => [3, 10],
+ avif => [3, 10],
+ jxl => [5, 32],
},
},
color_444 => {
parent => 'limits',
name => 'maximum number of channels',
score => {
- jpeg => 2,
- gif => 1,
- png => 2,
- jp2k => 5,
- webp => 2,
- heic => 3,
- avif => 3,
- jxl => 4,
- },
- data => {
- jpeg => 4, # cmyk
- gif => 3,
- png => 4, # cmyk
- jp2k => 2**15,
- webp => 4,
- heic => 5,
- avif => 5,
- jxl => 4099,
+ jpeg => [2, 4], # cmyk
+ gif => [1, 3],
+ png => [2, 4], # cmyk
+ jp2k => [5, 2**15],
+ webp => [2, 4],
+ heic => [3, 5],
+ avif => [3, 5],
+ jxl => [4, 4099],
},
},
features => {
parent => 'features',
name => 'supports animation',
score => {
- jpeg => 2,
+ jpeg => [2, 'MJPEG'],
gif => 'y',
- png => 4,
- jp2k => 2,
+ png => [4, 'APNG'],
+ jp2k => [2, 'MJP2'],
webp => 'y',
heic => 'y',
avif => 'y',
jxl => 'y',
},
- data => {
- jpeg => 'MJPEG',
- png => 'APNG',
- jp2k => 'MJP2',
- },
},
progressive => {
parent => 'features',
name => 'alpha transparency',
score => {
jpeg => 'n',
- gif => 3,
+ gif => [3, '1 bit'],
png => 'y',
jp2k => 'y',
webp => 'y',
avif => 'y',
jxl => 'y',
},
- data => {
- gif => '1 bit',
- },
},
depthmap => {
parent => 'features',
avif => 3,
jxl => 4,
},
- data => {
- gif => 'n/a',
- png => 'n/a',
- },
},
compat_jpeg => {
parent => 'features',
avif => 'n',
jxl => 'y',
},
- data => {
- jpeg => 'n/a',
- },
},
royalties => {
name => 'royalty-free',
my $info = do 'codec.inc.pl';
$info and %{$info} > 1 or Abort("cannot open operator include", 500, $@ // $!);
-my %BOOLSCORE = (y => 5, n => 1);
+my %BOOLSCORE = (y => [5, '✔'], n => [1, '✘'], 0 => [0, 'n/a']);
:>
<h1>Image codecs</h1>
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;
+ $featinfo->{score} 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}->{$_}),
- $featinfo->{data}->{$_} // (map {
- $BOOLSCORE{$_} ? ($_ eq 'y' ? '✔' : '✘') : '•' x ($_ - 1)
- } $featinfo->{score}->{$_}),
- ) for @codecs;
+ for (@codecs) {
+ my ($score, $data) = map { ref ? @$_ : $_ } $featinfo->{score}->{$_};
+ if (not defined $data) {
+ if (my $override = $BOOLSCORE{$score}) {
+ ($score, $data) = @{$override};
+ }
+ else {
+ $data = '•' x ($score - 1);
+ }
+ }
+ printf '<td class="l%d">%s', $score, $data;
+ }
say '</td>';
}