# Whiteboard Image Limits — Komplettdokumentation > **Letztes Update:** 2026-07-02 · **Status:** 6 JS-Patches aktiv, OOM-Problem identifiziert, URL-Referenzen als Lösung geplant --- ## 1. Problem Das Nextcloud Whiteboard (Excalidraw) hat mehrere hartkodierte Limits für Bildimporte: | Limit | Default | Effekt | |---|---|---| | Downscale auf max. Kantenlänge | **1440px** (Excalidraw) + **1440px** (Whiteboard-eigener `image-blob-reduce`) | Bilder schrumpfen auf Briefmarken-Größe | | Dateigrößen-Check | **4 MB** (Excalidraw) + **4 MB** (Whiteboard) | Größere Bilder werden abgelehnt | | RAM-Verbrauch (Base64 im JSON) | **~50 MB/Bild** (4000×3000px decoded) | Ab ~3 Bildern → Chrome OOM-Crash | Alle diese Limits sind **doppelt** vorhanden: einmal im Excalidraw-Core (`percentages-*.chunk.mjs`), einmal in der Whiteboard-Bridge (`NcSelect-*.chunk.mjs`). --- ## 2. Architektur: Warum kein Docker-Neustart nötig ist ``` Docker Image (read-only) Docker Volume (read-write) ┌──────────────────────────┐ ┌─────────────────────────────┐ │ Nextcloud PHP │ │ /custom_apps/whiteboard/js/ │ │ Apache/Nginx Config │ │ ├─ NcSelect-CknHatsl.mjs │ ← Patches #3–#6 │ System-Libs │ │ ├─ percentages-*.mjs │ ← Patches #1–#2 │ │ │ └─ whiteboard-*-patch.js │ ← Scroll + Quality │ (NIE angefasst) │ │ │ └──────────────────────────┘ └─────────────────────────────┘ ▲ Persistiert über Restarts, NICHT über App-Updates ``` **Der gesamte Bildverarbeitungs-Pipeline läuft im Browser:** 1. User dropped Bild → Whiteboard JS (`B0()` mit `image-blob-reduce`) 2. → Excalidraw JS (`initializeImage()`) 3. → Canvas-Rendering + Base64-Encode 4. → Upload JSON an Nextcloud (PHP macht **nichts** mit dem Bild) Deshalb reicht ein **Browser-Cache-Refresh (Cachebuster)** — kein Container-Neustart. --- ## 3. Alle Patches (Stand 2026-07-02) ### 3.1 Scroll-Zoom (Miro-like) **Datei:** `scripts/whiteboard-scroll-patch.js` - Scrollen = Zoomen, Mittelklick-Drag = Pannen - Registriert in `LoadViewerListener.php`, `WhiteboardDirectEditor.php`, `RecordingController.php` ### 3.2 Image Quality (Post-Processing) **Datei:** `scripts/whiteboard-image-patch.js` - Verhindert Qualitätsverlust durch Excalidraws internes `imageBlobReduce`-Postprocessing ### 3.3 `IM` und `TM` — Whiteboard-eigene Limits **Datei:** `percentages-BXMCSKIN-D6x-nnv3.chunk.mjs` ``` ...Cl=2,Ff=[1,2,3],dl=10,IM=1/0,TM=100*1024*1024,je=... ``` | Konstante | Vorher | Nachher | Bedeutung | |---|---|---|---| | `IM` | `1440` | `1/0` (=∞) | Max. Kantenlänge für `image-blob-reduce` | | `TM` | `4*1024*1024` | `100*1024*1024` | Max. Dateigröße für Whiteboard-Preprocessing | ### 3.4 `maxImageSizeBytes` — Excalidraw-Fallback **Datei:** `NcSelect-CknHatsl.chunk.mjs` ``` maxImageSizeBytes:F||9e15 ``` | Vorher | Nachher | |---|---| | `F` (Nextcloud Config, `undefined` → 4MB Hardcoded) | `F\|\|9e15` (Fallback ≈ unendlich) | ### 3.5 `maxWidthOrHeight` + `imageOptions` — Excalidraw-Limits **Datei:** `NcSelect-CknHatsl.chunk.mjs` ``` maxWidthOrHeight:8192,imageOptions:{maxWidthOrHeight:1/0,maxFileSizeBytes:1/0} ``` | Property | Vorher | Nachher | |---|---|---| | `maxWidthOrHeight` | `2048` (harter Reject) | `8192` | | `imageOptions.maxWidthOrHeight` | `1440` (Downscale) | `1/0` (=∞) | | `imageOptions.maxFileSizeBytes` | `4*1024*1024` (fileTooBig) | `1/0` (=∞) | ### 3.6 Infrastruktur | Ebene | Einstellung | Wert | |---|---|---| | Nextcloud DB | `occ config whiteboard maxFileSize` | `100` (MB) | | PHP | `upload_max_filesize` | `512M` | | PHP | `post_max_size` | `512M` | | PHP | `memory_limit` | `512M` | | Nginx | `client_max_body_size` | `0` (unlimited) | | Nginx | Whiteboard JS/CSS `Cache-Control` | `no-cache, no-store, must-revalidate` | | Cache | `theming cachebuster` | **26** | --- ## 4. Warum das nicht reicht (OOM-Problem) Mit `IM=1/0` und `imageOptions.maxWidthOrHeight=1/0` wird kein Downscaling mehr gemacht. Das bedeutet aber: **Jedes importierte Bild wird in voller原生auflösung als Base64 im Excalidraw-JSON gespeichert.** **RAM-Verbrauch pro Bild:** ``` Breite × Höhe × 4 Bytes (RGBA decoded) + Base64-String (~33% Overhead) 5000 × 2000 × 4 = 40 MB decoded + 13 MB Base64 = ~53 MB RAM/Bild 4000 × 3000 × 4 = 48 MB decoded + 16 MB Base64 = ~64 MB RAM/Bild ``` **Bei 3 Bildern → ~160 MB + UI-Overhead → OOM-Crash nach ~2 Minuten.** --- ## 5. Excalidraw vs. Miro: Der fundamentale Unterschied | | Excalidraw/Whiteboard | Miro | |---|---|---| | Bild-Speicherung | **Base64 inline im JSON** | URL-Referenz auf Server | | Rendering | Canvas 2D, alle Bilder immer im RAM | WebGL + Tiled-Streaming | | LOD | ❌ Nicht vorhanden | ✅ Nur sichtbare Kacheln geladen | | RAM pro 4K-Bild | ~50 MB | ~0 MB (lazy, GPU-Textur) | | 50× 4K-Bilder | 💥 unmöglich | ✅ problemlos | Miro speichert nur **URLs** (100 Bytes statt 50 MB) und lädt Bilder erst beim Hinscrollen. --- ## 6. Geplanter Fix: URL-Referenzen statt Base64 ### Ansatz Statt das Bild als `data:image/png;base64,...` im JSON zu speichern, soll nur eine **URL** gespeichert werden. Der Browser lädt das Bild dann nur bei Bedarf. ``` // JETZT: "files": { "abc123": { "dataURL": "data:image/png;base64,iVBORw0K...", ... } } // ZIEL: "files": { "abc123": { "url": "/remote.php/dav/files/.../image.png", ... } } ``` ### Was geändert werden muss | Komponente | Änderung | Aufwand | |---|---|---| | **Whiteboard Import** | Bild als Nextcloud-Datei speichern (WebDAV), nicht als Base64 | JS-Patch | | **Excalidraw JSON-Format** | `dataURL` → `url` (relativer Pfad) | JS-Patch | | **Excalidraw Rendering** | `Image()` vom Server laden statt aus Base64 | JS-Patch | | **Nextcloud CORS** | `Access-Control-Allow-Origin` für Bild-URLs | Config | | **File-ID Mapping** | `fileId` → Nextcloud-Dateipfad | JS-Patch | ### Risiken - Alles JS-Patches auf dem Volume → gehen bei App-Update verloren - Startup-Script zur Wiederherstellung nötig - Langfristig: Upstream-PR an Excalidraw/Whiteboard --- ## 7. Direkter Link zum Excalidraw-Upstream - **DEFAULT_IMAGE_OPTIONS** (Source of Truth): [`packages/common/src/constants.ts#L340-L342`](https://github.com/excalidraw/excalidraw/blob/master/packages/common/src/constants.ts) - **LOD Feature Request** (seit 2022 offen): [Issue #5334](https://github.com/excalidraw/excalidraw/issues/5334) - **Image Resolution Bug**: [Issue #5334](https://github.com/excalidraw/excalidraw/issues/5334) --- ## 8. Verifikation Server-seitig verifizieren (nach jedem Patch): ```bash # NcSelect curl -s "https://nextcloud.niklashmotion.art/custom_apps/whiteboard/js/NcSelect-CknHatsl.chunk.mjs?v=26" \ | grep -oP 'maxImageSizeBytes[^,]+|imageOptions:\{[^}]+\}' # Percentages curl -s "https://nextcloud.niklashmotion.art/custom_apps/whiteboard/js/percentages-BXMCSKIN-D6x-nnv3.chunk.mjs?v=26" \ | grep -oP 'IM=[^,]+|TM=[^,]+' ``` Automatisiert: `scripts/verify-whiteboard-patches.sh` (im Skill-Verzeichnis). --- ## 9. Nächste Schritte 1. [x] Alle Limits beseitigt (6 JS-Patches + Infrastruktur) 2. [ ] **4096px-Cap setzen** (Quick-Fix gegen OOM) — 2 Minuten, 12+ Bilder stabil 3. [ ] **URL-Referenzen implementieren** (echte Lösung) — 1–2 Tage Entwicklungszeit 4. [ ] Startup-Script für Persistenz über App-Updates 5. [ ] Langfristig: Upstream-PR für konfigurierbare Limits + URL-Referenzen