Блог от AS3Coder'a о JavaScript, HTML, CSS... и немного о Flash.

четверг, 7 августа 2014 г.

Сохранить изображение с камеры на JavaScript

Я уже писал, о том как сохранить изображение с камеры на ActionScript 3.0. Теперь самое время разобраться как сделать то же самое на JavaScript.

Вывод изображения с камеры

Для вывода изображения с камеры нам понадобится video-элемент. В нем мы будем отображать потоковое видео с веб-камеры. На странице выглядеть это будет так:
<video autoplay id="video"></video>
Также нам понадобиться метод navigator.getUserMedia. С помощью этого метода мы можем попросить браузер вернуть нам медиаданные пользователя, а именно: изображение с камеры и звук с микрофона. Метод довольно новый и реализован еще не во всех обозревателях (по данным caniuse.com в Chrome 21+, FireFox 17+ и Opera 18+), поэтому добавим такую вот обвязку:
navigator.getUserMedia = (navigator.getUserMedia ||
                          navigator.webkitGetUserMedia ||
                          navigator.mozGetUserMedia ||
                          navigator.msGetUserMedia);
Теперь попробуем вызвать метод:
navigator.getUserMedia({ video : true }, function (){}, function(){});
В первом параметре мы указываем тип необходимых нам данных. Допустимо два параметра audio и video. В нашем случае это только video. После вызова пользователь увидит сообщение с запросом на разрешение использовать указанные устройства:

Снимок в Opera 23.0

Для реакции на выбор пользователя имеются второй и третий параметры. В них указываются ссылки на обработчики событий. Второй вызывается, если доступ к камере разрешен. Третий, если доступ запрещен.
navigator.getUserMedia({ video : true }, 
//---
function ()
{
  // Доступ к камере разрешен
}, 
function()
{
  // Доступ к камере запрещен
});
Если доступ к камере имеется, то в соответствующем обработчике будет единственный аргумент - ссылка на потоковое видео с камеры. Чтобы отобразить видео, его нужно задать ранее созданному video-элементу c помощью URL.createObjectURL:
navigator.getUserMedia({ video : true }, 
//---
function ()
{
  var video = document.getElementById('video');
  video.src = window.URL.createObjectURL(stream);
}, 
function()
{
  alert('No access to the camera!')
});
В старой Opera (которая Presto) формат параметров и ссылка на локальный медиапоток немного отличается. В рамках данной статьи, мы этого рассматривать не будем.
После того как страница получает видео с камеры, на вкладке появляется индикатор записи. Например в Chrome это выглядит так:



Снимок с экрана

Для того, чтобы сделать снимок с video-элемента, нам понадобится canvas-элемент.
<canvas id="canvas"></canvas>
Только этот элемент может снимать растровые изображения с любого элемента на странице. Для этого у двухмерного контекста имеется метод .drawImage(); В нашем случае мы будем снимать изображение с video-элемента, в котором отображается видео с камеры.
var context = canvas.getContext('2d');
context.drawImage(video, 0, 0);
Сборка файла изображения

Теперь изображение можно открыть в отдельном окне, используя адрес полученный из метода .toDataURL(); Здесь вы можете получить изображения в необходимом вам формате. Для этого достаточно указать в первом параметре MIME-тип файла. Мы будем использовать PNG-формат.
canvas.toDataURL('image/png');
Открыв файл в новом окне, можно заметить, что изображение описывается прямо в адресной строке закодированное в системе Base64.



Для работы с Base64 в JavaScript имеются методы .atob(); и .btoa(); Для декодирования строки Base64 в бинарные данные представленные в UTF-8 мы будем использовать .atob();
var utf8 = atob(canvas.toDataURL('image/png').split(',')[1]);
Получив бинарные данные файла, мы должны оформить их в файл. Для работы с файлами в JavaScript имеется объект Blob. Чтобы записать данные в файл, по-символьно пройдемся по строке в UTF-8 и соберем в Uint8Array. В итоге получим вот такой метод:
function base64toblob (base64)
{
  var utf8 = atob(base64),
  array = [];
  //---
  for(var i = 0, j = utf8.length; i < j; i++)
    array.push(utf8.charCodeAt(i));
  //---
  return(new Blob([new Uint8Array(array)], {type: 'image/png'}));
}
Сохранение файла

Теперь о том, как сохранить файл на локальный диск пользователя. Мы воспользуемся готовым решением от Eli Grey, за которое ему огромное спасибо. Речь идет о реализации заявленного FileSaver для большинства современных браузеров. Итак, скачиваем FileSaver.js и подключаем к нашей странице. Скрипт распространяется с лицензией X11/MIT.
<script type="text/javascript" src="filesaver.js"></script>
Нам необходимо только вызвать единственный метод saveAs(); в который передаем ссылку на файл и его название:
saveAs(base64toblob(canvas.toDataURL('image/png').split(',')[1]), 'image_from_camera.png');
Готовый пример и исходный код под катом.
Пример

Video from camera: Picture preview:

Исходный код: camera.zip (5 кб)

Смотрите также:

1 комментарий:

  1. Привет! А подскажите как на web-страничке можно отобразить медиаданные, которые передает IP камера с известного нам url? По этому url, например, в VLC можно посмотреть rtsp поток.

    ОтветитьУдалить

Можно использовать некоторые HTML-теги, например <b>, <i>, <a>

Поиск по блогу

Обо мне



Farid Shamsutdinov (AS3Coder)
Russia, Tatarstan, Kazan
as3coder@gmail.com

Подробнее...

Постоянные читатели

© 2014 Farid Shamsutdinov. При копировании материалов, ссылка на источник обязательна. Технологии Blogger.