将图像保存在 Javascript
Saving Image in Javascript
我有一个 HTML 页面,我可以从该页面获取来自设备摄像头的视频源。我用 setTimeOut 循环将它绘制到 canvas 并拍摄图片到图像。然后我对该图像应用滤镜(棕褐色、灰度...)并保存。图像在没有过滤器的情况下保存。为什么保存的不是过滤后的图像,而是 "raw" 图像?我不太擅长Javascript所以请温柔点。
<video id = "video" autoplay></video>
<button onclick = "snap()">Snap</button>
<canvas id = "canvas" width = "400" height = "300"></canvas>
<img id = "photo" src = "pic.png" alt = "Photo">
<button onclick = "save()">Save</button>
<button onclick = "sepia()">Sepia</button>//Added in edit
//--------------
var video = document.getElementById('video');
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var photo = document.getElementById('photo');
navigator.getMedia({ video: true, audio: false }, success, failure);
function success(stream) {
video.src = vendorUrl.createObjectURL(stream);
}
function failure(error) {}
video.addEventListener('play', sendToCanvas, false);
function sendToCanvas() {
draw(this, context, canvas.width, canvas.height);
}
function draw(video, context, width, height) {
context.drawImage(video, 0, 0, width, height);
setTimeout(draw, 10, video, context, width, height);
}
function snap() {
photo.setAttribute('src', canvas.toDataURL("image/png"));
}
function save() {
var currentdate = new Date().toLocaleString();
var link = document.createElement('a');
link.download = currentdate + ".png";
link.href = photo.src;
link.click();
}
function sepia() {//Added in edit
photo.style["-webkit-filter"] = "sepia(100%)";
}
您正在使用 CSS 过滤器,这些过滤器并没有真正绘制到 canvas 中,而只是页面上的装饰。
因此,canvas' 提取其内容的方法不会保留这些过滤器。
这就像如果你确实为 canvas 元素设置了背景颜色而不绘制任何东西或一些边框,一旦你使用 toDataURL
方法就不会获得这些样式,只有在 canvas' 上下文中绘制的图本身是 canvas' 内容的一部分:
var ctx = c.getContext('2d');
//only this black rectangle is drawn onto the canvas
ctx.fillRect(10,10,20,20);
expImg.src = c.toDataURL();
/* these styles are only applied on the document,
not onto the canvas itself
*/
canvas{
background-color: lightgreen;
border: 10px solid red;
}
img{
border: 1px solid green;
}
<canvas id="c"></canvas>
<img id="expImg"/>
您必须了解 canvas 就像图像一样。当您在其上应用 CSS 过滤器时,您并没有真正修改文件,而只是它在文档中的显示。
现在,您可以直接在 canvas' 像素上处理过滤器,并能够保留它们。
这是一个小例子,向您展示如何修改 canvas 像素。
var draw = function() {
c.width = img.width;
c.height = img.height;
// first draw your image once
ctx.drawImage(img, 0, 0);
//then get its data
var imgData = ctx.getImageData(0, 0, c.width, c.height);
// get the array of pixels
var arr = imgData.data;
//loop through each pixels, 4 per loop because pixels are [R,G,B,A,R,G,B,A...]
for (var i = 0; i < arr.length; i += 4) {
// store the red value
var r = arr[i];
//replace the green value with the red one
arr[i] = arr[i + 1];
arr[i + 1] = r;
}
// put the modified imageData back to your canvas
ctx.putImageData(imgData, 0, 0);
};
var ctx = c.getContext('2d');
var img = new Image();
img.crossOrigin = 'anonymous';
img.onload = draw;
img.src = 'https://dl.dropboxusercontent.com/s/1alt1303g9zpemd/UFBxY.png';
<canvas id="c"></canvas>
Ps :看来我们很快就能直接设置上下文的 filter
属性,目前仅在 FF 上可用,在一个标志下,但这将使事情变得更好更简单!
我有一个 HTML 页面,我可以从该页面获取来自设备摄像头的视频源。我用 setTimeOut 循环将它绘制到 canvas 并拍摄图片到图像。然后我对该图像应用滤镜(棕褐色、灰度...)并保存。图像在没有过滤器的情况下保存。为什么保存的不是过滤后的图像,而是 "raw" 图像?我不太擅长Javascript所以请温柔点。
<video id = "video" autoplay></video>
<button onclick = "snap()">Snap</button>
<canvas id = "canvas" width = "400" height = "300"></canvas>
<img id = "photo" src = "pic.png" alt = "Photo">
<button onclick = "save()">Save</button>
<button onclick = "sepia()">Sepia</button>//Added in edit
//--------------
var video = document.getElementById('video');
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var photo = document.getElementById('photo');
navigator.getMedia({ video: true, audio: false }, success, failure);
function success(stream) {
video.src = vendorUrl.createObjectURL(stream);
}
function failure(error) {}
video.addEventListener('play', sendToCanvas, false);
function sendToCanvas() {
draw(this, context, canvas.width, canvas.height);
}
function draw(video, context, width, height) {
context.drawImage(video, 0, 0, width, height);
setTimeout(draw, 10, video, context, width, height);
}
function snap() {
photo.setAttribute('src', canvas.toDataURL("image/png"));
}
function save() {
var currentdate = new Date().toLocaleString();
var link = document.createElement('a');
link.download = currentdate + ".png";
link.href = photo.src;
link.click();
}
function sepia() {//Added in edit
photo.style["-webkit-filter"] = "sepia(100%)";
}
您正在使用 CSS 过滤器,这些过滤器并没有真正绘制到 canvas 中,而只是页面上的装饰。
因此,canvas' 提取其内容的方法不会保留这些过滤器。
这就像如果你确实为 canvas 元素设置了背景颜色而不绘制任何东西或一些边框,一旦你使用 toDataURL
方法就不会获得这些样式,只有在 canvas' 上下文中绘制的图本身是 canvas' 内容的一部分:
var ctx = c.getContext('2d');
//only this black rectangle is drawn onto the canvas
ctx.fillRect(10,10,20,20);
expImg.src = c.toDataURL();
/* these styles are only applied on the document,
not onto the canvas itself
*/
canvas{
background-color: lightgreen;
border: 10px solid red;
}
img{
border: 1px solid green;
}
<canvas id="c"></canvas>
<img id="expImg"/>
您必须了解 canvas 就像图像一样。当您在其上应用 CSS 过滤器时,您并没有真正修改文件,而只是它在文档中的显示。
现在,您可以直接在 canvas' 像素上处理过滤器,并能够保留它们。
这是一个小例子,向您展示如何修改 canvas 像素。
var draw = function() {
c.width = img.width;
c.height = img.height;
// first draw your image once
ctx.drawImage(img, 0, 0);
//then get its data
var imgData = ctx.getImageData(0, 0, c.width, c.height);
// get the array of pixels
var arr = imgData.data;
//loop through each pixels, 4 per loop because pixels are [R,G,B,A,R,G,B,A...]
for (var i = 0; i < arr.length; i += 4) {
// store the red value
var r = arr[i];
//replace the green value with the red one
arr[i] = arr[i + 1];
arr[i + 1] = r;
}
// put the modified imageData back to your canvas
ctx.putImageData(imgData, 0, 0);
};
var ctx = c.getContext('2d');
var img = new Image();
img.crossOrigin = 'anonymous';
img.onload = draw;
img.src = 'https://dl.dropboxusercontent.com/s/1alt1303g9zpemd/UFBxY.png';
<canvas id="c"></canvas>
Ps :看来我们很快就能直接设置上下文的 filter
属性,目前仅在 FF 上可用,在一个标志下,但这将使事情变得更好更简单!