codec: page request overrides image type
[sheet.git] / codec-image.inc.pl
1 use utf8;
2 +{
3 codec => {
4         jpeg => {
5                 name => '<abbr title="Joint Photographic Experts Group">JPEG</abbr>',
6                 available => 1992,
7         },
8         gif => {
9                 name => '<abbr title="Graphics Interchange Format">GIF</abbr>',
10                 available => 1987,
11         },
12         png => {
13                 name => '<abbr title="Portable Network Graphics">PNG</abbr>',
14                 available => 1996,
15         },
16         jp2k => {
17                 name => 'JPEG 2000',
18                 available => 2000,
19         },
20         webp => {
21                 name => 'WebP',
22                 available => 2010,
23         },
24         heic => {
25                 name => '<abbr title="High Efficiency Image Container (HEVC in HEIF)">HEIC</abbr>',
26                 available => 2015,
27         },
28         avif => {
29                 name => '<abbr title="AV1 Image File Format">AVIF</abbr>',
30                 available => 2019,
31         },
32         jxl => {
33                 name => 'JPEG XL',
34                 available => 2021,
35         },
36         pnm => {
37                 name => '<abbr title="Portable aNyMap">PNM</abbr>',
38                 available => 1988,
39         },
40 },
41 feature => {
42         default => {
43                 children => [qw( quality_photo quality_art speed limits features royalties overhead support )],
44         },
45         quality_photo => {
46                 name => 'compression (photo)',
47                 score => {
48                         jpeg => 3,
49                         pnm  => 'n',
50                         gif  => 1,
51                         png  => 1,
52                         jp2k => 4,
53                         webp => 3,
54                         heic => 5,
55                         avif => 5,
56                         jxl  => 5,
57                 },
58                 children => [qw( quality_photo_1 quality_photo_2 quality_photo_3 quality_photo_ll )],
59         },
60         quality_photo_1 => {
61                 parent => 'quality_photo',
62                 name => 'thumbnails',
63                 score => {
64                         jpeg => 2,
65                         pnm  => 1,
66                         gif  => 1,
67                         png  => 1,
68                         jp2k => 3,
69                         webp => 4,
70                         heic => 5,
71                         avif => 5,
72                         jxl  => 3,
73                 },
74         },
75         quality_photo_2 => {
76                 parent => 'quality_photo',
77                 name => 'medium fidelity',
78                 score => {
79                         jpeg => 3,
80                         pnm  => 1,
81                         gif  => 1,
82                         png  => 1,
83                         jp2k => 4,
84                         webp => 3,
85                         heic => 4,
86                         avif => 5,
87                         jxl  => 5,
88                 },
89         },
90         quality_photo_3 => {
91                 parent => 'quality_photo',
92                 name => 'high fidelity',
93                 score => {
94                         jpeg => 3,
95                         pnm  => 1,
96                         gif  => 1,
97                         png  => 2,
98                         jp2k => 4,
99                         webp => 2,
100                         heic => 3,
101                         avif => 4,
102                         jxl  => 5,
103                 },
104         },
105         quality_photo_ll => {
106                 parent => 'quality_photo',
107                 name => 'lossless',
108                 score => {
109                         jpeg => 1,
110                         pnm  => 1,
111                         gif  => 1,
112                         png  => 2,
113                         jp2k => 4,
114                         webp => 3,
115                         heic => 3,
116                         avif => 3,
117                         jxl  => 5,
118                 },
119         },
120         quality_art => {
121                 name => 'compression (other images)',
122                 score => {
123                         jpeg => 2,
124                         pnm  => 'n',
125                         gif  => 1,
126                         png  => 3,
127                         jp2k => 2,
128                         webp => 4,
129                         heic => 3,
130                         avif => 4.5,
131                         jxl  => 5,
132                 },
133                 children => [qw( quality_art_2 quality_art_ll quality_art_mixed )],
134         },
135         quality_art_2 => {
136                 name => 'lossy non-photographic',
137                 score => {
138                         jpeg => 2,
139                         pnm  => 1,
140                         gif  => 2,
141                         png  => 3,
142                         jp2k => 2,
143                         webp => 4,
144                         heic => 3,
145                         avif => 5,
146                         jxl  => 5,
147                 },
148         },
149         quality_art_ll => {
150                 name => 'lossless non-photographic',
151                 score => {
152                         jpeg => 1,
153                         pnm  => 1,
154                         gif  => 1,
155                         png  => 4,
156                         jp2k => 2,
157                         webp => 5,
158                         heic => 2,
159                         avif => 3,
160                         jxl  => 5,
161                 },
162         },
163         quality_art_mixed => {
164                 name => 'mixed photo/nonphoto',
165                 score => {
166                         jpeg => 2,
167                         pnm  => 1,
168                         gif  => 1,
169                         png  => 2,
170                         jp2k => 2,
171                         webp => 3,
172                         heic => 3,
173                         avif => 5,
174                         jxl  => 5,
175                 },
176         },
177         speed => {
178                 score => {
179                         jpeg => 5,
180                         pnm  => 5,
181                         gif  => 4,
182                         png  => 4,
183                         jp2k => 3,
184                         webp => 4,
185                         heic => 3,
186                         avif => 3,
187                         jxl  => 5,
188                 },
189                 children => [qw( speed_encode speed_decode speed_parallel )],
190         },
191         speed_encode => {
192                 parent => 'speed',
193                 name => 'single-core encode',
194                 score => {
195                         jpeg => 5,
196                         pnm  => 0,
197                         gif  => 3, # palette conversion
198                         png  => 3,
199                         jp2k => 4,
200                         webp => 4,
201                         heic => 3,
202                         avif => 2,
203                         jxl  => 5,
204                 },
205         },
206         speed_decode => {
207                 parent => 'speed',
208                 name => 'single-core decode',
209                 score => {
210                         jpeg => 5,
211                         pnm  => 0,
212                         gif  => 5,
213                         png  => 5,
214                         jp2k => 4,
215                         webp => 5,
216                         heic => 3,
217                         avif => 3,
218                         jxl  => 5,
219                 },
220         },
221         speed_parallel => {
222                 parent => 'speed',
223                 name => 'pararellizable',
224                 score => {
225                         jpeg => 2,
226                         pnm  => 0,
227                         gif  => 2,
228                         png  => 2,
229                         jp2k => 4,
230                         webp => 2,
231                         heic => 4,
232                         avif => 4,
233                         jxl  => 5,
234                 },
235         },
236         limits => {
237                 score => {
238                         jpeg => 3,
239                         pnm  => 3,
240                         gif  => 2,
241                         png  => 4,
242                         jp2k => 5,
243                         webp => 2,
244                         heic => 4,
245                         avif => 4.5,
246                         jxl  => 5,
247                 },
248                 children => [qw( max_dimensions max_bitdepth color_444 hdr max_channels  )],
249         },
250         max_dimensions => {
251                 parent => 'limits',
252                 name => 'maximum image dimensions',
253                 score => {
254                         jpeg => [3, '65k²'],   # 2**16
255                         pnm  => [5,    '∞'],
256                         gif  => [3, '65k²'],   # 2**16
257                         png  => [4,  '2G²'],   # 2**31
258                         jp2k => [4,  '4G²'],   # 2**32
259                         webp => [1, '16k²'],   # 2**14
260                         heic => [2,'8k×4k+', 'tilable, only 512×512 on Apple'], # 8193x4320
261                         avif => [3, '65k²+', 'tilable, 7680×4320 with Advanced profile'], # 2**16
262                         jxl  => [4,  '1G²'],   # 2**30
263                 },
264         },
265         max_bitdepth => {
266                 parent => 'limits',
267                 name => 'precision (max. bit depth)',
268                 score => {
269                         jpeg => [2,  8],
270                         pnm  => [2,  8, 'unofficial PFM extension for 32-bit'],
271                         gif  => [1,  8, '256 colour palette per frame'],
272                         png  => [4, 16],
273                         jp2k => [5, 38],
274                         webp => [2,  8],
275                         heic => [3, 10], #TODO 16?
276                         avif => [3, 12, '8, 10, 12 bit'],
277                         jxl  => [5, 32, '24-bit integer or 32-bit float'],
278                 },
279         },
280         color_444 => {
281                 parent => 'limits',
282                 name => 'chroma subsampling',
283                 score => {
284                         jpeg => ['y', undef, '4:2:0, 4:2:2, 4:4:4'],
285                         pnm  => [4, '✘'],
286                         gif  => [4, '✘'],
287                         png  => [4, '✘'],
288                         jp2k => 'y',
289                         webp => [1, '4:2:0'],
290                         heic => [1, '4:2:0'],
291                         avif => ['y', undef, '4:2:0, 4:2:2, 4:4:4'],
292                         jxl  => ['y', undef, 'for JPEG compatibility'],
293                 },
294         },
295         hdr => {
296                 parent => 'limits',
297                 name => 'wide gamut/HDR',
298                 score => {
299                         jpeg => 'n',
300                         pnm  => 'n',
301                         gif  => 'n',
302                         png  => 'y',
303                         jp2k => 'y',
304                         webp => 'n',
305                         heic => 'y',
306                         avif => 'y',
307                         jxl  => 'y',
308                 },
309         },
310         max_channels => {
311                 parent => 'limits',
312                 name => 'maximum number of channels',
313                 score => {
314                         jpeg => [3, 4, 'RGB or CMYK'],
315                         pnm  => [3, 3, 'RGB'],
316                         gif  => [3, 3, 'RGB palette'],
317                         png  => [3, 4, 'RGBA'],
318                         jp2k => [5, 2**15],
319                         webp => [3, 4, 'RGBA'],
320                         heic => [3, 3, 'RGB, separate alpha and depth'],
321                         avif => [3, 3, 'RGB, separate alpha and depth'],
322                         jxl  => [4, 4099, 'native XYB'],
323                 },
324         },
325         features => {
326                 score => {
327                         jpeg => 2,
328                         pnm  => [2, undef, 'great for simplicity and ASCII storage'],
329                         gif  => 2,
330                         png  => 3,
331                         jp2k => 4,
332                         webp => 2,
333                         heic => 4,
334                         avif => 4,
335                         jxl  => 5,
336                 },
337                 children => [qw( animation progressive alpha depthmap overlays authoring reencode compat_jpeg )],
338         },
339         animation => {
340                 parent => 'features',
341                 name => 'supports animation',
342                 score => {
343                         jpeg => [2, 'MJPEG'],
344                         pnm  => 'n',
345                         gif  => 'y',
346                         png  => [4, 'APNG', 'later backwards-compatible extension'],
347                         jp2k => [2, 'MJP2'],
348                         webp => 'y',
349                         heic => 'y',
350                         avif => 'y',
351                         jxl  => 'y',
352                 },
353         },
354         progressive => {
355                 parent => 'features',
356                 name => 'progressive decoding',
357                 score => {
358                         jpeg => 4,
359                         pnm  => 'n',
360                         gif  => 2,
361                         png  => 2,
362                         jp2k => 5,
363                         webp => 'n',
364                         heic => 'n',
365                         avif => 'n',
366                         jxl  => 5,
367                 },
368         },
369         alpha => {
370                 parent => 'features',
371                 name => 'alpha transparency',
372                 score => {
373                         jpeg => 'n',
374                         pnm  => ['n', undef, 'PAM extension'],
375                         gif  => [3, '1 bit'],
376                         png  => 'y',
377                         jp2k => 'y',
378                         webp => 'y',
379                         heic => 'y',
380                         avif => 'y',
381                         jxl  => 'y',
382                 },
383         },
384         depthmap => {
385                 parent => 'features',
386                 name => 'depth map',
387                 score => {
388                         jpeg => 'n',
389                         pnm  => 'n',
390                         gif  => 'n',
391                         png  => 'n',
392                         jp2k => 'n',
393                         webp => 'n',
394                         heic => 'y',
395                         avif => 'y',
396                         jxl  => 'y',
397                 },
398         },
399         overlays => {
400                 parent => 'features',
401                 name => 'overlays (layers)',
402                 score => {
403                         jpeg => 'n',
404                         pnm  => 'n',
405                         gif  => 'y',
406                         png  => 'n',
407                         jp2k => 'n',
408                         webp => 'n',
409                         heic => 'y',
410                         avif => 'y',
411                         jxl  => 'y',
412                 },
413         },
414         authoring => {
415                 parent => 'features',
416                 name => 'authoring workflow suitability',
417                 score => {
418                         jpeg => 2,
419                         pnm  => 2,
420                         gif  => 2,
421                         png  => 3,
422                         jp2k => 3,
423                         webp => 2,
424                         heic => 2,
425                         avif => 2,
426                         jxl  => 5,
427                 },
428         },
429         reencode => {
430                 parent => 'features',
431                 name => 'generation loss resilience',
432                 score => {
433                         jpeg => 4,
434                         pnm  => 0,
435                         png  => 0,
436                         gif  => 0,
437                         jp2k => 3,
438                         webp => 2,
439                         heic => 3,
440                         avif => 3,
441                         jxl  => 4,
442                 },
443         },
444         compat_jpeg => {
445                 parent => 'features',
446                 name => 'lossless JPEG recompression',
447                 score => {
448                         jpeg => 0,
449                         pnm  => 'n',
450                         gif  => 'n',
451                         png  => 'n',
452                         jp2k => 'n',
453                         webp => 'n',
454                         heic => 'n',
455                         avif => 'n',
456                         jxl  => 'y',
457                 },
458         },
459         royalties => {
460                 name => 'royalty-free',
461                 score => {
462                         jpeg => 5,
463                         pnm  => 5,
464                         gif  => [5, undef, 'patented before 2003'],
465                         png  => 5,
466                         jp2k => [3, undef, 'ISO specification not freely available'],
467                         webp => [4, undef, 'free format, low remaining risk of patent trolls'],
468                         heic => ['n', undef, 'heavily patented'],
469                         avif => [4, undef, 'free format, risk of patent trolls'],
470                         jxl  => [4, undef, 'free format, risk of patent trolls'],
471                 },
472                 children => [],
473         },
474         support => {
475                 score => {
476                         jpeg => 5,
477                         pnm  => [2, undef],
478                         gif  => 5,
479                         png  => 5,
480                         jp2k => [2, undef, 'Apple only'],
481                         webp => [4, undef, 'modern browsers'],
482                         heic => [1, undef, 'stored by latest cameras, no browser support'],
483                         avif => [3, undef, 'all modern browsers except Safari and Edge'],
484                         jxl  => [2, undef, 'upcoming in most browsers'],
485                 },
486         },
487         overhead => {
488                 name => 'container overhead (file size)',
489                 score => {
490                         png  => [3,  67, 'upto 70 bytes for specific RGBA'],
491                         jpeg => [2, 160, '159 bytes minimum for gray, 288 for specific colours'],
492                         gif  => [4,  35, '43 bytes for transparent'],
493                         webp => [4,  34, 'black or transparent lossless; 44-92 bytes lossy'],
494                         bpg  => [4,  31, 'lossy 29-62 bytes, lossless 37-160'],
495                         flif => [5,  14, 'black or transparent; 20 bytes for specific RGBA'],
496                         pnm  => [5,   8, 'monochrome text PBM; 12 bytes PPM; 69 bytes PAM'],
497                         jxl  => [5,  12, '512×256 black pixels'],
498                         avif => [1, 282, 'container overhead; 457 bytes with alpha'],
499                         jp2k => [2, 123, 'experimental results, likely not optimal'],
500                         heic => [1, 386],
501                 },
502         },
503 },
504 }