diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000..7400b0b65 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +template/collage/**/*.json diff --git a/api/admin.php b/api/admin.php index 0a6875fc4..c9c68ccea 100644 --- a/api/admin.php +++ b/api/admin.php @@ -30,7 +30,7 @@ $defaultConfig = $configurationService->getDefaultConfiguration(); $data = ArrayUtility::replaceBooleanValues($_POST); -$action = isset($data['type']) ? $data['type'] : null; +$action = $data['type'] ?? null; // Reset if ($action === 'reset') { @@ -257,59 +257,11 @@ // Collage json config $newConfig['collage']['limit'] = $newConfig['collage']['limit'] ?? $defaultConfig['collage']['limit']; if ($newConfig['collage']['enabled']) { - $collageConfigFilePath = Collage::getCollageConfigPath($newConfig['collage']['layout'], $newConfig['collage']['orientation']); - - if ($collageConfigFilePath !== null) { - $collageJson = json_decode((string)file_get_contents($collageConfigFilePath), true); - - if (is_array($collageJson)) { - if (isset($collageJson['layout']) && !empty($collageJson['layout'])) { - $layoutConfigArray = $collageJson['layout']; - - if (array_key_exists('placeholder', $collageJson)) { - $newConfig['collage']['placeholder'] = $collageJson['placeholder']; - } - if (array_key_exists('placeholderposition', $collageJson)) { - $newConfig['collage']['placeholderposition'] = $collageJson['placeholderposition']; - } - if (array_key_exists('placeholderpath', $collageJson)) { - $newConfig['collage']['placeholderpath'] = $collageJson['placeholderpath']; - } - } else { - $layoutConfigArray = $collageJson; - } - - // Calculate collage limit - if (str_starts_with($newConfig['collage']['layout'], '2x')) { - $newConfig['collage']['limit'] = (int) ceil(count($layoutConfigArray) / 2); - } else { - $newConfig['collage']['limit'] = count($layoutConfigArray); - } - - // If there is a collage placeholder whithin the correct range (0 < placeholderposition <= collage limit), we need to decrease the collage limit by 1 - if ($newConfig['collage']['placeholder']) { - $collagePlaceholderPosition = (int) $newConfig['collage']['placeholderposition']; - if ($collagePlaceholderPosition > 0 && $collagePlaceholderPosition <= $newConfig['collage']['limit']) { - $newConfig['collage']['limit'] = $newConfig['collage']['limit'] - 1; - } else { - $newConfig['collage']['placeholder'] = false; - $logger->debug('Placeholder position not in range. Placeholder disabled.'); - } - - if ($newConfig['collage']['placeholderpath'] === '') { - $newConfig['collage']['placeholder'] = false; - $logger->debug('Collage Placeholder is empty. Collage Placeholder disabled.'); - } - } - } else { - $newConfig['collage']['enabled'] = false; - $logger->debug('No valid collage json found. Collage disabled.'); - } - } + $limitData = Collage::calculateLimit($newConfig['collage'], $logger); + $newConfig['collage']['limit'] = $limitData['limit']; + $newConfig['collage']['placeholder'] = $limitData['placeholderEnabled']; if ($newConfig['collage']['limit'] < 1) { $newConfig['collage']['enabled'] = false; - $newConfig['collage']['limit'] = $defaultConfig['collage']['limit']; - $logger->debug('Invalid collage limit, must be 1 or greater. Collage disabled.'); } } diff --git a/api/applyEffects.php b/api/applyEffects.php index b8913225e..4108998b9 100644 --- a/api/applyEffects.php +++ b/api/applyEffects.php @@ -37,6 +37,15 @@ throw new \Exception('Invalid or missing style parameter'); } + if (isset($_POST['collageLayout'])) { + $config['collage']['layout'] = $_POST['collageLayout']; + + } + + $limitData = Collage::calculateLimit($config['collage'], $logger); + $config['collage']['limit'] = $limitData['limit']; + $config['collage']['placeholder'] = $limitData['placeholderEnabled']; + $vars['style'] = $_POST['style']; $vars['imageFilter'] = null; diff --git a/api/capture.php b/api/capture.php index 07d30962d..3f0ed8c65 100644 --- a/api/capture.php +++ b/api/capture.php @@ -19,6 +19,10 @@ throw new \Exception('No style provided'); } + if (isset($_POST['collageLimit'])) { + $config['collage']['limit'] = $_POST['collageLimit']; + } + if (!empty($_POST['file']) && (preg_match('/^[a-z0-9_]+\.jpg$/', $_POST['file']) || preg_match('/^[a-z0-9_]+\.(mp4)$/', $_POST['file']))) { $file = $_POST['file']; } else { diff --git a/assets/js/core.js b/assets/js/core.js index 5e3196023..8c5ee43f1 100644 --- a/assets/js/core.js +++ b/assets/js/core.js @@ -78,6 +78,8 @@ const photoBooth = (function () { api.chromaimage = ''; api.filename = ''; api.photoStyle = ''; + api.collageLayout = config.collage.layout; + api.collageLimit = config.collage.limit; api.isTimeOutPending = function () { return typeof timeOut !== 'undefined'; @@ -122,7 +124,6 @@ const photoBooth = (function () { api.init = function () { api.reset(); - startPage.addClass('stage--active'); if (usesBackgroundPreview) { photoboothPreview.startVideo(CameraDisplayMode.BACKGROUND); @@ -284,7 +285,7 @@ const photoBooth = (function () { '
' + (api.nextCollageNumber + 1) + ' / ' + - config.collage.limit; + api.collageLimit; labelElement.style.textAlign = 'center'; element.appendChild(labelElement); } else { @@ -561,6 +562,7 @@ const photoBooth = (function () { if (api.photoStyle === PhotoStyle.COLLAGE) { data.file = currentCollageFile; data.collageNumber = api.nextCollageNumber; + data.collageLimit = api.collageLimit; } if (api.photoStyle === PhotoStyle.CHROMA) { @@ -636,10 +638,10 @@ const photoBooth = (function () { loaderImage.show(); photoboothTools.console.logDev( - 'Taken collage photo number: ' + (result.current + 1) + ' / ' + result.limit + 'Taken collage photo number: ' + (result.current + 1) + ' / ' + api.collageLimit ); - if (result.current + 1 < result.limit) { + if (result.current + 1 < api.collageLimit) { photoboothTools.console.logDev('core: initialize Media.'); photoboothPreview.initializeMedia(); api.takingPic = false; @@ -650,7 +652,7 @@ const photoBooth = (function () { setTimeout(() => { api.clearLoaderImage(); imageUrl = ''; - if (result.current + 1 < result.limit) { + if (result.current + 1 < api.collageLimit) { api.thrill(PhotoStyle.COLLAGE); } else { currentCollageFile = ''; @@ -660,7 +662,7 @@ const photoBooth = (function () { }, continuousCollageTime); } else { // collage with interruption - if (result.current + 1 < result.limit) { + if (result.current + 1 < api.collageLimit) { const takePictureButton = $( '', + htmlspecialchars($layout->value), + $limit, + getLayoutPreviewSvg($layout, $orientation), + htmlspecialchars($layout->label()) + ); + } + } + + $html .= ''; // .collageSelector__options + $html .= ''; // .modal-body + $html .= ''; // .modal-buttonbar + $html .= ''; // .modal-inner + $html .= ''; // .modal + $html .= ''; // #collageSelector + + return $html; +} + +echo renderCollageOptionsFromEnumWithLimit($config['collage']); diff --git a/template/components/stage.start.php b/template/components/stage.start.php index 12cf152fc..caa5364b1 100644 --- a/template/components/stage.start.php +++ b/template/components/stage.start.php @@ -39,6 +39,9 @@ include PathUtility::getAbsolutePath('template/components/selfieAction.php'); } else { include PathUtility::getAbsolutePath('template/components/actionBtn.php'); + if ($config['collage']['enabled'] && $config['collage']['allow_selection']) { + include PathUtility::getAbsolutePath('template/components/collageSelection.php'); + } } ?> diff --git a/test/index.php b/test/index.php index a7a2bda42..083956d9a 100644 --- a/test/index.php +++ b/test/index.php @@ -39,6 +39,7 @@ echo getMenuBtn(PathUtility::getPublicPath('test/phpinfo.php'), 'phpinfo', ''); echo getMenuBtn(PathUtility::getPublicPath('test/photo.php'), 'pictureTest', ''); echo getMenuBtn(PathUtility::getPublicPath('test/collage.php'), 'collageTest', ''); +echo getMenuBtn(PathUtility::getPublicPath('test/text-positions.php'), 'testTextPositions', ''); echo getMenuBtn(PathUtility::getPublicPath('test/preview.php'), 'previewTest', ''); echo getMenuBtn(PathUtility::getPublicPath('test/chroma.php'), 'chromaPreviewTest', ''); echo getMenuBtn(PathUtility::getPublicPath('test/trigger.php'), 'remotebuzzerGetTrigger', ''); diff --git a/test/text-positions.php b/test/text-positions.php new file mode 100644 index 000000000..0c44301fb --- /dev/null +++ b/test/text-positions.php @@ -0,0 +1,213 @@ +getConfiguration(); +} else { + die('Keine Config-Quelle gefunden.'); +} + +// ---- Orientation aus Config ---- +$orientation = $config['collage']['orientation'] + ?? $config['collage']['format'] + ?? 'landscape'; + +$orientation = strtolower((string)$orientation); +if (!in_array($orientation, ['landscape', 'portrait'], true)) { + $orientation = 'landscape'; +} + +// ---- Text aktivieren (aus Config) ---- +$config['textoncollage']['enabled'] = true; + +// Sicherstellen dass kein Placeholder aktiv ist (wuerde das Limit aendern) +$config['collage']['placeholder'] = false; + +// Font setzen falls nicht vorhanden +$font = __DIR__ . '/../resources/fonts/GreatVibes-Regular.ttf'; +if (file_exists($font) && empty($config['textoncollage']['font'])) { + $config['textoncollage']['font'] = $font; +} + +function createTestImage(array $rgb, int $w, int $h, string $name): string +{ + $img = imagecreatetruecolor($w, $h); + $c = imagecolorallocate($img, $rgb[0], $rgb[1], $rgb[2]); + imagefill($img, 0, 0, $c); + $black = imagecolorallocate($img, 0, 0, 0); + imagestring($img, 5, (int)($w / 2 - 30), (int)($h / 2 - 8), $name, $black); + $file = __DIR__ . '/../data/tmp/' . $name . '.jpg'; + imagejpeg($img, $file, 90); + imagedestroy($img); + return $file; +} + +$colors = [ + [255, 100, 100], + [100, 255, 100], + [100, 100, 255], + [255, 255, 100], +]; + +// Alle verfuegbaren Layouts (landscape + portrait) +$pageTitle = 'Collage Text Positions - ' . ApplicationService::getInstance()->getTitle(); +include PathUtility::getAbsolutePath('admin/components/head.admin.php'); +include PathUtility::getAbsolutePath('admin/helper/index.php'); + +$layouts = [ + '1+3-1', '1+3-2', '3+1-1', '1+2-1', '2+1-1', + '2+2-1', '2+2-2', + '2x4-1', '2x4-2', '2x4-3', '2x4-4', + '2x3-1', '2x3-2', +]; + +?> +
+
+
+
+ translate('testTextPositions')?> +
+
+ + Orientation: + + + + Text-Zone (mode="zone") + +
+
+ +'; + echo '
' . htmlspecialchars($layout) . '
'; + echo '
Nicht verfuegbar fuer ' . $orientation . '
'; + echo '
'; + continue; + } + + // Korrekte Bildanzahl berechnen (fuer 2x Layouts: count/2) + $calcResult = Collage::calculateLimit($testConfig['collage']); + $imageCount = $calcResult['limit']; + + // WICHTIG: limit in Config setzen damit CollageConfigFactory den richtigen Wert verwendet + $testConfig['collage']['limit'] = $imageCount; + + // Template laden fuer Zone-Visualisierung + $json = json_decode(file_get_contents($templatePath), true); + + $w = $orientation === 'portrait' ? 600 : 800; + $h = $orientation === 'portrait' ? 800 : 600; + + for ($i = 0; $i < $imageCount; $i++) { + $tmp[] = createTestImage($colors[$i % 4], $w, $h, $layout . '_' . $i . '_' . $orientation); + } + + $dest = __DIR__ . '/../data/images/preview_' . $layout . '_' . $orientation . '.jpg'; + + $ok = Collage::createCollage($testConfig, $tmp, $dest); + + // Zone visualisieren falls vorhanden + $hasZone = false; + if ($ok && file_exists($dest)) { + if (isset($json['text_alignment']) && ($json['text_alignment']['mode'] ?? '') === 'zone') { + $hasZone = true; + $img = imagecreatefromjpeg($dest); + + if ($img) { + $width = imagesx($img); + $height = imagesy($img); + $ta = $json['text_alignment']; + + // Zone-Koordinaten berechnen + $rep = ['x' => $width, 'y' => $height]; + $zoneX = isset($ta['x']) ? (int) Helper::doMath(str_replace(array_keys($rep), array_values($rep), (string)$ta['x'])) : 0; + $zoneY = isset($ta['y']) ? (int) Helper::doMath(str_replace(array_keys($rep), array_values($rep), (string)$ta['y'])) : 0; + $zoneW = isset($ta['w']) ? (int) Helper::doMath(str_replace(array_keys($rep), array_values($rep), (string)$ta['w'])) : 0; + $zoneH = isset($ta['h']) ? (int) Helper::doMath(str_replace(array_keys($rep), array_values($rep), (string)$ta['h'])) : 0; + + // Magenta Zone zeichnen + imagesavealpha($img, true); + $fill = imagecolorallocatealpha($img, 255, 0, 255, 80); + $border = imagecolorallocate($img, 255, 255, 255); + imagefilledrectangle($img, $zoneX, $zoneY, $zoneX + $zoneW, $zoneY + $zoneH, $fill); + imagerectangle($img, $zoneX, $zoneY, $zoneX + $zoneW, $zoneY + $zoneH, $border); + imagerectangle($img, $zoneX + 1, $zoneY + 1, $zoneX + $zoneW - 1, $zoneY + $zoneH - 1, $border); + + imagejpeg($img, $dest, 90); + imagedestroy($img); + } + } + } + + echo '
'; + echo '
' . htmlspecialchars($layout) . '
'; + if ($ok && file_exists($dest)) { + echo ''; + $size = getimagesize($dest); + echo '
' . $size[0] . 'x' . $size[1]; + if ($hasZone) { + echo ' | Zone'; + } + echo '
'; + } else { + echo '
Fehler beim Erstellen
'; + } + echo '
'; + + foreach ($tmp as $f) { + @unlink($f); + } +} +?> + +
+
+ +
+ +
+
+ +
+
+
+ + +