How to get only 1 image from a video javascript - javascript

This code creates several images of a video, however I would like it to generate only one image, I know it is in looping, but if I remove it from the looping it generates a single image infinitely
I need to get only one image, just a single one, when I tried to do this it repeat itself infinitely until the browser tab crashesAs you can see when running the snippet it generates several images, I need to generate only one of a specific time.
var i = 0;
var video = document.createElement("video");
var thumbs = document.getElementById("thumbs");
video.addEventListener('loadeddata', function() {
thumbs.innerHTML = "";
video.currentTime = i;
}, false);
video.addEventListener('seeked', function() {
generateThumbnail(i);
i++;
if (i <= video.duration) {
video.currentTime = i;
}
else {
alert("done!")
}
}, false);
video.preload = "auto";
video.src = "http://blogger.com/video-play.mp4?contentId=6ffdd7d2229f9172";
function generateThumbnail() {
var c = document.createElement("canvas");
var ctx = c.getContext("2d");
c.width = 160;
c.height = 90;
ctx.drawImage(video, 0, 0, 160, 90);
thumbs.appendChild(c);
}
#video {width:320px}
<div id=thumbs>Loading video in background...</div>

Remove this:
i++;
if (i <= video.duration) {
video.currentTime = i;
}
else {
alert("done!")
}
And replace var i with another var like var time then you will get the frame of a specific second, like var time = 6
var time = 6;
var video = document.createElement("video");
var thumbs = document.getElementById("thumbs");
video.addEventListener('loadeddata', function() {
thumbs.innerHTML = "";
video.currentTime = time;
}, false);
video.addEventListener('seeked', function() {
generateThumbnail(time);
}, false);
video.preload = "auto";
video.src = "http://blogger.com/video-play.mp4?contentId=6ffdd7d2229f9172";
function generateThumbnail() {
var c = document.createElement("canvas");
var ctx = c.getContext("2d");
c.width = 160;
c.height = 90;
ctx.drawImage(video, 0, 0, 160, 90);
thumbs.appendChild(c);
}
#video {width:320px}
<div id=thumbs>Loading video in background...</div>

Related

how can i put base64 image file into opencv? (javascript)

I'm trying to get random image from input video file, and then put the image into opencv to get grayScale image on the webpage.
Getting random image from video is solved by below-solution.
Javascript how to extract frame from video?
but now i'm stuck to the problem, Is it impossible to give base 64 source image file into opencv(imread, imshow, cv.cvtColor)? Please help me.
'''
//const cv = require("./js/opencv");
var video = document.createElement("video");
var image = new Image();
var canvas = document.getElementById("prevImgCanvas");
var canvas_after = document.getElementById("canvas_after");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
video.addEventListener('loadeddata', function() {
reloadRandomFrame();
}, false);
video.addEventListener('seeked', function() {
var context = canvas.getContext('2d');
context.drawImage(video, 0, 0, canvas.width, canvas.height);
const dataurl = canvas.toDataURL("image/jpeg")
image.src = dataurl;
image.onload = function(){
console.log(image);
let mat = cv.imread(image);
cv.imshow('canvasOutput', mat);
mat.delete();
};
}, false);
var playSelectedFile = function(event) {
var file = this.files[0];
var fileURL = URL.createObjectURL(file);
video.src = fileURL;
}
var input = document.getElementById('fileinput');
input.addEventListener('change', playSelectedFile, false);
function reloadRandomFrame() {
if (!isNaN(video.duration)) {
var rand = Math.round(Math.random() * video.duration * 1000) + 1;
video.currentTime = rand / 1000;
}
}
'''
let image = new Image()
image.src = 'your base64'
await new Promise(r => {
image.onload = r
})
cv.imread(image)

Image concatenation script

everyone. I'm trying to write a script that would render images from file inputs on a canvas in a row.
First I cycle through images to calculate the canvas width (because the canvas is wiped on resizing). Then cycle again to render the images.
canvas.width = 0;
let x = 0,
y = 0,
totalWidth = 0;
for (let i = 0; i < document.querySelectorAll(".has-file").length; i++) {
let input = document.querySelectorAll(".has-file")[i];
let image = input.files[0];
let img = new Image();
console.log(img);
img.src = window.URL.createObjectURL(image);
img.addEventListener('load', () => {
console.log(img);
let newWidth = img.width * canvas.height / img.height;
totalWidth += newWidth;
canvas.width = totalWidth;
}, false);
};
for (let i = 0; i < document.querySelectorAll(".has-file").length; i++) {
let input = document.querySelectorAll(".has-file")[i];
let image = input.files[0];
let img = new Image();
img.src = window.URL.createObjectURL(image);
img.addEventListener('load', () => {
let newWidth = img.width * canvas.height / img.height;
ctx.drawImage(img, x, y, newWidth, canvas.height);
x += newWidth;
}, false);
};
}
The app behaves weird, the images are not always rendered, and when they do, not always where they supposed to be.
First problem with the code is that you're loading images twice, and the randomness is due to the fact that image loading can be ambiguous. Check out this jsfiddle. I have used text input instead of files, drawing takes place when it is the last image otherwise resizing the canvas can cause canvas to reset, losing the previous draw.
var canvas = document.getElementById("canvas");
const ctx = canvas.getContext('2d', {
antialias: false,
depth: false
});
canvas.width = 0;
let x = 0,
y = 0,
totalWidth = 0;
let obj = [];
let k = 0;
for (let i = 0; i < document.querySelectorAll(".has-file").length; i++) {
let input = document.querySelectorAll(".has-file")[i];
let image = input.value;
let img = new Image();
img.src = image;//window.URL.createObjectURL(image);
img.addEventListener('load', () => {
console.log(img);
let newWidth = img.width * canvas.height / img.height;
totalWidth += newWidth;
canvas.width = totalWidth;
obj.push({img: img, x: x, y: y, newWidth: newWidth, height: canvas.height});
k++;
x += newWidth;
if (k == document.querySelectorAll(".has-file").length )
draw();
}, false);
};
function draw() {
for (var i = 0; i < obj.length; i++) {
ctx.drawImage(obj[i].img, obj[i].x, obj[i].y, obj[i].newWidth, obj[i].height);
}
}
<input style="display: none;" class="has-file" value="https://i.imgur.com/I86rTVl.jpg" />
<input style="display: none;" class="has-file" value="https://images.unsplash.com/photo-1446292267125-fecb4ecbf1a5?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80" />
<canvas id="canvas"></canvas>

Drawing image on canvas in loop not working

var canvas = document.getElementById("canvas");
wheel = canvas.getContext("2d");
for (var i = 0; i < 10; i++) {
var img = new Image;
img.src = image;
wheel.drawImage(img, -170, -10, 140, 140);
}
My above code draw only 9(Nine) images but lastOne(10th) image not drawing on canvas. I tried above code but not getting success. Anyone can know solution for this problem.
Can any one help me to find out online JSFiddle Demo which draw image on canvas in loop.
Perhaps your image isn't finished loading before your first draw attempt.
Here is the syntax to make sure your image has finished loading:
var canvas = document.body.appendChild(document.createElement("canvas"));
canvas.width = 1100;
canvas.height = 110;
var wheel = canvas.getContext("2d");
var img = document.createElement("img");
img.onload = function() {
for (var i = 0; i < 10; i++) {
wheel.drawImage(img, 5 + 110 * i, 5);
}
};
img.src = "https://placeholdit.imgix.net/~text?txtsize=60&txt=1&w=100&h=100";
EDIT 1 - PROMISES
Working with multiple images:
List sources
map to generates DOM nodes
Setup a Promise per DOM node in a Promise.all
Then draw images
var canvas = document.body.appendChild(document.createElement("canvas"));
canvas.width = 1100;
canvas.height = 110;
var wheel = canvas.getContext("2d");
var images = [
"https://placeholdit.imgix.net/~text?txtsize=60&txt=1&w=100&h=100",
"https://placeholdit.imgix.net/~text?txtsize=60&txt=2&w=100&h=100",
"https://placeholdit.imgix.net/~text?txtsize=60&txt=3&w=100&h=100",
"https://placeholdit.imgix.net/~text?txtsize=60&txt=4&w=100&h=100",
"https://placeholdit.imgix.net/~text?txtsize=60&txt=5&w=100&h=100",
"https://placeholdit.imgix.net/~text?txtsize=60&txt=6&w=100&h=100",
"https://placeholdit.imgix.net/~text?txtsize=60&txt=7&w=100&h=100",
"https://placeholdit.imgix.net/~text?txtsize=60&txt=8&w=100&h=100",
"https://placeholdit.imgix.net/~text?txtsize=60&txt=9&w=100&h=100",
"https://placeholdit.imgix.net/~text?txtsize=60&txt=10&w=100&h=100",
]
.map(function(i) {
var img = document.createElement("img");
img.src = i;
return img;
});
Promise.all(images.map(function(image) {
return new Promise(function(resolve, reject) {
image.onload = resolve;
});
}))
.then(function() {
for (var i = 0; i < images.length; i++) {
var img = images[i];
wheel.drawImage(img, 5 + 110 * i, 5);
}
});
I would do the similar approach to Emil, only difference having a method that loads them individually and once the image is loaded, try to load the next one and so on ...
take a look:
var canvas = document.getElementById("canvas");
// setting canvas size
canvas.height = window.innerHeight - 10;
canvas.width = window.innerWidth - 10;
var image_test = document.querySelector(".hidden");
var count = 0;
var total_images = 10;
var wheel = canvas.getContext("2d");
function loadImage() {
var img = new Image();
img.onload = function() {
wheel.drawImage( this , 105 * count , 0 , 100, 100);
if( count < total_images ) {
count++;
loadImage();
}
}
// img.src = "image-" + count + ".jpg";
img.src = "https://placeholdit.imgix.net/~text?txtsize=60&txt=1&w=100&h=100";
}
loadImage();
https://jsfiddle.net/gugalondon/r5xw6u7L/7

Get back video format after <canvas>

Is there way to get the video from webcamera (getUserMedia), pass it to canvas, make some effects with this video and get back in video format (mp4 for example)?
I'm looking for a way to be done on client side only. And also it should be a real time process.
Yes you can, in modern browsers, but you'll loose every audio stream (Actually you can save it too), and I think that the mp4 requirement is not here yet and you should not wait for it (damn royalties) only webm or ogv export is currently available.
You can use a MediaRecorder and the canvas.captureStream() method.
var mediaRecorder = new MediaRecorder(canvas.captureStream(30));
Here is an example code (which will only work on latests FF and chrome !).
var startRecording = function(){
// make something happen on the canvas
var stopCanvas = initCanvasDrawing();
// really, that's it..
var recorder = new MediaRecorder(canvas.captureStream(30))
var chunks = [];
recorder.ondataavailable = function(e){
if(e.data.size){
chunks.push(e.data)
}
};
recorder.onstop = function(){
var blob = new Blob(chunks);
var url = URL.createObjectURL(blob);
unrelatedDOMStuff(url);
stopCanvas();
};
recorder.start();
setTimeout(function(){recorder.stop()}, 5000);
}
// the rest of the code is just for the demo
var unrelatedDOMStuff = function(url){
rec.style.display = canvas.style.display = 'none';
var vid = document.createElement('video');
vid.src = url
vid.controls = true;
document.body.appendChild(vid);
vid.play();
var a = document.createElement('a');
a.innerHTML = 'you can also get it here';
a.download = 'awesomeCanvasVid.webm';
a.href = url;
document.body.appendChild(a);
}
var initCanvasDrawing = function() {
var ctx = canvas.getContext('2d');
var objects = [];
ctx.fillStyle = 'ivory';
// taken from https://stackoverflow.com/a/23486828/3702797
for (var i = 0; i < 100; i++) {
objects.push({
angle: Math.random() * 360,
x: 100 + (Math.random() * canvas.width / 2),
y: 100 + (Math.random() * canvas.height / 2),
radius: 10 + (Math.random() * 40),
speed: 1 + Math.random() * 20
});
}
var stop = false;
var draw = function() {
ctx.fillRect(0, 0, canvas.width, canvas.height);
for (var n = 0; n < 100; n++) {
var entity = objects[n],
velY = Math.cos(entity.angle * Math.PI / 180) * entity.speed,
velX = Math.sin(entity.angle * Math.PI / 180) * entity.speed;
entity.x += velX;
entity.y -= velY;
ctx.drawImage(img, entity.x, entity.y, entity.radius, entity.radius);
entity.angle++;
}
if (!stop) {
requestAnimationFrame(draw);
}
}
var img = new Image();
img.onload = draw;
img.crossOrigin = 'anonymous';
img.src = "https://dl.dropboxusercontent.com/s/4e90e48s5vtmfbd/aaa.png";
return function() {
stop = true;
};
}
startRecording();
#rec{ width:2em; height:2em; border-radius:50%; background-color:red; position: absolute; top: 0; left: 0;}
a{display: block;}
video{border:1px solid green;}
<canvas id="canvas" width="500" height="250"></canvas>
<div id="rec"></div>
Note that since webm video format doesn't support transparency, every transparent pixels will be set to opaque black.

use window.URL.createObjectURL(stream) multible times

I have a SPA build with AngularJS.
ater Login i save the Streaming Object in a global variable for Future use (so i have to set the permission just once)
I use this StreamingObject at two userstories (for now)
Story one:
change profile image
Story two make a selfie and post it.
Everything works fine until i switch from Story one to Story Two.
This breaks the Stream.
I wrote this directive.
angular.module('myApp')
.controller('webcamCtrl', function ($scope, globVal) {
var width = 373;
var height = 0;
var streaming = false;
var video = null;
var canvas = null;
$scope.showPicture = false;
$scope.startup = function() {
video = document.getElementById('video');
canvas = document.getElementById('canvas');
$scope.$watch(function () {
return globVal.webcam;
}, function() {
if(globVal.webcam !== null){
video.src = globVal.webcam;
video.play();
}
});
video.addEventListener('canplay', function () {
if (!streaming) {
height = video.videoHeight / (video.videoWidth / width);
if (isNaN(height)) {
height = width / (4 / 3);
}
video.setAttribute('width', width);
video.setAttribute('height', height);
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);
streaming = true;
}
}, false);
$scope.clearphoto();
};
$scope.clearphoto = function() {
var context = canvas.getContext('2d');
context.fillStyle = '#AAA';
context.fillRect(0, 0, canvas.width, canvas.height);
$scope.showPicture = false;
globVal.image = null;
};
$scope.takepicture = function() {
var context = canvas.getContext('2d');
if(!$scope.showPicture){
if (width && height) {
canvas.width = width;
canvas.height = height;
context.drawImage(video, 0, 0, width, height);
$scope.showPicture = true;
$scope.acceptpicture();
} else {
$scope.clearphoto();
}
}else {
$scope.clearphoto();
}
};
$scope.acceptpicture = function() {
if($scope.showPicture){
var data = canvas.toDataURL('image/png');
globVal.image = data;
}else{
globVal.image = null;
}
};
$scope.startup();
});
any hints?
Solved. i add a ng-if to my directive so the $scope of teh webcam can destroyed safely
<web-cam ng-if="showCam"></web-cam

Categories

Resources