Skip to content

Commit 1adaf30

Browse files
authored
bugfix misc, downscaler, remotebuzzer spam (#1404)
* scale text on downscaled picture, only downscale if necessary * dont spam remotebuzzer if server is not reachable
1 parent 0e03923 commit 1adaf30

File tree

2 files changed

+170
-120
lines changed

2 files changed

+170
-120
lines changed

api/applyEffects.php

Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -135,41 +135,31 @@
135135

136136
if (!$vars['isCollage'] || $vars['editSingleCollage']) {
137137
$filterProcessSize = intval($config['filters']['process_size'] ?? 0);
138-
$downscaledForFilter = false;
139138

140-
// apply filter (optionally downscale first for performance)
141-
if ($vars['imageFilter'] !== null && $vars['imageFilter'] !== ImageFilterEnum::PLAIN) {
142-
$originalWidth = imagesx($imageResource);
143-
$originalHeight = imagesy($imageResource);
144-
$filterResource = $imageResource;
139+
// only downscale if filter not plain, rembg is enabled
140+
$originalResource = null;
141+
if ($vars['imageFilter'] !== ImageFilterEnum::PLAIN || $config['rembg']['enabled']) {
142+
$originalWidth = imagesx($imageResource);
143+
$originalHeight = imagesy($imageResource);
144+
$originalResource = $imageResource;
145145

146146
if ($filterProcessSize > 0 && ($originalWidth > $filterProcessSize || $originalHeight > $filterProcessSize)) {
147-
$downscaled = $imageHandler->resizeImage($imageResource, $filterProcessSize);
148-
if ($downscaled instanceof \GdImage) {
149-
$filterResource = $downscaled;
150-
$downscaledForFilter = true;
147+
$downscaledResource = $imageHandler->resizeImage($imageResource, $filterProcessSize);
148+
if ($downscaledResource instanceof \GdImage) {
149+
$imageResource = $downscaledResource;
151150
}
152151
}
152+
}
153153

154+
// apply filter (optionally downscale first for performance)
155+
if ($vars['imageFilter'] !== null && $vars['imageFilter'] !== ImageFilterEnum::PLAIN) {
154156
try {
155-
ImageUtility::applyFilter($vars['imageFilter'], $filterResource);
157+
ImageUtility::applyFilter($vars['imageFilter'], $imageResource);
156158
$imageHandler->imageModified = true;
157159
} catch (\Exception $e) {
158160
throw new \Exception('Error applying image filter.');
159161
}
160162

161-
if ($filterResource !== $imageResource) {
162-
$imageResource = $filterResource;
163-
// Maybe we want this later or configurable, will take some time to process upscale again
164-
// Upscale back to original size
165-
// $restored = $imageHandler->resizeImage($filterResource, $originalWidth, $originalHeight);
166-
// if ($restored instanceof \GdImage) {
167-
// if ($filterResource instanceof \GdImage) {
168-
// unset($filterResource);
169-
// }
170-
// $imageResource = $restored;
171-
// }
172-
}
173163
}
174164

175165
if ($config['picture']['flip'] !== 'off') {
@@ -197,20 +187,9 @@
197187
}
198188
}
199189

200-
// Apply rembg (downscale first if filters_process_size is set and not already downscaled for filters)
201-
if ($filterProcessSize > 0 && !$downscaledForFilter) {
202-
$width = imagesx($imageResource);
203-
$height = imagesy($imageResource);
204-
if ($width > $filterProcessSize || $height > $filterProcessSize) {
205-
$downscaled = $imageHandler->resizeImage($imageResource, $filterProcessSize);
206-
if ($downscaled instanceof \GdImage) {
207-
$imageResource = $downscaled;
208-
}
209-
}
210-
}
211-
212190
// Apply rembg
213191
[$imageHandler, $imageResource] = Rembg::process($imageHandler, $vars, $config['rembg'], $imageResource);
192+
214193
if ($config['picture']['polaroid_effect']) {
215194
$imageHandler->polaroidRotation = $config['picture']['polaroid_rotation'];
216195
$imageResource = $imageHandler->effectPolaroid($imageResource);
@@ -236,6 +215,18 @@
236215
throw new \Exception('Error applying frame to image resource.');
237216
}
238217
}
218+
219+
// Maybe we want this later or configurable, will take some time to process upscale again
220+
// Upscale back to original size
221+
// if (!empty($originalResource) && $originalResource !== $imageResource) {
222+
// $restored = $imageHandler->resizeImage($imageResource, $originalWidth, $originalHeight);
223+
// if ($restored instanceof \GdImage) {
224+
// if ($imageResource instanceof \GdImage) {
225+
// unset($imageResource);
226+
// }
227+
// $imageResource = $restored;
228+
// }
229+
// }
239230
}
240231
}
241232

@@ -260,16 +251,24 @@
260251
}
261252

262253
if ($config['textonpicture']['enabled'] && (!$vars['isCollage'] && !$vars['isChroma'] || $vars['editSingleCollage'])) {
263-
$imageHandler->fontSize = $config['textonpicture']['font_size'];
254+
// calculate and apply text on picture if image got downscaled before
255+
$scale = 1.0;
256+
if (isset($originalWidth) && isset($originalHeight)) {
257+
$currentWidth = imagesx($imageResource);
258+
$scale = $currentWidth / $originalWidth;
259+
}
260+
261+
// Cast after scaling to avoid implicit float-to-int deprecation warnings in PHP 8.4
262+
$imageHandler->fontSize = (int) round($config['textonpicture']['font_size'] * $scale);
263+
$imageHandler->textLineSpacing = (int) round($config['textonpicture']['linespace'] * $scale);
264+
$imageHandler->fontLocationX = (int) round($config['textonpicture']['locationx'] * $scale);
265+
$imageHandler->fontLocationY = (int) round($config['textonpicture']['locationy'] * $scale);
264266
$imageHandler->fontRotation = $config['textonpicture']['rotation'];
265-
$imageHandler->fontLocationX = $config['textonpicture']['locationx'];
266-
$imageHandler->fontLocationY = $config['textonpicture']['locationy'];
267267
$imageHandler->fontColor = $config['textonpicture']['font_color'];
268268
$imageHandler->fontPath = $config['textonpicture']['font'];
269269
$imageHandler->textLine1 = $config['textonpicture']['line1'];
270270
$imageHandler->textLine2 = $config['textonpicture']['line2'];
271271
$imageHandler->textLine3 = $config['textonpicture']['line3'];
272-
$imageHandler->textLineSpacing = $config['textonpicture']['linespace'];
273272
$imageResource = $imageHandler->applyText($imageResource);
274273
if (!$imageResource instanceof \GdImage) {
275274
throw new \Exception('Error applying text to image resource.');

assets/js/remotebuzzer-client.js

Lines changed: 132 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,30 @@ let remoteBuzzerClient;
55
let rotaryController;
66
let buttonController;
77

8+
// Quick reachability probe so we don't start socket.io polling when the server is down.
9+
// Uses XMLHttpRequest to avoid Node fetch lint issues; runs in the browser.
10+
const checkRemoteBuzzerReachable = (baseUrl, timeoutMs = 3000) =>
11+
new Promise((resolve) => {
12+
const xhr = new XMLHttpRequest();
13+
const timeout = setTimeout(() => {
14+
xhr.abort();
15+
resolve(false);
16+
}, timeoutMs);
17+
18+
xhr.onerror = () => {
19+
clearTimeout(timeout);
20+
resolve(false);
21+
};
22+
23+
xhr.onload = () => {
24+
clearTimeout(timeout);
25+
resolve(true);
26+
};
27+
28+
xhr.open('GET', baseUrl + '/socket.io/?EIO=4&transport=polling&t=' + Date.now(), true);
29+
xhr.send();
30+
});
31+
832
// eslint-disable-next-line no-unused-vars
933
function initRemoteBuzzerFromDOM() {
1034
photoboothTools.console.logDev(
@@ -18,101 +42,123 @@ function initRemoteBuzzerFromDOM() {
1842
*/
1943

2044
remoteBuzzerClient = (function () {
45+
photoboothTools.console.log('remoteBuzzerClient init');
46+
2147
let ioClient;
48+
let serverReachable = false;
2249
const api = {};
2350

2451
api.enabled = function () {
2552
return config.remotebuzzer.usebuttons || config.remotebuzzer.userotary;
2653
};
2754

55+
api.connected = function () {
56+
return serverReachable && !!ioClient;
57+
};
58+
2859
api.init = function () {
2960
if (!this.enabled()) {
3061
return;
3162
}
3263

3364
if (config.remotebuzzer.serverip) {
34-
ioClient = io(
35-
window.location.protocol + '//' + config.remotebuzzer.serverip + ':' + config.remotebuzzer.port
36-
);
37-
photoboothTools.console.logDev(
38-
'Remote buzzer connecting to ' +
39-
window.location.protocol +
40-
'//' +
41-
config.remotebuzzer.serverip +
42-
':' +
43-
config.remotebuzzer.port
44-
);
45-
46-
ioClient.on('photobooth-socket', function (data) {
47-
switch (data) {
48-
case 'start-picture':
49-
buttonController.takePicture();
50-
break;
51-
52-
case 'start-collage':
53-
buttonController.takeCollage();
54-
break;
55-
56-
case 'start-custom':
57-
buttonController.takeCustom();
58-
break;
59-
60-
case 'start-video':
61-
buttonController.takeVideo();
62-
break;
63-
64-
case 'collage-next':
65-
// Need to handle collage process in button handler
66-
if (buttonController.waitingToProcessCollage) {
67-
buttonController.processCollage();
68-
} else {
69-
buttonController.takeCollageNext();
65+
const baseUrl =
66+
window.location.protocol + '//' + config.remotebuzzer.serverip + ':' + config.remotebuzzer.port;
67+
68+
checkRemoteBuzzerReachable(baseUrl)
69+
.then((reachable) => {
70+
if (!reachable) {
71+
photoboothTools.console.log(
72+
'Remote buzzer server not reachable at ' + baseUrl + ' - skipping connection.'
73+
);
74+
return;
75+
}
76+
77+
photoboothTools.console.log(
78+
'Remote buzzer server is reachable at ' + baseUrl + ' - skipping connection.'
79+
);
80+
81+
serverReachable = true;
82+
ioClient = io(baseUrl);
83+
photoboothTools.console.logDev('Remote buzzer connecting to ' + baseUrl);
84+
85+
ioClient.on('photobooth-socket', function (data) {
86+
switch (data) {
87+
case 'start-picture':
88+
buttonController.takePicture();
89+
break;
90+
91+
case 'start-collage':
92+
buttonController.takeCollage();
93+
break;
94+
95+
case 'start-custom':
96+
buttonController.takeCustom();
97+
break;
98+
99+
case 'start-video':
100+
buttonController.takeVideo();
101+
break;
102+
103+
case 'collage-next':
104+
// Need to handle collage process in button handler
105+
if (buttonController.waitingToProcessCollage) {
106+
buttonController.processCollage();
107+
} else {
108+
buttonController.takeCollageNext();
109+
}
110+
break;
111+
112+
case 'print':
113+
buttonController.print();
114+
break;
115+
116+
case 'rotary-cw':
117+
rotaryController.focusNext();
118+
break;
119+
120+
case 'rotary-ccw':
121+
rotaryController.focusPrev();
122+
break;
123+
124+
case 'rotary-btn-press':
125+
rotaryController.click();
126+
break;
127+
128+
case 'start-move2usb':
129+
buttonController.move2usb();
130+
break;
131+
132+
default:
133+
break;
70134
}
71-
break;
72-
73-
case 'print':
74-
buttonController.print();
75-
break;
76-
77-
case 'rotary-cw':
78-
rotaryController.focusNext();
79-
break;
80-
81-
case 'rotary-ccw':
82-
rotaryController.focusPrev();
83-
break;
84-
85-
case 'rotary-btn-press':
86-
rotaryController.click();
87-
break;
88-
89-
case 'start-move2usb':
90-
buttonController.move2usb();
91-
break;
92-
93-
default:
94-
break;
95-
}
96-
});
97-
98-
ioClient.on('connect_error', function () {
99-
photoboothTools.console.log(
100-
'ERROR: Remote buzzer client unable to connect to Remote buzzer Server - please ensure Remote buzzer server is running on ' +
101-
config.remotebuzzer.serverip +
102-
'. Set Photobooth loglevel to 1 (or above) to create log file for debugging.'
103-
);
104-
});
105-
106-
ioClient.on('connect', function () {
107-
photoboothTools.console.logDev(
108-
'Remote buzzer client successfully connected to Remote buzzer Server.'
109-
);
110-
});
111-
112-
buttonController.init();
113-
rotaryController.init();
114-
115-
rotaryController.focusSet('.stage[data-stage="start"]');
135+
});
136+
137+
ioClient.on('connect_error', function () {
138+
photoboothTools.console.log(
139+
'ERROR: Remote buzzer client unable to connect to Remote buzzer Server - please ensure Remote buzzer server is running on ' +
140+
config.remotebuzzer.serverip +
141+
'. Set Photobooth loglevel to 1 (or above) to create log file for debugging.'
142+
);
143+
});
144+
145+
ioClient.on('connect', function () {
146+
photoboothTools.console.logDev(
147+
'Remote buzzer client successfully connected to Remote buzzer Server.'
148+
);
149+
});
150+
151+
buttonController.init();
152+
rotaryController.init();
153+
154+
rotaryController.focusSet('.stage[data-stage="start"]');
155+
})
156+
.catch(() => {
157+
serverReachable = false;
158+
photoboothTools.console.log(
159+
'Remote buzzer server not reachable at ' + baseUrl + ' - skipping connection.'
160+
);
161+
});
116162
} else {
117163
photoboothTools.console.log(
118164
'ERROR: Remote buzzer client unable to connect - Remote buzzer Server IP not defined in photobooth config!'
@@ -175,6 +221,11 @@ function initRemoteBuzzerFromDOM() {
175221
};
176222

177223
api.emitToServer = function (cmd, photoboothAction) {
224+
if (!this.connected()) {
225+
photoboothTools.console.logDev('Skip emitting remote buzzer command; server not connected.');
226+
return;
227+
}
228+
178229
switch (cmd) {
179230
case 'start-picture':
180231
ioClient.emit('photobooth-socket', 'start-picture');

0 commit comments

Comments
 (0)