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.',
4 keywords => [qw( image picture codec encoder encoding decode compression file format type mime )],
7 name => '<abbr title="Joint Photographic Experts Group">JPEG</abbr>',
12 name => '<abbr title="Graphics Interchange Format">GIF</abbr>',
17 name => '<abbr title="Portable Network Graphics">PNG</abbr>',
32 name => '<abbr title="High Efficiency Image Container (HEVC in HEIF)">HEIC</abbr>',
37 name => '<abbr title="AV1 Image File Format">AVIF</abbr>',
47 name => '<abbr title="Portable aNyMap">PNM</abbr>',
54 children => [qw( quality_photo quality_art speed limits features royalties overhead support web )],
57 name => 'compression (photo)',
69 children => [qw( quality_photo_ll quality_photo_3 quality_photo_2 quality_photo_1 quality_thumbs )],
72 parent => 'quality_photo',
87 parent => 'quality_photo',
88 name => 'low fidelity',
102 parent => 'quality_photo',
103 name => 'medium fidelity',
117 parent => 'quality_photo',
118 name => 'high fidelity',
131 quality_photo_ll => {
132 parent => 'quality_photo',
147 name => 'compression (other images)',
159 children => [qw( quality_art_2 quality_art_ll quality_art_mixed )],
162 name => 'lossy non-photographic',
176 name => 'lossless non-photographic',
189 quality_art_mixed => {
190 name => 'mixed photo/nonphoto',
215 children => [qw( speed_encode speed_decode speed_parallel )],
219 name => 'single-core encode',
223 gif => 3, # palette conversion
234 name => 'single-core decode',
249 name => 'pararellizable',
274 children => [qw( max_dimensions max_bitdepth color_444 hdr max_channels )],
278 name => 'maximum image dimensions',
280 jpeg => [3, '65k²'], # 2**16
282 gif => [3, '65k²'], # 2**16
283 png => [4, '2G²'], # 2**31
284 jp2k => [4, '4G²'], # 2**32
285 webp => [1, '16k²'], # 2**14
286 heic => [2,'8k×4k+', 'tilable, only 512×512 on Apple'], # 8193x4320
287 avif => [3, '65k²+', 'tilable, 7680×4320 with Advanced profile'], # 2**16
288 jxl => [4, '1G²'], # 2**30
293 name => 'precision (max. bit depth)',
296 pnm => [2, 8, 'unofficial PFM extension for 32-bit'],
297 gif => [1, 8, '256 colour palette per frame'],
301 heic => [3, 10], #TODO 16?
302 avif => [3, 12, '8, 10, 12 bit'],
303 jxl => [5, 32, '24-bit integer or 32-bit float'],
308 name => 'chroma subsampling',
310 jpeg => ['y', undef, '4:2:0, 4:2:2, 4:4:4'],
315 webp => [1, '4:2:0'],
316 heic => [1, '4:2:0'],
317 avif => ['y', undef, '4:2:0, 4:2:2, 4:4:4'],
318 jxl => ['y', undef, 'for JPEG compatibility'],
323 name => 'wide gamut/HDR',
338 name => 'maximum number of channels',
340 jpeg => [3, 4, 'RGB or CMYK'],
341 pnm => [3, 3, 'RGB'],
342 gif => [3, 3, 'RGB palette'],
343 png => [3, 4, 'RGBA'],
345 webp => [3, 4, 'RGBA'],
346 heic => [3, 3, 'RGB, separate alpha and depth'],
347 avif => [3, 3, 'RGB, separate alpha and depth'],
348 jxl => [4, 4099, 'native XYB'],
354 pnm => [2, undef, 'great for simplicity and ASCII storage'],
363 children => [qw( animation progressive alpha depthmap overlays vector authoring reencode compat_jpeg )],
366 parent => 'features',
367 name => 'supports animation',
369 jpeg => [2, 'MJPEG'],
372 png => [4, 'APNG', 'later backwards-compatible extension'],
381 parent => 'features',
382 name => 'progressive decoding',
396 parent => 'features',
397 name => 'vector drawing',
407 jxl => [2, undef, 'splines'],
411 parent => 'features',
412 name => 'alpha transparency',
415 pnm => ['n', undef, 'PAM extension'],
426 parent => 'features',
441 parent => 'features',
442 name => 'overlays (layers)',
456 parent => 'features',
457 name => 'authoring workflow suitability',
471 parent => 'features',
472 name => 'generation loss resilience',
486 parent => 'features',
487 name => 'lossless JPEG recompression',
501 name => 'royalty-free',
505 gif => [5, undef, 'patented before 2003'],
507 jp2k => [3, undef, 'ISO specification not freely available'],
508 webp => [4, undef, 'free format, low remaining risk of patent trolls'],
509 heic => ['n', undef, 'heavily patented'],
510 avif => [4, undef, 'free format, risk of patent trolls'],
511 jxl => [4, undef, 'free format, risk of patent trolls'],
516 name => 'browser support',
518 jpeg => [5, undef, 'ubiquitous since first inline images (1993)'],
519 pnm => [1, undef, 'rarely by (unix) systems'],
520 xbm => [2, undef, 'common before 200X'],
521 gif => [5, undef, 'predates the web, but unrestricted since 2004'],
522 png => [5, undef, 'problematic prior to IE7, currently ubiquitous'],
523 jp2k => [2, undef, 'just Safari'],
524 webp => [4, undef, 'widespread since 2020'],
525 heic => [1, undef, 'no browser support'],
526 avif => [3, undef, 'significant since 2021 (Safari 2023, no Edge yet)'],
527 jxl => [2, undef, 'experimental, blocked by chrome'],
533 jpeg => [5, undef, 'standard photography'],
534 pnm => [2, undef, 'uncomplicated bitmap interchange'],
535 gif => [4, undef, 'declining due to limitations'],
536 png => [5, undef, 'standard illustrations'],
537 jp2k => [3, undef, 'limited beyond Apple'],
538 webp => [4, undef, 'mostly online'],
539 heic => [2, undef, 'stored by latest cameras, interchange unlikely'],
540 avif => [3, undef, 'upcoming'],
541 jxl => [2, undef, 'ongoing'],
545 name => 'container overhead (file size)',
547 png => [3, 67, 'upto 70 bytes for specific RGBA'],
548 jpeg => [2, 160, '159 bytes minimum for gray, 288 for specific colours'],
549 gif => [4, 35, '43 bytes for transparent'],
550 webp => [4, 34, 'black or transparent lossless; 44-92 bytes lossy'],
551 bpg => [4, 31, 'lossy 29-62 bytes, lossless 37-160'],
552 flif => [5, 14, 'black or transparent; 20 bytes for specific RGBA'],
553 pnm => [5, 8, 'monochrome text PBM; 12 bytes PPM; 69 bytes PAM'],
554 jxl => [5, 12, '512×256 black pixels'],
555 avif => [1, 282, 'container overhead; 457 bytes with alpha'],
556 jp2k => [2, 123, 'experimental results, likely not optimal'],