Skip to content

SheetGrid

Namespace Nfty.Core.Publish in assembly Nfty.Core.

public sealed record SheetGrid

The grid a spritesheet is made of, as a sheet carries it: written into the PNG itself.

Remarks

The grid travels IN the file, as a tEXt chunk named nfty-grid, so a sheet handed to somebody else (or reopened next week) still knows how to slice itself with nothing recorded beside it. Readers that do not know the chunk ignore it, as the PNG spec requires of any ancillary chunk.

The text is parsed leniently on keys and strictly on values. Unknown keys are ignored so a later build can add one without making this one refuse the sheet; every number must be a positive invariant integer, and a count past the grid's capacity is malformed.

Constructors

SheetGrid(int, int, int, int, int)

public SheetGrid(int Columns, int Rows, int CellWidth, int CellHeight, int Count);

Parameters

  • Columns (int) - Cells across.
  • Rows (int) - Cells down.
  • CellWidth (int) - One cell's width in pixels.
  • CellHeight (int) - One cell's height in pixels.
  • Count (int) - How many cells hold a picture, in reading order; the rest are empty.

Remarks

The grid travels IN the file, as a tEXt chunk named nfty-grid, so a sheet handed to somebody else (or reopened next week) still knows how to slice itself with nothing recorded beside it. Readers that do not know the chunk ignore it, as the PNG spec requires of any ancillary chunk.

The text is parsed leniently on keys and strictly on values. Unknown keys are ignored so a later build can add one without making this one refuse the sheet; every number must be a positive invariant integer, and a count past the grid's capacity is malformed.

Fields

ChunkKeyword

public const string ChunkKeyword = "nfty-grid";

The PNG text keyword the grid is stored under.

Properties

CellHeight

public int CellHeight { get; init; }

One cell's height in pixels.

CellWidth

public int CellWidth { get; init; }

One cell's width in pixels.

Columns

public int Columns { get; init; }

Cells across.

Count

public int Count { get; init; }

How many cells hold a picture, in reading order; the rest are empty.

Rows

public int Rows { get; init; }

Cells down.

Methods

Detect(Image<Rgba32>)

public static SheetGrid? Detect(Image<Rgba32> image);

Finds a grid in a picture that does not say: equal cells separated by transparent gutters.

Parameters

  • image (Image<Rgba32>) - The picture.

Returns. The grid, or null when the picture is empty or is one picture (a 1 x 1 grid).

Remarks

Per axis, the SMALLEST divisor of the side such that no run of content (a maximal span of columns, or rows, holding any pixel with alpha above zero) crosses a multiple of it. Smallest, not largest: the largest divisor is always the whole side, which always "works" and says nothing. Equal cells hold by construction. Count runs to the last cell holding content in reading order, so a short last row is counted as it was drawn.

FromCellSize(int, int, int, int)

public static SheetGrid FromCellSize(int cellWidth, int cellHeight, int width, int height);

A grid from a cell size, every cell filled.

Parameters

  • cellWidth (int) - One cell's width.
  • cellHeight (int) - One cell's height.
  • width (int) - The picture's width.
  • height (int) - The picture's height.

Returns. The grid, with Count = columns x rows.

Exceptions

  • ArgumentException - The cell size does not divide the picture; the message says how.

FromColumnsRows(int, int, int, int)

public static SheetGrid FromColumnsRows(int columns, int rows, int width, int height);

A grid from a column and row count, every cell filled.

Parameters

  • columns (int) - Cells across.
  • rows (int) - Cells down.
  • width (int) - The picture's width.
  • height (int) - The picture's height.

Returns. The grid, with Count = columns x rows.

Exceptions

  • ArgumentException - The grid does not divide the picture; the message says how.

Parse(string)

public static SheetGrid? Parse(string text);

Reads chunk text back into a grid.

Parameters

  • text (string) - The chunk text.

Returns. The grid, or null when anything is missing or malformed.

ProblemWith(SheetGrid, int, int)

public static string? ProblemWith(SheetGrid grid, int width, int height);

Why a grid does not tile a picture exactly, or null when it does.

Parameters

  • grid (SheetGrid) - The grid.
  • width (int) - The picture's width.
  • height (int) - The picture's height.

Returns. A sentence naming both numbers, or null.

Remarks

Returns a problem rather than throwing, like Validator: a dialog binds this while someone is still typing a column count.

Read(string)

public static SheetGrid? Read(string pngPath);

Reads the grid a PNG carries, without decoding its pixels.

Parameters

  • pngPath (string) - The sheet.

Returns. The grid, or null when the file has no nfty-grid entry, it is malformed, or the file is not an image.

Exceptions

  • ArgumentException - pngPath is null or whitespace.

RemoveFrom(string)

public static long RemoveFrom(string pngPath);

Takes the grid out of a PNG, keeping every pixel exactly: the file becomes one picture again.

Parameters

  • pngPath (string) - The sheet to rewrite.

Returns. How many bytes the file changed by (negative when it shrank); 0, with nothing written, when the file carries no grid.

Exceptions

  • ArgumentException - pngPath is null or whitespace.

Remarks

Same temp-beside-then-replace write as SheetGrid.WriteInto().

ToChunkText()

public string ToChunkText();

The grid as chunk text: cols=8;rows=4;cell=64x64;count=29.

Returns. The text, invariant, with the keys in this fixed order so the bytes never vary.

TryFromCellSize(int, int, int, int, SheetGrid?)

public static string? TryFromCellSize(int cellWidth, int cellHeight, int width, int height, out SheetGrid? grid);

The same as SheetGrid.FromCellSize(), reporting a problem instead of throwing.

Parameters

  • cellWidth (int) - One cell's width.
  • cellHeight (int) - One cell's height.
  • width (int) - The picture's width.
  • height (int) - The picture's height.
  • grid (SheetGrid?) - The grid, or null when there is a problem.

Returns. A sentence naming the cell size typed and the picture size it fails to divide, or null.

TryFromColumnsRows(int, int, int, int, SheetGrid?)

public static string? TryFromColumnsRows(int columns, int rows, int width, int height, out SheetGrid? grid);

The same as SheetGrid.FromColumnsRows(), reporting a problem instead of throwing.

Parameters

  • columns (int) - Cells across.
  • rows (int) - Cells down.
  • width (int) - The picture's width.
  • height (int) - The picture's height.
  • grid (SheetGrid?) - The grid, or null when there is a problem.

Returns. A sentence naming the numbers typed and the size they fail to divide, or null.

Remarks

For a screen bound while someone is still typing; SheetGrid.FromColumnsRows() is this rule, thrown.

WriteInto(string, SheetGrid)

public static long WriteInto(string pngPath, SheetGrid grid);

Writes a grid into an existing PNG, keeping every pixel exactly.

Parameters

  • pngPath (string) - The sheet to rewrite.
  • grid (SheetGrid) - The grid to record.

Returns. How many bytes the file grew by; negative when it shrank.

Remarks

Loads WITHOUT naming a pixel type, so a 16-bit or palette sheet is re-encoded at its own depth instead of being rounded to 8-bit. Saves beside the file and moves over it, so a failure leaves the original untouched; the temp is removed either way. I/O errors propagate: the caller decides whether "could not write" means "keep the grid for the session".