Sprites.Media.Image
A full-colour bitmap editor and its model. Image is a full-colour bitmap over a high resolution pixel grid, drawn on a canvas so it stays fast at large sizes. It works like the sprite editor, the same brushes, tools, palette and windows, but has layers and no frames, and holds its pixels as a Sprites.Grid.Tiled block, a grid of small tiles, so a paint copies one tile, not the whole image. A layer is { tiles, visible }; a pixel is a packed RGBA colour, transparent where alpha is zero. Every function composes reactive values; the raw pixel work lives in Sprites.Grid.Tiled and the raw drawing in Sprites.Ui.Image.Pixels, so this module holds no Calculate.
- Sprites.Media.Image.MinSide
- Sprites.Media.Image.MaxSide
- Sprites.Media.Image.Tile
- Sprites.Media.Image.DefaultWidth
- Sprites.Media.Image.DefaultHeight
- Sprites.Media.Image.White
- Sprites.Media.Image.Transparent
- Sprites.Media.Image.ClampSide
- Sprites.Media.Image.New
- Sprites.Media.Image.NewDocument
- Sprites.Media.Image.NewLayer
- Sprites.Media.Image.CloneLayer
- Sprites.Media.Image.LayerGrid
- Sprites.Media.Image.SelectedGrid
- Sprites.Media.Image.Display
- Sprites.Media.Image.ResizeAll
- Sprites.Media.Image.Summary
- Sprites.Media.Image.Thumbnail
- Sprites.Media.Image.SpriteToGrid
- Sprites.Media.Image.Palette
- Sprites.Media.Image.Editor
Sprites.Media.Image.MinSide Number
The smallest a side may be, in pixels.
Value 1.
Sprites.Ui.Dom.Text('MinSide = ', Sprites.Media.Image.MinSide);
Sprites.Media.Image.MaxSide Number
The largest a side may be, in pixels. An image runs far larger than a sprite, so the maximum is high; the canvas draws it all the same, since it never makes one element per pixel.
Value 4096.
Sprites.Ui.Dom.Text('MaxSide = ', Sprites.Media.Image.MaxSide);
Sprites.Media.Image.Tile Number
The tile side the pixels are cut into, in pixels. A power of two, small enough that one tile copy on a paint is cheap and large enough that the tile count stays low.
Value 16.
Sprites.Ui.Dom.Text('Tile = ', Sprites.Media.Image.Tile);
Sprites.Media.Image.DefaultWidth Number
The default new image width, in pixels.
Value 256.
Sprites.Ui.Dom.Text('DefaultWidth = ', Sprites.Media.Image.DefaultWidth);
Sprites.Media.Image.DefaultHeight Number
The default new image height, in pixels.
Value 256.
Sprites.Ui.Dom.Text('DefaultHeight = ', Sprites.Media.Image.DefaultHeight);
Sprites.Media.Image.White Number
Opaque white as a packed RGBA integer, each byte a channel, the freeform brush default. A namespace constant holds a value, never a call, so the literal stands in place of a Pack.
Value 0xFFFFFFFF.
const css = Sprites.Colour.Css(Sprites.Media.Image.White);
Sprites.Ui.Dom.Text('White = ', css);
Sprites.Media.Image.Transparent Number
The transparent pixel: a packed RGBA integer with every channel zero, so its alpha is zero. A tile holds this where nothing is painted, and an erase writes it. A typed pixel buffer cannot hold undefined, so zero alpha is the absent pixel here.
Value 0.
Sprites.Ui.Dom.Text('Transparent = ', Sprites.Media.Image.Transparent);
Sprites.Media.Image.ClampSide Sprites.Reactive.Value
Sprites.Media.Image.ClampSide(n)
Clamp a side to the allowed range, as a whole number. A composite: round the value, then hold it between the smallest and largest a side may be.
| Input | Type | Description |
|---|---|---|
n | Number or Sprites.Reactive.Value | The requested side, rounded and clamped. |
Returns a Sprites.Reactive.Value holding the clamped whole side.
const asked = Sprites.Reactive.Value(8000);
const side = Sprites.Media.Image.ClampSide(asked);
Sprites.Ui.Input.Slider(asked, -100, 8000);
Sprites.Ui.Dom.Text(' clamped = ', side);
Sprites.Media.Image.New Sprites.Reactive.Value
Sprites.Media.Image.New(width, height)
A new tiled pixel block at the given size, or the default size, all transparent. A composite: it clamps the sides, then builds the block with the tiled grid primitive.
| Input | Type | Description |
|---|---|---|
width | Number or Sprites.Reactive.Value | The pixel width, or absent for the default. |
height | Number or Sprites.Reactive.Value | The pixel height, or absent for the default. |
Returns a Sprites.Reactive.Value holding the blank tiled grid.
const width = Sprites.Reactive.Value(64);
const block = Sprites.Media.Image.New(width, 48);
const w = Sprites.Grid.Tiled.Width(block);
Sprites.Ui.Input.Slider(width, 16, 128);
Sprites.Ui.Dom.Text(' block width = ', w);
Sprites.Media.Image.NewDocument Object
Sprites.Media.Image.NewDocument(width, height, optionalMode)
A new image document at the given size in the given mode: the { media, w, h, tile, mode, layers } shape the store keeps, its one visible layer holding the blank tiles. A boot factory a page hands to the store, so it snapshots the blank block plain here rather than staying a live reactive.
| Input | Type | Description |
|---|---|---|
width | Number | The pixel width. |
height | Number | The pixel height. |
optionalMode | String | The mode name stored on the document, or absent. |
Returns the plain { media, w, h, tile, mode, layers } document object.
const doc = Sprites.Media.Image.NewDocument(32, 24, 'Freeform');
const mode = Sprites.Object.Field(doc, 'mode');
const w = Sprites.Object.Field(doc, 'w');
const h = Sprites.Object.Field(doc, 'h');
const layers = Sprites.Object.Field(doc, 'layers');
const count = Sprites.Array.Length(layers);
Sprites.Ui.Dom.Text('mode ', mode, ', ', w, '×', h, ', layers ', count);
Sprites.Media.Image.NewLayer Sprites.Reactive.Value
Sprites.Media.Image.NewLayer(width, height, tile)
A new blank layer at the given size: one visible layer of transparent tiles, its block built with the tiled grid primitive. A composite, so a click that adds a layer passes it as a fresh reactive value the array insert commits.
| Input | Type | Description |
|---|---|---|
width | Number or Sprites.Reactive.Value | The pixel width. |
height | Number or Sprites.Reactive.Value | The pixel height. |
tile | Number or Sprites.Reactive.Value | The tile side. |
Returns a Sprites.Reactive.Value holding the { tiles, visible } layer.
const layer = Sprites.Media.Image.NewLayer(32, 32, 16);
const visible = Sprites.Object.Field(layer, 'visible');
Sprites.Ui.Dom.Text('new layer visible = ', visible);
Sprites.Media.Image.CloneLayer Sprites.Reactive.Value
Sprites.Media.Image.CloneLayer(layer)
A copy of a layer: a fresh layer object holding the same tiles and visible flag. Rebuilding the object keeps the copy independent, since a paint replaces the tiles rather than changing them in place, so editing one leaves the other be.
| Input | Type | Description |
|---|---|---|
layer | Object or Sprites.Reactive.Value | A { tiles, visible } layer. |
Returns a Sprites.Reactive.Value holding the copied layer.
const source = Sprites.Media.Image.NewLayer(16, 16, 16);
const copy = Sprites.Media.Image.CloneLayer(source);
const visible = Sprites.Object.Field(copy, 'visible');
Sprites.Ui.Dom.Text('copy visible = ', visible);
Sprites.Media.Image.LayerGrid Sprites.Reactive.Value
Sprites.Media.Image.LayerGrid(layer, width, height, tile)
The tiled grid of one layer at the document size: a { w, h, tile, tiles } block, for a thumbnail or a stamp. A composite over ReadOnly.
| Input | Type | Description |
|---|---|---|
layer | Object or Sprites.Reactive.Value | A { tiles, visible } layer. |
width | Number or Sprites.Reactive.Value | The document pixel width. |
height | Number or Sprites.Reactive.Value | The document pixel height. |
tile | Number or Sprites.Reactive.Value | The tile side. |
Returns a Sprites.Reactive.Value holding the { w, h, tile, tiles } grid.
const layer = Sprites.Media.Image.NewLayer(32, 32, 16);
const grid = Sprites.Media.Image.LayerGrid(layer, 32, 32, 16);
const pixel = Sprites.Grid.Tiled.At(grid, 0, 0);
Sprites.Ui.Dom.Text('top left pixel = ', pixel);
Sprites.Media.Image.SelectedGrid Sprites.Reactive.Value
Sprites.Media.Image.SelectedGrid(data, layerIndex)
A two way { w, h, tile, tiles } grid over the layer at layerIndex. Reading composes the grid from the size, the tile and that layer's tiles, so the editor edits one flat layer. Writing lays the edited tiles back into that one layer through the layers list, keeping the layer's visible flag and every other layer, so a paint touches only the selected layer.
| Input | Type | Description |
|---|---|---|
data | Sprites.Reactive.Value | The two way stored document. |
layerIndex | Number or Sprites.Reactive.Value | The selected layer. |
Returns a two-way Sprites.Reactive.Value over the selected layer's grid.
const document = Sprites.Media.Image.NewDocument(32, 32, 'Freeform');
const data = Sprites.Reactive.Binding(document);
const state = Sprites.Media.Image.SelectedGrid(data, 0);
const paint = Sprites.Reactive.Bindingundefined, () => {
const next = Sprites.Grid.Tiled.FillRect(state, 0, 0, 4, 4, 0xff4444ff);
Sprites.Reactive.Set(state, next);
});
const pixel = Sprites.Grid.Tiled.At(state, 0, 0);
Sprites.Ui.Button.Act(paint, 'Paint the layer');
Sprites.Ui.Dom.Text(' top left pixel = ', pixel);
Sprites.Media.Image.Display Sprites.Reactive.Value
Sprites.Media.Image.Display(data)
The image drawn as one tiled grid: the visible layers flattened bottom to top, a layer higher up over the ones below and a transparent pixel letting them show through. The canvas draws this, and a change repaints only the tiles it touched.
| Input | Type | Description |
|---|---|---|
data | Object or Sprites.Reactive.Value | The document. |
Returns a Sprites.Reactive.Value holding the flattened tiled grid.
const document = Sprites.Media.Image.NewDocument(32, 32, 'Freeform');
const data = Sprites.Reactive.Binding(document);
const state = Sprites.Media.Image.SelectedGrid(data, 0);
const paint = Sprites.Reactive.Bindingundefined, () => {
const next = Sprites.Grid.Tiled.FillRect(state, 0, 0, 6, 6, 0x44ff44ff);
Sprites.Reactive.Set(state, next);
});
const display = Sprites.Media.Image.Display(data);
const pixel = Sprites.Grid.Tiled.At(display, 2, 2);
Sprites.Ui.Button.Act(paint, 'Paint the layer');
Sprites.Ui.Dom.Text(' flattened pixel = ', pixel);
Sprites.Media.Image.ResizeAll Sprites.Reactive.Value
Sprites.Media.Image.ResizeAll(data, width, height, pad)
The same document resized so every layer is the new width and height, cropping or padding each layer's tiles with the padding colour. Width and height live on the document, shared by every layer. A composite keeping the tile, the mode and each layer's visible flag.
| Input | Type | Description |
|---|---|---|
data | Object or Sprites.Reactive.Value | The document. |
width | Number or Sprites.Reactive.Value | The new pixel width. |
height | Number or Sprites.Reactive.Value | The new pixel height. |
pad | Number or Sprites.Reactive.Value | The packed RGBA padding colour for new area. |
Returns a Sprites.Reactive.Value holding the resized document.
const document = Sprites.Media.Image.NewDocument(32, 32, 'Freeform');
const data = Sprites.Reactive.Binding(document);
const width = Sprites.Reactive.Value(48);
const resized = Sprites.Media.Image.ResizeAll(data, width, 32, Sprites.Media.Image.Transparent);
const w = Sprites.Object.Field(resized, 'w');
Sprites.Ui.Input.Slider(width, 16, 64);
Sprites.Ui.Dom.Text(' document width = ', w);
Sprites.Media.Image.Summary Sprites.Reactive.Value
Sprites.Media.Image.Summary(optionalModeName, width, height)
The meta info summary for an image: its mode and size as one short string, for the meta record a listing reads. The dimensions join, and the mode joins in front when there is one.
| Input | Type | Description |
|---|---|---|
optionalModeName | String or Sprites.Reactive.Value | The mode name, or undefined for none. |
width | Number or Sprites.Reactive.Value | The pixel width. |
height | Number or Sprites.Reactive.Value | The pixel height. |
Returns a Sprites.Reactive.Value holding the summary string.
const width = Sprites.Reactive.Value(128);
const summary = Sprites.Media.Image.Summary('Freeform', width, 64);
Sprites.Ui.Input.Slider(width, 16, 256);
Sprites.Ui.Dom.Text(' summary = ', summary);
Sprites.Media.Image.Thumbnail Sprites.Reactive.Value
Sprites.Media.Image.Thumbnail(grid)
A PNG data URL of a tiled grid, transparent where a pixel's alpha is zero, as a reactive value that follows the pixels, for a saved preview or a layer card. It reads every pixel, so a page runs it for a preview, not on a paint.
| Input | Type | Description |
|---|---|---|
grid | Object or Sprites.Reactive.Value | A { w, h, tile, tiles } tiled grid. |
Returns a Sprites.Reactive.Value holding the PNG data URL string.
const grid = Sprites.Grid.Tiled.Blank(16, 16, 16, 0xff4444ff);
const url = Sprites.Media.Image.Thumbnail(grid);
Sprites.Ui.Dom.Tag('img', () => {
Sprites.Ui.Dom.Attribute('src', url);
Sprites.Ui.Dom.Style('width', '64px');
Sprites.Ui.Dom.Style('image-rendering', 'pixelated');
});
Sprites.Media.Image.SpriteToGrid Sprites.Reactive.Value
Sprites.Media.Image.SpriteToGrid(spriteData)
A sprite's pixels as a { w, h, cells } grid of packed RGBA colours, its first frame's visible layers flattened, so a picked sprite can stamp into an image. It reads the freeform sprite's packed cells straight, so a freeform sprite stamps true to colour.
| Input | Type | Description |
|---|---|---|
spriteData | Object or Sprites.Reactive.Value | A sprite document, its frames each with layers. |
Returns a Sprites.Reactive.Value holding the { w, h, cells } grid.
const layer = { pixels: [0xff4444ff, undefined, undefined, 0x4444ffff], visible: true };
const frame = { layers: [layer] };
const sprite = { w: 2, h: 2, frames: [frame] };
const grid = Sprites.Media.Image.SpriteToGrid(sprite);
const cell = Sprites.Grid.Two.At(grid, 0, 0);
Sprites.Ui.Dom.Text('top left cell = ', cell);
Sprites.Media.Image.Palette Void
Sprites.Media.Image.Palette(hasSlots, slots, brush, visible)
The Palette window: a floating panel docked to the stage's bottom left. With platform slots it holds a swatch grid, a click setting the brush to that colour; freeform it holds an inline colour picker, so a paint colour is chosen in real time. hasSlots is a build time flag; slots is the packed colours; brush is the two way packed brush colour; visible is the show flag.
| Input | Type | Description |
|---|---|---|
hasSlots | Boolean | True for a swatch grid, false for the freeform picker. |
slots | Array or Sprites.Reactive.Value | The packed palette colours. |
brush | Sprites.Reactive.Value | The two way packed brush colour. |
visible | Sprites.Reactive.Value | The show flag the window follows. |
Returns nothing; it builds a floating window.
const brush = Sprites.Reactive.Value(Sprites.Media.Image.White);
const visible = Sprites.Reactive.Value(false);
Sprites.Ui.Button.SetValue(visible, true, 'Open the palette');
Sprites.Media.Image.Palette(false, [], brush, visible);
const css = Sprites.Colour.Css(brush);
Sprites.Ui.Dom.Text(' brush = ', css);
Sprites.Media.Image.Editor Void
Sprites.Media.Image.Editor(data, thumb, info, optionalModes, optionalModeName, optionalSlots)
The image editor. Builds the canvas view on the host, the pan and zoom overlay, the Tools window, each canvas tool's own window, the panel windows, and the Palette and Info windows. It builds interface and returns nothing; the doc fields it is given are where the edits land.
| Input | Type | Description |
|---|---|---|
data | Sprites.Reactive.Value | The document, a two way value of { media, w, h, tile, mode, layers }. |
thumb | Sprites.Reactive.Value | A value the editor Sets to a fresh PNG data URL of the pixels at a stroke's end. |
info | Sprites.Reactive.Value | A value the editor Sets to a short mode and size summary. |
optionalModes | Array | The platform's image modes, or absent for one freeform mode. |
optionalModeName | Sprites.Reactive.Value | A two way value of the current mode's name, or absent. |
optionalSlots | Array | The platform's palette as packed integers, or absent for the freeform picker. |
Returns nothing; it builds the full editor interface. The example gates it behind a button so the windows do not cover the page on load.
const open = Sprites.Reactive.Value(false);
Sprites.Ui.Button.SetValue(open, true, 'Open the editor');
Sprites.Reactive.If(open, () => {
const document = Sprites.Media.Image.NewDocument(64, 64, 'Freeform');
const data = Sprites.Reactive.Binding(document);
const thumb = Sprites.Reactive.Value(undefined);
const info = Sprites.Reactive.Value(undefined);
const modeName = Sprites.Object.Field(data, 'mode');
Sprites.Ui.Dom.Tag('div', () => {
Sprites.Ui.Dom.Class('editor-stage');
Sprites.Ui.Dom.Style('height', '420px');
Sprites.Media.Image.Editor(data, thumb, info, undefined, modeName);
});
});