# pxstud.io Lua scripting API — Images

> Part of the pxstud.io Lua scripting reference, whose overview (https://pxstud.io/docs/scripting.md) explains its conventions. The option groups and types it refers to are in https://pxstud.io/docs/scripting/option-groups.md and https://pxstud.io/docs/scripting/types.md. Everything in one file: https://pxstud.io/llms-full.txt. The whole site's index: https://pxstud.io/llms.txt.

### Images
The fast way to work pixel by pixel. app.getImage reads a cel (or part of it) into an Image, a pixel buffer that lives inside the script: img:getPixel and img:setPixel never leave the script, so a loop over every pixel of a 512 x 512 cel takes about a tenth of a second. app.putImage writes it back as one change, however many pixels you set. A pixel is one packed integer (app.pixelColor.rgba(r, g, b, a), as in Aseprite); setPixel also takes "#rrggbb[aa]" and { r, g, b, a } (alpha defaults to 255). On indexed sprites img:getIndex and img:setIndex work with palette indices, so duplicate colours stay apart. The usual pattern: local img = app.getImage(layer, frame); for y = 0, img.height - 1 do for x = 0, img.width - 1 do img:setPixel(x, y, ...) end end; app.putImage(layer, frame, img).

#### `app.getCompositeImage(frameId, rect?)` — reads
What a frame looks like, as an RGBA Image: every visible layer (image and tilemap) blended with its opacity and blend mode, exactly as exported, over rect (default the whole canvas). Reference layers are excluded (they aren't artwork); outside the canvas reads transparent. Use it to check your result, or as a source for img:drawImage.

- `frameId` (string)
- `rect` (table, optional) — The area to read, { x, y, width, height } on the canvas (integers; width and height 1-4096). Omitted = the whole canvas.
  - `x` (integer) — Left edge.
  - `y` (integer) — Top edge.
  - `width` (integer 1–4096) — Width in pixels.
  - `height` (integer 1–4096) — Height in pixels.

Returns (image): An Image (see img:getPixel and the other img: methods).

#### `app.getImage(layerId, frameId, rect?)` — reads
Reads a layer/frame's cel into an Image: a pixel buffer inside the script that you read and change with img:getPixel / img:setPixel (and img:getIndex / img:setIndex on indexed sprites) at no cost per call, then write back with app.putImage as one change. The Image covers rect (default the whole canvas), and its coordinates start at 0, 0 at the rect's top-left; img.x, img.y remember where on the canvas that is, which is where app.putImage writes it by default. Pixels with no cel read as transparent. A linked cel reads its shared image. Image layers only (tile images: app.getTilePixels).

- `layerId` (string)
- `frameId` (string)
- `rect` (table, optional) — The area to read, { x, y, width, height } on the canvas (integers; width and height 1-4096). Omitted = the whole canvas.
  - `x` (integer) — Left edge.
  - `y` (integer) — Top edge.
  - `width` (integer 1–4096) — Width in pixels.
  - `height` (integer 1–4096) — Height in pixels.

Returns (image): An Image (see img:getPixel and the other img: methods).

#### `app.newImage(width, height, colorMode?)` — reads
A blank (transparent) Image, at x = 0, y = 0: a scratch buffer to build pixels in before app.putImage, or to stamp onto other images with img:drawImage. An indexed one uses the sprite's palette.

- `width` (number) — 1-4096.
- `height` (number) — 1-4096.
- `colorMode` (ColorMode: "rgba" | "grayscale" | "indexed", optional) — Default the sprite's own. "rgba" on an indexed sprite gives a full-colour scratch image (app.putImage then maps its colours to the palette).

Returns (image): An Image (see img:getPixel and the other img: methods).

#### `app.pixelColor.rgba(r, g, b, a?)` — pure
Packs a colour into one pixel integer, the form img:getPixel returns and img:setPixel takes fastest (as in Aseprite).

- `r` (number) — 0-255.
- `g` (number) — 0-255.
- `b` (number) — 0-255.
- `a` (number, optional) — 0-255, default 255.

Returns (number): r | g << 8 | b << 16 | a << 24.

#### `app.pixelColor.rgbaA(pixel)` — pure
A packed pixel's alpha.

- `pixel` (number) — A packed pixel.

Returns (number): 0-255.

#### `app.pixelColor.rgbaB(pixel)` — pure
A packed pixel's blue.

- `pixel` (number) — A packed pixel.

Returns (number): 0-255.

#### `app.pixelColor.rgbaG(pixel)` — pure
A packed pixel's green.

- `pixel` (number) — A packed pixel.

Returns (number): 0-255.

#### `app.pixelColor.rgbaR(pixel)` — pure
A packed pixel's red.

- `pixel` (number) — A packed pixel.

Returns (number): 0-255.

#### `app.putImage(layerId, frameId, image, x?, y?)` — changes, undoable, refused on a locked layer
Writes an Image into a layer/frame's cel: every pixel of the rectangle it covers is replaced (no blending), as one change however many pixels you set. The cel grows to hold it and is trimmed to its visible pixels; what falls outside the canvas is dropped. Raw write: never clipped to the selection or mirrored. On an indexed sprite each pixel keeps its palette index (img:setIndex), unless the palette changed since and that entry no longer shows the pixel's colour; on a grayscale sprite colours become gray. Writing to a linked cel changes every frame it's linked to.

- `layerId` (string)
- `frameId` (string)
- `image` (image) — The Image to write.
- `x` (number, optional) — Where its top-left pixel lands; default image.x (where app.getImage read it, 0 for app.newImage).
- `y` (number, optional) — Default image.y.

Returns nothing.

#### `img:clear(x?, y?, width?, height?)` — pure
Makes a rectangle of the image (default all of it) transparent (the transparent index on indexed images).

- `x` (number, optional) — Default 0.
- `y` (number, optional) — Default 0.
- `width` (number, optional) — Default to the right edge.
- `height` (number, optional) — Default to the bottom edge.

Returns nothing.

#### `img:clone()` — pure
A copy of the image (same size, position and colour mode).

Returns (image): A new Image.

#### `img:drawImage(image, x?, y?, opacity?, blendMode?)` — pure
Draws another Image onto this one, blended like a layer (its transparent pixels leave this one as it was). Indexed onto indexed at full opacity copies the indices.

- `image` (image) — The Image to draw.
- `x` (number, optional) — Where its top-left lands; default 0.
- `y` (number, optional) — Default 0.
- `opacity` (number, optional) — 0-255, default 255.
- `blendMode` (string, optional) — A BlendMode, default "normal".

Returns nothing.

#### `img:fill(color, x?, y?, width?, height?)` — pure
Fills a rectangle of the image (default all of it) with one colour.

- `color` (color) — A packed pixel (app.pixelColor.rgba(r, g, b, a), what img:getPixel returns), "#rrggbb[aa]" or { r, g, b, a } (a defaults to 255).
- `x` (number, optional) — Default 0.
- `y` (number, optional) — Default 0.
- `width` (number, optional) — Default to the right edge.
- `height` (number, optional) — Default to the bottom edge.

Returns nothing.

#### `img:getIndex(x, y)` — pure
Indexed images only: the pixel's palette index (0-based, as in app.getPalette's order and app.setPaletteEntry), so duplicate palette colours can be told apart. Outside the image: the transparent index.

- `x` (number) — Column, 0 at the image's left edge.
- `y` (number) — Row, 0 at the top.

Returns (number): 0-255.

#### `img:getPixel(x, y)` — pure
A pixel's colour, packed into one integer (the fast form: no table is made). On an indexed image it is the palette colour of the pixel's index (transparent for the transparent index). Outside the image: 0 (transparent). x and y must be integers.

- `x` (number) — Column, 0 at the image's left edge.
- `y` (number) — Row, 0 at the top.

Returns (number): The packed pixel r | g << 8 | b << 16 | a << 24: take it apart with app.pixelColor (or & 255, >> 8 ...).

#### `img:setIndex(x, y, index)` — pure
Indexed images only: sets the pixel's palette index exactly, even to one of two entries with the same colour (palette cycling, index swaps).

- `x` (number) — Column, 0 at the image's left edge.
- `y` (number) — Row, 0 at the top.
- `index` (number) — A palette index, 0-based.

Returns nothing.

#### `img:setPixel(x, y, color)` — pure
Sets a pixel's colour. Takes the same colours as the draw commands, plus packed pixels, and refuses anything else ({ red = ... }, a list, a bad hex string) with an error. On an indexed image the colour becomes the nearest palette entry, keeping the pixel's index when that entry already shows the colour (img:setIndex picks an exact index); on a grayscale one it becomes gray. Outside the image nothing happens.

- `x` (number) — Column, 0 at the image's left edge.
- `y` (number) — Row, 0 at the top.
- `color` (color) — A packed pixel (app.pixelColor.rgba(r, g, b, a), what img:getPixel returns), "#rrggbb[aa]" or { r, g, b, a } (a defaults to 255).

Returns nothing.
