【问题标题】:Saving Image in Javascript用 Javascript 保存图像
【发布时间】:2016-06-29 12:18:59
【问题描述】:

我有一个 HTML 页面,可以从设备摄像头获取视频源。我使用 setTimeOut 循环将它绘制到画布上,然后将图片拍摄到图像上。然后我对该图像应用过滤器(棕褐色,灰度......)并保存它。图像在没有过滤器的情况下保存。为什么过滤后的图像没有保存,而是“原始”图像?我不太擅长 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,这是完全正常的。您必须将它应用到您从ctx.getImageData 获取的图像数据上。应用在画布上的样式并未真正绘制在画布中,因此无法通过其方法导出。
  • 每个过滤器都有一个按钮,每个过滤器都有自己的功能:function sepia() { photo.style["-webkit-filter"] = "sepia(100%)";}
  • 所以这只是 CSS 过滤器,重新阅读我的评论,这是你的答案
  • 但是我将过滤器应用到图像并在屏幕上应用它,只是没有保存。
  • 是的,但是如果你设置了画布的背景颜色,它仍然没有进入画布的图像,因此无法导出。

标签: javascript image html5-canvas html5-video href


【解决方案1】:

您正在使用 CSS 过滤器,它们并没有真正绘制到画布中,而只是页面上的装饰。

因此,canvas 提取其内容的方法不会保留这些过滤器。

这就像你在不绘制任何东西或一些边框的情况下为画布元素设置了背景颜色,一旦你使用toDataURL 方法,你将无法获得这些样式,只有在画布上绘制的绘图'上下文本身是画布内容的一部分:

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"/>

您必须了解画布就像图像一样。当您对其应用 CSS 过滤器时,您并没有真正修改文件,而只是修改了它在文档中的显示。

现在,您可以将过滤器直接处理到画布的像素上,并能够保留它们。

这是一个小例子,向您展示如何修改画布像素。

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';
&lt;canvas id="c"&gt;&lt;/canvas&gt;

Ps : 看来我们很快就能直接设置上下文的 filter 属性,目前仅在 FF 上可用,在一个标志下,但这会让事情变得更容易!

【讨论】:

  • 该死的。我想可能有一个简单的方法。感谢您的解释:)
  • 是的,这并不容易,但请注意,有一个建议是直接在画布上包含 css 过滤器:developer.mozilla.org/en-US/docs/Web/API/… 但在浏览器采用之前,您可以查看this link,它提供一些过滤操作。
  • @wantsToLearnAndroid 另外,如果这个答案确实解决了您的问题,或者至少解释了为什么无法解决,您可以接受它,这样您的问题就会从“需要答案”流中消失.见stackoverflow.com/help/someone-answers。
  • 这里有一个sepia filter的链接。 :-)
  • 刚刚尝试了将标志更改为 true 的 FF 并且可以正常工作。很酷:)
猜你喜欢
  • 2017-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多