Value & Palette Fields
A field is a fixed grid of cells. A ValueField holds numbers that a gradient colours. A PaletteField holds exact palette indices.
Create a field
var pc.ValueField levels = pc.valueField(240, 400) // rows, columns
var pc.PaletteField pixels = pc.paletteField(240, 400) // rows, columnsvalueField(rows, columns, initial = na)starts every cell atna, which is transparent.paletteField(rows, columns, initial = -1)starts every cell at-1, which is transparent. Index 0 selects the first palette colour.- A field needs at least 1 row and from 1 to 100,000 columns. To be drawn it needs at least 2 rows and 2 columns.
- The sizes are available afterwards as
field.rowsandfield.columns.
Row 0 is the bottom row and column 0 is the left, oldest column. Call invertRows() on the Canvas when a picture is easier to write top-down.
Read and write cells
levels.set(row, column, 42.5) // write one cell, returns the field
float value = levels.get(row, column)
pixels.set(row, column, 3) // palette index 3
pixels.set(row, column, -1) // transparent again
levels.fill(na) // every cell at once
pixels.fill(0)set() and fill() return the field, so writes can chain. A row or column outside the field raises a runtime error.
-1 or an index below the number of colours on the Canvas that draws it. Anything else stops the script with an error that names the valid range.Whole rows with row()
row(rowIndex) returns a writable array that shares the storage of one row. Writing to it writes the field, without a method call or index arithmetic per cell.
array<float> cells = levels.row(row)
for column = 0 to levels.columns - 1
cells.set(column, valueAt(row, column))Storage bands
A Pine array holds at most 100,000 elements, so a field keeps its cells in one or more bands, each a run of complete rows. A band holds as many rows as fit in one array, rounded down to a multiple of 32, so a small field usually has a single band. Loop over bandCount() instead of assuming one. Band access is the fastest way to write a large picture, and it is what Pine3D's rasterize() writes into.
| Call | Returns |
|---|---|
bandCount() | How many bands the field has, at least 1. |
band(index) | The writable array of one band, in row-major order. |
bandStart(index) | The field row that the band begins at. |
bandRows(index) | How many complete rows the band stores. |
Inside a band, the cell at a field row and column sits at (row - bandStart(index)) * columns + column.
for bandIndex = 0 to picture.bandCount() - 1
array<int> cells = picture.band(bandIndex)
int firstRow = picture.bandStart(bandIndex)
for localRow = 0 to picture.bandRows(bandIndex) - 1
int row = firstRow + localRow
for column = 0 to picture.columns - 1
cells.set(localRow * picture.columns + column, paletteIndexAt(row, column))set(), row(), and band() all update the same storage, so they can be mixed freely.
Field stamps
Stamps write simple shapes straight into a field. They clip to the field's bounds and return the field. Coordinates are rows and columns, not prices.
| Call | What it writes |
|---|---|
rect(row0, column0, row1, column1, value, filled = true) | A filled rectangle, or only its outline when filled is false. The corners may be given in any order. |
segment(row0, column0, row1, column1, value) | A straight line of cells between two points. |
circle(centerRow, centerColumn, radius, value, filled = false) | A one-cell ring, or a disc when filled is true. |
//@version=6
indicator("PineCanvas - Field Stamps", overlay = false, max_polylines_count = 100)
import Alien_Algorithms/PineCanvas/1 as pc
var pc.PaletteField board = pc.paletteField(40, 80)
var pc.Canvas canvas = pc.newCanvas(array.from(color.gray, color.orange, color.aqua))
if barstate.isfirst
board.rect(0, 0, 39, 79, 0, false) // an outline around the whole field
board.segment(0, 0, 39, 79, 1) // a diagonal line
board.circle(20, 40, 12, 2, true) // a filled disc
if barstate.islast and bar_index >= 80
canvas.drawLookback(board, 0, 0.0, 40.0)A stamped circle is round in cells. It looks round on the chart only when the cells are drawn square, which depends on the vertical bounds and the zoom.
Value field or palette field
Choose a ValueField when
The data is a magnitude and the colour should follow it: exposure, volume, probability, an oscillator. The Canvas maps the numbers through a gradient, and you can change the gradient, the level count, the range, or the gamma without rewriting a cell.
Choose a PaletteField when
Each cell has an exact colour: a picture, a rendered 3D frame, a market state. The palette is the Canvas's colour array, with 2 to 100 entries, and every index is drawn exactly as given.