# Krita

Ein Modell steuert Krita 5.2.9 über den Hub, um auf zwei Ebenen eine Postkarte zu malen und als .kra-Datei zu speichern. Das erste Skript funktionierte. Die Seite nennt den Text, das Skript, die Antworten des Hubs und die Aufnahme und sagt, wie die Brücke gestartet wurde: nicht aus Scripter, das nicht ausprobiert wurde.

*Wörter in mehreren Sprachen laufen über eine in Krita gemalte Landschaft; die Bewegung rendert der Hub in Blender.*

## Fakten

- Erprobte Version: 5.2.9
- Modus: `tcp`

## Krita mit seiner Brücke starten

Der [Leitfaden](https://github.com/RonanDavalan/LibreModular-MCP/blob/main/docs/modules/krita.md) lässt den Bediener die Brückendatei aus Scripter ausführen. Dieser Lauf nutzte dieses Vorgehen nicht. Er startete Krita auf einem virtuellen X-Display, in einem neuen Profil, mit einer Startup-Erweiterung, deren gesamte `__init__.py` die Brückendatei ausführt:

```sh
xvfb-run -a krita --nosplash
```

```python
exec(open('/usr/share/libremodular-mcp/bridges/krita_bridge.py', encoding='utf-8').read())
```

Die Kodierung ist nicht optional. Das eingebettete Python von Krita liest Dateien in der Kodierung des Locales, unter dem es gestartet wurde, und die Brückendatei enthält Zeichen mit Akzent: Unter dem Locale `C` brach ein Befehl ohne `encoding='utf-8'` mit `UnicodeDecodeError` ab, wie die Seite [Kompatibilität](https://libremodular.davalan.fr/de/compatibility/index.md#krita) festhält. Der Lauf nutzte in `config.toml` den Port 9312 und ein neues Token. Der Port lauschte 10,4 s nach dem Start, und `get_state` für `hub` listete Krita als verbunden auf:

**Antwort des Hubs**

```json
{
  "app": "hub",
  "app_version": "0.1.0",
  "bridge_version": null,
  "captured_at": "2026-10-21T12:47:48.951Z",
  "connected": true,
  "content_origin": "hub",
  "screenshot": null,
  "state": {
    "modules": [
      {
        "app_version": "5.2.9",
        "bridge_version": "1",
        "connected": true,
        "mode": "tcp",
        "name": "krita"
      }
    ]
  },
  "warnings": []
}
```


## Dem Modell gegebener Text

```text
In Krita, create a document named "Postcard", 600 by 400 pixels. On a paint layer named "Sky", paint a vertical gradient from dark blue (#1c385c) at the top to teal (#29a196) at the bottom. On a second paint layer named "Hill", paint a copper (#c25438) hill: the upper half of an ellipse centred on the bottom edge, 520 pixels wide and 240 pixels high. Save the document as postcard.kra in your working directory.
```


Vor dem Schreiben rief das Modell `get_state` für `krita` auf: `"document": null`. Das Dokument existiert noch nicht, das Skript muss es also anlegen und in einem Fenster öffnen, bevor es malen kann.

## Geschriebenes Skript

Ein Modell, Claude Sonnet 5.5, schrieb dieses Skript nach dem Leitfaden und nach diesem Zustand. Es ist kein Skript aus den Tests des Projekts. Das Skript schreibt Pixelbytes in der Reihenfolge Blau, Grün, Rot, Alpha; die Farben der Aufnahme unten zeigen, dass Krita diese Reihenfolge für dieses Dokument erwartet. Das Skript setzt vor `saveAs` den Stapelmodus; was ohne ihn geschieht, wurde nicht ausprobiert.

**Geschriebenes Skript**

```python
import os

krita = Krita.instance()
document = krita.createDocument(600, 400, "Postcard", "RGBA", "U8", "", 72.0)
krita.activeWindow().addView(document)
root = document.rootNode()

def lerp(a, b, t):
    return round(a + (b - a) * t)

top, bottom = (0x1c, 0x38, 0x5c), (0x29, 0xa1, 0x96)
sky_pixels = bytearray()
for y in range(400):
    t = y / 399
    r, g, b = (lerp(top[i], bottom[i], t) for i in range(3))
    sky_pixels += bytes((b, g, r, 255)) * 600
sky = document.createNode("Sky", "paintlayer")
root.addChildNode(sky, None)
sky.setPixelData(bytes(sky_pixels), 0, 0, 600, 400)

hill_pixels = bytearray()
for y in range(400):
    for x in range(600):
        inside = ((x - 300) / 260) ** 2 + ((y - 400) / 120) ** 2 <= 1
        hill_pixels += bytes((0x38, 0x54, 0xC2, 255)) if inside else bytes((0, 0, 0, 0))
hill = document.createNode("Hill", "paintlayer")
root.addChildNode(hill, None)
hill.setPixelData(bytes(hill_pixels), 0, 0, 600, 400)

document.refreshProjection()
document.setBatchmode(True)
path = os.path.join(LMM_WORK_DIR, "postcard.kra")
saved = document.saveAs(path)
result = {"saved": saved, "kra_bytes": os.path.getsize(path), "layers": [node.name() for node in document.topLevelNodes()]}
```


## Antwort des Hubs

**Antwort des Hubs**

```json
{
  "app": "krita",
  "duration_ms": 1060,
  "error": null,
  "result": {
    "kra_bytes": 110725,
    "layers": [
      "Background",
      "Sky",
      "Hill"
    ],
    "saved": true
  },
  "status": "ok",
  "stderr": "",
  "stdout": "",
  "truncated": false
}
```


Das Skript lief in 1,06 s. Das Dokument hat drei Ebenen, weil ein neues Krita-Dokument mit einer Ebene `Background` beginnt, die das Skript unberührt ließ, unter `Sky` und `Hill`. `get_state` beschrieb danach das Dokument und gab eine Aufnahme seiner Projektion zurück:

**Antwort des Hubs**

```json
{
  "app": "krita",
  "app_version": "5.2.9",
  "bridge_version": "1",
  "captured_at": "2026-10-21T12:47:50.526Z",
  "connected": true,
  "content_origin": "document",
  "screenshot": "$XDG_RUNTIME_DIR/libremodular-mcp/captures/krita-20261021T124750502Z.png",
  "state": {
    "document": {
      "active_layer": "{727e9cd9-e6e1-423c-ade7-1bf29d6d5289}",
      "color_depth": "U8",
      "color_model": "RGBA",
      "color_profile": "sRGB-elle-V2-srgbtrc.icc",
      "height": 400,
      "layers": [
        {
          "id": "{69f5540d-2916-4771-8df7-1fcad46b677f}",
          "name": "Background",
          "opacity": 255,
          "type": "paintlayer",
          "visible": true
        },
        {
          "id": "{ed307be8-5a93-4b16-8739-7508916ea687}",
          "name": "Sky",
          "opacity": 255,
          "type": "paintlayer",
          "visible": true
        },
        {
          "id": "{727e9cd9-e6e1-423c-ade7-1bf29d6d5289}",
          "name": "Hill",
          "opacity": 255,
          "type": "paintlayer",
          "visible": true
        }
      ],
      "name": "Postcard",
      "width": 600
    }
  },
  "warnings": []
}
```


## Erzeugtes Bild

Die Aufnahme ist das zusammengefügte Bild, das Krita anzeigt, 600 × 400 Pixel. Die darin gelesenen Pixel sind `#1C385C` oben, `#29A196` unten und `#C25438` im Hügel, die drei Farben, die der Text verlangt hat. Die vom Skript gespeicherte `.kra`-Datei hat 110 725 Bytes.

![Ein senkrechter Farbverlauf von Dunkelblau nach Türkis mit einer kupferfarbenen halben Ellipse, die vom unteren Rand aufsteigt.](https://libremodular.davalan.fr/images/applications/krita-postcard.png)

*Die Aufnahme des Dokuments Postcard nach dem Skript, wie der Hub sie exportiert hat.*


> **Grenze**
>
> Nicht ausprobiert: die Brücke aus Scripter starten (der Menüweg, die Umgebungsvariablen, die sie erreichen, wie lange sie lebt, wenn Scripter geschlossen wird), mehrere gleichzeitig geöffnete Dokumente und ein Dokument mit einer Ebenengruppe.

[Referenz-Leitfaden im Repository](https://github.com/RonanDavalan/LibreModular-MCP/blob/main/docs/modules/krita.md)

