Christoph Päper
2017-05-08 11:26:25 UTC
There are several reasons why and methods how people are putting multiple still
images into a single file. PNG currently only supports some of them and only
indirectly.
Some use cases frequently require several very similar still bitmap images. They
may only differ in a single color being substituted, which may be the background
color or any other, or in a different palette being used which may be shared by
several images. They may also differ simply by size or color mode, where lower
resolution or low-fidelity versions are not necessarily the results of simple
algorithmic transformations from the largest, most colorful image, cf. the ICO
and other icon formats.
I'm not at all interested in backporting everything found in MNG to PNG, but I
only want PNG to
1. better support techniques already employed and
2. support multiple related variants of a semantically identical image.
Sprite maps
------------
Regarding goal #1, PNGs are regularly used to contain a set of small images in a
so-called sprite map (e.g. for a collection of emojis). Serving a single sprite
map instead of many individual image files is more efficient when using HTTP
1.x. The authors of the MNG specification anticipated this use case when they
wrote [Example 17: Storing an icon
library](http://www.libpng.org/pub/mng/spec/#x17).
In a sprite map, each icon is put into a virtual cell in a grid of vertical
columns and horizontal rows. Their numbers and dimensions must be known and used
externally. In CSS, this is traditionally achieved by using the
`background-position` property for a PNG file included with the
`background-image` property, but the recently added [`image()`
notation](https://www.w3.org/TR/css3-images/#image-fragments) also requires
support for spatial [Media Fragments], i.e.
`#xywh=pixel:left-offset,top-offset,width,height` (`pixel:` is optional and
`percent:` is also supported), which has some advantages, e.g. for repeated
tiles. The [Media Fragments
specification](https://www.w3.org/TR/media-frags/#naming-space), however,
suggested that owners of media types like `image/png` (see [RFC2083]) should
formally update their registration to include the `xywh` URL fragment (and/or
semantic name. The `IDAT` image resource within a PNG file does not have a
natural language name, let alone multiple ones for arbitrary slices of it. I am
proposing a new `fMAP` chunk below which may be able to achieve this, see the
Github repository for details. I'm *not* proposing a method to directly
reference cells in a grid, e.g. `#cell=2,6` or `#col=2;row=6`.
<https://github.com/Crissov/PNG-extensions/blob/master/fcTL%2BfdAT.md>
<https://github.com/Crissov/PNG-extensions/blob/master/fMAP.md>
Please note that MNG does already support arbitrarily named views using the
[`eXPI` chunk](http://www.libpng.org/pub/mng/spec/#mng-eXPI), but that adds some
------------
Sprite maps fall back to a planar overview of all available sprites. This is not
desired in cases where there is a default image that has several variants. Emoji
images of people, for instance, should usually come in a default gender-neutral,
a female and a male variant, often identified either by a prefix `1f469`/`1F468`
or a suffix `-2640`/`_2642` that is based upon the respective hexadecimal
Unicode code point. Another example are "High DPI" or "Retina ready" bitmaps
that come in multiple resolutions, which are either referred to by the pixel
dimensions or by a (usually integer) scaling factor like `2x` that is often
preceded by an at-sign in the file name, e.g. `***@2x.png`, but other
conventions also exist. A third use case is found in internationalization (i18n)
or rather localization (l10n): some PNG files contain text and variants exists
for other languages, which are currently often recorded in separate files with
multiple dot-lead extensions based upon [BCP47], e.g. `map.en-us.png`.
The default graphic should be found in `IDAT` chunks, but vanilla PNG does not
have anything to put the alternatives in. I propose to take advantage of support
in existing implementations by adopting the `fdAT` and `fcTL` chunks for this,
which were introduced in the unofficial [APNG] extension currently maintained by
Mozilla. Its proprietary `acTL` is not needed for this, because I'm *not*
proposing to add animation support to PNG.
The `fcTL` chunk type is only needed for unique numeric identifiers for each
fragment, but I maintained compatibility with APNG by declaring some bytes
reserved for future use. This means, `foo.png#2` should work, but, again, named
fragments would be more user friendly, so the proposed `fMAP` chunk also applies
to sprite stacks, so `dancing_emoji.png#male`, `icon.png#@3x` and
`screenshot.png#UHD` would work. To make i18n more automatic, i.e. requiring
less effort, `fMAP` should also support language tags, so implementations would,
for instance, transparently and implicitly select `map.png#lang=en` if the
embedding environment of the PNG file is tagged as `en-us`, while authors could
still explicitly choose `map.png#french`.
<https://github.com/Crissov/PNG-extensions/blob/master/fcTL%2BfdAT%2BfMAP.md>
Layers
---------
Layers are a can of worms that I don't want to open right now, but do think
needs mentioning.
A sprite stack where the default `IDAT` image has the largest dimensions and all
`fdAT` fragments are partially transparent and all these chunks would be
rendered at once would constitute a simple open layered image format with `IDAT`
as the first or background layer. To be really useful, `fcTL` or another chunk
type would need to learn to specify blending modes etc. This is stuff for a
potential PNG 2.0, because the fallback to just the background seems inadequate
in general.
Palette manipulation
------------
Some image variants do not need additional bitmap data chunks at all. For
example, each emoji that shows a body part or complete person comes in six
variations for skin tones: non-human default, Fitzpatrick scale 1-2, 3, 4, 5 and
6 (darkest). Hair color and possibly eye color may also change with the
complexion, but overall it's just about replacing the color values for some
palette entries.
PNG already supports suggested palettes with the `sPLT` chunk (and `PLTE`+`hIST`
for the default), which can even be named, but these are tailored for dithering
of true-color images on limited-color devices. I'm proposing to add a new `aPLT`
chunk type with almost identical syntax to `sPLT` which would be used replace
`PLTE` in color modes that use this chunk if requested by the user, e.g. via
fragment identifiers `baby.png#pal=dark`.
<https://github.com/Crissov/PNG-extensions/blob/master/aPLT.md>
References
-------------
[Media Fragments]: https://www.w3.org/TR/media-frags/
[RFC2083]: https://tools.ietf.org/html/rfc2083#section-8 "RFC 2083: PNG
(Portable Network Graphics) Specification Version 1.0 (1997-03), section 8.2.
Internet media type"
[APNG]: https://wiki.mozilla.org/APNG_Specification
[BCP47]: https://tools.ietf.org/html/bcp47
images into a single file. PNG currently only supports some of them and only
indirectly.
Some use cases frequently require several very similar still bitmap images. They
may only differ in a single color being substituted, which may be the background
color or any other, or in a different palette being used which may be shared by
several images. They may also differ simply by size or color mode, where lower
resolution or low-fidelity versions are not necessarily the results of simple
algorithmic transformations from the largest, most colorful image, cf. the ICO
and other icon formats.
I'm not at all interested in backporting everything found in MNG to PNG, but I
only want PNG to
1. better support techniques already employed and
2. support multiple related variants of a semantically identical image.
Sprite maps
------------
Regarding goal #1, PNGs are regularly used to contain a set of small images in a
so-called sprite map (e.g. for a collection of emojis). Serving a single sprite
map instead of many individual image files is more efficient when using HTTP
1.x. The authors of the MNG specification anticipated this use case when they
wrote [Example 17: Storing an icon
library](http://www.libpng.org/pub/mng/spec/#x17).
In a sprite map, each icon is put into a virtual cell in a grid of vertical
columns and horizontal rows. Their numbers and dimensions must be known and used
externally. In CSS, this is traditionally achieved by using the
`background-position` property for a PNG file included with the
`background-image` property, but the recently added [`image()`
notation](https://www.w3.org/TR/css3-images/#image-fragments) also requires
support for spatial [Media Fragments], i.e.
`#xywh=pixel:left-offset,top-offset,width,height` (`pixel:` is optional and
`percent:` is also supported), which has some advantages, e.g. for repeated
tiles. The [Media Fragments
specification](https://www.w3.org/TR/media-frags/#naming-space), however,
suggested that owners of media types like `image/png` (see [RFC2083]) should
formally update their registration to include the `xywh` URL fragment (and/or
The Media Fragment WG has no authority to update registries of all targeted
media types.
We recommend media type owners to harmonize their existing schemes with the
ones proposed in this document
and update or add the fragment semantics specification to their media type
registration.
It would be even more user-friendly if authors could reference sprites by amedia types.
We recommend media type owners to harmonize their existing schemes with the
ones proposed in this document
and update or add the fragment semantics specification to their media type
registration.
semantic name. The `IDAT` image resource within a PNG file does not have a
natural language name, let alone multiple ones for arbitrary slices of it. I am
proposing a new `fMAP` chunk below which may be able to achieve this, see the
Github repository for details. I'm *not* proposing a method to directly
reference cells in a grid, e.g. `#cell=2,6` or `#col=2;row=6`.
<https://github.com/Crissov/PNG-extensions/blob/master/fcTL%2BfdAT.md>
<https://github.com/Crissov/PNG-extensions/blob/master/fMAP.md>
Please note that MNG does already support arbitrarily named views using the
[`eXPI` chunk](http://www.libpng.org/pub/mng/spec/#mng-eXPI), but that adds some
The eXPI chunk takes a snapshot of a viewable object (either concrete or
abstract),
associates the name with that snapshot,
and makes the name available to the "outside world" (like a scripting
language).
Sprite stackabstract),
associates the name with that snapshot,
and makes the name available to the "outside world" (like a scripting
language).
------------
Sprite maps fall back to a planar overview of all available sprites. This is not
desired in cases where there is a default image that has several variants. Emoji
images of people, for instance, should usually come in a default gender-neutral,
a female and a male variant, often identified either by a prefix `1f469`/`1F468`
or a suffix `-2640`/`_2642` that is based upon the respective hexadecimal
Unicode code point. Another example are "High DPI" or "Retina ready" bitmaps
that come in multiple resolutions, which are either referred to by the pixel
dimensions or by a (usually integer) scaling factor like `2x` that is often
preceded by an at-sign in the file name, e.g. `***@2x.png`, but other
conventions also exist. A third use case is found in internationalization (i18n)
or rather localization (l10n): some PNG files contain text and variants exists
for other languages, which are currently often recorded in separate files with
multiple dot-lead extensions based upon [BCP47], e.g. `map.en-us.png`.
The default graphic should be found in `IDAT` chunks, but vanilla PNG does not
have anything to put the alternatives in. I propose to take advantage of support
in existing implementations by adopting the `fdAT` and `fcTL` chunks for this,
which were introduced in the unofficial [APNG] extension currently maintained by
Mozilla. Its proprietary `acTL` is not needed for this, because I'm *not*
proposing to add animation support to PNG.
The `fcTL` chunk type is only needed for unique numeric identifiers for each
fragment, but I maintained compatibility with APNG by declaring some bytes
reserved for future use. This means, `foo.png#2` should work, but, again, named
fragments would be more user friendly, so the proposed `fMAP` chunk also applies
to sprite stacks, so `dancing_emoji.png#male`, `icon.png#@3x` and
`screenshot.png#UHD` would work. To make i18n more automatic, i.e. requiring
less effort, `fMAP` should also support language tags, so implementations would,
for instance, transparently and implicitly select `map.png#lang=en` if the
embedding environment of the PNG file is tagged as `en-us`, while authors could
still explicitly choose `map.png#french`.
<https://github.com/Crissov/PNG-extensions/blob/master/fcTL%2BfdAT%2BfMAP.md>
Layers
---------
Layers are a can of worms that I don't want to open right now, but do think
needs mentioning.
A sprite stack where the default `IDAT` image has the largest dimensions and all
`fdAT` fragments are partially transparent and all these chunks would be
rendered at once would constitute a simple open layered image format with `IDAT`
as the first or background layer. To be really useful, `fcTL` or another chunk
type would need to learn to specify blending modes etc. This is stuff for a
potential PNG 2.0, because the fallback to just the background seems inadequate
in general.
Palette manipulation
------------
Some image variants do not need additional bitmap data chunks at all. For
example, each emoji that shows a body part or complete person comes in six
variations for skin tones: non-human default, Fitzpatrick scale 1-2, 3, 4, 5 and
6 (darkest). Hair color and possibly eye color may also change with the
complexion, but overall it's just about replacing the color values for some
palette entries.
PNG already supports suggested palettes with the `sPLT` chunk (and `PLTE`+`hIST`
for the default), which can even be named, but these are tailored for dithering
of true-color images on limited-color devices. I'm proposing to add a new `aPLT`
chunk type with almost identical syntax to `sPLT` which would be used replace
`PLTE` in color modes that use this chunk if requested by the user, e.g. via
fragment identifiers `baby.png#pal=dark`.
<https://github.com/Crissov/PNG-extensions/blob/master/aPLT.md>
References
-------------
[Media Fragments]: https://www.w3.org/TR/media-frags/
[RFC2083]: https://tools.ietf.org/html/rfc2083#section-8 "RFC 2083: PNG
(Portable Network Graphics) Specification Version 1.0 (1997-03), section 8.2.
Internet media type"
[APNG]: https://wiki.mozilla.org/APNG_Specification
[BCP47]: https://tools.ietf.org/html/bcp47