mirror of
https://github.com/ychalier/datamoshing.git
synced 2026-06-16 12:31:19 +02:00
update readme and repo structure
This commit is contained in:
@@ -18,3 +18,7 @@ Here are some videos made using those scripts (click on the thumbnails to see th
|
||||
Drop h264 I-Frames | Optical Flow Transfer
|
||||
------------------ | ---------------------
|
||||
[](https://i.imgur.com/bOHT26q.mp4) | [](https://i.imgur.com/pt6Sq7A.mp4)
|
||||
|
||||
## Demo
|
||||
|
||||
Here is a [web demonstration](https://ychalier.github.io/datamoshing/optical-flow-transfer/www/) where you may try different video sources (such as the webcam) and image sources to perform optical flow transfer.
|
||||
@@ -36,3 +36,7 @@ python optical_flow_transfer.py <source-video> <source-image> <output-video>
|
||||
[](https://i.imgur.com/pt6Sq7A.mp4)
|
||||
|
||||
I wrote some details [on my blog](https://chalier.fr/blog/datamoshing#opticalflowtransfer).
|
||||
|
||||
## Demo
|
||||
|
||||
Here is a [web demonstration](www/) where you may try different video sources (such as the webcam) and image sources to perform optical flow transfer.
|
||||
@@ -1,106 +1,106 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Optical Flow Transfer</title>
|
||||
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/ychalier/pifekit/pifekit.min.css" />
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/ychalier/pifekit/pifekit.min.js"></script>
|
||||
<script src="opencv.js"></script>
|
||||
<script src="master.js"></script>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
|
||||
<body class="dark-blue">
|
||||
<div class="container text-center">
|
||||
<h1>Optical Flow Transfer</h1>
|
||||
|
||||
<div class="xcolumns">
|
||||
|
||||
<div class="xcolumn-left">
|
||||
<div class="media-container" id="container-video">
|
||||
<button class="btn btn-primary" onclick="showModal('modal-load-video')" id="button-video-modal">Load video</button>
|
||||
</div>
|
||||
<div style="height: .4em"></div>
|
||||
<div class="media-container" id="container-image">
|
||||
<button class="btn btn-primary" onclick="showModal('modal-load-image')" id="button-image-modal">Load image</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="xcolumn-right">
|
||||
<div id="container-canvas" rowspan="2">
|
||||
<canvas id="canvas" width="256" height="256"></canvas>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<button class="btn" id="button-reset" disabled>Reset</button>
|
||||
<button class="btn" id="button-download" disabled>Download</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<footer class="text-center">
|
||||
<p>
|
||||
More details on my <a href="https://chalier.fr/blog/datamoshing">blog</a> · Images from <a href="https://picsum.photos/">Lorem Picsum</a>
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<div class="modal" id="modal-load-video">
|
||||
<span class="modal-overlay" onclick="closeModal('modal-load-video')"></span>
|
||||
<div class="modal-container">
|
||||
<div class="modal-header">
|
||||
<div class="modal-title h5">Load video</div>
|
||||
<div class="modal-subtitle text-gray">Load a video from a URL, a local file, or your webcam</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group pb-2">
|
||||
<label class="form-label" for="input-video-url">URL</label>
|
||||
<input class="form-input" type="url" id="input-video-url" placeholder="https://example.org/axis-cgi/mjpg/video.cgi" />
|
||||
</div>
|
||||
<div class="divider text-center" data-content="OR"></div>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="input-video-file">File</label>
|
||||
<input class="form-input" type="file" id="input-video-file" accept="video/*" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-primary" id="button-video-webcam">Webcam</button>
|
||||
<button class="btn btn-primary" id="button-video-load">Load</button>
|
||||
<button class="btn" onclick="closeModal('modal-load-video')">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal" id="modal-load-image">
|
||||
<span class="modal-overlay" onclick="closeModal('modal-load-image')"></span>
|
||||
<div class="modal-container">
|
||||
<div class="modal-header">
|
||||
<div class="modal-title h5">Load image</div>
|
||||
<div class="modal-subtitle text-gray">Load an image from a URL or a local file</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group pb-2">
|
||||
<label class="form-label" for="input-image-url">URL</label>
|
||||
<input class="form-input" type="url" id="input-image-url" placeholder="https://example.org/image.jpg" />
|
||||
</div>
|
||||
<div class="divider text-center" data-content="OR"></div>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="input-image-file">File</label>
|
||||
<input class="form-input" type="file" id="input-image-file" accept="image/*" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-primary" id="button-image-random">Random</button>
|
||||
<button class="btn btn-primary" id="button-image-load">Load</button>
|
||||
<button class="btn" onclick="closeModal('modal-load-image')">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Optical Flow Transfer</title>
|
||||
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/ychalier/pifekit/pifekit.min.css" />
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/ychalier/pifekit/pifekit.min.js"></script>
|
||||
<script src="opencv.js"></script>
|
||||
<script src="master.js"></script>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
|
||||
<body class="dark-blue">
|
||||
<div class="container text-center">
|
||||
<h1>Optical Flow Transfer</h1>
|
||||
|
||||
<div class="xcolumns">
|
||||
|
||||
<div class="xcolumn-left">
|
||||
<div class="media-container" id="container-video">
|
||||
<button class="btn btn-primary" onclick="showModal('modal-load-video')" id="button-video-modal">Load video</button>
|
||||
</div>
|
||||
<div style="height: .4em"></div>
|
||||
<div class="media-container" id="container-image">
|
||||
<button class="btn btn-primary" onclick="showModal('modal-load-image')" id="button-image-modal">Load image</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="xcolumn-right">
|
||||
<div id="container-canvas" rowspan="2">
|
||||
<canvas id="canvas" width="256" height="256"></canvas>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<button class="btn" id="button-reset" disabled>Reset</button>
|
||||
<button class="btn" id="button-download" disabled>Download</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<footer class="text-center">
|
||||
<p>
|
||||
More details on my <a href="https://chalier.fr/blog/datamoshing">blog</a> · Images from <a href="https://picsum.photos/">Lorem Picsum</a>
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<div class="modal" id="modal-load-video">
|
||||
<span class="modal-overlay" onclick="closeModal('modal-load-video')"></span>
|
||||
<div class="modal-container">
|
||||
<div class="modal-header">
|
||||
<div class="modal-title h5">Load video</div>
|
||||
<div class="modal-subtitle text-gray">Load a video from a URL, a local file, or your webcam</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group pb-2">
|
||||
<label class="form-label" for="input-video-url">URL</label>
|
||||
<input class="form-input" type="url" id="input-video-url" placeholder="https://example.org/axis-cgi/mjpg/video.cgi" />
|
||||
</div>
|
||||
<div class="divider text-center" data-content="OR"></div>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="input-video-file">File</label>
|
||||
<input class="form-input" type="file" id="input-video-file" accept="video/*" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-primary" id="button-video-webcam">Webcam</button>
|
||||
<button class="btn btn-primary" id="button-video-load">Load</button>
|
||||
<button class="btn" onclick="closeModal('modal-load-video')">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal" id="modal-load-image">
|
||||
<span class="modal-overlay" onclick="closeModal('modal-load-image')"></span>
|
||||
<div class="modal-container">
|
||||
<div class="modal-header">
|
||||
<div class="modal-title h5">Load image</div>
|
||||
<div class="modal-subtitle text-gray">Load an image from a URL or a local file</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group pb-2">
|
||||
<label class="form-label" for="input-image-url">URL</label>
|
||||
<input class="form-input" type="url" id="input-image-url" placeholder="https://example.org/image.jpg" />
|
||||
</div>
|
||||
<div class="divider text-center" data-content="OR"></div>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="input-image-file">File</label>
|
||||
<input class="form-input" type="file" id="input-image-file" accept="image/*" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-primary" id="button-image-random">Random</button>
|
||||
<button class="btn btn-primary" id="button-image-load">Load</button>
|
||||
<button class="btn" onclick="closeModal('modal-load-image')">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,198 +1,198 @@
|
||||
navigator.getMedia = (navigator.getUserMedia ||
|
||||
navigator.webkitGetUserMedia ||
|
||||
navigator.mozGetUserMedia ||
|
||||
navigator.msGetUserMedia);
|
||||
|
||||
async function load_effect() {
|
||||
|
||||
var video_loaded = false;
|
||||
var image_loaded = false;
|
||||
|
||||
const size = 256;
|
||||
const width = size;
|
||||
const height = size;
|
||||
|
||||
const video_container = document.getElementById("container-video");
|
||||
const video = document.createElement("video");
|
||||
video.muted = true;
|
||||
video.loop = true;
|
||||
video.style.objectFit = "cover";
|
||||
video.setAttribute("width", size);
|
||||
video.setAttribute("height", size);
|
||||
video.addEventListener("canplay", () => {
|
||||
if (!video_loaded) {
|
||||
console.log("Video is loaded");
|
||||
video_container.innerHTML = "";
|
||||
video_container.appendChild(video);
|
||||
if (image_loaded) start_effect();
|
||||
}
|
||||
video_loaded = true;
|
||||
}, false);
|
||||
|
||||
const image_container = document.getElementById("container-image");
|
||||
const image = new Image();
|
||||
const image_canvas = document.createElement("canvas");
|
||||
image_canvas.width = width;
|
||||
image_canvas.height = height;
|
||||
const image_canvas_context = image_canvas.getContext("2d");
|
||||
image.crossOrigin = "anonymous";
|
||||
image.addEventListener("load", () => {
|
||||
if (!image_loaded) {
|
||||
console.log("Image is loaded");
|
||||
image_container.innerHTML = "";
|
||||
image_container.appendChild(image_canvas);
|
||||
const target_ratio = width / height;
|
||||
const current_ratio = image.width / image.height;
|
||||
var cropped_width = image.width;
|
||||
var cropped_height = image.height;
|
||||
if (target_ratio > current_ratio) {
|
||||
// Crop vertically
|
||||
cropped_height = cropped_width / target_ratio;
|
||||
} else if (target_ratio < current_ratio) {
|
||||
// Crop horizontaly
|
||||
cropped_width = target_ratio * cropped_height;
|
||||
}
|
||||
image_canvas_context.drawImage(image, (image.width - cropped_width) / 2, (image.height - cropped_height) / 2, cropped_width, cropped_height, 0, 0, width, height);
|
||||
context.drawImage(image, (image.width - cropped_width) / 2, (image.height - cropped_height) / 2, cropped_width, cropped_height, 0, 0, width, height);
|
||||
if (video_loaded) start_effect();
|
||||
}
|
||||
image_loaded = true;
|
||||
}, false);
|
||||
|
||||
const canvas = document.getElementById("canvas");
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
const context = canvas.getContext("2d");
|
||||
var image_data;
|
||||
var cap;
|
||||
|
||||
async function start_effect() {
|
||||
console.log("Both media loaded, starting the effect");
|
||||
|
||||
document.getElementById("button-reset").removeAttribute("disabled");
|
||||
document.getElementById("button-download").removeAttribute("disabled");
|
||||
|
||||
function takepicture() {
|
||||
let frame = new cv.Mat(height, width, cv.CV_8UC4);
|
||||
let frame_gray = new cv.Mat();
|
||||
cap.read(frame);
|
||||
cv.cvtColor(frame, frame_gray, cv.COLOR_RGBA2GRAY);
|
||||
return frame_gray;
|
||||
}
|
||||
|
||||
cap = new cv.VideoCapture(video);
|
||||
let reference = takepicture();
|
||||
image_data = context.getImageData(0, 0, width, height);
|
||||
while (true) {
|
||||
let current = takepicture();
|
||||
let flow = new cv.Mat();
|
||||
cv.calcOpticalFlowFarneback(reference, current, flow, 0.5, 3, 15, 3, 5, 1.2, 0);
|
||||
let image_data_copy = [...image_data.data];
|
||||
for (let i = 0; i < height; i++) {
|
||||
for (let j = 0; j < width; j++) {
|
||||
let k = (i * width + j);
|
||||
let ii = i + Math.round(flow.data32F[k * 2]);
|
||||
let jj = j + Math.round(flow.data32F[k * 2 + 1]);
|
||||
image_data.data[(ii * width + jj) * 4] = image_data_copy[(i * width + j) * 4];
|
||||
image_data.data[(ii * width + jj) * 4 + 1] = image_data_copy[(i * width + j) * 4 + 1];
|
||||
image_data.data[(ii * width + jj) * 4 + 2] = image_data_copy[(i * width + j) * 4 + 2];
|
||||
image_data.data[(ii * width + jj) * 4 + 3] = image_data_copy[(i * width + j) * 4 + 3];
|
||||
}
|
||||
}
|
||||
context.putImageData(image_data, 0, 0);
|
||||
await new Promise(x => requestAnimationFrame(x));
|
||||
current.copyTo(reference);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async function load_video_webcam() {
|
||||
console.log("Loading video from the webcam");
|
||||
navigator.getMedia({ video: true, audio: false }, (stream) => {
|
||||
if (navigator.mozGetUserMedia) {
|
||||
video.srcObject = stream;
|
||||
} else {
|
||||
video.src = vendorURL.createObjectURL(stream);
|
||||
}
|
||||
video.play();
|
||||
}, (err) => {
|
||||
alert(err);
|
||||
console.error(err);
|
||||
document.getElementById("button-video-modal").disabled = false;
|
||||
});
|
||||
while (!video_loaded) { await new Promise(resolve => setTimeout(resolve, 10)); }
|
||||
}
|
||||
|
||||
async function load_video_url(video_url) {
|
||||
console.log("Loading video from a URL:", video_url);
|
||||
video.src = video_url;
|
||||
video.play();
|
||||
}
|
||||
|
||||
async function load_video_file(video_file) {
|
||||
console.log("Loading video from a file:", video_file);
|
||||
video.src = URL.createObjectURL(video_file);
|
||||
video.play();
|
||||
}
|
||||
|
||||
document.getElementById("button-video-webcam").addEventListener("click", () => {
|
||||
document.getElementById("button-video-modal").disabled = true;
|
||||
closeModal("modal-load-video");
|
||||
load_video_webcam();
|
||||
});
|
||||
|
||||
document.getElementById("button-video-load").addEventListener("click", () => {
|
||||
let video_url = document.getElementById("input-video-url").value;
|
||||
let video_files = document.getElementById("input-video-file").files;
|
||||
if (video_url != "") {
|
||||
load_video_url(video_url);
|
||||
} else if (video_files.length > 0) {
|
||||
load_video_file(video_files[0]);
|
||||
} else {
|
||||
alert("Please specify one source!");
|
||||
return;
|
||||
}
|
||||
document.getElementById("button-video-modal").disabled = true;
|
||||
closeModal("modal-load-video");
|
||||
});
|
||||
|
||||
document.getElementById("button-image-random").addEventListener("click", () => {
|
||||
console.log("Loading random image");
|
||||
image.src = `https://picsum.photos/${ width }/${ height }`;
|
||||
if (document.getElementById("button-image-modal")) {
|
||||
document.getElementById("button-image-modal").disabled = true;
|
||||
}
|
||||
closeModal("modal-load-image");
|
||||
});
|
||||
|
||||
document.getElementById("button-image-load").addEventListener("click", () => {
|
||||
let image_url = document.getElementById("input-image-url").value;
|
||||
let image_files = document.getElementById("input-image-file").files;
|
||||
if (image_url != "") {
|
||||
console.log("Loading image from a URL:", image_url);
|
||||
image.src = image_url;
|
||||
} else if (image_files.length > 0) {
|
||||
console.log("Loading image from a file:", image_files[0]);
|
||||
image.src = URL.createObjectURL(image_files[0]);
|
||||
} else {
|
||||
alert("Please specify one source!");
|
||||
return;
|
||||
}
|
||||
document.getElementById("button-image-modal").disabled = true;
|
||||
closeModal("modal-load-image");
|
||||
});
|
||||
|
||||
document.getElementById("button-reset").addEventListener("click", () => {
|
||||
image_data = image_canvas_context.getImageData(0, 0, width, height);
|
||||
});
|
||||
|
||||
document.getElementById("button-download").addEventListener("click", () => {
|
||||
const link = document.createElement("a");
|
||||
link.download = `${ Date.now() }.png`;
|
||||
link.href = canvas.toDataURL();
|
||||
link.click();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
window.addEventListener("load", load_effect);
|
||||
navigator.getMedia = (navigator.getUserMedia ||
|
||||
navigator.webkitGetUserMedia ||
|
||||
navigator.mozGetUserMedia ||
|
||||
navigator.msGetUserMedia);
|
||||
|
||||
async function load_effect() {
|
||||
|
||||
var video_loaded = false;
|
||||
var image_loaded = false;
|
||||
|
||||
const size = 256;
|
||||
const width = size;
|
||||
const height = size;
|
||||
|
||||
const video_container = document.getElementById("container-video");
|
||||
const video = document.createElement("video");
|
||||
video.muted = true;
|
||||
video.loop = true;
|
||||
video.style.objectFit = "cover";
|
||||
video.setAttribute("width", size);
|
||||
video.setAttribute("height", size);
|
||||
video.addEventListener("canplay", () => {
|
||||
if (!video_loaded) {
|
||||
console.log("Video is loaded");
|
||||
video_container.innerHTML = "";
|
||||
video_container.appendChild(video);
|
||||
if (image_loaded) start_effect();
|
||||
}
|
||||
video_loaded = true;
|
||||
}, false);
|
||||
|
||||
const image_container = document.getElementById("container-image");
|
||||
const image = new Image();
|
||||
const image_canvas = document.createElement("canvas");
|
||||
image_canvas.width = width;
|
||||
image_canvas.height = height;
|
||||
const image_canvas_context = image_canvas.getContext("2d");
|
||||
image.crossOrigin = "anonymous";
|
||||
image.addEventListener("load", () => {
|
||||
if (!image_loaded) {
|
||||
console.log("Image is loaded");
|
||||
image_container.innerHTML = "";
|
||||
image_container.appendChild(image_canvas);
|
||||
const target_ratio = width / height;
|
||||
const current_ratio = image.width / image.height;
|
||||
var cropped_width = image.width;
|
||||
var cropped_height = image.height;
|
||||
if (target_ratio > current_ratio) {
|
||||
// Crop vertically
|
||||
cropped_height = cropped_width / target_ratio;
|
||||
} else if (target_ratio < current_ratio) {
|
||||
// Crop horizontaly
|
||||
cropped_width = target_ratio * cropped_height;
|
||||
}
|
||||
image_canvas_context.drawImage(image, (image.width - cropped_width) / 2, (image.height - cropped_height) / 2, cropped_width, cropped_height, 0, 0, width, height);
|
||||
context.drawImage(image, (image.width - cropped_width) / 2, (image.height - cropped_height) / 2, cropped_width, cropped_height, 0, 0, width, height);
|
||||
if (video_loaded) start_effect();
|
||||
}
|
||||
image_loaded = true;
|
||||
}, false);
|
||||
|
||||
const canvas = document.getElementById("canvas");
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
const context = canvas.getContext("2d");
|
||||
var image_data;
|
||||
var cap;
|
||||
|
||||
async function start_effect() {
|
||||
console.log("Both media loaded, starting the effect");
|
||||
|
||||
document.getElementById("button-reset").removeAttribute("disabled");
|
||||
document.getElementById("button-download").removeAttribute("disabled");
|
||||
|
||||
function takepicture() {
|
||||
let frame = new cv.Mat(height, width, cv.CV_8UC4);
|
||||
let frame_gray = new cv.Mat();
|
||||
cap.read(frame);
|
||||
cv.cvtColor(frame, frame_gray, cv.COLOR_RGBA2GRAY);
|
||||
return frame_gray;
|
||||
}
|
||||
|
||||
cap = new cv.VideoCapture(video);
|
||||
let reference = takepicture();
|
||||
image_data = context.getImageData(0, 0, width, height);
|
||||
while (true) {
|
||||
let current = takepicture();
|
||||
let flow = new cv.Mat();
|
||||
cv.calcOpticalFlowFarneback(reference, current, flow, 0.5, 3, 15, 3, 5, 1.2, 0);
|
||||
let image_data_copy = [...image_data.data];
|
||||
for (let i = 0; i < height; i++) {
|
||||
for (let j = 0; j < width; j++) {
|
||||
let k = (i * width + j);
|
||||
let ii = i + Math.round(flow.data32F[k * 2]);
|
||||
let jj = j + Math.round(flow.data32F[k * 2 + 1]);
|
||||
image_data.data[(ii * width + jj) * 4] = image_data_copy[(i * width + j) * 4];
|
||||
image_data.data[(ii * width + jj) * 4 + 1] = image_data_copy[(i * width + j) * 4 + 1];
|
||||
image_data.data[(ii * width + jj) * 4 + 2] = image_data_copy[(i * width + j) * 4 + 2];
|
||||
image_data.data[(ii * width + jj) * 4 + 3] = image_data_copy[(i * width + j) * 4 + 3];
|
||||
}
|
||||
}
|
||||
context.putImageData(image_data, 0, 0);
|
||||
await new Promise(x => requestAnimationFrame(x));
|
||||
current.copyTo(reference);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async function load_video_webcam() {
|
||||
console.log("Loading video from the webcam");
|
||||
navigator.getMedia({ video: true, audio: false }, (stream) => {
|
||||
if (navigator.mozGetUserMedia) {
|
||||
video.srcObject = stream;
|
||||
} else {
|
||||
video.src = vendorURL.createObjectURL(stream);
|
||||
}
|
||||
video.play();
|
||||
}, (err) => {
|
||||
alert(err);
|
||||
console.error(err);
|
||||
document.getElementById("button-video-modal").disabled = false;
|
||||
});
|
||||
while (!video_loaded) { await new Promise(resolve => setTimeout(resolve, 10)); }
|
||||
}
|
||||
|
||||
async function load_video_url(video_url) {
|
||||
console.log("Loading video from a URL:", video_url);
|
||||
video.src = video_url;
|
||||
video.play();
|
||||
}
|
||||
|
||||
async function load_video_file(video_file) {
|
||||
console.log("Loading video from a file:", video_file);
|
||||
video.src = URL.createObjectURL(video_file);
|
||||
video.play();
|
||||
}
|
||||
|
||||
document.getElementById("button-video-webcam").addEventListener("click", () => {
|
||||
document.getElementById("button-video-modal").disabled = true;
|
||||
closeModal("modal-load-video");
|
||||
load_video_webcam();
|
||||
});
|
||||
|
||||
document.getElementById("button-video-load").addEventListener("click", () => {
|
||||
let video_url = document.getElementById("input-video-url").value;
|
||||
let video_files = document.getElementById("input-video-file").files;
|
||||
if (video_url != "") {
|
||||
load_video_url(video_url);
|
||||
} else if (video_files.length > 0) {
|
||||
load_video_file(video_files[0]);
|
||||
} else {
|
||||
alert("Please specify one source!");
|
||||
return;
|
||||
}
|
||||
document.getElementById("button-video-modal").disabled = true;
|
||||
closeModal("modal-load-video");
|
||||
});
|
||||
|
||||
document.getElementById("button-image-random").addEventListener("click", () => {
|
||||
console.log("Loading random image");
|
||||
image.src = `https://picsum.photos/${ width }/${ height }`;
|
||||
if (document.getElementById("button-image-modal")) {
|
||||
document.getElementById("button-image-modal").disabled = true;
|
||||
}
|
||||
closeModal("modal-load-image");
|
||||
});
|
||||
|
||||
document.getElementById("button-image-load").addEventListener("click", () => {
|
||||
let image_url = document.getElementById("input-image-url").value;
|
||||
let image_files = document.getElementById("input-image-file").files;
|
||||
if (image_url != "") {
|
||||
console.log("Loading image from a URL:", image_url);
|
||||
image.src = image_url;
|
||||
} else if (image_files.length > 0) {
|
||||
console.log("Loading image from a file:", image_files[0]);
|
||||
image.src = URL.createObjectURL(image_files[0]);
|
||||
} else {
|
||||
alert("Please specify one source!");
|
||||
return;
|
||||
}
|
||||
document.getElementById("button-image-modal").disabled = true;
|
||||
closeModal("modal-load-image");
|
||||
});
|
||||
|
||||
document.getElementById("button-reset").addEventListener("click", () => {
|
||||
image_data = image_canvas_context.getImageData(0, 0, width, height);
|
||||
});
|
||||
|
||||
document.getElementById("button-download").addEventListener("click", () => {
|
||||
const link = document.createElement("a");
|
||||
link.download = `${ Date.now() }.png`;
|
||||
link.href = canvas.toDataURL();
|
||||
link.click();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
window.addEventListener("load", load_effect);
|
||||
Reference in New Issue
Block a user