Minimal Image Macro Server (mini-macro)
Self-hostable image macro creation and hosting service.
- Add and use whatever template images you want
- Add as many pieces of text, formatted as you want, to each image
- Images are stored and transferred efficiently as SVGs
- SVG markup is screen-reader accessible
- Web UI and REST API for managing image macros and templates
Efficient, Accessible SVG Image Macros
Rather than render new PNG (or other raster) formatted images, the renderer used here actually generates SVG files that look something like this:
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1"
width="800" height="600"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
style="user-select: none">
<title>Image Macro Title Text</title>
<!-- The image template is referenced as a separate, external file -->
<image x="0" y="0"
width="800" height="600"
xlink:href="http://example.com/abcdefghijkl">
<title>Image Template Title Text</title>
</image>
<!-- Each section of text gets its own <text> node -->
<text x="400" y="50"
text-anchor="middle"
font-size="48"
font-family="sans-serif"
font-weight="600"
stroke="#000"
stroke-width="2"
fill="#fff"
>Top Text</text>
<text x="400" y="550"
text-anchor="middle"
font-size="48"
font-family="sans-serif"
font-weight="600"
stroke="#000"
stroke-width="2"
fill="#fff"
>Bottom Text</text>
</svg>
That sample XML above is about 800 bytes in total with the comments removed; The raster formats that might otherwise be used would typically be several kilobytes at least.
Obviously, the externally referenced template image still has to be downloaded. However that external image (the largest part of an image macro, and the part that gets reused over and over) can be cached separately by clients so that it does not need to be downloaded separately each time it gets used to make a new image. Additionally, only one copy of it actually gets stored on the server, regardless of how many times its used.
Additionally, since an SVG is markup rather than a raster image, they can be read by screen readers (including the additional <title>
text for both the whole image, and the template).
Embedding in HTML
The one drawback to this approach is that, in web browsers, SVGs do not load external resources when rendered in an image context (e.g. when used in an <img>
tag). That said, you can embed it using either the <embed>
or <object>
elements, which will both render it as a document.
<!-- NOT This: <img> doesn't work with external resources -->
<img type="image/svg+xml" src="http://example.com/FrztglsLexLRWg">
<!-- Either of these will work: -->
<embed type="image/svg+xml" src="http://example.com/FrztglsLexLRWg"></embed>
<object type="image/svg+xml" data="http://example.com/FrztglsLexLRWg"></object>
REST API
Image Template List
Media Type: application/vnd.mini-macro.image-templates+json
todo
Supports: GET
{
"items": [
{
"id": "<template_id>",
"title": "Image Template Title",
"width": 800,
"height": 600,
"links": {
"self": {
"href": "/templates/<template_id>",
"type": "application/vnd.mini-macro.image-template+json"
},
"alternate": {
"href": "/templates/<template_id>",
"type": "image/png"
}
}
}
],
"links": {
"next": {
"href": "/templates?anchor=<template_id>",
"type": "application/vnd.mini-macro.image-templates+json"
}
}
}
Image Template
General Support: DELETE
Media Type: application/vnd.mini-macro.image-template+json
todo
Supports: GET
, POST
, PUT
{
"id": "<template_id>",
"title": "Image Template Title",
"width": 800,
"height": 600,
"links": {
"self": {
"href": "/templates/<template_id>",
"type": "application/vnd.mini-macro.image-template+json"
},
"alternate": {
"href": "/templates/<template_id>",
"type": "image/png"
}
}
}
Other Media Types: image/png
, image/jpeg
Supports: GET
, PUT
Image Macro
General Support: DELETE
Media Type: application/vnd.mini-macro.image-macro+json
todo
Supports: GET
, POST
, PUT
{
"id": "<image_id>",
"name": "Image Macro Name",
"text_style": {
"fill": "#fff",
"stroke": "#000",
"stroke_width": 2,
"font_size": 48,
"font_family": "sans-serif",
"font_weight": 600
},
"text": [
{
"text": "Top Text",
"top": 50,
"left": 400,
},
{
"text": "Bottom Text",
"top": 550,
"left": 400,
},
]
"links": {
"self": {
"href": "/images/<template_id>",
"type": "application/vnd.mini-macro.image-macro+json"
},
"alternate": {
"href": "/images/<template_id>",
"type": "image/png"
},
"/rel/template": {
"href": "/templates/<template_id>",
"type": "application/vnd.mini-macro.image-template+json"
}
}
}
Other Media Types: image/svg+xml
Supports: GET