From 3ad5dcf65aad8c7a521d5de25a4f0bccc2d3b44f Mon Sep 17 00:00:00 2001 From: Roland Gruber Date: Wed, 22 Jul 2020 13:28:17 +0200 Subject: [PATCH] webcam support --- lam/lib/html.inc | 6 +++ lam/lib/modules/inetOrgPerson.inc | 79 ++++++++++++++++++------------- lam/style/500_layout.css | 5 ++ lam/templates/lib/500_lam.js | 39 +++++++++++++-- 4 files changed, 93 insertions(+), 36 deletions(-) diff --git a/lam/lib/html.inc b/lam/lib/html.inc index 051d88f1..e41ed223 100644 --- a/lam/lib/html.inc +++ b/lam/lib/html.inc @@ -3078,7 +3078,13 @@ class htmlStatusMessage extends htmlElement { * @return array List of input field names and their type (name => type) */ public function generateHTML($module, $input, $values, $restricted, &$tabindex, $scope) { + if (!empty($this->cssClasses)) { + echo '
'; + } StatusMessage($this->type, $this->title, $this->text, $this->params); + if (!empty($this->cssClasses)) { + echo '
'; + } return array(); } diff --git a/lam/lib/modules/inetOrgPerson.inc b/lam/lib/modules/inetOrgPerson.inc index f6439fab..d9852cb7 100644 --- a/lam/lib/modules/inetOrgPerson.inc +++ b/lam/lib/modules/inetOrgPerson.inc @@ -1629,7 +1629,7 @@ class inetOrgPerson extends baseModule implements passwordService { if ($this->isAdminReadOnly('jpegPhoto')) { return array(); } - if (isset($_POST['form_subpage_' . get_class($this) . '_photo_upload'])) { + if (isset($_POST['form_subpage_' . get_class($this) . '_photo_upload']) || isset($_POST['webcamData'])) { return $this->uploadPhoto(); } if (isset($_POST['form_subpage_' . get_class($this) . '_attributes_crop'])) { @@ -1656,7 +1656,11 @@ class inetOrgPerson extends baseModule implements passwordService { */ private function uploadPhoto() { $messages = array(); - if ($_FILES['photoFile'] && ($_FILES['photoFile']['size'] > 0)) { + if ((empty($_FILES['photoFile']) || ($_FILES['photoFile']['size'] <= 0)) && empty($_POST['webcamData'])) { + $messages[] = $this->messages['file'][0]; + return $messages; + } + if (!empty($_FILES['photoFile']['tmp_name'])) { $handle = fopen($_FILES['photoFile']['tmp_name'], "r"); $data = fread($handle, 100000000); if (!empty($this->moduleSettings['inetOrgPerson_jpegPhoto_maxSize'][0]) && (strlen($data) > (1024 * $this->moduleSettings['inetOrgPerson_jpegPhoto_maxSize'][0]))) { @@ -1666,30 +1670,32 @@ class inetOrgPerson extends baseModule implements passwordService { return array($errMsg); } fclose($handle); - // convert to JPG - try { - include_once dirname(__FILE__) . '/../imageutils.inc'; - $imageManipulator = ImageManipulationFactory::getImageManipulator($data); - // resize if maximum values specified - if (!empty($this->moduleSettings['inetOrgPerson_jpegPhoto_maxWidth'][0]) || !empty($this->moduleSettings['inetOrgPerson_jpegPhoto_maxHeight'][0])) { - $maxWidth = empty($this->moduleSettings['inetOrgPerson_jpegPhoto_maxWidth'][0]) ? $imageManipulator->getWidth() : $this->moduleSettings['inetOrgPerson_jpegPhoto_maxWidth'][0]; - $maxHeight = empty($this->moduleSettings['inetOrgPerson_jpegPhoto_maxHeight'][0]) ? $imageManipulator->getHeight() : $this->moduleSettings['inetOrgPerson_jpegPhoto_maxHeight'][0]; - $imageManipulator->thumbnail($maxWidth, $maxHeight); - } - $imageManipulator->convertToJpeg(); - $data = $imageManipulator->getImageData(); - } - catch (Exception $e) { - $msg = $this->messages['file'][2]; - $msg[] = htmlspecialchars($e->getMessage()); - $messages[] = $msg; - return $messages; - } - $this->attributes['jpegPhoto'][0] = $data; } - else { - $messages[] = $this->messages['file'][0]; + elseif (isset($_POST['webcamData'])) { + $data = $_POST['webcamData']; + $data = str_replace('data:image/png;base64,', '', $data); + $data = base64_decode($data); } + // convert to JPG + try { + include_once dirname(__FILE__) . '/../imageutils.inc'; + $imageManipulator = ImageManipulationFactory::getImageManipulator($data); + // resize if maximum values specified + if (!empty($this->moduleSettings['inetOrgPerson_jpegPhoto_maxWidth'][0]) || !empty($this->moduleSettings['inetOrgPerson_jpegPhoto_maxHeight'][0])) { + $maxWidth = empty($this->moduleSettings['inetOrgPerson_jpegPhoto_maxWidth'][0]) ? $imageManipulator->getWidth() : $this->moduleSettings['inetOrgPerson_jpegPhoto_maxWidth'][0]; + $maxHeight = empty($this->moduleSettings['inetOrgPerson_jpegPhoto_maxHeight'][0]) ? $imageManipulator->getHeight() : $this->moduleSettings['inetOrgPerson_jpegPhoto_maxHeight'][0]; + $imageManipulator->thumbnail($maxWidth, $maxHeight); + } + $imageManipulator->convertToJpeg(); + $data = $imageManipulator->getImageData(); + } + catch (Exception $e) { + $msg = $this->messages['file'][2]; + $msg[] = htmlspecialchars($e->getMessage()); + $messages[] = $msg; + return $messages; + } + $this->attributes['jpegPhoto'][0] = $data; return $messages; } @@ -1710,16 +1716,23 @@ class inetOrgPerson extends baseModule implements passwordService { $container->addVerticalSpacer('1rem'); $webcamContent = new htmlResponsiveRow(); $webcamContent->add(new htmlSubTitle(_('Get from webcam')), 12); - $webcamContent->addLabel(new htmlOutputText(_('Image'))); - $webcamContent->addField(new htmlVideo('lam-webcam-video')); - $webcamContent->addLabel(new htmlOutputText(' ', false)); - $webcamButtonGroup = new htmlGroup(); - $captureButton = new htmlButton('lam-webcam-capture', _('Capture')); + $errorMessage = new htmlStatusMessage('ERROR', ''); + $errorMessage->setCSSClasses(array('hidden', 'lam-webcam-message')); + $webcamContent->add($errorMessage, 12); + $captureButton = new htmlButton('lam-webcam-capture', _('Start capture')); $captureButton->setOnClick('window.lam.tools.startWebcamCapture(event);'); - $webcamButtonGroup->addElement($captureButton); - $webcamButtonGroup->addElement(new htmlAccountPageButton(get_class($this), 'photo', 'upload', _('Upload'))); - $webcamButtonGroup->addElement(new htmlCanvas('lam-webcam-canvas')); - $webcamContent->addField($webcamButtonGroup); + $webcamContent->add($captureButton, 12, 12, 12, 'text-center'); + $video = new htmlVideo('lam-webcam-video'); + $video->setCSSClasses(array('hidden')); + $webcamContent->add($video, 12, 12, 12, 'text-center'); + $webcamContent->addVerticalSpacer('0.5rem'); + $webcamUploadButton = new htmlButton('uploadWebcam', _('Upload')); + $webcamUploadButton->setCSSClasses(array('btn-lam-webcam-upload', 'hidden')); + $webcamUploadButton->setOnClick('window.lam.tools.startWebcamUpload();'); + $webcamContent->add($webcamUploadButton, 12, 12, 12, 'text-center'); + $canvas = new htmlCanvas('lam-webcam-canvas'); + $canvas->setCSSClasses(array('hidden')); + $webcamContent->add($canvas, 12); $webcamDiv = new htmlDiv('lam_webcam_div', $webcamContent, array('hidden')); $container->add($webcamDiv, 12); $container->addVerticalSpacer('1rem'); diff --git a/lam/style/500_layout.css b/lam/style/500_layout.css index 3312b922..157d6f23 100644 --- a/lam/style/500_layout.css +++ b/lam/style/500_layout.css @@ -314,6 +314,11 @@ table.collapse { font-weight: bold; } +#lam-webcam-video { + max-width: 200px; + max-height: 200px; +} + /** buttons */ .saveButton { background-image: url(../graphics/save.png) !important; diff --git a/lam/templates/lib/500_lam.js b/lam/templates/lib/500_lam.js index 4ec1ce52..edb3d32e 100644 --- a/lam/templates/lib/500_lam.js +++ b/lam/templates/lib/500_lam.js @@ -959,8 +959,9 @@ window.lam.tools.initWebcamCapture = function() { */ window.lam.tools.startWebcamCapture = function(event) { event.preventDefault(); - var canvas = document.getElementById('lam-webcam-canvas'); - var video = document.getElementById('lam-webcam-videofor'); + var video = document.getElementById('lam-webcam-video'); + var msg = jQuery('.lam-webcam-message'); + msg.hide(); navigator.mediaDevices.getUserMedia({ video: { facingMode: 'user', @@ -972,13 +973,45 @@ window.lam.tools.startWebcamCapture = function(event) { .then(function(stream) { video.srcObject = stream; video.play(); + window.lam.tools.webcamStream = stream; + jQuery('#btn_lam-webcam-capture').hide(); + jQuery('.btn-lam-webcam-upload').show(); + jQuery('#lam-webcam-video').show(); }) .catch(function(err) { - console.log("An error occurred: " + err); + msg.find('.statusTitle').text(err); + msg.show(); }); return false; } +/** + * Starts the webcam upload. + */ +window.lam.tools.startWebcamUpload = function() { + var canvas = document.getElementById('lam-webcam-canvas'); + var video = document.getElementById('lam-webcam-video'); + var form = jQuery('#lam-webcam-canvas').closest('form'); + canvas.setAttribute('width', video.videoWidth); + canvas.setAttribute('height', video.videoHeight); + var context = canvas.getContext('2d'); + context.drawImage(video, 0, 0, video.videoWidth, video.videoHeight); + var canvasData = canvas.toDataURL("image/png"); + var canvasDataInput = jQuery(""); + canvasDataInput.attr('name', 'webcamData'); + canvasDataInput.attr('type', 'hidden'); + canvasDataInput.attr('value', canvasData); + video.pause(); + window.lam.tools.webcamStream.getTracks().forEach(function(track) { + track.stop(); + }); + form.append(canvasDataInput); + jQuery(canvas).remove(); + jQuery(video).remove(); + form.submit(); + return true; +} + window.lam.tools.schema = window.lam.tools.schema || {}; /**