diff --git a/ChangeLog.md b/ChangeLog.md
index 2c77720..5fa2acd 100644
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,30 @@
# Changelog
+## 1.7.0 — 2026-08-28
+
+### Fotoqualität ist einstellbar — Vorgabe ist jetzt 1:1
+
+Die Baustelle-PWA hat **jedes** Foto fest auf 2000 px heruntergerechnet. Auf Typenschildern,
+Zählerständen und Mängeln war danach beim Hineinzoomen nichts mehr zu erkennen. Das war
+nirgends einstellbar, sondern eine Zahl im JavaScript.
+
+- **Admin → Bericht → „📷 Fotoqualität der Baustellen-App"**: `BERICHT_PHOTO_MAXSIDE`
+ (0 = Originalgröße, sonst 4000/3000/2000/1600 px) und `BERICHT_PHOTO_QUALITY`
+ (JPEG-Qualität, greift nur beim Verkleinern).
+- **Vorgabe ist 0 = Originalgröße.** Ohne Eingriff lädt die App ab jetzt das unveränderte
+ Kamerabild hoch. Die PHP-Limits auf Prod tragen das mühelos (`upload_max_filesize` 300M).
+- Neuer Endpoint **`api/config.php`** liefert die Werte an die PWA (Auth wie überall per
+ `awl_sso`-Cookie). Die App merkt sich die Antwort lokal, damit auch offline klar ist,
+ was gilt.
+
+### Nebenbefund: den bisherigen Fotos fehlt das EXIF komplett
+
+Ein Foto aus dem Bestand nachgemessen: `Quality: 85`, **kein** `DateTimeOriginal`, kein
+EXIF-Block. Das Herunterrechnen lief über ein Canvas, und dabei geht sämtliche
+EXIF-Information verloren — Aufnahmezeitpunkt, Ausrichtung, GPS. `bericht_file_taken_at()`
+musste deshalb bisher immer auf das Dateidatum ausweichen. Mit der neuen Vorgabe (1:1, kein
+Canvas) bleibt das EXIF der Kamera erhalten.
+
## 1.6.0 — 2026-08-28
### Dasselbe Foto kommt kein zweites Mal in den Auftragsordner
diff --git a/admin/setup.php b/admin/setup.php
index 4b0ef44..b3e9cd8 100644
--- a/admin/setup.php
+++ b/admin/setup.php
@@ -68,6 +68,10 @@ if ($action === 'save_const') {
'BERICHT_TAB_ON_SHIPMENT' => GETPOST('tab_shipment', 'int') ? '1' : '0',
'BERICHT_SIGNATURE_IMAGE_RATIO' => str_replace(',', '.', (string) GETPOST('sig_ratio', 'alphanohtml')) ?: '0.35',
'BERICHT_BURN_ANNOTATIONS' => GETPOST('burn', 'int') ? '1' : '0',
+ // Fotoqualitaet der Baustelle-PWA. 0 = Originalgroesse (1:1, Vorgabe),
+ // sonst die laengste Kante in Pixeln.
+ 'BERICHT_PHOTO_MAXSIDE' => (string) max(0, GETPOSTINT('photo_maxside')),
+ 'BERICHT_PHOTO_QUALITY' => (string) min(100, max(50, GETPOSTINT('photo_quality') ?: 100)),
'BERICHT_LIBREOFFICE_BIN' => GETPOST('lobin', 'alphanohtml'),
'BERICHT_WHISPER_URL' => GETPOST('whisper_url', 'alphanohtml'),
'BERICHT_WHISPER_MODE' => GETPOST('whisper_mode', 'alphanohtml'),
@@ -229,6 +233,25 @@ print ' '.$langs->trans("BerichtSetupSignat
print '';
print '
'.$langs->trans("BerichtSetupBurnAnnotations").'
'.$cb('burn', 'BERICHT_BURN_ANNOTATIONS', '1').'
';
+// --- Fotoqualitaet der Baustelle-PWA ---
+// Bis v1.6.0 hat die PWA jedes Foto fest auf 2000 px verkleinert. Auf Typenschildern
+// und Zaehlerstaenden war danach nichts mehr zu lesen. Jetzt einstellbar, Vorgabe 1:1.
+$photo_maxside = getDolGlobalInt('BERICHT_PHOTO_MAXSIDE', 0);
+$photo_quality = getDolGlobalInt('BERICHT_PHOTO_QUALITY', 100);
+print '
';
diff --git a/api/config.php b/api/config.php
new file mode 100644
index 0000000..2c66ef8
--- /dev/null
+++ b/api/config.php
@@ -0,0 +1,19 @@
+ 0).
+ */
+require_once __DIR__.'/_inc.php';
+
+api_authenticate();
+
+api_ok(array(
+ 'photo_maxside' => getDolGlobalInt('BERICHT_PHOTO_MAXSIDE', 0),
+ 'photo_quality' => getDolGlobalInt('BERICHT_PHOTO_QUALITY', 100),
+));
diff --git a/langs/de_DE/bericht.lang b/langs/de_DE/bericht.lang
index 5c6133a..f401672 100644
--- a/langs/de_DE/bericht.lang
+++ b/langs/de_DE/bericht.lang
@@ -60,6 +60,12 @@ BerichtSetupTabShipment = Reiter auf Lieferungen anzeigen
BerichtSetupSignatureRatio = Größen-Faktor Lieferschein-Unterschrift
BerichtSetupSignatureRatioDesc = Wie groß das {signature}-Bild im gerenderten ODT-PDF wird (0.35 ≈ 7×3.5 cm; höher = größer). Wird zur Laufzeit gegen die PNG-Pixel multipliziert.
BerichtSetupBurnAnnotations = Annotationen ins PDF einbrennen (statt als PDF-Annotations)
+BerichtSetupPhotoHeader = Fotoqualität der Baustellen-App
+BerichtSetupPhotoMaxSide = Fotos verkleinern auf
+BerichtSetupPhotoFull = Originalgröße (1:1, volle Kameraqualität)
+BerichtSetupPhotoMaxSideDesc = Längste Kante, auf die ein Foto vor dem Hochladen gerechnet wird. Originalgröße lädt das Bild unverändert hoch — nötig, damit Typenschilder, Zählerstände und Mängel beim Hineinzoomen lesbar bleiben. Kleinere Werte sparen Mobilfunk-Daten.
+BerichtSetupPhotoQuality = JPEG-Qualität
+BerichtSetupPhotoQualityDesc = Wirkt nur, wenn oben verkleinert wird. Bei Originalgröße bleibt die Datei so, wie die Kamera sie geliefert hat.
BerichtSetupLibreOfficeBin = Pfad zu LibreOffice (für ODT→PDF)
BerichtPlaceholdersTitle = Verfügbare Platzhalter in der ODT-Vorlage
BerichtErrorNoParent = Übergeordnetes Dokument nicht gefunden
diff --git a/langs/en_US/bericht.lang b/langs/en_US/bericht.lang
index ba3721e..406e3c2 100644
--- a/langs/en_US/bericht.lang
+++ b/langs/en_US/bericht.lang
@@ -60,6 +60,12 @@ BerichtSetupTabShipment = Show tab on shipments
BerichtSetupSignatureRatio = Delivery signature image ratio
BerichtSetupSignatureRatioDesc = How large the {signature} image is in the rendered ODT PDF (0.35 ≈ 7×3.5 cm; higher = bigger). Multiplied against PNG pixels at runtime.
BerichtSetupBurnAnnotations = Burn annotations into PDF (instead of PDF annotations)
+BerichtSetupPhotoHeader = Photo quality of the site app
+BerichtSetupPhotoMaxSide = Resize photos to
+BerichtSetupPhotoFull = Original size (1:1, full camera quality)
+BerichtSetupPhotoMaxSideDesc = Longest edge a photo is scaled to before upload. Original size uploads the image untouched — required to keep rating plates, meter readings and defects readable when zooming in. Smaller values save mobile data.
+BerichtSetupPhotoQuality = JPEG quality
+BerichtSetupPhotoQualityDesc = Only applies when resizing above. At original size the file stays exactly as the camera produced it.
BerichtSetupLibreOfficeBin = LibreOffice binary path (for ODT→PDF)
BerichtPlaceholdersTitle = Available placeholders in ODT template
BerichtErrorNoParent = Parent document not found