Skip to content

Commit

Permalink
Crushed PNGs, EXIF embedding for AVIF
Browse files Browse the repository at this point in the history
- Support for Crushed PNGs has been added.
- EXIF metadata is now embedded in AVIF files as well as PNG.
- Documentation has been updated to reflect the new crushed PNG format.
- New metadata documentation for showing how to add licensing metadata to images.
  • Loading branch information
dzuk-mutant committed Jan 31, 2020
1 parent e090270 commit 5745f88
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 15 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ Mutant Standard's [code of conduct](docs/code_of_conduct.md).

- Declarative language for defining semantics of emoji set
- Color mapping (recoloring)
- Outputting emoji both as shortcode-named files (ie. 'ice_cream') and unicode codepoint-named files (ie. '1f368').
- SVG, PNG, Lossless WebP, Lossless AVIF and FLIF exports
- Optional space-saving optimisations for SVG files
- Supports multiple SVG renderers: rendersvg, Inkscape and ImageMagick
- Outputting emoji both as shortcode-named files (ie. 'ice_cream') and unicode codepoint-named files (ie. '1f368')
- Export to SVG, PNG, Lossless WebP, Lossless AVIF and FLIF
- Optional lossless crushing of SVG and PNG files
- Supports multiple SVG renderers (rendersvg, Inkscape and ImageMagick)
- Output options including emoji filtering, customisable export directory
structure and filenaming
- JSON output of emoji set metadata
Expand All @@ -53,6 +53,7 @@ Mutant Standard's [code of conduct](docs/code_of_conduct.md).
- ImageMagick
- exiftool (Optional; for embedding EXIF license metadata)
- [svgcleaner](https://github.com/RazrFalcon/svgcleaner) (Optional; for Optimised SVG output)
- [oxipng](https://github.com/shssoichiro/oxipng) (Optional; for Crushed PNG output)
- [FLIF](https://github.com/FLIF-hub/FLIF) (Optional; for FLIF output)
- [libwebp](https://developers.google.com/speed/webp/docs/precompiled) (Optional; for Lossless WebP output)
- [go-avif](https://github.com/Kagami/go-avif) (Optional; for AVIF output) (Experimental; does not currently produce truly lossless images. We're trying to figure out why that is.)
Expand Down
2 changes: 2 additions & 0 deletions dest_paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ def format_path(path, emoji, format):
res = res + '.svg'
elif format.startswith('png-'):
res = res + '.png'
elif format.startswith('pngc-'):
res = res + '.png'
elif format.startswith('flif-'):
res = res + '.flif'
elif format.startswith('webp-'):
Expand Down
6 changes: 6 additions & 0 deletions docs/dzuk/howto.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ Using this means that you're just exporting JSON for this command, you can't use

----

# [Metadata](metadata.md)

forc can embed SVG or EXIF metadata into your exported emoji sets.

---

# Extra flags

## Force Text Descriptions (`--force-desc`)
Expand Down
17 changes: 15 additions & 2 deletions docs/dzuk/image_formats.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,18 @@
*(check the [readme](../../readme.md) for all the information on dependencies)*

#### `svgo` Optimised SVG
Optimised SVG is the same format as SVG, but it's losslessly compressed to create a smaller file size (in Mutant Standard tests, optimised SVGs are 30-40% smaller). It requires an extra processing stage, and it needs the dependency listed. Check the [svgcleaner](https://github.com/RazrFalcon/svgcleaner) repo to see the documentation for it so you can see what it does to the SVG files.
Optimised SVG is the same format as SVG, but it's losslessly compressed to create a smaller file size. It requires an extra processing stage (which is very cheap on CPU), and it needs the dependency listed. Check the [svgcleaner](https://github.com/RazrFalcon/svgcleaner) repo to see the documentation for it so you can see what it does to the SVG files.

orxporter uses svgcleaner with the following settings:
orxporter uses svgcleaner with the following command:

`svgcleaner <in file> <out file> --remove-metadata=no --quiet`

In Mutant Standard tests, optimised SVGs are 30-40% smaller than normal SVGs. Unless you're doing something in particular, it's probably worth using Optimise SVGs by default instead of SVGs in your workflow.


### Raster
- `png` PNG
- `pngc` Crushed PNG (requires oxipng)
- `webp` Lossless WebP (requires cwebp)
- `avif` Lossless AVIF (requires go-avif)
- `flif` FLIF (requires flif)
Expand All @@ -32,3 +35,13 @@ avif-128
webp-512
png-60
```

#### `pngc` Crushed PNG
Crushed PNG is the same format as PNG, but it's losslessly compressed to create a smaller file size. It requires an extra processing stage (which can be quite expensive on CPU at very large sizes like 512px), and it needs the dependency listed. Check the [oxipng](https://github.com/shssoichiro/oxipng) repo to see the documentation for it so you can see what it does to the PNG files.

orxporter uses oxipng with the following command:

`oxipng <in file> --out, <out file> --quiet`

In Mutant Standard tests, Crushed PNGs have a file size reduction of about 25% compared to normal PNGs, but only on larger sizes (128px upwards).
At 32px, crushing PNGs only has an average file size reduction of 3%.
66 changes: 66 additions & 0 deletions docs/dzuk/metadata.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Metadata (Licenses)

Orxporter can embed metadata into your resulting emoji. This is useful if you want to put author or license information into your work for public distribution.

You add metadata to your manifests using the orx keyword `license`, as shown below:

```
license svg = license/svg.xml exif = license/exif.json
```

Metadata is automatically embedded in your resulting images, but if you want to leave it out...

- Use the flag `-l` if you're using the [simple exporting method](image_easy,md).
- Use `license = no` in your Parameters file if you're using the [advanced exporting method](image_advanced),

Metadata embedding is only done with certain formats:

- EXIF metadata can be embedded in PNG and AVIF files.
- SVG metadata can be embedded in SVG files.

---

## `svg`: SVG Metadata

SVG Metadata is an XML file you create that contains stuff that gets inserted in the `<metadata>` tag of your resulting SVGs.

Below is an example XML file with Mutant Standard's SVG metadata:

```
<rdf:RDF xmlns:cc="http://web.resource.org/cc/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc = "http://purl.org/dc/elements/1.1/"
>
<rdf:Description rdf:about="">
<dc:title>Mutant Standard emoji v0.4.1</dc:title>
</rdf:Description>
<cc:work rdf:about="">
<cc:license rdf:resource="http://creativecommons.org/licenses/by-nc-sa/4.0/"/>
<cc:attributionName>Dzuk</cc:attributionName>
<cc:attributionURL>http://mutant.tech/</cc:attributionURL>
</cc:work>
</rdf:RDF>
```

---

## `exif`: EXIF Metadata

EXIF Metadata is a JSON file you create that contains stuff that gets inserted in the EXIF metadata of your resulting raster images.

Below is an example JSON file with Mutant Standard's EXIF metadata:

```
{
"XMP-dc:title": "Mutant Standard emoji v0.4.1",
"XMP-dc:rights": "This work is licensed to the public under the Attribution-NonCommercial-ShareAlike 4.0 International license https://creativecommons.org/licenses/by-nc-sa/4.0/",
"XMP-xmpRights:UsageTerms": "This work is licensed to the public under the Attribution-NonCommercial-ShareAlike 4.0 International license https://creativecommons.org/licenses/by-nc-sa/4.0/",
"XMP-cc:AttributionName": "Dzuk",
"XMP-cc:AttributionURL": "mutant.tech",
"XMP-cc:License": "https://creativecommons.org/licenses/by-nc-sa/4.0/"
}
```
2 changes: 1 addition & 1 deletion docs/kiilas/manifest.md
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ The *svg* parameter must point to a file containing the desired string to be
inserted inside each SVG file's *metadata* tag.

The *exif* parameter must point to a JSON file containing a single object with
the desired EXIF tags to be written to each PNG file.
the desired EXIF tags to be written to each PNG or AVIF file.

Text descriptions
-----------------
Expand Down
3 changes: 2 additions & 1 deletion export.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ def export(m, filtered_emoji, input_path, formats, path, src_size,
png_files = []
for e in exporting_emoji:
for f in formats:
if f.startswith('png-'):
# png, pngc or avif
if f.startswith('png') or f.startswith('avif-'):
try:
png_files.append(format_path(path, e, f))
except FilterException:
Expand Down
4 changes: 3 additions & 1 deletion export_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ def to_raster(emoji_svg, out_path, renderer, format, size, name):
# two-step process
image_proc.render_svg(tmp_svg_path, tmp_png_path, renderer, size)

if format == "webp":
if format == "pngc":
image_proc.crush_png(tmp_png_path, out_path)
elif format == "webp":
image_proc.convert_webp(tmp_png_path, out_path)
elif format == "avif":
image_proc.convert_avif(tmp_png_path, out_path)
Expand Down
3 changes: 3 additions & 0 deletions export_thread.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ def export_emoji(self, emoji, emoji_svg, f, path, license):
if raster_format[0] == "png":
export_task.to_raster(emoji_svg, final_path, self.renderer, "png", size, self.name)

elif raster_format[0] == "pngc":
export_task.to_raster(emoji_svg, final_path, self.renderer, "pngc", size, self.name)

elif raster_format[0] == "webp":
export_task.to_raster(emoji_svg, final_path, self.renderer, "webp", size, self.name)

Expand Down
13 changes: 7 additions & 6 deletions orxport.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,13 @@
----------------------------------------------------
-F Format (default: {DEF_OUTPUT_FORMATS[0]})
comma separated with no spaces (ie. 'svg,png-64,flif-128')
- svg
- svgo
- png-SIZE
- flif-SIZE
- webp-SIZE
- avif-SIZE
- svg (SVG)
- svgo (Optimised SVG)
- png-SIZE (PNG)
- pngc-SIZE (Crushed PNG)
- flif-SIZE (FLIF)
- webp-SIZE (Lossless WebP)
- avif-SIZE (Lossless AVIF)
-f Directory/filename naming system for output (default: {DEF_OUTPUT_NAMING})
See the documentation for how this works.
Expand Down

0 comments on commit 5745f88

Please sign in to comment.