如何使用CSS过滤器从画布保存图像

时间:2015-05-23 04:39:31

标签: javascript html css canvas

我需要在客户端使用CSS过滤器后保存图像(不使用使用后端)。到目前为止我所拥有的:

  1. 使用CSS过滤器
  2. 转换为画布
  3. 使用var data = myCanvas.toDataURL("image/png");
  4. 保存
  5. 哭泣。保存的图像没有效果。
  6. 的index.html

    <div class="large-7 left">
        <img id="image1" src="./img/lusy-portret-ochki-makiyazh.jpg"/><br>
        <canvas id="myCanvas"></canvas>
    </div>
    

    Photo.js

    var buttonSave = function() {
        var myCanvas = document.getElementById("myCanvas");
        var img = document.getElementById('image1');
        var ctx = myCanvas.getContext ? myCanvas.getContext('2d') : null; 
        ctx.drawImage(img, 0, 0, myCanvas.width, myCanvas.height);
            var grayValue = localStorage.getItem('grayValue');
            var blurValue = localStorage.getItem('blurValue');
            var brightnessValue = localStorage.getItem('brightnessValue');
            var saturateValue = localStorage.getItem('saturateValue');
            var contrastValue = localStorage.getItem('contrastValue');
            var sepiaValue = localStorage.getItem('sepiaValue');
    
            filterVal = "grayscale("+ grayValue +"%)" + " " + "blur("+ blurValue +"px)" + " " + "brightness("+brightnessValue+"%)" + " " + "saturate(" + saturateValue +"%)" + " " + "contrast(" + contrastValue + "%)" + " " + "sepia(" + sepiaValue + "%)" ;
            $('#myCanvas')
              .css('filter',filterVal)
              .css('webkitFilter',filterVal)
              .css('mozFilter',filterVal)
              .css('oFilter',filterVal)
              .css('msFilter',filterVal);
    
        var data = myCanvas.toDataURL("image/png");
        localStorage.setItem("elephant", data);
        if (!window.open(data)) {
            document.location.href = data;
        }
    
    }
    

    然而,这会生成没有任何滤镜的图像。

4 个答案:

答案 0 :(得分:3)

应用于画布的CSS滤镜不会应用于生成的图像。您需要在画布中复制过滤器,或者重新将相同的过滤器应用于生成的图像。

尝试将生成的图像数据放入img标记的源代码中。应用相同的过滤器。

答案 1 :(得分:2)

上下文对象上有一个鲜为人知的property,方便地命名为filter

这可以将CSS过滤器作为参数并将其应用于位图。 但是,这是不是官方标准的一部分,它只适用于Firefox,因此存在限制。。从那时起,这个答案最初被写成了official standard的一部分。

您可以检查是否存在此属性,如果是,则使用CSS过滤器,或者如果没有,则使用后备手动将过滤器应用于图像。唯一的优势是可用时真正的性能。

CSS和DOM是与用于图像和画布的位图分开的世界。位图本身不受CSS的影响,只有作为位图的镜像的元素才会受到影响。唯一的方法是在像素级别工作(当 context 的过滤器属性不可用时)。

如何计算各种过滤器可以在Filter Effects Module Level 1中找到。另请参阅SVG FiltersColor Matrix

实施例

这将对其自身的上下文应用过滤器。如果过滤器属性不存在,则必须提供回退(此处未显示)。然后,它使用应用的滤镜作为图像(右侧版本)提取图像。在下次绘制操作之前,必须先设置过滤器。

&#13;
&#13;
var img = new Image();
img.crossOrigin = ""; 
img.onload = draw; img.src = "//i.imgur.com/WblO1jx.jpg";

function  draw() {
  var canvas = document.querySelector("canvas"),
      ctx = canvas.getContext("2d");

  canvas.width = this.width;
  canvas.height = this.height;
  
  // filter
  if (typeof ctx.filter !== "undefined") {
    ctx.filter = "sepia(0.8)";
    ctx.drawImage(this, 0, 0);
  }
  else {
    ctx.drawImage(this, 0, 0);
    // TODO: manually apply filter here.
  }

  document.querySelector("img").src = canvas.toDataURL();
}
&#13;
canvas, img {width:300px;height:auto}
&#13;
<canvas></canvas><img>
&#13;
&#13;
&#13;

答案 2 :(得分:1)

您的CSS属性实际上并未应用于画布数据。将CSS视为放置在canvas元素上的另一层。您可以使用context.getImageData来获取原始RGBA值的数组,然后执行过滤器工作,然后使用context.putImageData将其写回来实现自己的图像过滤器。但是,我认为你真的只想保存CSS过滤器的输出。您可以使用rasterizeHTML

等工具执行此操作

答案 3 :(得分:1)

请注意,如果src的{​​{1}}不在同一个来源img,可能会导致var data = myCanvas.toDataURL("image/png")

error

另请注意,问题Uncaught SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': tainted canvases may not be exported. 处的图片似乎是html,而不是jpg

png

可能的“解决方法”可能是将<img id="image1" src="./img/lusy-portret-ochki-makiyazh.jpg"/> img设置为src图像;打电话

data URI

尽管如上所述,在上面的答案中,似乎不会保留设置在var data = myCanvas.toDataURL("image/jpg") 元素的css filter

注意,“解决方法”; “保存图片”在这里,将是“保存HTML”;因为“下载”将是img objectURL DOM元素的html

另请注意,已保存的img文件中的img src仍为原始本地或外部html图片;如果在加载前没有转换为src

方法是将data URI设置为对window.location.href objectURL元素DOM的{​​{1}}引用,这应该保留img属性设置为{ {1}}

尝试使用outerHTMLstyle;在.css("[vendorPrefix]-filter", filterVal)设置URL.createObjectURL URL.revokeObjectURL,而不是css元素;创建filter img canvasBlobimg;创建对outerHTML的引用:type;将text/html设为URL.createObjectURL; 在objURL引用window.location.href

上致电objURL

URL.revokeObjectURL
objectURL