The ImageStackr API provides a flexible way to dynamically create images by overlaying text and other images on a base image. This functionality is perfect for generating custom playing cards, NFTs, merchandise designs, and more.
Field Name | Type | Description |
---|---|---|
base_image | File | The base image over which overlays will be added. Required for all requests. |
metadata | JSON | A JSON object describing overlays (both text and image) to be added to the base image. |
Dynamic Fields | File | Image files for overlays, with field names matching the fieldName in the overlays JSON. |
Property | Type | Description |
---|---|---|
type | String | Must be “image”. Required. |
fieldName | String | Name of the form field that contains the image file. Required. |
position | String | Position relative to the base image. Optional, defaults to “top-left”. |
offset | Object | { x: number, y: number } Position offset from the specified position . |
size | Object | { width: number, height: number } Size of the overlay image (Optional). |
Property | Type | Description |
---|---|---|
type | String | Must be “text”. Required. |
text | String | The text content. Required. |
offset | Object | { x: number, y: number } Position offset from the top-left corner. |
font | Object | Font settings object (See Font Settings table below). |
Property | Type | Description (all optional) |
---|---|---|
size | Integer | Font size in pixels. Default 20. |
color | String | Font color, specified as a HEX value. Default “#000000”. |
family | String | Font family. Default “arial”. |
align | String | Horizontal alignment: “left”, “center”, “right”. Default “left”. |
valign | String | Vertical alignment: “top”, “middle”, “bottom”. Default “bottom” |
lineHeight | Float | Line height in relation to the font size. Default 1.25 |
wrap | Integer | Maximum width in pixels before text wraps. Defaults to width of the base image. |
Font Name | Family (in JSON) |
---|---|
Arial | arial |
Verdana | verdana |
Times New Roman | times |
Georgia | georgia |
Comic Sans MS | comic |
We will be adding more and updating this list.
When specifying overlays in the JSON payload, it’s important to be aware of their stacking order. Overlays are processed sequentially, from the top of the list to the bottom. This means that each overlay is placed on top of the previous ones. If overlays overlap in space, the later ones in the list will appear above the earlier ones. This behavior allows for precise control over the final appearance of the composed image.
Ensure your overlays are ordered in the JSON array according to how you want them to be layered on the base image.
For this tutorial, we will be using the following example images:
Base Image: A playing card background. We have an area marked out where we will overlay our main character images, this is not necessary, it just makes it a bit easier to tell what we are going to do with it.
Overlay Images
Ripley: Our first character, main picture.
Name-bar: Image to be used as a backing for our name text
Circle: Image to go in the top corner as a backing for our “age” stat
These are a lot smaller than the actual images, to make it a bit easier to read this page!
The metadata for your image stack should describe each overlay’s type, position, size, and for text, font specifications.
We will start our json by defining our images. ripley
and name-bar
will be placed at offsets relative to the top-left corner, and circle
will be in the top-right corner. The default position is top-left
and offset is 0,0
{
"overlays": [
{
"type": "image",
"fieldName": "ripley",
"offset": {
"x": 45,
"y": 38
}
},
{
"type": "image",
"fieldName": "name-bar",
"offset": {
"x": 163,
"y": 1030
},
"size": {
"width": 50,
"height": 50
}
},
{
"type": "image",
"fieldName": "circle",
"position": "top-right",
"offset": {
"x": 0,
"y": 0
},
"size": {
"width": 50,
"height": 50
}
}
]
}
Each image overlay we upload must have a corresponding image file with the form field name matching the fieldName
property in the json metadata.
So far we will get an image looking like this
Now we want to add our text overlays for headings, labels, and stats.
RIPLEY our character name placed over the name bar, using a custom font mvboli
7 is our main age stat, placed in the top right corner
months another label, a bit smaller, under our stat
{
"overlays": [
... images from previous section...
{
"type": "text",
"text": "RIPLEY",
"offset": {
"x": 600,
"y": 1110
},
"font": {
"size": 80,
"color": "#00052a",
"family": "mvboli",
"align": "center",
"valign": "middle"
}
},
{
"type": "text",
"text": "7",
"offset": {
"x": 1080,
"y": 140
},
"font": {
"size": 120,
"color": "#00052a",
"family": "mvboli",
"align": "center",
"valign": "bottom"
}
},
{
"type": "text",
"text": "months",
"offset": {
"x": 1080,
"y": 188
},
"font": {
"size": 30,
"color": "#00052a",
"family": "arial",
"align": "center"
}
}
]
}
Our image is coming along nicely…
We’ll put a few more headings and stats in to finish off the card!
Here we have a heading under our character name name, in the middle of the card, a description which goes to a maximum width of 960 px and then wraps to a new line, some right aligned headings, and corresponding numbers as our stats.
... items from previous sections ...
{
"type": "text",
"text": "FUTURE DEFENDER",
"offset": {
"x": 600,
"y": 1210
},
"font": {
"size": 32,
"color": "#13b7c3",
"family": "arial",
"align": "center"
}
},
{
"type": "text",
"text": "A playful protector in training, Ripley's set to lead and defend.",
"offset": {
"x": 600,
"y": 1290
},
"font": {
"size": 32,
"wrap": 960,
"color": "#b0d5d8",
"family": "arial",
"align": "center",
"valign": "middle",
"lineHeight": 2.4
}
},
{
"type": "text",
"text": "ENERGY",
"offset": {
"x": 390,
"y": 1420
},
"font": {
"size": 40,
"color": "#13b7c3",
"family": "arial",
"align": "right"
}
},
{
"type": "text",
"text": "PLAYFULNESS",
"offset": {
"x": 390,
"y": 1520
},
"font": {
"size": 40,
"color": "#13b7c3",
"family": "arial",
"align": "right"
}
},
{
"type": "text",
"text": "LEADERSHIP",
"offset": {
"x": 940,
"y": 1420
},
"font": {
"size": 40,
"color": "#13b7c3",
"family": "arial",
"align": "right"
}
},
{
"type": "text",
"text": "COURAGE",
"offset": {
"x": 940,
"y": 1520
},
"font": {
"size": 40,
"color": "#13b7c3",
"family": "arial",
"align": "right"
}
},
{
"type": "text",
"text": "98",
"offset": {
"x": 420,
"y": 1420
},
"font": {
"size": 40,
"color": "#b0d5d8",
"family": "arial",
"align": "left"
}
},
{
"type": "text",
"text": "95",
"offset": {
"x": 420,
"y": 1520
},
"font": {
"size": 40,
"color": "#b0d5d8",
"family": "arial",
"align": "left"
}
},
{
"type": "text",
"text": "72",
"offset": {
"x": 970,
"y": 1420
},
"font": {
"size": 40,
"color": "#b0d5d8",
"family": "arial",
"align": "left"
}
},
{
"type": "text",
"text": "88",
"offset": {
"x": 970,
"y": 1520
},
"font": {
"size": 40,
"color": "#b0d5d8",
"family": "arial",
"align": "left"
}
}
]
We would do this programatically based on our data rather than typing all this in by hand, so we can easily generate other versions of our card now. This is the our final Ripley card, along our other two dogs, Arnold and Yoshi.