如何使用这些 stackoverflow 答案保存应用过滤器的 canvas?

How do I save a canvas with filters applied, using these stackoverflow answers?

我知道关于如何实际将 CSS 滤镜应用于图像的问题已被问过多次。给出的一些答案实际上并未使用 CSS 过滤器,但似乎仍能完成工作。不幸的是,我是 JavaScript 的新手,我不理解这些答案。

所以,我的问题分为两部分:

  1. 由于其中一些答案是旧的,是否已经开发出一种方法来保存应用了 CSS 滤镜的 canvas 图像?

  2. 如果没有,我该如何实施这些 Whosebug 答案之一中描述的解决方案?我本质上需要一个实际将多个过滤器应用于图像或像素的代码示例,原始答案中没有包含它。

谢谢

答案:

在第一个答案中,我迷失了循环中的“...”。在第二个答案中,没有关于步骤 4 的详细信息。如果我是正确的,这两个都使用 CSS3 个过滤器,这是我的首选Capture/save/export an image with CSS filter effects applied

我在这一步的第 3 步迷路了:is anyone solve about saving filtered canvas as an image?

同样,我对非 CSS 过滤器的应用感到困惑:How to save image from canvas with css filters

JavaScript:

  // I know I eventually need to move these globals so they're passed as parameters.        
  var image; 
  var c; 
  var context; 
  var file; 

  // Begin File Open Code. 
  function fileOpen()
  {
    var fileInput = document.getElementById('fileInput');
    var fileDisplayArea = document.getElementById('iDisplay');

    fileInput.addEventListener('change', function(e)
    {
      file = fileInput.files[0];
      var imageType = /image.*/;
      if (file.type.match(imageType)) 
      {
        var reader = new FileReader();
        reader.onload = function(e)
        {                 
          iDisplay.innerHTML = "";
          image = new Image();

          image.src = reader.result;
          image.id = "I";               // Add an id attribute so the image editor code can access the image. // Image has since been moved to canvas.   
          iDisplay.appendChild(image);
          image.onload = function()
          {
            c = document.getElementById("C"); 
            context = c.getContext("2d");
            c.width = image.width; 
            c.height = image.height; 
            context.drawImage(image,0,0);  
          }                
        }
        reader.readAsDataURL(file); 
            }
      else
      {
        iDisplay.innerHTML = "File type not supported."
            }
        }); 
    setValues(); // Call setValues() as function exits to set Image Editing Code Hue Slider to 0.  
  }
  // End File Open Code 

  // Begin Image Editing Code. 
  var degrees = 0;
  var percentB = 100; 
  var percentC = 100;

  // Set initial values of sliders 
  function setValues()
  {      
    form1.brightness.value = 100;
    form1.contrast.value = 100;
    form1.hue.value = 0;      
  }

  // Get slider settings and apply changes to image
  function apply()
  { 
    degrees = form1.hue.value;
    percentC = form1.contrast.value;
    percentB = form1.brightness.value;
    // This is the crux of my question: How do I apply this properly, using the Whosebug answers, so that the edited image may be saved?   
    if (document.getElementById("C") != null) document.getElementById("C").style.filter = "brightness(" + parseInt(percentB) + "%)" + " contrast(" + parseInt(percentC) + "%)" + " hue-rotate(" + parseInt(degrees) + "deg)";   
    if (document.getElementById("C") != null) document.getElementById("C").style.WebkitFilter = "brightness(" + parseInt(percentB) + "%)" + " contrast(" + parseInt(percentC) + "%)" + " hue-rotate(" + parseInt(degrees) + "deg)";   
  }
  // End Image Editing Code 

  // Canvas was not cooperating, it needed c.width not c.style.width, can probably remove these and replace with small default values.    
  function setCanvasWidth()
  {
    c.width = image.width;  
  }

  function setCanvasHeight()
  {
    c.height = image.height;  
  }

  // Begin File Save Code (or user can right click and save if filters get applied.  
  function save()
  {
    alert("Place file save code here.")
  }

HTML

 <!doctype html>
 <html lang="en">
 <head>
   <title>HTML5 CSS3 Javascript Image Editor</title>
   <meta charset="utf-8"/>
   <link rel="stylesheet" type="text/css" href="default.css"/>
   <script src="nav.js"></script>
   <script type="text/javascript">
   // JavaScript is in here. 
   </script>  

<!-- style elements specific to this page are placed in the style tags. -->  
<style>

  image  
  {
    max-width: 100%;
    display: block;
    margin: auto; 
    margin-left: auto; 
    margin-right: auto;  
  }

  #C 
  {
    max-width: 100%;
    display: block;
    margin: auto;     
    left: 0;
    right: 0;
    margin-left: auto; 
    margin-right: auto;  
  }

  #iDisplay 
  {
    margin-top: 2em;
    max-width: 100%;
    overflow-x: auto;
    margin-left: auto; 
    margin-right: auto;  
    display: none; 
  }

</style> 
</head>
  <body onload="setValues()">
<header>
  <a href="index.html"><img src="logoglow.png" alt="Logo Image" width="215" height="135" /></a>
  <a href="index.html"><img src="ac.png" alt="Header Image" width="800" height="135" /></a>
</header>
<main>
  <h3>An Ongoing Experiment in HTML5 / CSS3 / JavaScript Image Editing</h3>
  <div>
  <!-- Nav is floating left and Main is floating right, clear float styles (IF NEEDED) so they dont interfere with new image. -->     
    <p style="float:left;">  
    <input type="file" id="fileInput" onclick="fileOpen()"></p>
    <br style="clear:both">
  </div>
  <div id="iDisplay"></div>  
  <br style="clear:both"><br style="clear:both">
  <!-- <script>document.write('<img src="' + file + '"/>');</script><br><br> --> 
  <!-- <div style="overflow:scroll;">  -->
  <canvas style="color:#FFFFFF;" id="C" width="javascript:setCanvasWidth()" height="javascript:setCanvasHeight()">Your browser is too old to support this feature. <br>Please consider updating to a modern browser.</canvas>
  <!-- </div> --> 
  <!-- use javascript:function() to get width and height?  -->
  <div id="afterCanvas">  
  <br><br> 
  <form name="form1" id="form1id" action="javascript:save();" style="font-size:90%; text-align:center;">
    Brightness: <input type="range" name="brightness" min="0" max="200" step="5" onmousemove="apply()" ontouchmove="apply()" style="vertical-align:-7px;" />&nbsp; &nbsp;
    Contrast: <input type="range" name="contrast" min="0" max="200" step="5" onmousemove="apply()" ontouchmove="apply()" style="vertical-align:-7px;"/>&nbsp; &nbsp;
    Hue: <input type="range" name="hue" min="0" max="360" step="5" onmousemove="apply()" ontouchmove="apply()" style="vertical-align:-7px;"/>
    <br><br>  
    <input type="submit" style="float:left;" value="Save Changes" /> <!-- chnage to type="submit" if form action is needed --> 
  </form>
  </div>
</main>
</body>
</html>  

让我们从你的问题来看这部分,因为如果你只支持它工作的浏览器,这就是你所需要的:

Again, I'm lost on the application of the non-CSS filters: How to save image from canvas with css filters

上下文的 filter property 就像 CSS 过滤器一样工作 – 它具有相同的功能 – 但重要的是要知道,与 CSS 不同的是,将过滤器应用于context 不会 更改 canvas' current 图像。它仅适用于后续 绘图操作。

这是一个例子。当您 运行 下面的代码片段时,您会看到两个 canvas。第一个应用了 CSS filter,第二个没有(第一个 canvas 的边框模糊且呈粉红色,而第二个清晰且清晰绿色)。

然后单击 "Copy image" 按钮时,代码

  1. 查看当前应用于第一个 canvas、
  2. 的 CSS 过滤器
  3. 将此过滤器值应用于第二个上下文,
  4. 将第一个 canvas 绘制到第二个上。

因为2),3)中的绘图操作会应用滤镜。

第二个 canvas 现在看起来像第一个,但是第二个 canvas 现在真正包含了色调旋转和模糊的像素,而第一个仍然有红色和清晰的像素 – 你只是因为 CSS 过滤器而看不到。

此时,您可以将第二个 canvas保存为图像,它看起来和预期的一样。

window.onload = function () {
  var cnv1 = document.getElementById("canvas1");
  var ctx1 = cnv1.getContext("2d");
  
  var cnv2 = document.getElementById("canvas2");
  var ctx2 = cnv2.getContext("2d");
  
  ctx1.font = "30px sans-serif";
  ctx1.fillStyle = "red";
  ctx1.fillText("Hello world!", 30, 80);

  var button = document.getElementById("button");
  button.onclick = function () {
  
    // take whatever CSS filter is applied to the first canvas
    var cssFilter = getComputedStyle(cnv1).filter;
    
    // use that filter as the second canvas' context's filter
    // all subsequent drawing operations will have this filter applied
    ctx2.filter = cssFilter;
    
    // take whatever is in canvas 1 and draw it onto canvas 2
    // the text on cnv1 is red and un-blurred (it's only the css
    // that makes it look otherwise), but the above filter will
    // cause blurring and hue-shifting to be applied to the drawImage
    // operation
    ctx2.drawImage(cnv1, 0, 0);
  };
}
* {
  vertical-align: top;
}

canvas {
  border: 2px solid green;
}
#canvas1 {
  filter: blur(2px) hue-rotate(180deg);
}
<canvas id="canvas1" width="200" height="200"></canvas>

<canvas id="canvas2" width="200" height="200"></canvas>

<button id="button">Copy image</button>