3 intro => 'Comparison of image encoding formats, based on <a href="https://cloudinary.com/blog/one_pixel_is_worth_three_thousand_words">Cloudinary</a> research.',
6 name => '<abbr title="Joint Photographic Experts Group">JPEG</abbr>',
11 name => '<abbr title="Graphics Interchange Format">GIF</abbr>',
16 name => '<abbr title="Portable Network Graphics">PNG</abbr>',
31 name => '<abbr title="High Efficiency Image Container (HEVC in HEIF)">HEIC</abbr>',
36 name => '<abbr title="AV1 Image File Format">AVIF</abbr>',
46 name => '<abbr title="Portable aNyMap">PNM</abbr>',
53 children => [qw( quality_photo quality_art speed limits features royalties overhead support web )],
56 name => 'compression (photo)',
68 children => [qw( quality_photo_ll quality_photo_3 quality_photo_2 quality_photo_1 quality_thumbs )],
71 parent => 'quality_photo',
86 parent => 'quality_photo',
87 name => 'low fidelity',
101 parent => 'quality_photo',
102 name => 'medium fidelity',
116 parent => 'quality_photo',
117 name => 'high fidelity',
130 quality_photo_ll => {
131 parent => 'quality_photo',
146 name => 'compression (other images)',
158 children => [qw( quality_art_2 quality_art_ll quality_art_mixed )],
161 name => 'lossy non-photographic',
175 name => 'lossless non-photographic',
188 quality_art_mixed => {
189 name => 'mixed photo/nonphoto',
214 children => [qw( speed_encode speed_decode speed_parallel )],
218 name => 'single-core encode',
222 gif => 3, # palette conversion
233 name => 'single-core decode',
248 name => 'pararellizable',
273 children => [qw( max_dimensions max_bitdepth color_444 hdr max_channels )],
277 name => 'maximum image dimensions',
279 jpeg => [3, '65k²'], # 2**16
281 gif => [3, '65k²'], # 2**16
282 png => [4, '2G²'], # 2**31
283 jp2k => [4, '4G²'], # 2**32
284 webp => [1, '16k²'], # 2**14
285 heic => [2,'8k×4k+', 'tilable, only 512×512 on Apple'], # 8193x4320
286 avif => [3, '65k²+', 'tilable, 7680×4320 with Advanced profile'], # 2**16
287 jxl => [4, '1G²'], # 2**30
292 name => 'precision (max. bit depth)',
295 pnm => [2, 8, 'unofficial PFM extension for 32-bit'],
296 gif => [1, 8, '256 colour palette per frame'],
300 heic => [3, 10], #TODO 16?
301 avif => [3, 12, '8, 10, 12 bit'],
302 jxl => [5, 32, '24-bit integer or 32-bit float'],
307 name => 'chroma subsampling',
309 jpeg => ['y', undef, '4:2:0, 4:2:2, 4:4:4'],
314 webp => [1, '4:2:0'],
315 heic => [1, '4:2:0'],
316 avif => ['y', undef, '4:2:0, 4:2:2, 4:4:4'],
317 jxl => ['y', undef, 'for JPEG compatibility'],
322 name => 'wide gamut/HDR',
337 name => 'maximum number of channels',
339 jpeg => [3, 4, 'RGB or CMYK'],
340 pnm => [3, 3, 'RGB'],
341 gif => [3, 3, 'RGB palette'],
342 png => [3, 4, 'RGBA'],
344 webp => [3, 4, 'RGBA'],
345 heic => [3, 3, 'RGB, separate alpha and depth'],
346 avif => [3, 3, 'RGB, separate alpha and depth'],
347 jxl => [4, 4099, 'native XYB'],
353 pnm => [2, undef, 'great for simplicity and ASCII storage'],
362 children => [qw( animation progressive alpha depthmap overlays vector authoring reencode compat_jpeg )],
365 parent => 'features',
366 name => 'supports animation',
368 jpeg => [2, 'MJPEG'],
371 png => [4, 'APNG', 'later backwards-compatible extension'],
380 parent => 'features',
381 name => 'progressive decoding',
395 parent => 'features',
396 name => 'vector drawing',
406 jxl => [2, undef, 'splines'],
410 parent => 'features',
411 name => 'alpha transparency',
414 pnm => ['n', undef, 'PAM extension'],
425 parent => 'features',
440 parent => 'features',
441 name => 'overlays (layers)',
455 parent => 'features',
456 name => 'authoring workflow suitability',
470 parent => 'features',
471 name => 'generation loss resilience',
485 parent => 'features',
486 name => 'lossless JPEG recompression',
500 name => 'royalty-free',
504 gif => [5, undef, 'patented before 2003'],
506 jp2k => [3, undef, 'ISO specification not freely available'],
507 webp => [4, undef, 'free format, low remaining risk of patent trolls'],
508 heic => ['n', undef, 'heavily patented'],
509 avif => [4, undef, 'free format, risk of patent trolls'],
510 jxl => [4, undef, 'free format, risk of patent trolls'],
515 name => 'browser support',
517 jpeg => [5, undef, 'ubiquitous since first inline images (1993)'],
518 pnm => [1, undef, 'rarely by (unix) systems'],
519 xbm => [2, undef, 'common before 200X'],
520 gif => [5, undef, 'predates the web, but unrestricted since 2004'],
521 png => [5, undef, 'problematic prior to IE7, currently ubiquitous'],
522 jp2k => [2, undef, 'just Safari'],
523 webp => [4, undef, 'widespread since 2020'],
524 heic => [1, undef, 'no browser support'],
525 avif => [3, undef, 'significant since 2021 (Safari 2023, no Edge yet)'],
526 jxl => [2, undef, 'experimental, blocked by chrome'],
532 jpeg => [5, undef, 'standard photography'],
533 pnm => [2, undef, 'uncomplicated bitmap interchange'],
534 gif => [4, undef, 'declining due to limitations'],
535 png => [5, undef, 'standard illustrations'],
536 jp2k => [3, undef, 'limited beyond Apple'],
537 webp => [4, undef, 'mostly online'],
538 heic => [2, undef, 'stored by latest cameras, interchange unlikely'],
539 avif => [3, undef, 'upcoming'],
540 jxl => [2, undef, 'ongoing'],
544 name => 'container overhead (file size)',
546 png => [3, 67, 'upto 70 bytes for specific RGBA'],
547 jpeg => [2, 160, '159 bytes minimum for gray, 288 for specific colours'],
548 gif => [4, 35, '43 bytes for transparent'],
549 webp => [4, 34, 'black or transparent lossless; 44-92 bytes lossy'],
550 bpg => [4, 31, 'lossy 29-62 bytes, lossless 37-160'],
551 flif => [5, 14, 'black or transparent; 20 bytes for specific RGBA'],
552 pnm => [5, 8, 'monochrome text PBM; 12 bytes PPM; 69 bytes PAM'],
553 jxl => [5, 12, '512×256 black pixels'],
554 avif => [1, 282, 'container overhead; 457 bytes with alpha'],
555 jp2k => [2, 123, 'experimental results, likely not optimal'],