webcam support

This commit is contained in:
Roland Gruber 2020-07-22 13:28:17 +02:00
parent 6768c7e7ef
commit 3ad5dcf65a
4 changed files with 93 additions and 36 deletions

View File

@ -3078,7 +3078,13 @@ class htmlStatusMessage extends htmlElement {
* @return array List of input field names and their type (name => type) * @return array List of input field names and their type (name => type)
*/ */
public function generateHTML($module, $input, $values, $restricted, &$tabindex, $scope) { public function generateHTML($module, $input, $values, $restricted, &$tabindex, $scope) {
if (!empty($this->cssClasses)) {
echo '<div class="' . implode(' ', $this->cssClasses) . '">';
}
StatusMessage($this->type, $this->title, $this->text, $this->params); StatusMessage($this->type, $this->title, $this->text, $this->params);
if (!empty($this->cssClasses)) {
echo '</div>';
}
return array(); return array();
} }

View File

@ -1629,7 +1629,7 @@ class inetOrgPerson extends baseModule implements passwordService {
if ($this->isAdminReadOnly('jpegPhoto')) { if ($this->isAdminReadOnly('jpegPhoto')) {
return array(); 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(); return $this->uploadPhoto();
} }
if (isset($_POST['form_subpage_' . get_class($this) . '_attributes_crop'])) { if (isset($_POST['form_subpage_' . get_class($this) . '_attributes_crop'])) {
@ -1656,7 +1656,11 @@ class inetOrgPerson extends baseModule implements passwordService {
*/ */
private function uploadPhoto() { private function uploadPhoto() {
$messages = array(); $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"); $handle = fopen($_FILES['photoFile']['tmp_name'], "r");
$data = fread($handle, 100000000); $data = fread($handle, 100000000);
if (!empty($this->moduleSettings['inetOrgPerson_jpegPhoto_maxSize'][0]) && (strlen($data) > (1024 * $this->moduleSettings['inetOrgPerson_jpegPhoto_maxSize'][0]))) { 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); return array($errMsg);
} }
fclose($handle); 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 { elseif (isset($_POST['webcamData'])) {
$messages[] = $this->messages['file'][0]; $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; return $messages;
} }
@ -1710,16 +1716,23 @@ class inetOrgPerson extends baseModule implements passwordService {
$container->addVerticalSpacer('1rem'); $container->addVerticalSpacer('1rem');
$webcamContent = new htmlResponsiveRow(); $webcamContent = new htmlResponsiveRow();
$webcamContent->add(new htmlSubTitle(_('Get from webcam')), 12); $webcamContent->add(new htmlSubTitle(_('Get from webcam')), 12);
$webcamContent->addLabel(new htmlOutputText(_('Image'))); $errorMessage = new htmlStatusMessage('ERROR', '');
$webcamContent->addField(new htmlVideo('lam-webcam-video')); $errorMessage->setCSSClasses(array('hidden', 'lam-webcam-message'));
$webcamContent->addLabel(new htmlOutputText('&nbsp;', false)); $webcamContent->add($errorMessage, 12);
$webcamButtonGroup = new htmlGroup(); $captureButton = new htmlButton('lam-webcam-capture', _('Start capture'));
$captureButton = new htmlButton('lam-webcam-capture', _('Capture'));
$captureButton->setOnClick('window.lam.tools.startWebcamCapture(event);'); $captureButton->setOnClick('window.lam.tools.startWebcamCapture(event);');
$webcamButtonGroup->addElement($captureButton); $webcamContent->add($captureButton, 12, 12, 12, 'text-center');
$webcamButtonGroup->addElement(new htmlAccountPageButton(get_class($this), 'photo', 'upload', _('Upload'))); $video = new htmlVideo('lam-webcam-video');
$webcamButtonGroup->addElement(new htmlCanvas('lam-webcam-canvas')); $video->setCSSClasses(array('hidden'));
$webcamContent->addField($webcamButtonGroup); $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')); $webcamDiv = new htmlDiv('lam_webcam_div', $webcamContent, array('hidden'));
$container->add($webcamDiv, 12); $container->add($webcamDiv, 12);
$container->addVerticalSpacer('1rem'); $container->addVerticalSpacer('1rem');

View File

@ -314,6 +314,11 @@ table.collapse {
font-weight: bold; font-weight: bold;
} }
#lam-webcam-video {
max-width: 200px;
max-height: 200px;
}
/** buttons */ /** buttons */
.saveButton { .saveButton {
background-image: url(../graphics/save.png) !important; background-image: url(../graphics/save.png) !important;

View File

@ -959,8 +959,9 @@ window.lam.tools.initWebcamCapture = function() {
*/ */
window.lam.tools.startWebcamCapture = function(event) { window.lam.tools.startWebcamCapture = function(event) {
event.preventDefault(); event.preventDefault();
var canvas = document.getElementById('lam-webcam-canvas'); var video = document.getElementById('lam-webcam-video');
var video = document.getElementById('lam-webcam-videofor'); var msg = jQuery('.lam-webcam-message');
msg.hide();
navigator.mediaDevices.getUserMedia({ navigator.mediaDevices.getUserMedia({
video: { video: {
facingMode: 'user', facingMode: 'user',
@ -972,13 +973,45 @@ window.lam.tools.startWebcamCapture = function(event) {
.then(function(stream) { .then(function(stream) {
video.srcObject = stream; video.srcObject = stream;
video.play(); 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) { .catch(function(err) {
console.log("An error occurred: " + err); msg.find('.statusTitle').text(err);
msg.show();
}); });
return false; 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("<input></input>");
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 || {}; window.lam.tools.schema = window.lam.tools.schema || {};
/** /**