From 2ae06404f7bd05ac1ce5e2402b1381c00f5906d0 Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Mon, 14 Sep 2020 10:14:49 +0200 Subject: [PATCH 01/32] feature (auto print): allow to print picture directly after taken Inspired by implementation from alzo425: https://github.com/alzo425/photobooth/commit/90099f17faa16ac4b4b3dd28a0ef7403dc2e29d6 - Slight adjustments for latest Photobooth, removed unneeded code changes. Change-Id: I24a192dbab03952f9310c2d8f8efe6f2538d7135 --- config/config.inc.php | 1 + lib/configsetup.inc.php | 5 +++++ resources/lang/en.json | 2 ++ src/js/core.js | 5 +++++ 4 files changed, 13 insertions(+) diff --git a/config/config.inc.php b/config/config.inc.php index dac810f72..b7ddda05a 100644 --- a/config/config.inc.php +++ b/config/config.inc.php @@ -9,6 +9,7 @@ $config['auto_reload_on_error'] = true; $config['pictureRotation'] = '0'; $config['use_print'] = false; +$config['auto_print'] = false; $config['use_qr'] = true; $config['use_download'] = true; $config['use_slideshow'] = true; diff --git a/lib/configsetup.inc.php b/lib/configsetup.inc.php index 0549e0bfb..f0f8be043 100644 --- a/lib/configsetup.inc.php +++ b/lib/configsetup.inc.php @@ -82,6 +82,11 @@ 'name' => 'use_print', 'value' => $config['use_print'] ], + 'auto_print' => [ + 'type' => 'checkbox', + 'name' => 'auto_print', + 'value' => $config['auto_print'] + ], 'use_qr' => [ 'type' => 'checkbox', 'name' => 'use_qr', diff --git a/resources/lang/en.json b/resources/lang/en.json index 8f5d8a7df..199bde63c 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -3,6 +3,7 @@ "admin_panel": "Admin panel", "allow_delete": "Allow deletion of the image", "allow_delete_from_gallery": "Allow deletion of images from gallery", + "auto_print": "Print picture immediately after taken", "auto_reload": "Photobooth reloads automatically...", "auto_reload_on_error": "Automatically reload Photobooth on error", "available_version": "Available version", @@ -112,6 +113,7 @@ "mail_username": "Username of the e-mail account", "manual_allow_delete": "If enabled pictures can be deleted on result page directly after they have been taken.", "manual_allow_delete_from_gallery": "If enabled pictures can be deleted from the gallery at any time.", + "manual_auto_print": "If enabled, the picture will immediately printed after it was taken.", "manual_auto_reload_on_error": "If an error occurs while taking a picture, Photobooth will reload automatically after 5 seconds.", "manual_chroma_keying": "If enabled, chromakeying can be accessed from gallery for your pictures.", "manual_commands_exiftool_cmd": "EXIFtool command line which is executed after taking a picture if \"Preserve EXIF data\" is enabled.", diff --git a/src/js/core.js b/src/js/core.js index 8ad51fa95..a690d204f 100644 --- a/src/js/core.js +++ b/src/js/core.js @@ -478,6 +478,11 @@ const photoBooth = (function () { }); }); + // If autoprint is activated the picture will immediately printed after taken. + if (config.auto_print) { + api.printImage(filename); + } + resultPage .find('.deletebtn') .off('click') From d27cd1268b38cff341b8ee8b04680017ba64bf8e Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Tue, 15 Sep 2020 18:44:30 +0200 Subject: [PATCH 02/32] feature (print): allow to delay auto print function Change-Id: Iba09c5dfba27d7c8dd9ef0bab55ab39e8a3f174c --- config/config.inc.php | 1 + lib/configsetup.inc.php | 10 ++++++++++ resources/lang/en.json | 2 ++ src/js/core.js | 4 +++- 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/config/config.inc.php b/config/config.inc.php index b7ddda05a..51fe89075 100644 --- a/config/config.inc.php +++ b/config/config.inc.php @@ -10,6 +10,7 @@ $config['pictureRotation'] = '0'; $config['use_print'] = false; $config['auto_print'] = false; +$config['auto_print_delay'] = '1000'; $config['use_qr'] = true; $config['use_download'] = true; $config['use_slideshow'] = true; diff --git a/lib/configsetup.inc.php b/lib/configsetup.inc.php index f0f8be043..02fe80c6f 100644 --- a/lib/configsetup.inc.php +++ b/lib/configsetup.inc.php @@ -87,6 +87,16 @@ 'name' => 'auto_print', 'value' => $config['auto_print'] ], + 'auto_print_delay' => [ + 'type' => 'range', + 'placeholder' => $defaultConfig['auto_print_delay'], + 'name' => 'auto_print_delay', + 'value' => $config['auto_print_delay'], + 'range_min' => 250, + 'range_max' => 10000, + 'range_step' => 250, + 'unit' => 'milliseconds' + ], 'use_qr' => [ 'type' => 'checkbox', 'name' => 'use_qr', diff --git a/resources/lang/en.json b/resources/lang/en.json index 199bde63c..21181947c 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -54,6 +54,7 @@ "gallery_pictureTime": "Milliseconds an image is displayed at slideshow", "gallery_pswp_bgOpacity": "Background opacity", "general": "General", + "general_auto_print_delay": "Delay automatic printing of the image", "general_camera_mode": "Camera facing mode", "general_cheese_time": "Cheeeeeeeese!-Timer:", "general_cntdwn_time": "Countdown timer:", @@ -141,6 +142,7 @@ "manual_gallery_date_format": "Enter your date style.", "manual_gallery_pictureTime": "Add a value which is used as milliseconds an image is displayed at slideshow inside the gallery.", "manual_gallery_pswp_bgOpacity": "Background opacity, low values make the background more transparent.", + "manual_general_auto_print_delay": "Enter in milliseconds by which the automatic printing of the image is delayed.", "manual_general_camera_mode": "Choose between front- or back facing camera mode of your device cam.", "manual_general_cheese_time": "Set a time to display \"Cheeeeeeeese!\" after the countdown.", "manual_general_cntdwn_time": "Set your countdown time.", diff --git a/src/js/core.js b/src/js/core.js index a690d204f..29b95dc37 100644 --- a/src/js/core.js +++ b/src/js/core.js @@ -480,7 +480,9 @@ const photoBooth = (function () { // If autoprint is activated the picture will immediately printed after taken. if (config.auto_print) { - api.printImage(filename); + setTimeout(function () { + api.printImage(filename); + }, config.auto_print_delay); } resultPage From 4a56aaec4054ccb2d357356fa069f6224f978696 Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Tue, 15 Sep 2020 18:46:38 +0200 Subject: [PATCH 03/32] adjust (config): move print settings to print menu Change-Id: I35cb076859bb2a70e893e0a2b1891f4df9bbe1db --- lib/configsetup.inc.php | 30 +++++++++++++++--------------- resources/lang/en.json | 4 ++-- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/configsetup.inc.php b/lib/configsetup.inc.php index 02fe80c6f..a14f20054 100644 --- a/lib/configsetup.inc.php +++ b/lib/configsetup.inc.php @@ -82,21 +82,6 @@ 'name' => 'use_print', 'value' => $config['use_print'] ], - 'auto_print' => [ - 'type' => 'checkbox', - 'name' => 'auto_print', - 'value' => $config['auto_print'] - ], - 'auto_print_delay' => [ - 'type' => 'range', - 'placeholder' => $defaultConfig['auto_print_delay'], - 'name' => 'auto_print_delay', - 'value' => $config['auto_print_delay'], - 'range_min' => 250, - 'range_max' => 10000, - 'range_step' => 250, - 'unit' => 'milliseconds' - ], 'use_qr' => [ 'type' => 'checkbox', 'name' => 'use_qr', @@ -616,6 +601,21 @@ ] ], 'print' => [ + 'auto_print' => [ + 'type' => 'checkbox', + 'name' => 'auto_print', + 'value' => $config['auto_print'] + ], + 'auto_print_delay' => [ + 'type' => 'range', + 'placeholder' => $defaultConfig['auto_print_delay'], + 'name' => 'auto_print_delay', + 'value' => $config['auto_print_delay'], + 'range_min' => 250, + 'range_max' => 10000, + 'range_step' => 250, + 'unit' => 'milliseconds' + ], 'print_qrcode' => [ 'type' => 'checkbox', 'name' => 'print_qrcode', diff --git a/resources/lang/en.json b/resources/lang/en.json index 21181947c..f07845043 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -54,7 +54,6 @@ "gallery_pictureTime": "Milliseconds an image is displayed at slideshow", "gallery_pswp_bgOpacity": "Background opacity", "general": "General", - "general_auto_print_delay": "Delay automatic printing of the image", "general_camera_mode": "Camera facing mode", "general_cheese_time": "Cheeeeeeeese!-Timer:", "general_cntdwn_time": "Countdown timer:", @@ -142,7 +141,6 @@ "manual_gallery_date_format": "Enter your date style.", "manual_gallery_pictureTime": "Add a value which is used as milliseconds an image is displayed at slideshow inside the gallery.", "manual_gallery_pswp_bgOpacity": "Background opacity, low values make the background more transparent.", - "manual_general_auto_print_delay": "Enter in milliseconds by which the automatic printing of the image is delayed.", "manual_general_camera_mode": "Choose between front- or back facing camera mode of your device cam.", "manual_general_cheese_time": "Set a time to display \"Cheeeeeeeese!\" after the countdown.", "manual_general_cntdwn_time": "Set your countdown time.", @@ -196,6 +194,7 @@ "manual_previewCamTakesPic": "If enabled, a picture is taken from device cam instead executing the \"Take picture command\". Please note that the resolution depends on the given hight and width because it's acts like taking a screenshot.", "manual_previewFromCam": "If enabled, a preview by your device cam is used at countdown. Preview by \"device cam\" will always use the camera of the device where Photobooth get opened in a Browser (e.g. on a tablet it will always show the tablet camera while on a smartphone it will always show the smartphone camera instead)! A secure origin or exception is required! You can find out how to set an exception here.", "manual_previewFromIPCam": "If enabled, a preview by defined url will be visible at countdown. Make sure to have a stream available you can use (e.g. from your Webcam, Smartphone Camera or Raspberry Pi Camera).", + "manual_print_auto_print_delay": "Enter in milliseconds by which the automatic printing of the image is delayed.", "manual_print_crop_height": "Enter a value for the height which is used for the picture if \"Crop picture at print\" is enabled.", "manual_print_crop_width": "Enter a value for the width which is used for the picture if \"Crop picture at print\" is enabled.", "manual_print_font_path": "Enter the path to the font used to print text onto your image.", @@ -274,6 +273,7 @@ "previewFromCam": "See preview by device cam", "previewFromIPCam": "Preview from URL", "print": "Print", + "print_auto_print_delay": "Delay automatic printing of the image", "print_crop_height": "New height at print (px)", "print_crop_width": "New width at print (px)", "print_font_path": "Font", From ead173895f46b790a075fbb58881d91afde0d536 Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Tue, 15 Sep 2020 18:55:50 +0200 Subject: [PATCH 04/32] feature (print): allow to adjust time printing info is visible Change-Id: I2aed70538041ec5d7aa2d22d972e03804edf74bd --- config/config.inc.php | 1 + lib/configsetup.inc.php | 10 ++++++++++ resources/lang/en.json | 2 ++ src/js/chromakeying.js | 2 +- src/js/core.js | 2 +- 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/config/config.inc.php b/config/config.inc.php index 51fe89075..3fb18249e 100644 --- a/config/config.inc.php +++ b/config/config.inc.php @@ -11,6 +11,7 @@ $config['use_print'] = false; $config['auto_print'] = false; $config['auto_print_delay'] = '1000'; +$config['printing_time'] = '5000'; $config['use_qr'] = true; $config['use_download'] = true; $config['use_slideshow'] = true; diff --git a/lib/configsetup.inc.php b/lib/configsetup.inc.php index a14f20054..5aea21a5e 100644 --- a/lib/configsetup.inc.php +++ b/lib/configsetup.inc.php @@ -616,6 +616,16 @@ 'range_step' => 250, 'unit' => 'milliseconds' ], + 'printing_time' => [ + 'type' => 'range', + 'placeholder' => $defaultConfig['printing_time'], + 'name' => 'printing_time', + 'value' => $config['printing_time'], + 'range_min' => 250, + 'range_max' => 20000, + 'range_step' => 250, + 'unit' => 'milliseconds' + ], 'print_qrcode' => [ 'type' => 'checkbox', 'name' => 'print_qrcode', diff --git a/resources/lang/en.json b/resources/lang/en.json index f07845043..140c27bad 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -207,6 +207,7 @@ "manual_print_linespace": "Enter used linespace while printing text on your picture.", "manual_print_locationx": "X-Coordinates of the text while printing text on your picture.", "manual_print_locationy": "Y-Coordinates of the text while printing text on your picture.", + "manual_print_printing_time": "Enter in milliseconds, how long \"Started printing! Please wait....\" is displayed after a print job has started.", "manual_print_qrcode": "If enabled, a QR-Code is printed onto the right side of the picture while printing.", "manual_print_rotation": "Enter a value which is used as degrees a picture gets rotated at print.", "manual_protect_admin": "If enabled, admin panel can only be accessed if a username and password is entered.", @@ -286,6 +287,7 @@ "print_linespace": "Line spacing", "print_locationx": "X Coordinate", "print_locationy": "Y Coordinate", + "print_printing_time": "Printing time", "print_qrcode": "QR-Code on the picture while printing", "print_rotation": "Text rotation", "printing": "Started printing! Please wait...", diff --git a/src/js/chromakeying.js b/src/js/chromakeying.js index 05dc71c53..187a73ab2 100644 --- a/src/js/chromakeying.js +++ b/src/js/chromakeying.js @@ -157,7 +157,7 @@ function printImage(filename, cb) { $('#print_mesg').html(''); } cb(); - }, 5000); + }, config.printing_time); }, error: (jqXHR, textStatus) => { console.log('An error occurred: ', textStatus); diff --git a/src/js/core.js b/src/js/core.js index 29b95dc37..582a0cae9 100644 --- a/src/js/core.js +++ b/src/js/core.js @@ -647,7 +647,7 @@ const photoBooth = (function () { ); } cb(); - }, 5000); + }, config.printing_time); }, error: (jqXHR, textStatus) => { console.log('An error occurred: ', textStatus); From 02e22da78e42f1c7c4e9f4e28f015b7abe87fa83 Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Tue, 15 Sep 2020 20:41:24 +0200 Subject: [PATCH 05/32] print (fix): don't try to print if we are printing already Change-Id: Icb40c3a21b3e304ccbf487b387d686edaa9fcc32 --- src/js/chromakeying.js | 82 +++++++++++++++++++++++----------------- src/js/core.js | 86 +++++++++++++++++++++++------------------- src/js/photoinit.js | 17 ++++++--- 3 files changed, 107 insertions(+), 78 deletions(-) diff --git a/src/js/chromakeying.js b/src/js/chromakeying.js index 187a73ab2..ed0dc465d 100644 --- a/src/js/chromakeying.js +++ b/src/js/chromakeying.js @@ -4,6 +4,7 @@ let mainImage; let mainImageWidth; let mainImageHeight; let backgroundImage; +let isPrinting = false; function greenToTransparency(imageIn, imageOut) { for (let y = 0; y < imageIn.getHeight(); y++) { @@ -132,47 +133,58 @@ function calculateAspectRatioFit(srcWidth, srcHeight, maxWidth, maxHeight) { function printImage(filename, cb) { const errormsg = i18n('error'); - setTimeout(function () { - $.ajax({ - method: 'GET', - url: 'api/print.php', - data: { - filename: filename - }, - success: (data) => { - console.log('Picture processed: ', data); - - if (data.error) { - console.log('An error occurred: ', data.error); + if (isPrinting) { + console.log('Printing already: ' + isPrinting); + } else { + isPrinting = true; + setTimeout(function () { + $.ajax({ + method: 'GET', + url: 'api/print.php', + data: { + filename: filename + }, + success: (data) => { + console.log('Picture processed: ', data); + + if (data.error) { + console.log('An error occurred: ', data.error); + $('#print_mesg').empty(); + $('#print_mesg').html( + '' + ); + } + + setTimeout(function () { + $('#print_mesg').removeClass('modal--show'); + if (data.error) { + $('#print_mesg').empty(); + $('#print_mesg').html( + '' + ); + } + cb(); + isPrinting = false; + }, config.printing_time); + }, + error: (jqXHR, textStatus) => { + console.log('An error occurred: ', textStatus); $('#print_mesg').empty(); $('#print_mesg').html( - '' + '' ); - } - setTimeout(function () { - $('#print_mesg').removeClass('modal--show'); - if (data.error) { + setTimeout(function () { + $('#print_mesg').removeClass('modal--show'); $('#print_mesg').empty(); $('#print_mesg').html(''); - } - cb(); - }, config.printing_time); - }, - error: (jqXHR, textStatus) => { - console.log('An error occurred: ', textStatus); - $('#print_mesg').empty(); - $('#print_mesg').html(''); - - setTimeout(function () { - $('#print_mesg').removeClass('modal--show'); - $('#print_mesg').empty(); - $('#print_mesg').html(''); - cb(); - }, 5000); - } - }); - }, 1000); + cb(); + isPrinting = false; + }, 5000); + } + }); + }, 1000); + } } function saveImage(cb) { diff --git a/src/js/core.js b/src/js/core.js index 582a0cae9..347670255 100644 --- a/src/js/core.js +++ b/src/js/core.js @@ -22,6 +22,7 @@ const photoBooth = (function () { videoSensor = document.querySelector('#video--sensor'); let timeOut, + isPrinting = false, takingPic = false, nextCollageNumber = 0, currentCollageFile = '', @@ -617,54 +618,63 @@ const photoBooth = (function () { }; api.printImage = function (imageSrc, cb) { - modal.open('#print_mesg'); const errormsg = i18n('error'); - setTimeout(function () { - $.ajax({ - method: 'GET', - url: 'api/print.php', - data: { - filename: imageSrc - }, - success: (data) => { - console.log('Picture processed: ', data); - - if (data.error) { - console.log('An error occurred: ', data.error); + if (isPrinting) { + console.log('Printing already: ' + isPrinting); + } else { + modal.open('#print_mesg'); + isPrinting = true; + setTimeout(function () { + $.ajax({ + method: 'GET', + url: 'api/print.php', + data: { + filename: imageSrc + }, + success: (data) => { + console.log('Picture processed: ', data); + + if (data.error) { + console.log('An error occurred: ', data.error); + $('#print_mesg').empty(); + $('#print_mesg').html( + '' + ); + } + + setTimeout(function () { + modal.close('#print_mesg'); + if (data.error) { + $('#print_mesg').empty(); + $('#print_mesg').html( + '' + ); + } + cb(); + isPrinting = false; + }, config.printing_time); + }, + error: (jqXHR, textStatus) => { + console.log('An error occurred: ', textStatus); $('#print_mesg').empty(); $('#print_mesg').html( - '' + '' ); - } - setTimeout(function () { - modal.close('#print_mesg'); - if (data.error) { + setTimeout(function () { + modal.close('#print_mesg'); $('#print_mesg').empty(); $('#print_mesg').html( '' ); - } - cb(); - }, config.printing_time); - }, - error: (jqXHR, textStatus) => { - console.log('An error occurred: ', textStatus); - $('#print_mesg').empty(); - $('#print_mesg').html( - '' - ); - - setTimeout(function () { - modal.close('#print_mesg'); - $('#print_mesg').empty(); - $('#print_mesg').html(''); - cb(); - }, 5000); - } - }); - }, 1000); + cb(); + isPrinting = false; + }, 5000); + } + }); + }, 1000); + } }; api.deleteImage = function (imageName, cb) { diff --git a/src/js/photoinit.js b/src/js/photoinit.js index 9f452dc6d..ab0525d0e 100644 --- a/src/js/photoinit.js +++ b/src/js/photoinit.js @@ -4,7 +4,8 @@ function initPhotoSwipeFromDOM(gallerySelector) { let gallery, ssRunning = false, - ssOnce = false; + ssOnce = false, + isPrinting = false; const ssDelay = config.gallery_pictureTime, ssButtonClass = '.pswp__button--playpause'; @@ -230,11 +231,17 @@ function initPhotoSwipeFromDOM(gallerySelector) { e.preventDefault(); e.stopPropagation(); - const img = gallery.currItem.src.split('\\').pop().split('/').pop(); + if (isPrinting) { + console.log('Printing already in progress!'); + } else { + isPrinting = true; + const img = gallery.currItem.src.split('\\').pop().split('/').pop(); - photoBooth.printImage(img, () => { - gallery.close(); - }); + photoBooth.printImage(img, () => { + gallery.close(); + isPrinting = false; + }); + } }); // Close Gallery while Taking a Picture or Collage From 66e5f500f3ddfbde6d2682bf260e4ebb0c5fb7eb Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Wed, 16 Sep 2020 11:51:37 +0000 Subject: [PATCH 06/32] feature (print): allow to print via defined key Change-Id: Iceedd49b20f87c9f48a0930155923f3ec5bf09ff --- config/config.inc.php | 1 + lib/configsetup.inc.php | 6 ++++++ resources/lang/en.json | 2 ++ src/js/chromakeying.js | 10 ++++++++++ src/js/core.js | 9 +++++++++ src/js/photoinit.js | 10 ++++++++++ 6 files changed, 38 insertions(+) diff --git a/config/config.inc.php b/config/config.inc.php index 3fb18249e..a5d1a3b64 100644 --- a/config/config.inc.php +++ b/config/config.inc.php @@ -72,6 +72,7 @@ // use for example https://keycode.info to get the key code $config['photo_key'] = null; $config['collage_key'] = null; +$config['print_key'] = null; // LANGUAGE // possible values: de, el, en, es, fr diff --git a/lib/configsetup.inc.php b/lib/configsetup.inc.php index 5aea21a5e..1bee21450 100644 --- a/lib/configsetup.inc.php +++ b/lib/configsetup.inc.php @@ -626,6 +626,12 @@ 'range_step' => 250, 'unit' => 'milliseconds' ], + 'print_key' => [ + 'type' => 'input', + 'name' => 'print_key', + 'placeholder' => '', + 'value' => $config['print_key'] + ], 'print_qrcode' => [ 'type' => 'checkbox', 'name' => 'print_qrcode', diff --git a/resources/lang/en.json b/resources/lang/en.json index 140c27bad..e8bb83dc7 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -207,6 +207,7 @@ "manual_print_linespace": "Enter used linespace while printing text on your picture.", "manual_print_locationx": "X-Coordinates of the text while printing text on your picture.", "manual_print_locationy": "Y-Coordinates of the text while printing text on your picture.", + "manual_print_print_key": "Specify the key id to use that key to print a picture (e.g. 13 is the enter key). For example use https://keycode.info to find out the key id.", "manual_print_printing_time": "Enter in milliseconds, how long \"Started printing! Please wait....\" is displayed after a print job has started.", "manual_print_qrcode": "If enabled, a QR-Code is printed onto the right side of the picture while printing.", "manual_print_rotation": "Enter a value which is used as degrees a picture gets rotated at print.", @@ -287,6 +288,7 @@ "print_linespace": "Line spacing", "print_locationx": "X Coordinate", "print_locationy": "Y Coordinate", + "print_print_key": "Key code which triggers printing", "print_printing_time": "Printing time", "print_qrcode": "QR-Code on the picture while printing", "print_rotation": "Text rotation", diff --git a/src/js/chromakeying.js b/src/js/chromakeying.js index ed0dc465d..110f3c75f 100644 --- a/src/js/chromakeying.js +++ b/src/js/chromakeying.js @@ -246,6 +246,16 @@ function closeHandler(ev) { } } +$(document).on('keyup', function (ev) { + if (config.use_print && config.print_key && parseInt(config.print_key, 10) === ev.keyCode) { + if (isPrinting) { + console.log('Printing already in progress!'); + } else { + $('#print-btn').trigger('click'); + } + } +}); + $(document).ready(function () { $('#save-btn').on('click', saveImageHandler); $('#print-btn').on('click', printImageHandler); diff --git a/src/js/core.js b/src/js/core.js index 347670255..fc5685fc7 100644 --- a/src/js/core.js +++ b/src/js/core.js @@ -899,6 +899,15 @@ const photoBooth = (function () { console.log('Taking photo already in progress!'); } } + + if (config.use_print && config.print_key && parseInt(config.print_key, 10) === ev.keyCode) { + if (isPrinting) { + console.log('Printing already in progress!'); + } else { + $('.printbtn').trigger('click'); + $('.printbtn').blur(); + } + } }); // clear Timeout to not reset the gallery, if you clicked anywhere diff --git a/src/js/photoinit.js b/src/js/photoinit.js index ab0525d0e..86260463d 100644 --- a/src/js/photoinit.js +++ b/src/js/photoinit.js @@ -303,4 +303,14 @@ function initPhotoSwipeFromDOM(gallerySelector) { } $(gallerySelector).on('click', onThumbnailClick); + + $(document).on('keyup', function (ev) { + if (config.use_print && config.print_key && parseInt(config.print_key, 10) === ev.keyCode) { + if (isPrinting) { + console.log('Printing already in progress!'); + } else { + $('.pswp__button--print').trigger('click'); + } + } + }); } From 97dddc3addd5f582d67de70560769cb6b8d94f9e Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Thu, 17 Sep 2020 19:31:13 +0200 Subject: [PATCH 07/32] feature (print): allow to show the print button independent Change-Id: I63cdcd71f95e0f4d3405c0e55b5b0c00a74c4827 --- chromakeying.php | 2 +- config/config.inc.php | 23 +++++++++++++---------- index.php | 2 +- lib/configsetup.inc.php | 20 +++++++++++++++----- resources/lang/de.json | 2 -- resources/lang/el.json | 1 - resources/lang/en.json | 8 ++++++-- resources/lang/es.json | 2 -- resources/lang/fr.json | 1 - src/js/chromakeying.js | 2 +- src/js/core.js | 2 +- src/js/photoinit.js | 2 +- template/pswp.template.php | 2 +- 13 files changed, 40 insertions(+), 29 deletions(-) diff --git a/chromakeying.php b/chromakeying.php index 7ff431cda..ecbb19f33 100644 --- a/chromakeying.php +++ b/chromakeying.php @@ -71,7 +71,7 @@
- + diff --git a/config/config.inc.php b/config/config.inc.php index a5d1a3b64..b1e6da292 100644 --- a/config/config.inc.php +++ b/config/config.inc.php @@ -8,19 +8,9 @@ $config['show_error_messages'] = true; $config['auto_reload_on_error'] = true; $config['pictureRotation'] = '0'; -$config['use_print'] = false; -$config['auto_print'] = false; -$config['auto_print_delay'] = '1000'; -$config['printing_time'] = '5000'; $config['use_qr'] = true; $config['use_download'] = true; $config['use_slideshow'] = true; -$config['print_qrcode'] = false; -$config['print_frame'] = false; -$config['print_frame_path'] = '../resources/img/frames/frame.png'; -$config['crop_onprint'] = false; -$config['crop_width'] = '1000'; -$config['crop_height'] = '500'; $config['use_mail'] = false; // mail data needs to be configured $config['show_fork'] = true; $config['previewFromCam'] = false; // experimental see https://github.com/andreknieriem/photobooth/pull/30 @@ -154,6 +144,19 @@ $config['slideshow_randomPicture'] = true; $config['slideshow_use_thumbs'] = false; +// PRINT +$config['use_print_result'] = false; +$config['use_print_gallery'] = false; +$config['use_print_chromakeying'] = false; +$config['auto_print'] = false; +$config['auto_print_delay'] = '1000'; +$config['printing_time'] = '5000'; +$config['print_qrcode'] = false; +$config['print_frame'] = false; +$config['print_frame_path'] = '../resources/img/frames/frame.png'; +$config['crop_onprint'] = false; +$config['crop_width'] = '1000'; +$config['crop_height'] = '500'; // TEXT ON PRINT $config['is_textonprint'] = false; $config['textonprint']['line1'] = 'line 1'; diff --git a/index.php b/index.php index ca7cb7598..233292268 100644 --- a/index.php +++ b/index.php @@ -162,7 +162,7 @@ - + diff --git a/lib/configsetup.inc.php b/lib/configsetup.inc.php index 1bee21450..5417c1d7f 100644 --- a/lib/configsetup.inc.php +++ b/lib/configsetup.inc.php @@ -77,11 +77,6 @@ 'placeholder' => '0644', 'value' => $config['picture_permissions'] ], - 'use_print' => [ - 'type' => 'checkbox', - 'name' => 'use_print', - 'value' => $config['use_print'] - ], 'use_qr' => [ 'type' => 'checkbox', 'name' => 'use_qr', @@ -601,6 +596,21 @@ ] ], 'print' => [ + 'use_print_result' => [ + 'type' => 'checkbox', + 'name' => 'use_print_result', + 'value' => $config['use_print_result'] + ], + 'use_print_gallery' => [ + 'type' => 'checkbox', + 'name' => 'use_print_gallery', + 'value' => $config['use_print_gallery'] + ], + 'use_print_chromakeying' => [ + 'type' => 'checkbox', + 'name' => 'use_print_chromakeying', + 'value' => $config['use_print_chromakeying'] + ], 'auto_print' => [ 'type' => 'checkbox', 'name' => 'auto_print', diff --git a/resources/lang/de.json b/resources/lang/de.json index 6f9d22b02..409ad7a18 100644 --- a/resources/lang/de.json +++ b/resources/lang/de.json @@ -245,7 +245,6 @@ "manual_use_download": "Wenn diese Option aktiviert ist, ist für jedes Bild in der Galerie eine Download-Schaltfläche sichtbar.", "manual_use_filter": "Wenn diese Option aktiviert ist, kann der Benutzer nach dem Aufnehmen eines Bildes einen Bildfilter auswählen.", "manual_use_mail": "Wenn diese Option aktiviert ist, ist für jedes Bild in der Galerie eine E-Mail-Schaltfläche sichtbar. Abhängig von Ihren Einstellungen können Sie Bilder direkt per E-Mail senden oder die eingegebene E-Mail-Adresse in einer Datenbank sammeln.", - "manual_use_print": "Wenn diese Option aktiviert ist, wird eine Druckschaltfläche auf dem Ergebnisbildschirm, der Galerie und der Chromakeying-Seite angezeigt.", "manual_use_qr": "Wenn diese Option aktiviert ist, wird eine QR-Schaltfläche auf dem Ergebnisbildschirm und in der Galerie angezeigt. Der Benutzer kann beim Scannen des QR-Codes ein Bild herunterladen. Wenn Sie über \"localhost\", \"127.0.0.1\" auf Photobooth zugreifen oder Photobooth in einem Unterordner installiert haben, definieren Sie bitte die IP-Adresse des Photobooth-Webservers, damit der QR-Code funktioniert.

Beispiel, wenn auf Photobooth direkt zugegriffen werden kann: 192.168.0.50.

Beispiel, wenn Photobooth in einem Unterordner installiert ist: 192.168.0.50/photobooth.

", "manual_use_slideshow": "Wenn diese Option aktiviert ist, wird in der Galerie eine Diashow-Schaltfläche angezeigt, mit der Sie eine Diashow starten / stoppen können.", "manual_use_thumbs": "Wenn diese Option aktiviert ist, werden Miniaturansichten für die Diashow verwendet. Dadurch wird die Leistung leicht verbessert.", @@ -349,7 +348,6 @@ "use_download": "Download aktivieren", "use_filter": "Bildfilter erlauben", "use_mail": "E-Mail aktivieren", - "use_print": "Drucken aktivieren", "use_qr": "QR-Code aktivieren", "use_slideshow": "Diashow in Galerie erlauben", "use_thumbs": "Thumbnails für die Diashow verwenden", diff --git a/resources/lang/el.json b/resources/lang/el.json index 1b708bffe..fb17d4eef 100644 --- a/resources/lang/el.json +++ b/resources/lang/el.json @@ -119,7 +119,6 @@ "use_download": "Επιτρέψτε τη λήψη", "use_filter": "Αφήστε φίλτρα εικόνας", "use_mail": "E-Mail Ενεργοποίηση", - "use_print": "Ενεργοποίηση εκτύπωσης", "use_qr": "Ενεργοποιήστε τον κωδικό QR", "user_interface": "διεπαφή χρήστη", "user_interface_background_admin": "Διαδρομή εικόνας φόντου διαχειριστή", diff --git a/resources/lang/en.json b/resources/lang/en.json index e8bb83dc7..f05ca0f1f 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -252,7 +252,9 @@ "manual_use_download": "If enabled, a download button is visible on each picture inside the gallery.", "manual_use_filter": "If enabled, user can choose a imagefiler after taking a picture.", "manual_use_mail": "If enabled, a email button is visible on each picture inside the gallery. Depending on your setup you can send pictures via email directly or collect entered email address inside a database.", - "manual_use_print": "If enabled, a print button is visible on result screen, gallery and chromakeying page.", + "manual_use_print_chromakeying": "If enabled, a print button is visible on chromakeying page.", + "manual_use_print_gallery": "If enabled, a print button is visible inside the gallery.", + "manual_use_print_result": "If enabled, a print button is visible on result screen.", "manual_use_qr": "If enabled, a QR-Button is visible on the result screen and inside gallery. User can download a picture while scanning the QR-Code. If you're accessing Photobooth via \"localhost\", \"127.0.0.1\" or if you have Photobooth installed inside a subfolder, please define IP address of the Photobooth web server to make the QR-Code working.

Example if Photobooth can be accessed directly: 192.168.0.50.

Example if Photobooth is installed inside a subfolder: 192.168.0.50/photobooth.

", "manual_use_slideshow": "If enabled, a slideshow button is visible inside the gallery to start/stop a slideshow.", "manual_use_thumbs": "If enabled, thumbnails are used for standalone gallery. This will improve the performance slightly.", @@ -361,7 +363,9 @@ "use_download": "Allow downloads", "use_filter": "Allow image filter", "use_mail": "Use E-Mail", - "use_print": "Use Print", + "use_print_chromakeying": "Allow printing from chromakeying", + "use_print_gallery": "Allow printing from gallery", + "use_print_result": "Allow printing from result page", "use_qr": "Use QR Codes", "use_slideshow": "Allow slideshow in gallery", "use_thumbs": "Use thumbnails for slideshow", diff --git a/resources/lang/es.json b/resources/lang/es.json index 5784a6a0b..999b8efe5 100644 --- a/resources/lang/es.json +++ b/resources/lang/es.json @@ -209,7 +209,6 @@ "manual_use_download": "Si está activado, un botón de descarga es visible en cada imagen dentro de la galería.", "manual_use_filter": "Si está habilitado, el usuario puede elegir un imagefiler después de tomar una foto.", "manual_use_mail": "Si está habilitado, un botón de correo electrónico es visible en cada imagen dentro de la galería. Dependiendo de su configuración puede enviar imágenes por correo electrónico directamente o recopilar la dirección de correo electrónico introducida dentro de una base de datos.", - "manual_use_print": "Si está activado, un botón de impresión es visible en la pantalla de resultados, la galería y la página de cromakey.", "manual_use_qr": "Si está activado, un botón QR es visible en la pantalla de resultados y dentro de la galería. El usuario puede descargar una imagen mientras escanea el código QR. Si está accediendo a Photobooth a través de \"localhost\", \"127.0.0.1\" o si tiene Photobooth instalado dentro de una subcarpeta, defina la dirección IP del servidor web Photobooth para que el código QR funcione.

Por ejemplo, si Photobooth se puede acceder directamente: 192.168.0.50.

Por ejemplo, si Photobooth está instalado dentro de una subcarpeta: 192.168.0.50/photobooth.

", "manual_use_thumbs": "Si está habilitada, las miniaturas se utilizan para la galería independiente. Esto mejorará ligeramente el rendimiento.", "manual_user_interface_background_admin": "Estilo CSS para fondo en el panel de administración.", @@ -287,7 +286,6 @@ "use_download": "Permitir descargas", "use_filter": "Autorice el tratamiento de imagen", "use_mail": "Utilizar el correo electrónico", - "use_print": "Utilizar la impresion", "use_qr": "Utilizar los códigos QR", "use_thumbs": "Usar miniaturas para la presentación de diapositivas", "user_interface": "Interfaz de usuario", diff --git a/resources/lang/fr.json b/resources/lang/fr.json index f739eb5b0..aaf1edac1 100644 --- a/resources/lang/fr.json +++ b/resources/lang/fr.json @@ -123,7 +123,6 @@ "use_download": "Autoriser les téléchargements", "use_filter": "Autorisez le filtre d'image", "use_mail": "Utiliser le courrier électronique", - "use_print": "Utiliser l'impression", "use_qr": "Utiliser le QR code", "user_interface": "Interface utilisateur", "user_interface_background_admin": "Chemin de l'image d'arrière-plan du panneau d'administration", diff --git a/src/js/chromakeying.js b/src/js/chromakeying.js index 110f3c75f..8633d01c5 100644 --- a/src/js/chromakeying.js +++ b/src/js/chromakeying.js @@ -247,7 +247,7 @@ function closeHandler(ev) { } $(document).on('keyup', function (ev) { - if (config.use_print && config.print_key && parseInt(config.print_key, 10) === ev.keyCode) { + if (config.use_print_chromakeying && config.print_key && parseInt(config.print_key, 10) === ev.keyCode) { if (isPrinting) { console.log('Printing already in progress!'); } else { diff --git a/src/js/core.js b/src/js/core.js index fc5685fc7..98ff92998 100644 --- a/src/js/core.js +++ b/src/js/core.js @@ -900,7 +900,7 @@ const photoBooth = (function () { } } - if (config.use_print && config.print_key && parseInt(config.print_key, 10) === ev.keyCode) { + if (config.use_print_result && config.print_key && parseInt(config.print_key, 10) === ev.keyCode) { if (isPrinting) { console.log('Printing already in progress!'); } else { diff --git a/src/js/photoinit.js b/src/js/photoinit.js index 86260463d..dd819eb6c 100644 --- a/src/js/photoinit.js +++ b/src/js/photoinit.js @@ -305,7 +305,7 @@ function initPhotoSwipeFromDOM(gallerySelector) { $(gallerySelector).on('click', onThumbnailClick); $(document).on('keyup', function (ev) { - if (config.use_print && config.print_key && parseInt(config.print_key, 10) === ev.keyCode) { + if (config.use_print_gallery && config.print_key && parseInt(config.print_key, 10) === ev.keyCode) { if (isPrinting) { console.log('Printing already in progress!'); } else { diff --git a/template/pswp.template.php b/template/pswp.template.php index 96eb88c0f..fb9e0a940 100644 --- a/template/pswp.template.php +++ b/template/pswp.template.php @@ -33,7 +33,7 @@ - + From c7fb7f4c5be92cbbb88720b2b8962c11f4395f63 Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Fri, 18 Sep 2020 07:19:32 +0200 Subject: [PATCH 08/32] fix (deletePhoto): also delete keying and tmp pictures - depends on user settings Change-Id: Iab333ca4636904380c20ef49cd86b51c3ad7b067 --- api/deletePhoto.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/api/deletePhoto.php b/api/deletePhoto.php index 5fa88b9c5..42e1ff518 100644 --- a/api/deletePhoto.php +++ b/api/deletePhoto.php @@ -13,6 +13,8 @@ $file = $_POST['file']; $filePath = $config['foldersAbs']['images'] . DIRECTORY_SEPARATOR . $file; $filePathThumb = $config['foldersAbs']['thumbs'] . DIRECTORY_SEPARATOR . $file; +$filePathKeying = $config['foldersAbs']['keying'] . DIRECTORY_SEPARATOR . $file; +$filePathTmp = $config['foldersAbs']['tmp'] . DIRECTORY_SEPARATOR . $file; // Only jpg/jpeg are supported $imginfo = getimagesize($filePath); @@ -29,6 +31,24 @@ ])); } +if ($config['chroma_keying']) { + if (is_readable($filePathKeying)) { + if (!unlink ($filePathKeying)) { + die(json_encode([ + 'error' => 'Could not delete keying file', + ])); + } + } +} + +if (is_readable($filePathTmp)) { + if (!unlink ($filePathTmp)) { + die(json_encode([ + 'error' => 'Could not delete tmp file', + ])); + } +} + deleteImageFromDB($file); echo json_encode([ From b7c0573726f3ea651e26bb549a74bea0403cbe67 Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Fri, 18 Sep 2020 17:40:36 +0200 Subject: [PATCH 09/32] improve (admin): reorder folder setup Change-Id: I701adc7d50061e729959f4971e5e03a6d10a4268 --- lib/configsetup.inc.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/configsetup.inc.php b/lib/configsetup.inc.php index 5417c1d7f..8fad9c5ad 100644 --- a/lib/configsetup.inc.php +++ b/lib/configsetup.inc.php @@ -511,6 +511,12 @@ ] ], 'folders' => [ + 'data' => [ + 'type' => 'input', + 'placeholder' => $defaultConfig['folders']['data'], + 'name' => 'folders[data]', + 'value' => $config['folders']['data'] + ], 'images' => [ 'type' => 'input', 'placeholder' => $defaultConfig['folders']['images'], @@ -546,12 +552,6 @@ 'placeholder' => $defaultConfig['folders']['tmp'], 'name' => 'folders[tmp]', 'value' => $config['folders']['tmp'] - ], - 'data' => [ - 'type' => 'input', - 'placeholder' => $defaultConfig['folders']['data'], - 'name' => 'folders[data]', - 'value' => $config['folders']['data'] ] ], 'event' => [ From 5f324dee9b6804c4aab92f52974cbe4b53193153 Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Fri, 18 Sep 2020 21:48:31 +0200 Subject: [PATCH 10/32] feature (thumbnail): allow to choose between differen thumbnail resolutions Change-Id: I522cb0a3041566d9486db97e2c7ab08e3dc0c58f --- api/applyEffects.php | 3 ++- config/config.inc.php | 1 + lib/configsetup.inc.php | 13 +++++++++++++ resources/lang/en.json | 2 ++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/api/applyEffects.php b/api/applyEffects.php index 09d9ae86f..14f6668ad 100644 --- a/api/applyEffects.php +++ b/api/applyEffects.php @@ -23,6 +23,7 @@ $frame_path = __DIR__ . DIRECTORY_SEPARATOR .$config['take_frame_path']; $collage_frame_path = __DIR__ . DIRECTORY_SEPARATOR .$config['take_collage_frame_path']; $picture_permissions = $config['picture_permissions']; +$thumb_size = substr($config['thumb_size'], 0, -2); if (isset($_POST['isCollage']) && $_POST['isCollage'] === 'true') { $collageBasename = substr($filename_tmp, 0, -4); @@ -115,7 +116,7 @@ } // image scale, create thumbnail -$thumbResource = resizeImage($imageResource, 500, 500); +$thumbResource = resizeImage($imageResource, $thumb_size, $thumb_size); imagejpeg($thumbResource, $filename_thumb, $config['jpeg_quality_thumb']); imagedestroy($thumbResource); diff --git a/config/config.inc.php b/config/config.inc.php index b1e6da292..8e42aec95 100644 --- a/config/config.inc.php +++ b/config/config.inc.php @@ -31,6 +31,7 @@ $config['collage_cntdwn_time'] = '3'; // control countdown timer between collage pictures $config['cheese_time'] = '1000'; // control time for cheeeeese! $config['keep_images'] = true; +$config['thumb_size'] = '540px'; $config['image_preview_before_processing'] = true; $config['preserve_exif_data'] = false; $config['use_filter'] = true; diff --git a/lib/configsetup.inc.php b/lib/configsetup.inc.php index 8fad9c5ad..bddea0b1e 100644 --- a/lib/configsetup.inc.php +++ b/lib/configsetup.inc.php @@ -44,6 +44,19 @@ 'name' => 'keep_images', 'value' => $config['keep_images'] ], + 'thumb_size' => [ + 'type' => 'select', + 'name' => 'thumb_size', + 'placeholder' => $defaultConfig['thumb_size'], + 'options' => [ + '360px' => 'XS', + '540px' => 'S', + '900px' => 'M', + '1080px' => 'L', + '1260px' => 'XL' + ], + 'value' => $config['thumb_size'] + ], 'show_error_messages' => [ 'type' => 'checkbox', 'name' => 'show_error_messages', diff --git a/resources/lang/en.json b/resources/lang/en.json index f05ca0f1f..8513c74a1 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -74,6 +74,7 @@ "general_start_screen_title": "Start screen (title)", "general_take_collage_frame_path": "Frame", "general_take_frame_path": "Frame", + "general_thumb_size": "Thumbnail size", "general_time_to_live": "Show image after capture:", "general_videoHeight": "Device cam picture height", "general_videoWidth": "Device cam picture width", @@ -161,6 +162,7 @@ "manual_general_start_screen_title": "Enter the title visible on startpage", "manual_general_take_collage_frame_path": "Enter the path of the frame which is applied to your collage after taking it.", "manual_general_take_frame_path": "Enter the path of the frame which is applied to your picture after taking it.", + "manual_general_thumb_size": "Choose thumbnail size: XS = max 360px, S = max 540px, M = max 900px, L = max 1080px, XL = max 1260px", "manual_general_time_to_live": "Enter a value used as milliseconds. This value defines the time your picture is visible on the result screen after taking a picture.", "manual_general_videoHeight": "Enter a value which is used as height for preview by device cam.", "manual_general_videoWidth": "Enter a value which is used as width for preview by device cam.", From d9959eb773a0996efa86d2a6bbd8a41974cc8bc5 Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Sat, 19 Sep 2020 10:24:41 +0200 Subject: [PATCH 11/32] api (download): use own download implementation again Change-Id: Ib625afe09865e320a2a36b83fa5667a5c5868d6b --- src/js/photoinit.js | 8 +++++++- src/sass/photoswipe-bottom.scss | 2 ++ src/sass/vendor/_photoswipe.scss | 1 + template/pswp.template.php | 5 +++-- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/js/photoinit.js b/src/js/photoinit.js index dd819eb6c..4542a52f8 100644 --- a/src/js/photoinit.js +++ b/src/js/photoinit.js @@ -146,11 +146,17 @@ function initPhotoSwipeFromDOM(gallerySelector) { }); gallery.listen('afterChange', function () { + const img = gallery.currItem.src.split('\\').pop().split('/').pop(); + if (config.dev) { - const img = gallery.currItem.src.split('\\').pop().split('/').pop(); console.log('Current image: ' + img); } + $('.pswp__button--custom-download').attr({ + href: 'api/download.php?image=' + img, + download: img + }); + if (ssRunning && ssOnce) { ssOnce = false; setTimeout(gotoNextSlide, ssDelay); diff --git a/src/sass/photoswipe-bottom.scss b/src/sass/photoswipe-bottom.scss index c3f199eab..e57e08928 100644 --- a/src/sass/photoswipe-bottom.scss +++ b/src/sass/photoswipe-bottom.scss @@ -4,6 +4,7 @@ .pswp__button--print, .pswp__button--print-chroma-keying, .pswp__button--download, +.pswp__button--custom-download, .pswp__button--mail, .pswp__button--playpause, .pswp__button--share, @@ -60,6 +61,7 @@ .pswp__button--print, .pswp__button--print-chroma-keying, .pswp__button--download, + .pswp__button--custom-download, .pswp__button--mail, .pswp__button--playpause, .pswp__button--share, diff --git a/src/sass/vendor/_photoswipe.scss b/src/sass/vendor/_photoswipe.scss index 35e0be950..cf8597b5f 100644 --- a/src/sass/vendor/_photoswipe.scss +++ b/src/sass/vendor/_photoswipe.scss @@ -3,6 +3,7 @@ .pswp__button--print, .pswp__button--print-chroma-keying, .pswp__button--download, +.pswp__button--custom-download, .pswp__button--mail, .pswp__button--playpause, .pswp__button--share, diff --git a/template/pswp.template.php b/template/pswp.template.php index fb9e0a940..8764e2a47 100644 --- a/template/pswp.template.php +++ b/template/pswp.template.php @@ -41,8 +41,9 @@ - - + + + From e70280bd37d892fcec65ef6168f01910e1b5834b Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Sat, 19 Sep 2020 10:46:47 +0200 Subject: [PATCH 12/32] feature (download): allow using thumbnails on download Change-Id: I48d66326fdf7f2beddadeb57be0aa5a2cfdb3c2e --- api/download.php | 11 ++++++++++- config/config.inc.php | 1 + lib/configsetup.inc.php | 5 +++++ resources/lang/en.json | 2 ++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/api/download.php b/api/download.php index 69d57dbba..2a94c17e2 100644 --- a/api/download.php +++ b/api/download.php @@ -1,9 +1,18 @@ 'use_download', 'value' => $config['use_download'] ], + 'download_thumbs' => [ + 'type' => 'checkbox', + 'name' => 'download_thumbs', + 'value' => $config['download_thumbs'] + ], 'use_slideshow' => [ 'type' => 'checkbox', 'name' => 'use_slideshow', diff --git a/resources/lang/en.json b/resources/lang/en.json index 8513c74a1..6154316fd 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -31,6 +31,7 @@ "dev": "Dev-Mode", "disk_usage": "Disk Usage", "dot": ".", + "download_thumbs": "Use thumbnails for download", "error": "Something went wrong. Please try it again.", "event": "Event", "event_symbol": "Symbol", @@ -127,6 +128,7 @@ "manual_crop_onprint": "If enabled, pictures are cropped at print by given height and width (px).", "manual_cups_button": "Show a button on startpage to easily access CUPS (Common Unix Printing System).", "manual_dev": "Enables development mode. Sample pictures will be used instead taking a picture.", + "manual_download_thumbs": "If enabled, thumbnails will be used at download (if exist) instead the full sized image.", "manual_event_symbol": "Choose a symbol which is shown between entered text.", "manual_event_textLeft": "Enter the text visible on the left side of the chosen symbol.", "manual_event_textRight": "Enter the text visible on the right side of the chosen symbol.", From 4251b769bf4322f1e0d1ae4d08776f4d421ea683 Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Mon, 14 Sep 2020 10:01:33 +0200 Subject: [PATCH 13/32] feature (collage): choose between 2x2 & 2x4 pictures on collage Implementation by alzo425: https://github.com/alzo425/photobooth/commit/90099f17faa16ac4b4b3dd28a0ef7403dc2e29d6 Adjustments: - Only use collage related changes. - Fixed spaces. - Adjusted config. - Fixed Windows compatibility. Change-Id: Ie371872e774a9cccf4da2cf507d929f1e55db177 --- api/applyEffects.php | 3 +- config/config.inc.php | 2 + lib/collage.php | 84 ++++++++++++------ lib/configsetup.inc.php | 16 ++++ .../img/frames/DefaultCollageBackground.png | Bin 0 -> 70953 bytes resources/lang/en.json | 4 + 6 files changed, 82 insertions(+), 27 deletions(-) create mode 100644 resources/img/frames/DefaultCollageBackground.png diff --git a/api/applyEffects.php b/api/applyEffects.php index 14f6668ad..3cb54e0bf 100644 --- a/api/applyEffects.php +++ b/api/applyEffects.php @@ -22,6 +22,7 @@ $filename_thumb = $config['foldersAbs']['thumbs'] . DIRECTORY_SEPARATOR . $file; $frame_path = __DIR__ . DIRECTORY_SEPARATOR .$config['take_frame_path']; $collage_frame_path = __DIR__ . DIRECTORY_SEPARATOR .$config['take_collage_frame_path']; +$collage_background = __DIR__ . DIRECTORY_SEPARATOR .$config['collage_background']; $picture_permissions = $config['picture_permissions']; $thumb_size = substr($config['thumb_size'], 0, -2); @@ -33,7 +34,7 @@ $collageSrcImagePaths[] = $collageBasename . '-' . $i . '.jpg'; } - if (!createCollage($collageSrcImagePaths, $filename_tmp, $config['take_collage_frame'], $collage_frame_path)) { + if (!createCollage($collageSrcImagePaths, $filename_tmp, $config['take_collage_frame'], $collage_frame_path, $config['collage_layout'], $collage_background)) { die(json_encode([ 'error' => 'Could not create collage' ])); diff --git a/config/config.inc.php b/config/config.inc.php index 57fd06d47..9bc84848b 100644 --- a/config/config.inc.php +++ b/config/config.inc.php @@ -46,6 +46,8 @@ $config['take_frame_path'] = '../resources/img/frames/frame.png'; $config['take_collage_frame'] = false; $config['take_collage_frame_path'] = '../resources/img/frames/frame.png'; +$config['collage_layout'] = '2x2'; // possible values are '2x2' or '2x4' +$config['collage_background'] = '../resources/img/frames/DefaultCollageBackground.png'; $config['chroma_keying'] = false; $config['use_collage'] = true; $config['continuous_collage'] = true; diff --git a/lib/collage.php b/lib/collage.php index 50cd6de3b..82ff40087 100644 --- a/lib/collage.php +++ b/lib/collage.php @@ -1,41 +1,73 @@ 'take_collage_frame_path', 'value' => htmlentities($config['take_collage_frame_path']) ], + 'collage_layout' => [ + 'type' => 'select', + 'name' => 'collage_layout', + 'placeholder' => $defaultConfig['collage_layout'], + 'options' => [ + '2x2' => '2x2', + '2x4' => '2x4' + ], + 'value' => $config['collage_layout'] + ], + 'collage_background' => [ + 'type' => 'input', + 'name' => 'collage_background', + 'placeholder' => $defaultConfig['collage_background'], + 'value' => $config['collage_background'] + ], 'collage_cntdwn_time' => [ 'type' => 'range', 'name' => 'collage_cntdwn_time', diff --git a/resources/img/frames/DefaultCollageBackground.png b/resources/img/frames/DefaultCollageBackground.png new file mode 100644 index 0000000000000000000000000000000000000000..c042712937effdff175dc6c0bebc820d0de01423 GIT binary patch literal 70953 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�>fbTaL;7ug|;t^nJV)_vz}g#5kLwuyxb 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 zW}https://keycode.info to find out the key id.", + "manual_general_collage_layout": "Choose between 2x2 and 2x4 pictures collage layout.", "manual_general_db_file": "Name of the database file.", "manual_general_default_imagefilter": "Choose an image filter which is applied by default after taking a picture.", "manual_general_disabled_filters": "Choose filters which get removed from the available image filters.", From 8361984a55b7c7b2f5f6c63c5a393218cb2059dc Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Mon, 14 Sep 2020 20:14:38 +0200 Subject: [PATCH 14/32] lib (collage): adjust given parameter --- lib/collage.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/collage.php b/lib/collage.php index 82ff40087..a544978ef 100644 --- a/lib/collage.php +++ b/lib/collage.php @@ -1,6 +1,6 @@ Date: Fri, 18 Sep 2020 13:00:29 +0200 Subject: [PATCH 15/32] Added a third collage layout Change-Id: I666532f8d9ddbe69356d3935b3bbe4d86ab6ef7b --- lib/collage.php | 51 +++++++++++++++++++++++++++++++++++++++++ lib/configsetup.inc.php | 3 ++- resources/lang/en.json | 4 ++-- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/lib/collage.php b/lib/collage.php index a544978ef..ccb0eb337 100644 --- a/lib/collage.php +++ b/lib/collage.php @@ -37,6 +37,57 @@ function createCollage($srcImagePaths, $destImagePath, $takeFrame, $framePath, $ imagedestroy($my_collage); break; case '2x4': + $degrees = 90; + + list($width_before, $height_before) = getimagesize($srcImagePaths[0]); + + $my_collage_width = $width_before; + $my_collage_height = $height_before; + + $my_collage = imagecreatetruecolor($my_collage_width,$my_collage_height); + $background = imagecolorallocate($my_collage, 240, 240, 240); + imagefill($my_collage,0,0,$background); + + $images_rotated = array(); + + for ($i = 0; $i < 4; $i++) { + $img_tmp = imagecreatefromjpeg($srcImagePaths[$i]); + + if ($takeFrame) { + $frame = imagecreatefrompng($framePath); + $frame = resizePngImage($frame, imagesx($img_tmp), imagesy($img_tmp)); + $x = (imagesx($img_tmp)/2) - (imagesx($frame)/2); + $y = (imagesy($img_tmp)/2) - (imagesy($frame)/2); + imagecopy($img_tmp, $frame, $x, $y, 0, 0, imagesx($frame), imagesy($frame)); + } + + $img_rotate_tmp = imagerotate($img_tmp, $degrees, 0); + $images_rotated[] = resizeImage($img_rotate_tmp, $height_before/3.3, $width_before/3.5); + } + + $new_width = imagesx($images_rotated[0]); + $new_height = imagesy($images_rotated[0]); + + $height_offset = ((($my_collage_height/2)-$new_height)/2); + $width_offset = (($my_collage_width-($new_width*4))/5); + + $positions_top = [[$width_offset, $height_offset], [($width_offset*2+$new_width), $height_offset], [($width_offset*3+2*$new_width), $height_offset], [($width_offset*4+3*$new_width), $height_offset]]; + $positions_bottom = [[$width_offset, ($new_height+(3*$height_offset))], [($width_offset*2+$new_width), ($new_height+(3*$height_offset))], [($width_offset*3+2*$new_width), ($new_height+(3*$height_offset))], [($width_offset*4+3*$new_width), ($new_height+(3*$height_offset))]]; + + for ($i = 0; $i < 4; $i++) { + $position_top = $positions_top[$i]; + $position_bottom = $positions_bottom[$i]; + + imagecopy( $my_collage, $images_rotated[$i],$position_top[0],$position_top[1],0,0,$new_width,$new_height); + imagecopy( $my_collage, $images_rotated[$i],$position_bottom[0],$position_bottom[1],0,0,$new_width,$new_height); + } + + imagescale($my_collage, $width_before, $height_before); + + imagejpeg($my_collage, $destImagePath); + imagedestroy($my_collage); + break; + case '2x4BI': $widthNew=321; $heightNew=482; $PositionsX = [63, 423, 785, 1146]; //X offset in Pixel diff --git a/lib/configsetup.inc.php b/lib/configsetup.inc.php index bb47b3f82..34e8d560a 100644 --- a/lib/configsetup.inc.php +++ b/lib/configsetup.inc.php @@ -256,7 +256,8 @@ 'placeholder' => $defaultConfig['collage_layout'], 'options' => [ '2x2' => '2x2', - '2x4' => '2x4' + '2x4' => '2x4', + '2x4BI' => '2x4 + background image' ], 'value' => $config['collage_layout'] ], diff --git a/resources/lang/en.json b/resources/lang/en.json index 385b5c55f..3c640be74 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -58,7 +58,7 @@ "general_camera_mode": "Camera facing mode", "general_cheese_time": "Cheeeeeeeese!-Timer:", "general_cntdwn_time": "Countdown timer:", - "general_collage_background": "Path to the background for 2x4 collage", + "general_collage_background": "Path to the background for \"2x4 + background image\" collage", "general_collage_cntdwn_time": "Collage-countdown timer:", "general_collage_key": "Key code which triggers a collage", "general_collage_layout": "Choose collage layout:", @@ -149,7 +149,7 @@ "manual_general_camera_mode": "Choose between front- or back facing camera mode of your device cam.", "manual_general_cheese_time": "Set a time to display \"Cheeeeeeeese!\" after the countdown.", "manual_general_cntdwn_time": "Set your countdown time.", - "manual_general_collage_background": "Enter the path of the background which is applied to your collage on 2x4 collage layout.", + "manual_general_collage_background": "Enter the path of the background which is applied to your collage on \"2x4 + background image\" collage layout.", "manual_general_collage_cntdwn_time": "Set your countdown time between pictures while taking a collage.", "manual_general_collage_key": "Specify the key id to use that key to take a collage (e.g. 13 is the enter key). For example use https://keycode.info to find out the key id.", "manual_general_collage_layout": "Choose between 2x2 and 2x4 pictures collage layout.", From f118c7ebf0b3c0e0ef520cf63ab9f6c8d620844e Mon Sep 17 00:00:00 2001 From: Kai Haupt Date: Sat, 19 Sep 2020 12:58:36 +0200 Subject: [PATCH 16/32] lib (collage): move Layout definition Change-Id: I9739cb98735a89256cfffd5134b5dc7b8a93b117 --- api/applyEffects.php | 2 +- lib/collage.php | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/api/applyEffects.php b/api/applyEffects.php index 3cb54e0bf..f8ecc3342 100644 --- a/api/applyEffects.php +++ b/api/applyEffects.php @@ -34,7 +34,7 @@ $collageSrcImagePaths[] = $collageBasename . '-' . $i . '.jpg'; } - if (!createCollage($collageSrcImagePaths, $filename_tmp, $config['take_collage_frame'], $collage_frame_path, $config['collage_layout'], $collage_background)) { + if (!createCollage($collageSrcImagePaths, $filename_tmp, $config['take_collage_frame'], $collage_frame_path, $collage_background)) { die(json_encode([ 'error' => 'Could not create collage' ])); diff --git a/lib/collage.php b/lib/collage.php index ccb0eb337..688b1fca2 100644 --- a/lib/collage.php +++ b/lib/collage.php @@ -1,12 +1,15 @@ Date: Sat, 19 Sep 2020 13:13:19 +0200 Subject: [PATCH 17/32] fix (collage): only apply frame once Change-Id: Icfea70b2925a519db9a15531db57cbafd1dd9009 --- lib/collage.php | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/lib/collage.php b/lib/collage.php index 688b1fca2..3426396ae 100644 --- a/lib/collage.php +++ b/lib/collage.php @@ -47,27 +47,31 @@ function createCollage($srcImagePaths, $destImagePath, $takeFrame, $framePath, $ $my_collage_width = $width_before; $my_collage_height = $height_before; - $my_collage = imagecreatetruecolor($my_collage_width,$my_collage_height); + $my_collage = imagecreatetruecolor($my_collage_width, $my_collage_height); $background = imagecolorallocate($my_collage, 240, 240, 240); - imagefill($my_collage,0,0,$background); + imagefill($my_collage, 0, 0, $background); $images_rotated = array(); for ($i = 0; $i < 4; $i++) { $img_tmp = imagecreatefromjpeg($srcImagePaths[$i]); - if ($takeFrame) { - $frame = imagecreatefrompng($framePath); - $frame = resizePngImage($frame, imagesx($img_tmp), imagesy($img_tmp)); - $x = (imagesx($img_tmp)/2) - (imagesx($frame)/2); - $y = (imagesy($img_tmp)/2) - (imagesy($frame)/2); - imagecopy($img_tmp, $frame, $x, $y, 0, 0, imagesx($frame), imagesy($frame)); + if (!file_exists($srcImagePaths[$i])) { + return false; } $img_rotate_tmp = imagerotate($img_tmp, $degrees, 0); $images_rotated[] = resizeImage($img_rotate_tmp, $height_before/3.3, $width_before/3.5); } + if ($takeFrame) { + $frame = imagecreatefrompng($framePath); + $frame = resizePngImage($frame, $my_collage_width, $my_collage_height); + $x = (imagesx($my_collage)/2) - (imagesx($frame)/2); + $y = (imagesy($my_collage)/2) - (imagesy($frame)/2); + imagecopy($my_collage, $frame, $x, $y, 0, 0, $my_collage_width, $my_collage_height); + } + $new_width = imagesx($images_rotated[0]); $new_height = imagesy($images_rotated[0]); From 41bf073d6880bf024eb8e4626c27d808834c199b Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Sat, 19 Sep 2020 14:08:50 +0200 Subject: [PATCH 18/32] feature (collage): allow to apply frame once or to every picture Change-Id: I4679880a2b97f7a0a5e90361347805ac0196ab6a --- api/applyEffects.php | 2 +- config/config.inc.php | 1 + lib/collage.php | 26 ++++++++++++++++++++++---- lib/configsetup.inc.php | 5 +++++ resources/lang/en.json | 2 ++ 5 files changed, 31 insertions(+), 5 deletions(-) diff --git a/api/applyEffects.php b/api/applyEffects.php index f8ecc3342..3d59cfdb2 100644 --- a/api/applyEffects.php +++ b/api/applyEffects.php @@ -34,7 +34,7 @@ $collageSrcImagePaths[] = $collageBasename . '-' . $i . '.jpg'; } - if (!createCollage($collageSrcImagePaths, $filename_tmp, $config['take_collage_frame'], $collage_frame_path, $collage_background)) { + if (!createCollage($collageSrcImagePaths, $filename_tmp, $config['take_collage_frame'], $config['take_collage_frame_always'], $collage_frame_path, $collage_background)) { die(json_encode([ 'error' => 'Could not create collage' ])); diff --git a/config/config.inc.php b/config/config.inc.php index 9bc84848b..1648fa54b 100644 --- a/config/config.inc.php +++ b/config/config.inc.php @@ -45,6 +45,7 @@ $config['take_frame'] = false; $config['take_frame_path'] = '../resources/img/frames/frame.png'; $config['take_collage_frame'] = false; +$config['take_collage_frame_always'] = false; $config['take_collage_frame_path'] = '../resources/img/frames/frame.png'; $config['collage_layout'] = '2x2'; // possible values are '2x2' or '2x4' $config['collage_background'] = '../resources/img/frames/DefaultCollageBackground.png'; diff --git a/lib/collage.php b/lib/collage.php index 3426396ae..1da2d79e8 100644 --- a/lib/collage.php +++ b/lib/collage.php @@ -3,7 +3,7 @@ define('LAYOUT', $config['collage_layout']); -function createCollage($srcImagePaths, $destImagePath, $takeFrame, $framePath, $background_image) { +function createCollage($srcImagePaths, $destImagePath, $takeFrame, $takeFrameAlways, $framePath, $background_image) { if (!is_array($srcImagePaths) || count($srcImagePaths) !== 4) { return false; @@ -28,13 +28,23 @@ function createCollage($srcImagePaths, $destImagePath, $takeFrame, $framePath, $ $tempSubImage = imagecreatefromjpeg($srcImagePaths[$i]); + if ($takeFrame && $takeFrameAlways) { + $frame = imagecreatefrompng($framePath); + $frame = resizePngImage($frame, imagesx($tempSubImage), imagesy($tempSubImage)); + $x = (imagesx($tempSubImage)/2) - (imagesx($frame)/2); + $y = (imagesy($tempSubImage)/2) - (imagesy($frame)/2); + imagecopy($tempSubImage, $frame, $x, $y, 0, 0, imagesx($frame), imagesy($frame)); + } + imagecopyresized($my_collage, $tempSubImage, $position[0], $position[1], 0, 0, $width / 2, $height / 2, $width, $height); imagedestroy($tempSubImage); } - if ($takeFrame) { + if ($takeFrame && !$takeFrameAlways) { $frame = imagecreatefrompng($framePath); $frame = resizePngImage($frame, $width, $height); - imagecopy($my_collage, $frame, 0, 0, 0, 0, $width, $height); + $x = (imagesx($my_collage)/2) - (imagesx($frame)/2); + $y = (imagesy($my_collage)/2) - (imagesy($frame)/2); + imagecopy($my_collage, $frame, $x, $y, 0, 0, $width, $height); } imagejpeg($my_collage, $destImagePath); imagedestroy($my_collage); @@ -60,11 +70,19 @@ function createCollage($srcImagePaths, $destImagePath, $takeFrame, $framePath, $ return false; } + if ($takeFrame && $takeFrameAlways) { + $frame = imagecreatefrompng($framePath); + $frame = resizePngImage($frame, imagesx($img_tmp), imagesy($img_tmp)); + $x = (imagesx($img_tmp)/2) - (imagesx($frame)/2); + $y = (imagesy($img_tmp)/2) - (imagesy($frame)/2); + imagecopy($img_tmp, $frame, $x, $y, 0, 0, imagesx($frame), imagesy($frame)); + } + $img_rotate_tmp = imagerotate($img_tmp, $degrees, 0); $images_rotated[] = resizeImage($img_rotate_tmp, $height_before/3.3, $width_before/3.5); } - if ($takeFrame) { + if ($takeFrame && !$takeFrameAlways) { $frame = imagecreatefrompng($framePath); $frame = resizePngImage($frame, $my_collage_width, $my_collage_height); $x = (imagesx($my_collage)/2) - (imagesx($frame)/2); diff --git a/lib/configsetup.inc.php b/lib/configsetup.inc.php index 34e8d560a..0ca709577 100644 --- a/lib/configsetup.inc.php +++ b/lib/configsetup.inc.php @@ -244,6 +244,11 @@ 'name' => 'take_collage_frame', 'value' => $config['take_collage_frame'] ], + 'take_collage_frame_always' => [ + 'type' => 'checkbox', + 'name' => 'take_collage_frame_always', + 'value' => $config['take_collage_frame_always'] + ], 'take_collage_frame_path' => [ 'type' => 'input', 'placeholder' => $defaultConfig['take_collage_frame_path'], diff --git a/resources/lang/en.json b/resources/lang/en.json index 3c640be74..36d90acec 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -254,6 +254,7 @@ "manual_slideshow_pictureTime": "Add a value which is used as milliseconds an image is displayed at standalone slideshow.", "manual_slideshow_refreshTime": "Refresh standalone slideshow after entered seconds.", "manual_take_collage_frame": "If enabled, defined frame will be applied to your collage after taking it.", + "manual_take_collage_frame_always": "If enabled, defined collage frame will be applied to each picture of your collage instead once after taking it. \"Take collage with frame\" needs to be enabled.", "manual_take_frame": "If enabled, defined frame will be applied to your picture after taking it.", "manual_toggle_fs_button": "If enabled, a button to toggle fullscreenmode will be added to the start screen.", "manual_use_collage": "If enabled, user can take a collage. A collage consists of 4 pictures. Optional you can take a collage with or without interruption.", @@ -361,6 +362,7 @@ "takeCollage": "Take Collage!", "takePhoto": "Take Pic!", "take_collage_frame": "Take collage with frame", + "take_collage_frame_always": "Apply frame to each picture of the collage", "take_frame": "Take picture with frame", "test_update_available": "There is a test update available.", "toggleFullscreen": "Toggle Fullscreen", From 9c427647809e4a7bd319334f9fa300ea2b3ad472 Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Sat, 19 Sep 2020 15:18:23 +0200 Subject: [PATCH 19/32] fix (collage): apply frame once on 2x4 collage with background image Change-Id: I8eee49d2432e4ef66ffdb525a33361fa7162b81b --- lib/collage.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/collage.php b/lib/collage.php index 1da2d79e8..5f18b13ad 100644 --- a/lib/collage.php +++ b/lib/collage.php @@ -118,6 +118,7 @@ function createCollage($srcImagePaths, $destImagePath, $takeFrame, $takeFrameAlw $PositionsX = [63, 423, 785, 1146]; //X offset in Pixel $PositionsY =[57, 642]; //Y offset in Pixel $my_collage= imagecreatefrompng($background_image); + list($bg_width, $bg_height) = getimagesize($background_image); for ($j = 0; $j < 2; $j++) { //delta Y $dY =$PositionsY[$j]; @@ -134,6 +135,13 @@ function createCollage($srcImagePaths, $destImagePath, $takeFrame, $takeFrameAlw imagedestroy($tempSubRotated); // Destroy temporary images } } + if ($takeFrame && !$takeFrameAlways) { + $frame = imagecreatefrompng($framePath); + $frame = resizePngImage($frame, $bg_width, $bg_height); + $x = (imagesx($my_collage)/2) - (imagesx($frame)/2); + $y = (imagesy($my_collage)/2) - (imagesy($frame)/2); + imagecopy($my_collage, $frame, $x, $y, 0, 0, $bg_width, $bg_height); + } imagejpeg($my_collage, $destImagePath); // Transfer immage to destImagePath with returns the image to core imagedestroy($my_collage); // Destroy the created collage in memory break; From 21aa0720ff649dd7eb0f9b8f96a5fd43f85b684b Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Sat, 19 Sep 2020 16:38:41 +0200 Subject: [PATCH 20/32] fix (collage): apply frame to each photo on 2x4 collage with background image Change-Id: Ice486264d35a8a2c22f6e7cbb88c078a2a95fc9f --- lib/collage.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/collage.php b/lib/collage.php index 5f18b13ad..970c78434 100644 --- a/lib/collage.php +++ b/lib/collage.php @@ -128,6 +128,15 @@ function createCollage($srcImagePaths, $destImagePath, $takeFrame, $takeFrameAlw return false; } $tempSubImage = imagecreatefromjpeg($srcImagePaths[$i]); + + if ($takeFrame && $takeFrameAlways) { + $frame = imagecreatefrompng($framePath); + $frame = resizePngImage($frame, imagesx($tempSubImage), imagesy($tempSubImage)); + $x = (imagesx($tempSubImage)/2) - (imagesx($frame)/2); + $y = (imagesy($tempSubImage)/2) - (imagesy($frame)/2); + imagecopy($tempSubImage, $frame, $x, $y, 0, 0, imagesx($frame), imagesy($frame)); + } + $tempSubRotated = imagerotate($tempSubImage, 90, 0);// Rotate image list($width, $height) = getimagesize($srcImagePaths[0]); imagecopyresized($my_collage, $tempSubRotated, $dX, $dY, 0, 0, $widthNew, $heightNew, $height, $width); // copy image to background From 0bcd6c0ce50db1a1d823fb9bb8c2ba36ffe92266 Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Sat, 19 Sep 2020 16:45:54 +0200 Subject: [PATCH 21/32] lib (collage): some adjustments Change-Id: I03d2ef1a12fe7b0d3094f8cacf4117de1d90e755 --- lib/collage.php | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/lib/collage.php b/lib/collage.php index 970c78434..97c2ac5c9 100644 --- a/lib/collage.php +++ b/lib/collage.php @@ -64,7 +64,7 @@ function createCollage($srcImagePaths, $destImagePath, $takeFrame, $takeFrameAlw $images_rotated = array(); for ($i = 0; $i < 4; $i++) { - $img_tmp = imagecreatefromjpeg($srcImagePaths[$i]); + $tempSubImage = imagecreatefromjpeg($srcImagePaths[$i]); if (!file_exists($srcImagePaths[$i])) { return false; @@ -72,14 +72,14 @@ function createCollage($srcImagePaths, $destImagePath, $takeFrame, $takeFrameAlw if ($takeFrame && $takeFrameAlways) { $frame = imagecreatefrompng($framePath); - $frame = resizePngImage($frame, imagesx($img_tmp), imagesy($img_tmp)); - $x = (imagesx($img_tmp)/2) - (imagesx($frame)/2); - $y = (imagesy($img_tmp)/2) - (imagesy($frame)/2); - imagecopy($img_tmp, $frame, $x, $y, 0, 0, imagesx($frame), imagesy($frame)); + $frame = resizePngImage($frame, imagesx($tempSubImage), imagesy($tempSubImage)); + $x = (imagesx($tempSubImage)/2) - (imagesx($frame)/2); + $y = (imagesy($tempSubImage)/2) - (imagesy($frame)/2); + imagecopy($tempSubImage, $frame, $x, $y, 0, 0, imagesx($frame), imagesy($frame)); } - $img_rotate_tmp = imagerotate($img_tmp, $degrees, 0); - $images_rotated[] = resizeImage($img_rotate_tmp, $height_before/3.3, $width_before/3.5); + $tempSubRotated = imagerotate($tempSubImage, $degrees, 0); + $images_rotated[] = resizeImage($tempSubRotated, $height_before/3.3, $width_before/3.5); } if ($takeFrame && !$takeFrameAlways) { @@ -113,6 +113,7 @@ function createCollage($srcImagePaths, $destImagePath, $takeFrame, $takeFrameAlw imagedestroy($my_collage); break; case '2x4BI': + $degrees = 90; $widthNew=321; $heightNew=482; $PositionsX = [63, 423, 785, 1146]; //X offset in Pixel @@ -137,11 +138,11 @@ function createCollage($srcImagePaths, $destImagePath, $takeFrame, $takeFrameAlw imagecopy($tempSubImage, $frame, $x, $y, 0, 0, imagesx($frame), imagesy($frame)); } - $tempSubRotated = imagerotate($tempSubImage, 90, 0);// Rotate image + $tempSubRotated = imagerotate($tempSubImage, $degrees, 0);// Rotate image list($width, $height) = getimagesize($srcImagePaths[0]); imagecopyresized($my_collage, $tempSubRotated, $dX, $dY, 0, 0, $widthNew, $heightNew, $height, $width); // copy image to background - imagedestroy($tempSubImage); // Destroy temporary images imagedestroy($tempSubRotated); // Destroy temporary images + imagedestroy($tempSubImage); // Destroy temporary images } } if ($takeFrame && !$takeFrameAlways) { @@ -151,14 +152,14 @@ function createCollage($srcImagePaths, $destImagePath, $takeFrame, $takeFrameAlw $y = (imagesy($my_collage)/2) - (imagesy($frame)/2); imagecopy($my_collage, $frame, $x, $y, 0, 0, $bg_width, $bg_height); } - imagejpeg($my_collage, $destImagePath); // Transfer immage to destImagePath with returns the image to core + imagejpeg($my_collage, $destImagePath); // Transfer image to destImagePath with returns the image to core imagedestroy($my_collage); // Destroy the created collage in memory break; default: list($width, $height) = getimagesize($srcImagePaths[0]); $my_collage = imagecreatetruecolor($width, $height); - imagejpeg($my_collage, $destImagePath); // Transfer immage to destImagePath with returns the image to core + imagejpeg($my_collage, $destImagePath); // Transfer image to destImagePath with returns the image to core imagedestroy($my_collage); // Destroy the created collage in memory break; } From 61b741110fe0da1222c087058c70d01fb79d8d17 Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Sun, 20 Sep 2020 09:27:27 +0200 Subject: [PATCH 22/32] docs (README): new features always on GitHub for everyone --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index c5881e3d2..385e0a080 100644 --- a/README.md +++ b/README.md @@ -133,10 +133,6 @@ If you like my work and like to keep me motivated you can buy me a coconut water [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/andreasblaesius) -### :information_source: Donators Early Access - -Donators who donated 5€ or more get early access to new features/options i am adding (please leave a message at donation telling your email address). - ### :mortar_board: Tutorial [Raspberry Pi Weddingphotobooth (german)](https://www.andrerinas.de/tutorials/raspberry-pi-einen-dslr-weddingphotobooth-erstellen.html) From eac9a03ddd3481ac9e8d71be8d7517bcdd1c2eb5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Sep 2020 05:13:18 +0000 Subject: [PATCH 23/32] build(deps-dev): bump prettier from 2.1.1 to 2.1.2 Bumps [prettier](https://github.com/prettier/prettier) from 2.1.1 to 2.1.2. - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/master/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/2.1.1...2.1.2) Signed-off-by: dependabot[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index a71f12f2d..d8b37ec9a 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,6 @@ "eslint-plugin-node": "^11.1.0", "git-tag-version": "^1.3.1", "gulp-babel": "^8.0.0", - "prettier": "^2.1.1" + "prettier": "^2.1.2" } } diff --git a/yarn.lock b/yarn.lock index 86b740c86..7bb09d7e4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3957,10 +3957,10 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prettier@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.1.1.tgz#d9485dd5e499daa6cb547023b87a6cf51bee37d6" - integrity sha512-9bY+5ZWCfqj3ghYBLxApy2zf6m+NJo5GzmLTpr9FsApsfjriNnS2dahWReHMi7qNPhhHl9SYHJs2cHZLgexNIw== +prettier@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.1.2.tgz#3050700dae2e4c8b67c4c3f666cdb8af405e1ce5" + integrity sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg== pretty-hrtime@^1.0.0: version "1.0.3" From 65726ad7f3141e2aa7494c23d4ffc33a6e284381 Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Tue, 22 Sep 2020 19:58:35 +0200 Subject: [PATCH 24/32] pack-build: add simple-translator directory - adds missing source-map --- scripts/pack-build.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/pack-build.js b/scripts/pack-build.js index 0070d2454..3b77ddb16 100644 --- a/scripts/pack-build.js +++ b/scripts/pack-build.js @@ -69,8 +69,7 @@ function createArchive(fileName, archive) { archive.file('phpinfo.php'); archive.file('README.md'); archive.file('update-booth.sh'); - archive.file('node_modules/@andreasremdt/simple-translator/LICENSE'); - archive.file('node_modules/@andreasremdt/simple-translator/dist/umd/translator.min.js'); + archive.directory('node_modules/@andreasremdt/simple-translator/'); archive.directory('node_modules/font-awesome/'); archive.file('node_modules/github-markdown-css/github-markdown.css'); archive.file('node_modules/github-markdown-css/license'); From 2b5335b9585ecaebbb0e6e180de8f10bc8a27544 Mon Sep 17 00:00:00 2001 From: Andreas Remdt Date: Thu, 24 Sep 2020 14:53:36 +0200 Subject: [PATCH 25/32] fix: only load the currently required language --- src/js/i18n-sub.js | 2 +- src/js/i18n.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/js/i18n-sub.js b/src/js/i18n-sub.js index b2ff6a451..4b72b0d00 100644 --- a/src/js/i18n-sub.js +++ b/src/js/i18n-sub.js @@ -8,6 +8,6 @@ const translator = new Translator({ debug: config.dev }); -translator.fetch(['de', 'en', 'es', 'el', 'fr']).then(() => { +translator.fetch(config.language).then(() => { translator.translatePageTo(config.language); }); diff --git a/src/js/i18n.js b/src/js/i18n.js index e1fda9380..1f841f69e 100644 --- a/src/js/i18n.js +++ b/src/js/i18n.js @@ -8,6 +8,6 @@ const translator = new Translator({ debug: config.dev }); -translator.fetch(['de', 'en', 'es', 'el', 'fr']).then(() => { +translator.fetch(config.language).then(() => { translator.translatePageTo(config.language); }); From fc5f339bb06ce31b31db88eb3c72fd28368859b5 Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Sun, 27 Sep 2020 09:06:16 +0200 Subject: [PATCH 26/32] fix (simple-translator): fallback to english if translation is missing Change-Id: Ibb4cc272de545af8010801d89cfb4ce3e0184f7d --- src/js/i18n-sub.js | 10 ++++++++-- src/js/i18n.js | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/js/i18n-sub.js b/src/js/i18n-sub.js index 4b72b0d00..564b52e0b 100644 --- a/src/js/i18n-sub.js +++ b/src/js/i18n-sub.js @@ -8,6 +8,12 @@ const translator = new Translator({ debug: config.dev }); -translator.fetch(config.language).then(() => { - translator.translatePageTo(config.language); +translator.fetch('en').then(() => { + translator.translatePageTo(); }); + +if (config.language !== 'en') { + translator.fetch(config.language).then(() => { + translator.translatePageTo(config.language); + }); +} diff --git a/src/js/i18n.js b/src/js/i18n.js index 1f841f69e..188ef0262 100644 --- a/src/js/i18n.js +++ b/src/js/i18n.js @@ -8,6 +8,12 @@ const translator = new Translator({ debug: config.dev }); -translator.fetch(config.language).then(() => { - translator.translatePageTo(config.language); +translator.fetch('en').then(() => { + translator.translatePageTo(); }); + +if (config.language !== 'en') { + translator.fetch(config.language).then(() => { + translator.translatePageTo(config.language); + }); +} From dfd6b0a2b150c3ae2cf0e4cb343bc24279818a42 Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Sun, 27 Sep 2020 09:10:11 +0200 Subject: [PATCH 27/32] en: adjust manual string Change-Id: Ib771619c97a0575ab59b4b612b0764214e4edfda --- resources/lang/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/lang/en.json b/resources/lang/en.json index 36d90acec..92be4332c 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -254,7 +254,7 @@ "manual_slideshow_pictureTime": "Add a value which is used as milliseconds an image is displayed at standalone slideshow.", "manual_slideshow_refreshTime": "Refresh standalone slideshow after entered seconds.", "manual_take_collage_frame": "If enabled, defined frame will be applied to your collage after taking it.", - "manual_take_collage_frame_always": "If enabled, defined collage frame will be applied to each picture of your collage instead once after taking it. \"Take collage with frame\" needs to be enabled.", + "manual_take_collage_frame_always": "If enabled, defined collage frame will be applied to each picture of your collage instead of applying once at the end of the collage. \"Take collage with frame\" needs to be enabled.", "manual_take_frame": "If enabled, defined frame will be applied to your picture after taking it.", "manual_toggle_fs_button": "If enabled, a button to toggle fullscreenmode will be added to the start screen.", "manual_use_collage": "If enabled, user can take a collage. A collage consists of 4 pictures. Optional you can take a collage with or without interruption.", From c9f2b05257a37235df391679fb12339310fb479d Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Sun, 27 Sep 2020 09:12:59 +0200 Subject: [PATCH 28/32] Crowdin translation import Change-Id: I781aa1f55fcc5122adab0534c9cd86c88e9effb7 --- resources/lang/de.json | 36 ++++++++++++++++++++++++++++++++---- resources/lang/el.json | 3 --- resources/lang/es.json | 5 ----- resources/lang/fr.json | 4 ---- 4 files changed, 32 insertions(+), 16 deletions(-) diff --git a/resources/lang/de.json b/resources/lang/de.json index 409ad7a18..57138064f 100644 --- a/resources/lang/de.json +++ b/resources/lang/de.json @@ -3,6 +3,7 @@ "admin_panel": "Admin Panel", "allow_delete": "Löschen des Bildes erlauben", "allow_delete_from_gallery": "Löschen von Bildern aus der Galerie zulassen", + "auto_print": "Bild unmittelbar nach der Aufnahme drucken", "auto_reload": "Photobooth wird automatisch neu geladen...", "auto_reload_on_error": "Photobooth bei Fehler automatisch neu laden", "available_version": "Verfügbare Version", @@ -10,7 +11,7 @@ "busyCollage": "Collage wird verarbeitet ...", "check_version": "Version überprüfen", "cheese": "Cheeeeeeeese!", - "cheeseCollage": "Cheeeeeeeese Collageeeeeeeeee!", + "cheeseCollage": "Cheeeeeeeese Collageeeeeeeeeee!", "chroma_keying": "Chroma-Keying erlauben", "close": "Schließen", "commands": "Befehle", @@ -25,9 +26,12 @@ "cups_button": "CUPS Taste anzeigen", "current_version": "Aktuelle Version", "default_imagefilter": "Bildfilter auswählen", + "degrees": "°", "delete": "Löschen", "dev": "Entwicklungs-Modus", "disk_usage": "Festplattenbelegung", + "dot": ".", + "download_thumbs": "Thumbnails zum Herunterladen verwenden", "error": "Es ist ein Fehler aufgetreten, bitte versuche es erneut!", "event": "Veranstaltungen", "event_symbol": "Symbol", @@ -54,8 +58,10 @@ "general_camera_mode": "Kamerabildmodus", "general_cheese_time": "Cheeeeeeeese!-Timer:", "general_cntdwn_time": "Countdown Timer:", + "general_collage_background": "Pfad zum Hintergrund für die Collage \"2x4 + background image\"", "general_collage_cntdwn_time": "Collage-Countdown Timer:", "general_collage_key": "Tastencode welcher eine Collage auslöst", + "general_collage_layout": "Collage Layout wählen:", "general_db_file": "Name der Datenbankdatei", "general_default_imagefilter": "Standardbildfilter", "general_disabled_filters": "Deaktivierte Bildfilter", @@ -71,12 +77,13 @@ "general_start_screen_title": "Startbildschirm (Titel)", "general_take_collage_frame_path": "Rahmen", "general_take_frame_path": "Rahmen", + "general_thumb_size": "Thumbnailgröße", "general_time_to_live": "Bildanzeige nach Aufnahme:", "general_videoHeight": "Gerätekamera Bildhöhe", "general_videoWidth": "Gerätekamera Bildbreite", "general_webserver_ip": "IP-Adresse des Photobooth Webservers", "general_wifi_ssid": "Wireless-Netzwerkname (SSID) für den Zugriff auf die Photobooth", - "home": "Home", + "home": "Startseite", "image_preview_before_processing": "Bild laden bevor Filter berechnet werden", "insertMail": "Gebe deine E-Mail-Adresse ein, um das Foto zugesendet zu bekommen.", "is_event": "Veranstaltung", @@ -110,6 +117,7 @@ "mail_username": "Benutzername des E-Mail Accounts", "manual_allow_delete": "Wenn diese Option aktiviert ist, können Bilder direkt nach der Aufnahme auf der Ergebnisseite gelöscht werden.", "manual_allow_delete_from_gallery": "Wenn diese Option aktiviert ist, können Bilder jederzeit aus der Galerie heraus gelöscht werden.", + "manual_auto_print": "Wenn aktiviert, wird das Bild sofort ausgedruckt, nachdem es aufgenommen wurde.", "manual_auto_reload_on_error": "Wenn beim Aufnehmen eines Bildes ein Fehler auftritt, wird die Photobooth nach 5 Sekunden automatisch neu geladen.", "manual_chroma_keying": "Wenn diese Option aktiviert ist, können Sie für Ihre Bilder über die Galerie auf Chromakeying zugreifen.", "manual_commands_exiftool_cmd": "EXIFtool-Befehlszeile, die nach dem Aufnehmen eines Bildes ausgeführt wird. Die Option \"EXIF-Daten beibehalten\" muss aktiviert sein.", @@ -122,6 +130,7 @@ "manual_crop_onprint": "Wenn diese Option aktiviert ist, werden Bilder beim Drucken auf die angegebene Höhe und Breite zugeschnitten (px).", "manual_cups_button": "Schaltfläche zum einfachen Zugriff auf CUPS (Common Unix Printing System) auf der Startseite anzeigen.", "manual_dev": "Aktiviert den Entwicklungsmodus. Beispielbilder werden verwendet anstatt ein Bild aufzunehmen.", + "manual_download_thumbs": "Wenn aktiviert, werden Thumbnails beim Download verwendet (falls vorhanden) statt dem Bild in voller Größe.", "manual_event_symbol": "Wählen Sie ein Symbol, welches zwischen dem eingegebenen Text angezeigt wird.", "manual_event_textLeft": "Geben Sie den Text ein, der auf der linken Seite des ausgewählten Symbols sichtbar ist.", "manual_event_textRight": "Geben Sie den Text ein, der auf der rechten Seite des ausgewählten Symbols sichtbar ist.", @@ -140,8 +149,10 @@ "manual_general_camera_mode": "Wählen Sie den Kameramodus Ihrer Gerätekamera (Kamera mit Blick nach vorne oder hinten).", "manual_general_cheese_time": "Legen Sie eine Zeit fest zur Anzeige von \"Cheeeeeeeese!\" nach dem Countdown.", "manual_general_cntdwn_time": "Legen Sie Ihre Countdown-Zeit fest.", + "manual_general_collage_background": "Geben Sie den Pfad des Hintergrunds ein, der für die Collage im Collage Layout \"2x4 + background image\" verwendet wird.", "manual_general_collage_cntdwn_time": "Legen Sie Ihre Countdown-Zeit fest, welche zwischen den Bildern für eine Collage verwendet wird.", "manual_general_collage_key": "Geben Sie die Keyl-ID an, welche zum Erstellen einer Collage verwendet werden soll (z.B. 13 ist die Eingabetaste). Verwenden Sie beispielsweise https://keycode.info, um die Key-ID herauszufinden.", + "manual_general_collage_layout": "Wählen Sie zwischen den 2x2 und 2x4 Bilder Layouts für die Collage.", "manual_general_db_file": "Name der Datenbankdatei.", "manual_general_default_imagefilter": "Wählen Sie einen Bildfilter, der standardmäßig nach der Aufnahme angewendet wird.", "manual_general_disabled_filters": "Wählen Sie Filter aus, die aus den verfügbaren Bildfiltern entfernt werden.", @@ -157,6 +168,7 @@ "manual_general_start_screen_title": "Geben Sie den auf der Startseite sichtbaren Titel ein.", "manual_general_take_collage_frame_path": "Geben Sie den Pfad des Rahmens ein, der nach der Aufnahme auf Ihre Collage angewendet wird.", "manual_general_take_frame_path": "Geben Sie den Pfad des Rahmens ein, der nach der Aufnahme auf Ihr Bild angewendet wird.", + "manual_general_thumb_size": "Thumbnail-Größe auswählen: XS = max 360px, S = max 540px, M = max 900px, L = max 1080px, XL = max 1260px", "manual_general_time_to_live": "Definieren Sie die Zeit in Millisekunden, die Ihr Bild nach der Aufnahme auf dem Ergebnisbildschirm sichtbar ist.", "manual_general_videoHeight": "Geben Sie einen Wert ein, der als Höhe für die Vorschau der Gerätekamera verwendet wird.", "manual_general_videoWidth": "Geben Sie einen Wert ein, der als Breite für die Vorschau der Gerätekamera verwendet wird.", @@ -190,6 +202,7 @@ "manual_previewCamTakesPic": "Wenn diese Option aktiviert ist, wird ein Bild von der Gerätekamera aufgenommen, anstatt den Befehl \"Bild aufnehmen\" auszuführen. Bitte beachten Sie, dass die Auflösung des Bildes von der angegebenen Höhe und Breite abhängt, da dies wie ein Screenshot aufgenommen wird.", "manual_previewFromCam": "Wenn diese Option aktiviert ist, wird während des Countdown eine Vorschau aus Ihrer Gerätekamera angezeigt. Bei der Vorschau durch die \"Gerätekamera\" wird immer die Kamera des Geräts verwendet, auf dem die Photobooth in einem Browser geöffnet wird (z. B. wird auf einem Tablet immer die Tablet-Kamera angezeigt, während auf einem Smartphone stattdessen immer die Smartphone-Kamera angezeigt wird)! Ein sicherer Ursprung oder eine Ausnahme ist zwingend erforderlich! Wie Sie eine Ausnahme definieren finden Sie hier.", "manual_previewFromIPCam": "Wenn diese Option aktiviert ist, wird während des Countdown eine Vorschau aus definierter URL angezeigt. Stellen Sie sicher, dass ein Stream verfügbar ist, den Sie verwenden können (z. B. von Ihrer Webcam, Smartphone-Kamera oder Raspberry Pi-Kamera).", + "manual_print_auto_print_delay": "Geben Sie die Zeit in Millisekunden an, um die der automatische Druck des Bildes verzögert wird.", "manual_print_crop_height": "Geben Sie einen Wert für die Höhe ein, die für das Bild verwendet wird, wenn \"Bild bei Ausdruck zurechtschneiden\" aktiviert ist.", "manual_print_crop_width": "Geben Sie einen Wert für die Breite ein, die für das Bild verwendet wird, wenn \"Bild bei Ausdruck zurechtschneiden\" aktiviert ist.", "manual_print_font_path": "Geben Sie den Pfad zu der Schriftart ein, mit der Text auf Ihr Bild gedruckt wird.", @@ -202,6 +215,8 @@ "manual_print_linespace": "Geben Sie den zu verwendenden Zeilenabstand ein, wenn Text auf Ihr Bild gedruckt wird.", "manual_print_locationx": "X-Koordinaten des Textes beim Drucken von Text auf Ihr Bild.", "manual_print_locationy": "Y-Koordinaten des Textes beim Drucken von Text auf Ihr Bild.", + "manual_print_print_key": "Geben Sie die Keyl-ID an, welche zum Drucken eines Fotos verwendet werden soll (z.B. 13 ist die Eingabetaste). Verwenden Sie beispielsweise https://keycode.info, um die Key-ID herauszufinden.", + "manual_print_printing_time": "Geben Sie in Millisekunden an, wie lange \"Druckauftrag gestartet! Bitte warten....\" angezeigt wird, nachdem ein Druckauftrag gestartet wurde.", "manual_print_qrcode": "Wenn diese Option aktiviert ist, wird beim Drucken ein QR-Code auf die rechte Seite des Bildes gedruckt.", "manual_print_rotation": "Geben Sie einen Wert ein um den ein Bild beim Drucken gedreht wird.", "manual_protect_admin": "Wenn diese Option aktiviert ist, kann auf das Admin-Panel nur zugegriffen werden, wenn ein Benutzername und ein Passwort eingegeben werden.", @@ -239,12 +254,16 @@ "manual_slideshow_pictureTime": "Geben Sie in Millisekunden an, wie lange ein Bild während der Standalone-Diashow angezeigt wird.", "manual_slideshow_refreshTime": "Die Standalone-Diashow wird nach eingegebenen Sekunden neu geladen.", "manual_take_collage_frame": "Wenn diese Option aktiviert ist, wird nach der Aufnahme ein definierter Rahmen auf Ihre Collage angewendet.", + "manual_take_collage_frame_always": "Wenn aktiviert, wird der definierte Rahmen auf jedes Bild Ihrer Collage angewendet, anstatt einmal nach der Aufnahme der Collage. \"Foto-Collage mit Rahmen aufnehmen\" muss aktiviert sein.", "manual_take_frame": "Wenn diese Option aktiviert ist, wird nach der Aufnahme ein definierter Rahmen auf Ihr Bild angewendet.", "manual_toggle_fs_button": "Wenn diese Option aktiviert ist, wird dem Startbildschirm eine Schaltfläche zum Umschalten des Vollbildmodus hinzugefügt.", "manual_use_collage": "Wenn diese Option aktiviert ist, kann der Benutzer eine Collage aufnehmen. Eine Collage besteht aus 4 Bildern. Optional können Sie eine Collage mit oder ohne Unterbrechung aufnehmen.", "manual_use_download": "Wenn diese Option aktiviert ist, ist für jedes Bild in der Galerie eine Download-Schaltfläche sichtbar.", "manual_use_filter": "Wenn diese Option aktiviert ist, kann der Benutzer nach dem Aufnehmen eines Bildes einen Bildfilter auswählen.", "manual_use_mail": "Wenn diese Option aktiviert ist, ist für jedes Bild in der Galerie eine E-Mail-Schaltfläche sichtbar. Abhängig von Ihren Einstellungen können Sie Bilder direkt per E-Mail senden oder die eingegebene E-Mail-Adresse in einer Datenbank sammeln.", + "manual_use_print_chromakeying": "Wenn aktiviert, ist auf der Chromakey-Seite eine Druck-Schaltfläche sichtbar.", + "manual_use_print_gallery": "Wenn aktiviert, wird eine Druck-Schaltfläche in der Galerie angezeigt.", + "manual_use_print_result": "Wenn aktiviert, wird eine Druck-Schaltfläche auf der Ergebnisseite angezeigt.", "manual_use_qr": "Wenn diese Option aktiviert ist, wird eine QR-Schaltfläche auf dem Ergebnisbildschirm und in der Galerie angezeigt. Der Benutzer kann beim Scannen des QR-Codes ein Bild herunterladen. Wenn Sie über \"localhost\", \"127.0.0.1\" auf Photobooth zugreifen oder Photobooth in einem Unterordner installiert haben, definieren Sie bitte die IP-Adresse des Photobooth-Webservers, damit der QR-Code funktioniert.

Beispiel, wenn auf Photobooth direkt zugegriffen werden kann: 192.168.0.50.

Beispiel, wenn Photobooth in einem Unterordner installiert ist: 192.168.0.50/photobooth.

", "manual_use_slideshow": "Wenn diese Option aktiviert ist, wird in der Galerie eine Diashow-Schaltfläche angezeigt, mit der Sie eine Diashow starten / stoppen können.", "manual_use_thumbs": "Wenn diese Option aktiviert ist, werden Miniaturansichten für die Diashow verwendet. Dadurch wird die Leistung leicht verbessert.", @@ -258,6 +277,7 @@ "newest_first": "Neueste Bilder zuerst anzeigen", "nextPhoto": "Nächstes Bild", "path": "Pfad:", + "percent": "%", "polaroid_effect": "Polaroid Effekt", "preserve_exif_data": "Exif-Daten erhalten", "previewCamBackground": "Stream der Gerätekamera als Hintergrund nutzen", @@ -266,6 +286,7 @@ "previewFromCam": "Vorschau aus der Gerätekamera anzeigen", "previewFromIPCam": "Vorschau von URL", "print": "Drucken", + "print_auto_print_delay": "Automatisches Drucken des Bildes verzögern", "print_crop_height": "Neue Bildhöhe bei Ausdruck (px)", "print_crop_width": "Neue Bildbreite bei Ausdruck (px)", "print_font_path": "Schriftart", @@ -278,6 +299,8 @@ "print_linespace": "Zeilenabstand", "print_locationx": "X-Koordinaten", "print_locationy": "Y-Koordinaten", + "print_print_key": "Tastencode welcher einen Druckauftrag auslöst", + "print_printing_time": "Druckdauer", "print_qrcode": "QR-Code auf dem Bild beim Drucken", "print_rotation": "Text-Rotation", "printing": "Druckauftrag gestartet! Bitte warten...", @@ -296,10 +319,11 @@ "pswp_preventSwiping": "Wischgeste ausschalten", "pswp_tapToToggleControls": "Sichtbarkeit von Steuerelementen / Schaltflächen durch Tippen umschalten", "pswp_zoomEl": "PhotoSwipe Zoom-Schaltfläche anzeigen", - "qr": "QR Code", + "qr": "QR-Code", "qrHelp": "Um das Bild auf Ihr Handy herunterzuladen, verbinden Sie sich mit dem WLAN:", "randomPicture": "Zufällige Bilder anzeigen", "really_delete": "Wollen Sie wirklich alle Bilder löschen? Das kann nicht rückgängig gemacht werden!", + "really_delete_image": "wird gelöscht! Dies kann nicht rückgängig gemacht werden! Bild wirklich löschen?", "reload": "Seite neu laden", "remotebuzzer": "Remote Buzzer Server", "remotebuzzer_collagetime": "Sekunden gedrückt halten für Collage", @@ -307,7 +331,7 @@ "remotebuzzer_logfile": "Logfile", "remotebuzzer_nodebin": "Node.js Pfad", "remotebuzzer_pin": "Raspberry Pi GPIO Pin (0 zum Abschalten)", - "remotebuzzer_port": "Server Port", + "remotebuzzer_port": "Server-Port", "remove_config": "Persönliche Konfiguration löschen (my.config.inc.php)", "remove_images": "Bilder löschen", "remove_mailtxt": "E-Mail-Adressen-Datenbankdatei löschen", @@ -338,6 +362,7 @@ "takeCollage": "Collage erstellen!", "takePhoto": "Foto erstellen!", "take_collage_frame": "Foto-Collage mit Rahmen aufnehmen", + "take_collage_frame_always": "Rahmen auf jedes Bild der Collage anwenden", "take_frame": "Bild mit Rahmen aufnehmen", "test_update_available": "Es ist ein Test-Update verfügbar.", "toggleFullscreen": "Vollbildmodus umschalten", @@ -348,6 +373,9 @@ "use_download": "Download aktivieren", "use_filter": "Bildfilter erlauben", "use_mail": "E-Mail aktivieren", + "use_print_chromakeying": "Drucken von Chromakeying erlauben", + "use_print_gallery": "Drucken von Galerie erlauben", + "use_print_result": "Drucken von Ergebnisseite erlauben", "use_qr": "QR-Code aktivieren", "use_slideshow": "Diashow in Galerie erlauben", "use_thumbs": "Thumbnails für die Diashow verwenden", diff --git a/resources/lang/el.json b/resources/lang/el.json index fb17d4eef..9c4f4335f 100644 --- a/resources/lang/el.json +++ b/resources/lang/el.json @@ -5,7 +5,6 @@ "busy": "Η εικόνα βρίσκεται υπό επεξεργασία ...", "busyCollage": "Το κολάζ υποβάλλεται σε επεξεργασία ...", "check_version": "Επαληθεύστε την έκδοση", - "cheese": "Cheeeeeeeese!", "cheeseCollage": "Cheeeeeeeese κολάάάάάάζζζζζζζζ!", "chroma_keying": "Chroma-Keying επιτρέπονται", "close": "Κλείσε", @@ -58,14 +57,12 @@ "jpeg_quality_jpeg_quality_image": "Ποιότητα JPEG για φωτογραφίες (-1 ... 100)", "jpeg_quality_jpeg_quality_thumb": "Ποιότητα JPEG για μικρογραφίες (-1 ... 100)", "language": "Επιλέξτε γλώσσα", - "mail": "E-Mail", "mailError": "Σφάλμα κατά την αποστολή του E-Mail", "mailSent": "E-Mail αποστέλλονται", "mail_fromAddress": "Διεύθυνση αποστολέα", "mail_fromName": "Όνομα αποστολέα", "mail_host": "E-Mail Διεύθυνση κεντρικού υπολογιστή", "mail_password": "κωδικό πρόσβασης", - "mail_port": "Port", "mail_secure": "ασφάλεια (tls ή ssl)", "mail_subject": "σχέση", "mail_text": "κείμενο", diff --git a/resources/lang/es.json b/resources/lang/es.json index 999b8efe5..a87303940 100644 --- a/resources/lang/es.json +++ b/resources/lang/es.json @@ -22,7 +22,6 @@ "cups_button": "Mostrar el botón CUPS", "current_version": "Versión actual", "default_imagefilter": "Elegir filtro de imagen", - "degrees": "°", "delete": "Eliminar", "dev": "Modo desarrollador", "error": "Hubo un problema. Por favor intente otra vez.", @@ -43,7 +42,6 @@ "gallery_bottom_bar": "Mostrar la barra del botón por dentro la galería en la parte inferior", "gallery_date_format": "Formato de fecha", "gallery_no_image": "La galeri es vacía. ¡Saque fotos!", - "general": "General", "general_camera_mode": "Modo orientado a la cámara", "general_cheese_time": "¡Definir el tiempo para el patataaaaas!en milisegundos.", "general_cntdwn_time": "Cuenta regresiva en segundos", @@ -79,7 +77,6 @@ "keep_images": "Mantener imágenes originales en la carpeta TMP", "keyingerror": "¡La incrustación en el croma verde es imposible!", "language": "Elija el idioma", - "login": "Login", "login_enabled": "Login habilitado", "login_invalid": "¡Nombre de usuario o contraseña no es válido!", "login_password": "Contraseña", @@ -220,7 +217,6 @@ "newPhoto": "Una foto más", "newest_first": "Primero muestre las últimas páginas", "nextPhoto": "Siguiente imagen", - "percent": "%", "polaroid_effect": "Efecto polaroid", "preserve_exif_data": "Conservar los datos EXIF", "previewCamBackground": "Utilice la transmisión desde la cámara del dispositivo como fondo", @@ -257,7 +253,6 @@ "reset": "Reiniciar", "rounded_corners": "Esquinas redondeadas", "save": "Salvar", - "saveerror": "Error", "saving": "En proceso de copia de seguridad.", "scrollbar": "Muestre la barra de desplazamiento en la galería", "seconds": "segundo(s)", diff --git a/resources/lang/fr.json b/resources/lang/fr.json index aaf1edac1..07a513bd0 100644 --- a/resources/lang/fr.json +++ b/resources/lang/fr.json @@ -5,7 +5,6 @@ "busy": "En cours de traitement", "busyCollage": "En cours de traitement", "check_version": "Vérifier la version", - "cheese": "Cheeeeeeeese!", "cheeseCollage": "Cheeeeeeeese 4 fois !", "chroma_keying": "Activez le fond vert", "close": "Fermer", @@ -67,7 +66,6 @@ "mail_fromName": "Nom de l'expéditeur", "mail_host": "Adresse mail de l'hôte", "mail_password": "Mot de passe", - "mail_port": "Port", "mail_secure": "Sécurité (tls ou ssl)", "mail_subject": "objet du mail", "mail_text": "Texte", @@ -92,10 +90,8 @@ "print_qrcode": "QR-Code sur l'image en cours d'impression", "print_rotation": "Rotation du texte", "printing": "I'impression a commencé", - "qr": "QR Code", "randomPicture": "Afficher des images aléatoires", "really_delete": "Vraiment supprimer toutes les images? Ça ne peut pas être annulé!", - "really_delete_image": "wird gelöscht! Das kann nicht rückgängig gemacht werden! Wollen Sie das Bild wirklich löschen?", "reload": "Recharger la page", "reset": "Réinitialiser", "save": "Sauvegarder", From 7345a46aca3debd2c5b1cc8774852e365325c293 Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Wed, 16 Sep 2020 12:37:01 +0000 Subject: [PATCH 29/32] lang (pl): add polish to supported languages Change-Id: Ie5a9b9d3a9dc3994fd924bf9ce75e6fb0c58bba8 --- config/config.inc.php | 2 +- lib/configsetup.inc.php | 3 +- resources/lang/pl.json | 340 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 343 insertions(+), 2 deletions(-) create mode 100644 resources/lang/pl.json diff --git a/config/config.inc.php b/config/config.inc.php index 1648fa54b..8e82879ad 100644 --- a/config/config.inc.php +++ b/config/config.inc.php @@ -70,7 +70,7 @@ $config['print_key'] = null; // LANGUAGE -// possible values: de, el, en, es, fr +// possible values: de, el, en, es, fr, pl $config['language'] = 'en'; // StartScreen diff --git a/lib/configsetup.inc.php b/lib/configsetup.inc.php index 0ca709577..c126c8d12 100644 --- a/lib/configsetup.inc.php +++ b/lib/configsetup.inc.php @@ -12,7 +12,8 @@ 'el' => 'EL', 'en' => 'EN', 'es' => 'ES', - 'fr' => 'FR' + 'fr' => 'FR', + 'pl' => 'PL' ], 'value' => $config['language'] ], diff --git a/resources/lang/pl.json b/resources/lang/pl.json new file mode 100644 index 000000000..27e021ef0 --- /dev/null +++ b/resources/lang/pl.json @@ -0,0 +1,340 @@ +{ + "abort": "Przerwij", + "admin_panel": "Panel administracyjny", + "allow_delete": "Zezwalaj na usunięcie obrazu", + "allow_delete_from_gallery": "Pozwól na usuwanie obrazów z galerii", + "auto_print": "Drukuj zdjęcie natychmiast po wykonaniu", + "auto_reload": "Fotobudka przeładowuje się automatycznie...", + "auto_reload_on_error": "Automatycznie przeładuj fotobudkę po błędzie", + "available_version": "Dostępna wersja", + "busy": "Przetwarzanie", + "busyCollage": "Przetwarzanie kolażu", + "check_version": "Sprawdź wersję", + "cheese": "Uśmiech!", + "cheeseCollage": "Uśmiech Kolaż!", + "chroma_keying": "Zezwalaj na chroma keying", + "close": "Zamknij", + "commands": "Polecenia", + "commands_exiftool_cmd": "Polecenie EXIFtool", + "commands_print_cmd": "Polecenie Drukuj", + "commands_print_msg": "Wiadomość z powodzeniem wydruku", + "commands_take_picture_cmd": "Wiadomość zrób zdjęcie", + "commands_take_picture_msg": "Wiadomość o pomyślnym wykonaniu zdjęcia", + "continuous_collage": "Zrób kolaż bez przerw", + "crop_onprint": "Przytnij zdjęcie przy wydruku", + "cups_button": "Pokaż przycisk CUPS", + "current_version": "Aktualna wersja", + "default_imagefilter": "Wybierz filtr obrazu", + "degrees": "°", + "delete": "Usuń", + "dev": "Tryb Deweloperski", + "disk_usage": "Użycie dysku", + "dot": ".", + "download_thumbs": "Użyj miniatur do pobrania", + "error": "Coś poszło nie tak. Spróbuj ponownie.", + "event": "Zdarzenie", + "event_symbol": "Symbol", + "event_textLeft": "Tekst z lewej", + "event_textRight": "Tekst z prawej", + "filecount": "Liczba plików:", + "folders": "Foldery", + "folders_data": "Folder Danych", + "folders_images": "Folder zdjęć", + "folders_print": "Folder wydruków", + "folders_qrcodes": "Folder kodów QR", + "folders_thumbs": "Folder miniarurek", + "folders_tmp": "Katalog tmp", + "foldersize": "Rozmiar katalogu:", + "force_buzzer": "Ukryj przycisk wyzwalacza", + "gallery": "Galeria", + "gallery_bottom_bar": "Pokaż pasek przycisków wewnątrz galerii na dole", + "gallery_date_format": "Styl daty", + "gallery_no_image": "Galeria jest nadal pusta. Zrób kilka zdjęć!", + "gallery_pswp_bgOpacity": "Przezroczystość tła", + "general": "Ogólne", + "general_cheese_time": "Uśmiech!-Timer:", + "general_cntdwn_time": "Odliczanie czasu:", + "general_collage_background": "Ścieżka do tła dla \"2x4 + obraz tła\" kolażu", + "general_collage_cntdwn_time": "Czas odliczania kolażu:", + "general_collage_key": "Kod klawisza, który wyzwala kolaż", + "general_collage_layout": "Wybierz układ kolażu:", + "general_db_file": "Nazwa pliku bazy danych", + "general_default_imagefilter": "Domyślny filtr obrazu", + "general_disabled_filters": "Wyłączone filtry obrazów", + "general_file_naming": "Nazwa pliku", + "general_ipCamPreviewRotation": "Obróć podgląd z adresu URL", + "general_ipCamURL": "Podgląd-adres URL", + "general_language": "Język", + "general_photo_key": "Kod klawisza, który wyzwala zdjęcie", + "general_pictureRotation": "Obróć zdjęcie po wykonaniu (w stopniach)", + "general_picture_permissions": "Uprawnienia zdjęć", + "general_polaroid_rotation": "Obrót obrazów Polaroid", + "general_start_screen_subtitle": "Ekran startowy (napisy)", + "general_start_screen_title": "Ekran startowy (tytuł)", + "general_take_collage_frame_path": "Ramka", + "general_take_frame_path": "Ramka", + "general_thumb_size": "Rozmiar miniatur", + "general_time_to_live": "Pokaż obraz po wyzwoleniu:", + "general_videoHeight": "Wysokość obrazu z kamery urządzenia", + "general_videoWidth": "Szerokość obrazu z kamery urządzenia", + "general_webserver_ip": "Adres IP serwera WWW Fotobudki", + "general_wifi_ssid": "Nazwa sieci bezprzewodowej (SSID) używana do uzyskania dostępu do Fotobudki", + "home": "Strona główna", + "image_preview_before_processing": "Wstępnie załaduj i pokaż obraz podczas przetwarzania filtrów", + "insertMail": "Wpisz swój adres e-mail, aby otrzymać zdjęcie.", + "is_event": "Wydarzenie", + "is_textonprint": "Drukuj tekst na obrazach", + "jpeg_quality": "Jakość JPEG", + "jpeg_quality_jpeg_quality_chroma": "Jakość JPEG dla chroma-keying (-1 ... 100):", + "jpeg_quality_jpeg_quality_image": "Jakość JPEG dla obrazów (-1 ... 100):", + "jpeg_quality_jpeg_quality_thumb": "Jakość JPEG dla miniaturek (-1 ... 100):", + "keep_images": "Zachowaj oryginalne zdjęcia w folderze tmp", + "keyingerror": "Chroma keying nie jest możliwa!", + "language": "Wybierz język", + "login": "Logowanie", + "login_enabled": "Logowanie włączone", + "login_invalid": "Nazwa użytkownika lub Hasło jest nieprawidłowe!", + "login_password": "Hasło", + "login_username": "Nazwa użytkownika", + "logout": "Wyloguj", + "mail": "E-mail", + "mailError": "Błąd podczas wysyłania wiadomości e-mail", + "mailSaved": "Adres e-mail zapisany pomyślnie", + "mailSent": "E-mail został wysłany", + "mail_file": "Nazwa pliku bazy danych adresów e-mail", + "mail_fromAddress": "Adres zwrotny", + "mail_fromName": "Nazwa nadawcy", + "mail_host": "Adres e-mail hosta", + "mail_password": "Hasło", + "mail_port": "Port", + "mail_secure": "Zabezpieczenie (tls lub ssl)", + "mail_subject": "Temat", + "mail_text": "Tekst", + "mail_username": "Nazwa użytkownika dla konta e-mail", + "manual_allow_delete": "Jeśli włączone, zdjęcia mogą zostać usunięte na stronie wyników bezpośrednio po ich wykonaniu.", + "manual_allow_delete_from_gallery": "Jeśli włączone, zdjęcia mogą zostać usunięte z galerii w dowolnym momencie.", + "manual_auto_print": "Jeśli włączone, zdjęcie zostanie wydrukowane natychmiast po wykonaniu.", + "manual_auto_reload_on_error": "Jeśli wystąpi błąd podczas wykonywania zdjęcia, fotobudka przeładuje się automatycznie po 5 sekundach.", + "manual_chroma_keying": "Jeśli włączone chromakeying może być dostępne z galerii dla Twoich zdjęć.", + "manual_commands_print_cmd": "Wiersz poleceń, który jest wykonywany podczas naciśnięcia przycisku \"Drukuj\".", + "manual_commands_print_msg": "Wiadomość zwrotna z polecenia wydruku.", + "manual_commands_take_picture_cmd": "Wiersz poleceń, który jest wykonywany podczas naciśnięcia przycisku \"Zrób zdjęcie\". Na Linux możesz na przykład użyć gphoto2 do robienia zdjęć, w systemie Windows możesz użyć digiCamControl.", + "manual_commands_take_picture_msg": "Wiadomość zwrotna z polecenia zrób zdjęcie.", + "manual_continuous_collage": "Zrób kolaż bez przerw.", + "manual_crop_onprint": "Jeśli włączone, zdjęcia są przycięte na wydruku o podanej wysokości i szerokości (px).", + "manual_cups_button": "Pokaż przycisk na stronie startowej, aby łatwo uzyskać dostęp do CUPS (Common Unix Printing System).", + "manual_dev": "Włącza tryb deweloperski. Przykładowe zdjęcia będą używane zamiast robienia zdjęć.", + "manual_download_thumbs": "Jeśli włączone, miniatury będą używane podczas pobierania (jeśli istnieje) zamiast pełnego rozmiaru obrazu.", + "manual_event_symbol": "Wybierz symbol, który jest wyświetlany pomiędzy wprowadzonym tekstem.", + "manual_event_textLeft": "Wprowadź tekst widoczny po lewej stronie wybranego symbolu.", + "manual_event_textRight": "Wprowadź tekst widoczny po prawej stronie wybranego symbolu.", + "manual_folders_data": "Wprowadź nazwę folderu danych.", + "manual_folders_images": "Wprowadź ścieżkę i nazwę folderu obrazów. Powinien to być podfolder folderu \"data\"!", + "manual_folders_keying": "Wprowadź ścieżkę i nazwę folderu chromakeying. Powinien to być podfolder folderu \"data\"!", + "manual_folders_print": "Wprowadź ścieżkę i nazwę folderu wydruków. Powinien to być podfolder folderu \"data\"!", + "manual_folders_qrcodes": "Wprowadź ścieżkę i nazwę folderu kodów QR. Powinien to być podfolder folderu \"data\"!", + "manual_folders_thumbs": "Wprowadź ścieżkę i nazwę folderu dla miniatur. Powinien to być podfolder folderu \"data\"!", + "manual_folders_tmp": "Wprowadź ścieżkę i nazwę folderu TEMP. Powinien to być podfolder folderu \"data\"!", + "manual_force_buzzer": "Jeśli włączone, przyciski zrób zdjęcie i kolaż znikną. Otrzymasz przycisk, który mówi aby użyć buzera do wykonania zdjęcia lub kolażu.", + "manual_gallery_bottom_bar": "Jeśli włączone, pasek przycisków jest wyświetlany w galerii u dołu.", + "manual_gallery_date_format": "Wprowadź swój styl daty.", + "manual_gallery_pswp_bgOpacity": "Przezroczystość tła, niskie wartości czynią tło bardziej przezroczystym.", + "manual_general_cheese_time": "Ustaw czas wyświetlania \"Uśmiech!\" po odliczaniu.", + "manual_general_cntdwn_time": "Ustaw czas odliczania.", + "manual_general_collage_cntdwn_time": "Ustaw czas odliczania pomiędzy zdjęciami podczas wykonywania kolażu.", + "manual_general_db_file": "Nazwa pliku bazy danych.", + "manual_general_default_imagefilter": "Wybierz filtr obrazu, który jest domyślnie stosowany po wykonaniu zdjęcia.", + "manual_general_disabled_filters": "Wybierz filtry, które zostaną usunięte z dostępnych filtrów obrazów.", + "manual_general_file_naming": "Wybierz między datą, numerowaniem lub losową nazwą obrazów. Dla zdjęć nazwanych datą możesz wyświetlić obraz z datą i czasem wewnątrz galerii.", + "manual_general_ipCamPreviewRotation": "Wybierz, aby obrócić podgląd z adresu URL.", + "manual_general_ipCamURL": "Styl CSS do użycia strumienia z adresu URL do podglądu podczas odliczania.

Przykład: url(../img/bg_bluegray.jpg)

", + "manual_general_language": "Wybierz język interfejsu.

Jeśli brakuje języka lub chcesz pomóc w ulepszeniu tłumaczeń, odwiedź \"Jak zaktualizować lub dodać tłumaczenie? Instrukcja na WIKI Photobooth.

", + "manual_general_photo_key": "Określ identyfikator klawisza, aby użyć go do zrobienia zdjęcia (np. 13 jest klawiszem enter). Przykładowo użyj https://keycode.info, aby uzyskać identyfikator klawisza.", + "manual_general_pictureRotation": "Wprowadź wartość, która ustawi stopnie obrotu obrazu po jego wykonaniu.", + "manual_general_picture_permissions": "Zmień uprawnienia zdjęć poleceniem \"chmod\". Zmień tę wartość tylko, jeśli znasz uprawnienia plików w Linux/Unix.", + "manual_general_polaroid_rotation": "Wprowadź wartość, która ustawi stopnie obrotu obrazu po jego wykonaniu z efektem polaroid.", + "manual_general_start_screen_subtitle": "Wprowadź podtytuł widoczny na stronie startowej.", + "manual_general_start_screen_title": "Wprowadź tytuł widoczny na stronie startowej", + "manual_general_take_collage_frame_path": "Wprowadź ścieżkę ramki, która zostanie zastosowana do Twojego kolażu po jego użyciu.", + "manual_general_take_frame_path": "Wprowadź ścieżkę ramki, która zostanie zastosowana do zdjęcia po jego wykonaniu.", + "manual_general_thumb_size": "Wybierz rozmiar miniatury: XS = max 360px, S = max 540px, M = max 900px, L = max 1080px, XL = max 1260px", + "manual_general_time_to_live": "Wprowadź wartość w milisekundach. Ta wartość definiuje czas, w którym obraz jest widoczny na ekranie wyników po wykonaniu zdjęcia.", + "manual_general_videoHeight": "Wprowadź wartość, która jest używana jako wysokość do podglądu przez kamerę urządzenia.", + "manual_general_videoWidth": "Wprowadź wartość, która jest używana jako szerokość dla podglądu przez kamerę urządzenia.", + "manual_general_webserver_ip": "Proszę zdefiniować adres IP serwera WWW Fotobudki, aby kod QR działał w przypadku uzyskania dostępu do Fotobudki przez \"localhost\", \"127.0.0.1\" lub jeśli masz zainstalowaną fotobudkę w podfolderze.

Przykład, jeśli Fotobudka jest dostępna bezpośrednio: 192.168.0.50.

Przykład, jeśli Fotobudka jest zainstalowana w podfolderze: 192.168.0.50/photobooth

", + "manual_general_wifi_ssid": "Proszę zdefiniować nazwę sieci bezprzewodowej (SSID), która ma być użyta do uzyskania dostępu do Fotobudki. Nazwa sieci bezprzewodowej (SSID) jest wyświetlana na stronie wyników po wywołaniu kodu QR.", + "manual_image_preview_before_processing": "Jeśli włączone, obrazy są wstępnie załadowane i wyświetlane podczas przetwarzania filtrów.", + "manual_is_event": "Jeśli włączone, możesz zdefiniować tekst i wybrać między różnymi symbolami, które są widoczne na stronie startowej.", + "manual_is_textonprint": "Jeśli włączone, możesz wydrukować jakiś tekst na zdjęciach.", + "manual_jpeg_quality_jpeg_quality_chroma": "Jakość obrazu używana do obrazów chromakeying.", + "manual_jpeg_quality_jpeg_quality_image": "Jakość obrazu używana do wykonanych zdjęć.", + "manual_jpeg_quality_jpeg_quality_thumb": "Jakość obrazu używana w miniaturach.", + "manual_keep_images": "Jeśli włączone, oryginalne obrazy będą przechowywane wewnątrz folderu tmp.", + "manual_login_enabled": "Jeśli włączone, nazwa użytkownika i hasło będą potrzebne do uzyskania dostępu do strony administracyjnej i/lub ekranu startowego (w zależności od konfiguracji).", + "manual_login_password": "Zdefiniuj swoje hasło używane do logowania. Pamiętaj: po zapisaniu hasła będzie widoczne jako hash w panelu administracyjnym. Aby zalogować się nie wpisuj hash, wprowadź hasło, które ustawiłeś.", + "manual_login_username": "Zdefiniuj nazwę użytkownika używaną do logowania się do Fotobudki.", + "manual_mail_file": "Nazwa pliku bazy danych adresów e-mail.", + "manual_mail_fromAddress": "Wprowadź swój adres zwrotny, który jest używany podczas wysyłania zdjęć pocztą elektroniczną.", + "manual_mail_fromName": "Wprowadź nazwę nadawcy, która jest używana podczas wysyłania zdjęć pocztą elektroniczną.", + "manual_mail_host": "Wprowadź adres hosta e-mail.", + "manual_mail_password": "Wprowadź hasło używane do zalogowania się na twoje konto e-mail.", + "manual_mail_port": "Wprowadź port używany do wysyłania e-mail.", + "manual_mail_secure": "Wprowadź protokół używany do szyfrowania między klientem poczty a serwerem poczty (ssl lub tls).", + "manual_mail_subject": "Podaj temat używany podczas wysyłania zdjęć pocztą elektroniczną.", + "manual_mail_text": "Wprowadź tekst e-mail, który jest używany podczas wysyłania zdjęć pocztą elektroniczną.", + "manual_mail_username": "Wprowadź nazwę użytkownika używaną do zalogowania się na twoje konto e-mail.", + "manual_newest_first": "Jeśli włączone, najnowsze zdjęcia będą wyświetlane jako pierwsze w galerii.", + "manual_polaroid_effect": "Jeśli opcja jest włączona, efekt polaroidowy zostanie zastosowany do zdjęcia po jego wykonaniu.", + "manual_previewCamBackground": "Jeśli włączone, jako tło na ekranie początkowym używany jest strumień z kamery urządzenia.", + "manual_previewCamFlipHorizontal": "Jeśli włączone, podgląd z kamery urządzenia jest odbiciem lustrzanym.", + "manual_print_auto_print_delay": "Wprowadź w milisekundach, opóźnienie automatycznego wydruku zdjęcia.", + "manual_print_crop_height": "Wprowadź wartość dla wysokości, która jest używana dla obrazka, jeśli opcja \"Przytnij obraz przy wydruku\" jest włączona.", + "manual_print_crop_width": "Wprowadź wartość dla szerokości, która jest używana dla obrazka, jeśli opcja \"Przytnij obraz przy wydruku\" jest włączona.", + "manual_print_font_path": "Wprowadź ścieżkę do czcionki używanej do drukowania tekstu na zdjęciu.", + "manual_print_fontsize": "Wprowadź rozmiar czcionki używany do drukowania tekstu na zdjęciu.", + "manual_print_frame": "Jeśli włączone, na zdjęciu w wydruku zostanie zastosowana ramka.", + "manual_print_frame_path": "Wprowadź ścieżkę ramki, która jest stosowana do zdjęcia w wydruku.", + "manual_print_line1": "Tekst używany do 1. Wiersza, który zostanie wydrukowany na zdjęciu.", + "manual_print_line2": "Tekst używany do 2. Wiersza, który zostanie wydrukowany na zdjęciu.", + "manual_print_line3": "Tekst używany do 3. Wiersza, który zostanie wydrukowany na zdjęciu.", + "manual_print_linespace": "Wprowadź wartość przerwy pomiędzy wierszami podczas drukowania tekstu na zdjęciu.", + "manual_print_locationx": "Współrzędne X tekstu podczas drukowania tekstu na zdjęciu.", + "manual_print_locationy": "Współrzędne Y tekstu podczas drukowania tekstu na zdjęciu.", + "manual_print_print_key": "Określ identyfikator klawisza, aby użyć go do zrobienia zdjęcia (np. 13 jest klawiszem enter). Przykładowo użyj https://keycode.info, aby uzyskać identyfikator klawisza.", + "manual_print_printing_time": "Wprowadź w milisekundach, jak długo napis \"Rozpoczęto drukowanie! Proszę czekać....\" wyświetla się po uruchomieniu zadania.", + "manual_print_qrcode": "Jeśli opcja jest włączona, kod QR jest drukowany na prawej stronie obrazu podczas drukowania.", + "manual_print_rotation": "Wprowadź wartość, która ustawi stopnie obrotu obrazu do wydruku.", + "manual_protect_admin": "Jeśli włączone, dostęp do panelu administratora jest możliwy tylko wtedy, gdy zostanie wprowadzona nazwa użytkownika i hasło.", + "manual_protect_index": "Jeśli włączone, ekran startowy może być dostępny tylko wtedy, gdy zostanie wprowadzona nazwa użytkownika i hasło.", + "manual_pswp_animateTransitions": "Jeśli włączone, efekt slajdu jest używany do przejścia podczas przełączania na następny/poprzedni obraz wewnątrz galerii.", + "manual_pswp_clickToCloseNonZoomable": "Kliknięcie myszy na obraz powinno zamknąć galerię, ale tylko wtedy, gdy obraz jest mniejszy niż rozmiar widoku.", + "manual_pswp_closeOnOutsideClick": "Galeria zostaje zamknięta po kliknięciu na zewnątrz obrazu.", + "manual_pswp_closeOnScroll": "Zamknij obraz przy przewijaniu strony. Opcja działa tylko dla urządzeń bez obsługi dotyku sprzętowego.", + "manual_pswp_closeOnVerticalDrag": "Jeśli włączone, galeria zostanie zamknięta, gdy obraz zostanie przeciągnięty w pionie i obraz nie zostanie powiększony.", + "manual_pswp_counterEl": "Jeśli włączone, licznik zdjęć jest widoczny wewnątrz galerii.", + "manual_pswp_history": "Jeśli nieaktywne wyłącza moduł historii (przycisk Wstecz, aby zamknąć galerię, unikalny URL dla każdego slajdu).", + "manual_pswp_loop": "Pętla obrazów podczas używania gestu przesunięcia. Jeśli włączone, będziesz mógł przesunąć palcem od ostatniego do pierwszego obrazu. Opcja jest zawsze wyłączona, gdy istnieje mniej niż 3 obrazy.", + "manual_pswp_preventSwiping": "Jeśli włączone, gest przesuwania będzie wyłączony (nawet dla urządzeń dotykowych), a strzałki będą wyświetlane na urządzeniach dotykowych. Tylko strzałki mogą przełączać obrazy.", + "manual_pswp_tapToToggleControls": "Jeśli włączone, widoczność sterowania / przycisków jest przełączana przez dotyk.", + "manual_randomPicture": "Jeśli włączone, losowe zdjęcia będą wyświetlane na galerii samodzielnej.", + "manual_remotebuzzer_collagetime": "Jeśli przycisk wyzwalacza jest wciśnięty (GPIO podciągnięty do GND) mniej lub równą liczbę sekund, wyzwolenie będzie włączone. Jeśli przycisk zostanie wciśnięty przez więcej sekund zostanie uruchomiony kolaż. Jeśli kolaż jest wyłączony w ustawieniach administratora, kolaż nie będzie uruchomiony", + "manual_remotebuzzer_enabled": "Funkcja ta umożliwia monitorowanie GPIO dla wyzwalacza sprzętowego podłączonego do pinów GPIO Raspberry w połączeniu z podłączonymi wyświetlaczami i ekranami WLAN (i. . iPad). Prosimy o skonfigurowanie adresu IP serwera WWW Photobooth w sekcji \"Ogólne\"", + "manual_remotebuzzer_logfile": "Jeśli tryb debugowania jest włączony, informacja o debugowaniu serwera zostanie zapisana do pliku dziennika, znajdującego się w folderze tmp i domyślnie io_server.log", + "manual_remotebuzzer_nodebin": "Ścieżka do pliku wykonywalnego dla node.js - przykład /usr/bin/node", + "manual_remotebuzzer_port": "Port TCP serwera - przykład 14711", + "manual_user_interface_font_size": "Wprowadź domyślny rozmiar czcionki używany dla interfejsu Fotobudki.", + "milliseconds": "milisekundy", + "newCollage": "Nowy kolaż", + "newPhoto": "Nowy obraz", + "newest_first": "Pokaż najpierw najnowsze obrazy", + "nextPhoto": "Następny obraz", + "path": "Ścieżka:", + "percent": "%", + "polaroid_effect": "Efekt polaroid", + "previewCamBackground": "Użyj strumienia z kamery urządzenia jako tła", + "previewCamFlipHorizontal": "Odwróć obraz z kamery urządzenia w poziomie", + "previewCamTakesPic": "Kamerka urządzenia robi zdjęcie", + "previewFromCam": "Zobacz podgląd z kamery urządzenia", + "previewFromIPCam": "Podgląd z adresu URL", + "print": "Drukuj", + "print_auto_print_delay": "Opóźnienie automatycznego drukowania obrazu", + "print_crop_height": "Nowa wysokość przy wydruku (px)", + "print_crop_width": "Nowa szerokość przy wydruku (px)", + "print_font_path": "Czcionka", + "print_fontsize": "Rozmiar czcionki", + "print_frame": "Drukuj ramkę na obrazku", + "print_frame_path": "Ramka", + "print_line1": "Tekst dla wiersza 1", + "print_line2": "Tekst dla wiersza 2", + "print_line3": "Tekst dla wiersza 3", + "print_linespace": "Odstępy między wierszami", + "print_locationx": "Współrzędna X", + "print_locationy": "Współrzędna Y", + "print_print_key": "Kod klawisza, który wyzwala drukowanie", + "print_printing_time": "Czas drukowania", + "print_qrcode": "Kod QR na obrazku podczas druku", + "print_rotation": "Obrót tekstu", + "printing": "Rozpoczęto drukowanie! Proszę czekać...", + "protect_admin": "Chroń panel administratora", + "protect_index": "Chroń ekran startowy", + "pswp_animateTransitions": "Zmiana obrazów z efektem przejścia slajdu", + "pswp_clickToCloseNonZoomable": "Kliknięcie myszy na obrazek powinno zamknąć galerię", + "pswp_closeOnOutsideClick": "Zamknij galerię, jeśli kliknięto na zewnątrz obrazu", + "pswp_closeOnScroll": "Zamknij obraz przy przewijaniu strony", + "pswp_closeOnVerticalDrag": "Zamknij galerię podczas przeciągania pionowo i gdy obraz nie jest powiększony", + "pswp_counterEl": "Pokaż licznik zdjęć", + "pswp_preventSwiping": "Wyłącz gesty przesuwania palcem", + "pswp_tapToToggleControls": "Przełącz widoczność sterowania/przycisków poprzez dotknięcie", + "qr": "Kod QR", + "qrHelp": "Aby pobrać zdjęcie na swój smartfon, połącz się z WiFi:", + "randomPicture": "Pokaż losowe zdjęcia", + "really_delete": "Naprawdę usunąć wszystkie zdjęcia? Tej operacji nie można cofnąć!", + "really_delete_image": "zostanie usunięte! Tej operacji nie można cofnąć! Naprawdę usunąć zdjęcie?", + "reload": "Przeładuj Stronę", + "remotebuzzer": "Serwer Zdalnego Buzera", + "remotebuzzer_collagetime": "Przytrzymaj przycisk x sekund, aby wyzwolić kolaż", + "remotebuzzer_enabled": "Jeśli włączone, upewnij się, że poprawnie ustawiono adres IP serwera WWW Fotobudki (sekcja \"Ogólne\")", + "remotebuzzer_logfile": "Plik dziennika", + "remotebuzzer_nodebin": "Ścieżka wykonywalna Node.js", + "remotebuzzer_pin": "Raspberry Pi PIN", + "remotebuzzer_port": "Port serwera", + "remove_config": "Usuń konfigurację osobistą (my.config.inc.php)", + "remove_images": "Usuń obrazki", + "remove_mailtxt": "Usuń bazę danych adresów e-mail", + "reset": "Reset", + "rounded_corners": "Zaokrąglone narożniki", + "save": "Zapisz", + "saveerror": "Błąd", + "saving": "Zapisuję", + "scrollbar": "Pokaż pasek przewijania w galerii", + "seconds": "sekunda(y)", + "selectFilter": "Filtr obrazu", + "send": "Wyślij", + "sendAllMail": "Wyślij mi link do wszystkich zdjęć w ciągu najbliższych kilku dni", + "send_all_later": "Aktywuj pole wyboru, aby dodać wprowadzony adres do pliku (na przykład, aby wysłać wiadomość z wszystkimi zdjęciami później)", + "show_date": "Pokaż datę poniżej zdjęć w galerii (działa tylko wtedy, gdy używane są zdjęcia dateformat)", + "show_error_messages": "Pokaż komunikaty błędów", + "show_faq": "Otwórz FAQ", + "show_gallery": "Pokaż galerię", + "show_manual": "Otwórz Instrukcję", + "show_wiki": "Otwórz Wiki (wymagane połączenie internetowe)", + "success": "Zapisano poprawnie", + "symbol": "Wybierz symbol", + "takeCollage": "Zrób kolaż!", + "takePhoto": "Zrób zdjęcie!", + "take_collage_frame": "Zrób kolaż z ramką", + "take_collage_frame_always": "Zastosuj ramkę do każdego zdjęcia kolażu", + "take_frame": "Zrób zdjęcie z ramką", + "toggleFullscreen": "Przełącz na pełny ekran", + "toggle_fs_button": "Pokaż przycisk, aby włączyć tryb pełnoekranowy", + "update_available": "Dostępna jest aktualizacja.", + "use_button": "Użyj Buzera aby zrobić zdjęcie", + "use_collage": "Zezwalaj na kolaż zdjęć", + "use_download": "Zezwól na pobieranie", + "use_filter": "Zezwól na filtry obrazu", + "use_mail": "Użyj E-Mail", + "use_print_chromakeying": "Zezwalaj na drukowanie z chromakeying", + "use_print_gallery": "Zezwól na drukowanie z galerii", + "use_print_result": "Zezwalaj na drukowanie na stronie wyników", + "use_qr": "Użyj kodów QR", + "use_slideshow": "Zezwalaj na pokaz slajdów w galerii", + "use_thumbs": "Użyj miniatur do pokazu slajdów", + "user_interface": "Interfejs użytkownika", + "user_interface_background_admin": "Ścieżka obrazu tła panelu administracyjnego", + "user_interface_background_chroma": "Ścieżka obrazu tła chromakeying", + "user_interface_background_image": "Ścieżka obrazu tła", + "user_interface_colors_background_countdown": "Kolor tła dla odliczania", + "user_interface_colors_border": "Kolor obramowania", + "user_interface_colors_box": "Kolor pola", + "user_interface_colors_button_font": "Kolor czcionki przycisków", + "user_interface_colors_cheese": "Uśmiech!-Kolor", + "user_interface_colors_countdown": "Kolor czasu odliczania", + "user_interface_colors_font": "Kolor czcionki", + "user_interface_colors_gallery_button": "Kolor przycisku galerii", + "user_interface_colors_panel": "Kolor panelu administratora i logowania", + "user_interface_colors_primary": "Kolor podstawowy", + "user_interface_colors_secondary": "Kolor Dodatkowy", + "user_interface_colors_start_font": "Kolor czcionki ekranu startowego", + "user_interface_font_size": "Domyślny rozmiar czcionki", + "using_latest_version": "Używasz najnowszej dostępnej wersji Fotobudki." +} From 9c8f61f0f97d2d1b033372b47975fe03489e363f Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Sun, 27 Sep 2020 09:30:53 +0200 Subject: [PATCH 30/32] docs (README): update features Change-Id: Icdcd7448f28873407a40335d347caabe3b983832 --- README.md | 48 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 385e0a080..e2833eb05 100644 --- a/README.md +++ b/README.md @@ -25,12 +25,8 @@ This is my personal Photobooth fork with some extras on top (more information ca - Standalone Gallery ([localhost/gallery.php](http://localhost/gallery.php)). - Slideshow via Gallery or standalone Gallery (under [localhost/slideshow](http://localhost/slideshow)). - Settings can be changed via Admin Panel (under [localhost/admin](http://localhost/admin)): - - Multi-language support: - - German - - English - - Spanish - - French - - Greek + - Multi-language support + - [Translate on Crowdin](https://crowdin.com/project/photobooth) - Login to protect Admin Panel and/or Start page can be enabled. - Gallery: - Order pictures in gallery ascending oder descending by picture age. @@ -65,6 +61,7 @@ This is my personal Photobooth fork with some extras on top (more information ca - access login via [localhost/login](http://localhost/login) instead [localhost/login.php](http://localhost/login.php) - offline manual with settings explained under [localhost/manual](http://localhost/manual) ([andi34/photobooth#59](https://github.com/andi34/photobooth/pull/59)) - offline FAQ under [localhost/manual/faq.html](http://localhost/manual/faq.html) + - disk usage page, access via admin panel or at [localhost/admin/diskusage.php](http://localhost/admin/diskusage.php) - fix windows compatibility - fix check for image filter - performance improvement ([andreknieriem/photobooth#226](https://github.com/andreknieriem/photobooth/pull/226)) @@ -94,10 +91,47 @@ This is my personal Photobooth fork with some extras on top (more information ca - Preview/Stream from device cam as background on start page ([andi34/photobooth#58](https://github.com/andi34/photobooth/pull/58)) - Allow using a stream from URL at countdown for preview - Allow to rotate preview from URL - - Show button bar inside gallery on bottom or on top of the image - Auto reload Photobooth on error while taking a photo - Allow to change permissons on picture - qrHelp: define WiFi SSID used on QR via admin panel + - Updated [PhotoSwipe Gallery](https://github.com/andi34/PhotoSwipe) + - Show button bar inside gallery on bottom or on top of the image + - allow to adjust PhotoSwipe Gallery config via Adminpanel, also allow to use some PhotoSwipe functions and make more PhotoSwipe settings available (settings explained inside the manual): + - Mouse click on image should close the gallery (enable/disable) + - Close gallery if clicked outside of the image (enable/disable) + - Close picture on page scroll (enable/disable) + - Close gallery when dragging vertically and when image is not zoomed (enable/disable) + - Show image counter (enable/disable) + - Show PhotoSwipe fullscreen button (enable/disable) + - Show PhotoSwipe zoom button (enable/disable) + - PhotoSwipe history module (enable/disable) + - Pinch to close gallery (enable/disable) + - Toggle visibility of controls/buttons by tap (enable/disable) + - allow to adjust PhotoSwipe background opacity (0-1) + - Loop images (enable/disable) + - Slide transition effect (enable/disable) + - Swiping to change slides (enable/disable) + - gallery: button to delete an image, enable by default + - Remote Buzzer Server based on io sockets + - Enables a GPIO pin connected hardware button / buzzer for a setup where the display / screen is connected via WLAN / network to the photobooth webserver (e.g. iPad) + - Choose thumbnail size: + - XS = max 360px + - S = max 540px + - M = max 900px + - L = max 1080px + - XL = max 1260px" + - Advanced printing functions [#109](https://github.com/andi34/photobooth/pull/109): + - Auto print function + - allow to delay auto print + - allow to adjust time "Started printing! Please wait..." is visible + - allow to trigger print via defined key + - options to show the print button independent (e.g. can be only visible on gallery) + - Advanced collage options [#108](https://github.com/andi34/photobooth/pull/108): + - Choose collage layout: + - 2x2 + - 2x4 + - 2x4 + background image + - Collage: apply frame once after taking or to every picture of the collage ## :camera: Screenshots From 5e970b2e9d12349374c3c327ea01634f445776db Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Sun, 27 Sep 2020 09:34:58 +0200 Subject: [PATCH 31/32] api (fix): only try to delete tmp image if keep images is enabled Change-Id: Ib4bd8d63a2e64453429a99698f6b3a0315a7ff73 --- api/deletePhoto.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/api/deletePhoto.php b/api/deletePhoto.php index 42e1ff518..52f375c5f 100644 --- a/api/deletePhoto.php +++ b/api/deletePhoto.php @@ -41,11 +41,13 @@ } } -if (is_readable($filePathTmp)) { - if (!unlink ($filePathTmp)) { - die(json_encode([ - 'error' => 'Could not delete tmp file', - ])); +if ($config['keep_images']) { + if (is_readable($filePathTmp)) { + if (!unlink ($filePathTmp)) { + die(json_encode([ + 'error' => 'Could not delete tmp file', + ])); + } } } From b3bee971a0d3b4efbfea08e05047ffb8b24574f4 Mon Sep 17 00:00:00 2001 From: Andreas Blaesius Date: Sun, 27 Sep 2020 10:40:45 +0200 Subject: [PATCH 32/32] fix (gallery): trigger print via defined key only if gallery is defined Change-Id: I2c3ee43d1fb091ba0a3f351d74ad2dc22e3f59c1 --- src/js/photoinit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/photoinit.js b/src/js/photoinit.js index 4542a52f8..291163ab4 100644 --- a/src/js/photoinit.js +++ b/src/js/photoinit.js @@ -314,7 +314,7 @@ function initPhotoSwipeFromDOM(gallerySelector) { if (config.use_print_gallery && config.print_key && parseInt(config.print_key, 10) === ev.keyCode) { if (isPrinting) { console.log('Printing already in progress!'); - } else { + } else if ($('#gallery').hasClass('gallery--open') && typeof gallery !== 'undefined') { $('.pswp__button--print').trigger('click'); } }