> For the complete documentation index, see [llms.txt](https://viridian-games.gitbook.io/pixel-palette/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://viridian-games.gitbook.io/pixel-palette/core-components/file-system/file-system-technical-details.md).

# File System Technical Details

All file operations are in **`PixelArtFileIO`**. In the Editor they use native OS dialogs (`SaveFilePanel`/`OpenFilePanel`). In builds they use `Application.persistentDataPath` with fixed filenames.

#### PNG Export

**Composite PNG** (`ExportCompositePNG(int scale)`) — grabs the composite texture, scales it by nearest-neighbor at the given scale (1×, 2×, 4×, 8×), encodes with `EncodeToPNG()`, writes to disk. Scale=1 encodes the original directly — no intermediate texture.

```
EncodeScaledPNG(Texture2D source, int scale):
  if scale ≤ 1 → return source.EncodeToPNG()  (fast path)
  for each pixel (x,y) in source:
    write c into a scale×scale block at (x*scale, y*scale)
  encode and return
```

**All Layers PNG** (`ExportAllLayersPNG`) — exports each layer as `{layerName}.png` plus a `composite.png` to a chosen folder.

#### PNG Import

Two variants:

| Method                      | What it does                                                                                                                  |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `ImportPNG(path)`           | Loads the image, scales it to fit the canvas (nearest-neighbor), writes onto the active layer. Wrapped in undo capture.       |
| `ImportPNGAsNewLayer(path)` | Adds a new layer named "Imported {filename}", scales the image to fit, writes onto the new layer. No undo (it's a new layer). |

Scaling uses `floor(x / canvasWidth * imageWidth)` to map each canvas pixel to a source pixel (nearest-neighbor).

#### Spritesheet Export

`ExportSpriteSheet(AnimationManager anim)` — composites all animation frames at 8× scale and lays them out horizontally in one PNG:

```
sheet.width  = canvasWidth * 8 * frameCount
sheet.height = canvasHeight * 8
```

Each frame is blitted into its column using `sheet.SetPixel` (per-pixel). Encoded with `EncodeToPNG()`.

#### Project Save/Load (.pxl)

Binary format:

```
Offset  Size  Field
0       4     Magic "PXL" (0x50584C)
4       1     Version (1)
5       4     Canvas width
9       4     Canvas height
13      4     Layer count
        ┌─ Per layer (repeated) ──────────────────────────────┐
        │  Variable  Layer name (Unity binary string format)  │
        │  1         Visible (bool)                           │
        │  4         Opacity (float)                          │
        │  4         Pixel count (= width * height)           │
        │  Variable  RGBA bytes (pixelCount × 4)              │
        └─────────────────────────────────────────────────────┘
        1      Terminator (0x00)
```

**Save** (`SaveProject`) — serializes all layers: name, visibility, opacity, and raw pixel data (R,G,B,A bytes).

**Load** (`LoadProjectInternal`) — validates the magic header, reads canvas dimensions, resizes the canvas via `canvas.SetCanvasSize()`, rebuilds the grid, then reads each layer:

* Layer 0 overwrites the existing first layer
* Subsequent layers use `AddLayer()` to create new ones

After loading, calls `CompositeAllLayers()` and `ResetView()` on the view controller.

#### Platform Handling

```
#if UNITY_EDITOR
    → native save/open file dialogs (UnityEditor.EditorUtility)
#else
    → fixed paths in Application.persistentDataPath
#endif
```

`DrawingSettings` wraps every file operation with `CheckDemo()` — in demo mode, the operation is blocked and `OnDemoBlocked` fires to show a popup.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://viridian-games.gitbook.io/pixel-palette/core-components/file-system/file-system-technical-details.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
