Make a plugin for Cloud Photo
A plugin adds a filter to Cloud Photo’s Filter menu. It gets pixels and settings, and changes the pixels. The result goes on a new layer above the original.
Download the kit (zip, 11 KB) Try the sample
The kit has this guide, a sample plugin and a script that builds it.
One file
- A
.cloudphoto-pluginfile is a zip with two files:manifest.jsonandplugin.wasm - People install it with File › Plugins, and it shows in Filter › Plugin
Any language
- The filter is WebAssembly, so any language that compiles to it will do
- The kit’s build script compiles AssemblyScript, which reads like TypeScript
Kept to its pixels
- A plugin gets the pixels and nothing else: no internet, files or account
- Cloud Photo draws its controls, and the original layer always stays
Plugins work in Cloud Photo in the browser and on Windows from version 1.8.0. The Mac gets them in its next update.
Try the sample
You need Node.js 22.2 or later. Unzip the kit, then in its folder run:
npm install assemblyscript
node build.mjs sample
That makes sample/sample.cloudphoto-plugin. In Cloud Photo, choose File › Plugins, then Install a plugin, and pick the file. Soft glow is now in the Filter menu.
To make your own, copy the sample folder, change manifest.json and plugin.ts, and run node build.mjs with your folder’s name.
manifest.json
What the plugin is called and which controls it has.
| Field | Needed | What it is |
|---|---|---|
format | Yes | 1 |
id | Yes | Letters, digits, ., _ and -, up to 64. A new version keeps it. |
name | Yes | Up to 40 characters, shown in the Filter menu |
version | Yes | Up to 20 characters |
author | No | Up to 60 characters |
description | No | Up to 300 characters |
margin | No | How far your filter looks past a pixel, 0 to 256 (see Tiles) |
settings | No | Up to 16 controls, drawn by Cloud Photo |
Each setting has a label (up to 40 characters) and a type:
type | Other fields | Value your plugin gets |
|---|---|---|
slider | min, max, step, default | The number |
checkbox | default (true or false) | 1 or 0 |
color | default ("#rrggbb") | The number 0xRRGGBB |
A plugin can’t draw controls or screens of its own. The sample’s manifest:
{
"format": 1,
"id": "com.mycloudsuites.sample.soft-glow",
"name": "Soft glow",
"version": "1.0.0",
"author": "MyCloudSuites",
"description": "The sample plugin: spreads the light parts of a picture.",
"margin": 32,
"settings": [
{ "type": "slider", "label": "Radius", "min": 1, "max": 32, "step": 1, "default": 8 },
{ "type": "slider", "label": "Strength", "min": 0, "max": 100, "step": 1, "default": 50 },
{ "type": "checkbox", "label": "Tint the glow", "default": false },
{ "type": "color", "label": "Tint", "default": "#ffcc88" }
]
}
What the module must do
It must import its memory as env.memory and import nothing else. It must not define a memory of its own. A module that does either is refused when someone installs it.
It must export these three functions:
// Called once for each setting, in manifest order, before any pixels.
// Needed only with settings.
setting(index: i32, value: f64): void
// Makes room for `bytes` bytes of pixels and returns where they go. Called once.
// Grow the memory here if you need to. The memory can reach 1 GB.
buffer(bytes: i32): i32
// Changes w × h pixels at `ptr` in place: RGBA rows, 8 bits a channel, not
// premultiplied, with no gaps between rows. (x, y) is where these pixels are
// in a W × H picture. Called once for each tile.
// Return 0, or any other number to say something went wrong.
filter(ptr: i32, w: i32, h: i32, x: i32, y: i32, W: i32, H: i32): i32
Tiles
Large pictures arrive a tile at a time, up to 1024 × 1024 pixels plus margin on each side, and only the tile itself is kept. If your filter looks up to 32 pixels away, set margin to at least 32 and no seams will show.
buffer is called once, for the largest tile, so filter can get smaller ones after it. Your variables stay between tiles.
The preview runs your filter on a smaller copy of the picture, so effects measured in pixels look stronger there.
Limits
- The file can be up to 32 MB.
- A plugin that doesn’t finish a tile within 60 seconds is stopped, and nothing changes.
- If the plugin fails, returns a number other than 0 or doesn’t make room, nothing changes.
- Pixels are 8 bits a channel, including those from 16-bit layers. The original layer keeps its 16.
- In the browser, a plugin is kept in that browser and doesn’t follow the person’s account.
Questions
How do people get my plugin?
Share the .cloudphoto-plugin file however you like, on your website or by email. There’s no plugin store in Cloud Photo.
What do people see when they install it?
Its name, version, author and description, and a reminder that MyCloudSuites hasn’t checked it, and that it can only change the pixels it’s given. Installing a new version with the same id replaces the old one.
Can a plugin make a whole new tool?
Not yet. A plugin is a filter: it changes a layer’s pixels, or the pixels inside a selection, with the controls in its manifest.
Something isn’t working. Who do I ask?
Tell us what you tried and what happened.
Make your first filter.
The kit builds the sample in two commands.