【问题标题】:How do I download an image after applying filter on it? [duplicate]应用滤镜后如何下载图像? [复制]
【发布时间】:2021-12-04 20:08:46
【问题描述】:

我正在使用照片编辑器,我想在用户对原始图像进行必要的更改后下载编辑后的图像。所以过滤值取决于用户,不是恒定的

更改工作正常,但是当我单击下载时,我得到的是原始版本而不是修改后的版本。有人对我如何进一步进行有任何想法吗? (P.S. 我搜索了整个 Stack Overflow 并尝试在我的代码中实现每个解决方案,但没有任何效果)

const canvas = document.getElementById("img");
const ctx = canvas.getContext("2d");

let img = new Image();
let fileName = "";

const downloadBtn = document.getElementById("download-btn");
const uploadFile = document.getElementById("upload-file");
const revertBtn = document.getElementById("revert-btn");

// Upload File
uploadFile.addEventListener("change", () => {
  // Get File
  const file = document.getElementById("upload-file").files[0];
  // Init FileReader API
  const reader = new FileReader();

  // Check for file
  if (file) {
    // Set file name
    fileName = file.name;
    // Read data as URL
    reader.readAsDataURL(file);
  }

  // Add image to canvas
  reader.addEventListener(
    "load",
    () => {
      // Create image
      img = new Image();
      // Set image src
      img.src = reader.result;
      // On image load add to canvas
      img.onload = function() {
        canvas.width = img.width;
        canvas.height = img.height;
        ctx.drawImage(img, 0, 0, img.width, img.height);
        canvas.removeAttribute("data-caman-id");
      };
    },
    false
  );
});
// Download Event
downloadBtn.addEventListener("click", () => {
  // Get ext
  const fileExtension = fileName.slice(-4);

  // Init new filename
  let newFilename;

  // Check image type
  if (fileExtension === ".jpg" || fileExtension === ".png") {
    // new filename
    newFilename = fileName.substring(0, fileName.length - 4) + "-edited.jpg";
  }

  // Call download
  download(canvas, newFilename);
});

// Download
function download(canvas, filename) {
  // Init event
  let e;
  // Create link
  const link = document.createElement("a");

  // Set props
  link.download = filename;
  link.href = canvas.toDataURL("image/jpeg", 0.8);
  // New mouse event
  e = new MouseEvent("click");
  // Dispatch event
  link.dispatchEvent(e);
}
const options = {
  sepia: 0,
  rotation: 0,
  scale: 1,

};

function setSepia(e) {
  options.sepia = e.value;
  document.getElementById('Amount').innerHTML = "(" + e.value + ")";
  redraw();
}
let rotation = 0;

function RotateImg() {
  rotation += 90;
  if (rotation == 360) {
    rotation = 0;
  }
  options.rotation = rotation;
  redraw();
}

let scale = 1

function flipping() {
  scale -= 2
  if (scale <= -2) {
    scale = 1;
  }
  options.scale = scale;
  redraw();
}

let invertVal = 0

function invert() {
  invertVal += 100
  if (invertVal > 100) {
    invertVal = 0
  }
  options.invertVal = invertVal;
  redraw();
}

function redraw() {
  document.getElementById("img").style["webkitFilter"] = "sepia(" + options.sepia + ") 
  grayscale(" + options.grayscale + ") brightness(" + options.brightness + ") contrast(" + 
    options.contrast + ") opacity(" + options.opacity + ") invert(" + options.invertVal + ")"; document.querySelector("img").style.transform = `rotate(${options.rotation}deg) 
scaleX(${options.scale})`;
  }
<!-- class="custom-file-label" -->
<p><input type="file" id="upload-file">upload</input>
</p>
<p><label for="upload-file">Upload Image</label></p>
<p><canvas id="img"></canvas></p>

<button id="download-btn" class="btn btn-primary btn-block">Download</button>
<div class="sidenav">
  <label for="filter-select">FILTER AND ADJUST</label>
  <div class="slider">
    <p style="color: aliceblue;">Sepia</p>
    <input id="sepia" type="range" oninput="setSepia(this);" value="0" step="0.1" min="0" max="1"><span id="Amount" style="color: white;"> (0)</span><br /><br>


  </div>
  <label onclick="RotateImg()">ROTATE</label>
  <label onclick="flipping()">FLIP</label>
</div>

【问题讨论】:

    标签: javascript html canvas html5-canvas


    【解决方案1】:

    乔·卡维亚,

    欢迎来到stackoverflow!我试图运行你的代码但没有成功,但我知道你想要做什么,所以我开始构建一个图像编辑器,它应该可以解决你的许多疑问

    我会在此留下一些注意事项:

    • 我从这个nice editor sample的主干开始
    • 我将原始文件保存在&lt;img&gt; 中,并将编辑后的图像放入&lt;canvas&gt;
    • previewFiles()方法用于设置两张图片,最多来自this page
    • 按照您的正确做法以及 this question 的建议,您需要 &lt;canvas&gt; 才能保存应用了 CSS 过滤器的图像
    • 我将应用多个过滤器,如great example 所示
    • 然后我们将在另一个great example之后下载编辑后的图像[实际上是&lt;canvas&gt;]

    注意:当我尝试在 StackOverflow 编辑器中运行示例时 [下面这个] 我无法真正下载图像,但如果您在 JSFiddle 中运行相同的代码,它就可以工作
    注意:我在 Chrome 上对其进行了测试,但如果这可能是一个问题,我会更深入地检查浏览器兼容性

    // checking activity on filters values
    // calling the apply_filter method as soon as a slider is moved or set into a position
    $(document).ready(function() {
      $(".range").change(apply_filter).mousemove(apply_filter);
    });
    
    
    // global variable
    const original_image = document.getElementById('original_image_preview');
    
    
    // setting canva size and return its context to drawing functions
    function initializeCanva() {
      // creating the additional canva to show the filters action
      const canvas = document.getElementById('edited_image_canva');
      const ctx = canvas.getContext('2d');
    
      // assigning it the same size of the original image preview
      canvas.width = original_image.width;
      canvas.height = original_image.height;
    
      return ctx;
    }
    
    // loading and previewing the files
    function previewFiles() {
    
      const preview = document.querySelector('img');
      const file = document.querySelector('input[type=file]').files[0];
      const reader = new FileReader();
    
      // the load event is fired only when a file has been read successfully, unlike loadend - because we need a success to get started
      reader.addEventListener("load", function() {
        // returning the file content
        preview.src = reader.result;
    
        // creating the canva to reflect the edits immediately after the original image has been loaded
        const ctx = initializeCanva();
    
        // drawing the original image on the canva
        ctx.drawImage(original_image, 0, 0, original_image.width, original_image.height);
      }, false);
    
      // reading the contents of the specified [image] file
      // when the read operation is successfully finished, the load event is triggered - at that time, the result attribute contains the data as a data: URL representing the file's data as a base64 encoded string
      if (file) {
        reader.readAsDataURL(file);
      }
    
    }
    
    // called everytime a slider is hovered or moved around
    // atm needed also to show the canva after the original image has been loaded
    function apply_filter() {
    
      // getting the filter values from the sliders elements
      var grayscale_val = $("#grayscale").val();
      //console.log(grayscale_val + "%");
      var blur_val = $("#blur").val();
      var exposure_val = $("#exposure").val();
      var sepia_val = $("#sepia").val();
      var opacity_val = $("#opacity").val();
    
      // getting the context where to apply the changes
      const ctx = initializeCanva();
    
      // creating the filter from sliders values
      ctx.filter = 'grayscale(' + grayscale_val + '%) blur(' + blur_val + 'px) brightness(' + exposure_val + '%) sepia(' + sepia_val + '%) opacity(' + opacity_val + '%)';
      // console.log(ctx.filter);
    
      // applying the filter on the original image
      ctx.drawImage(original_image, 0, 0, original_image.width, original_image.height);
    }
    
    
    // triggered by clicking on the download button
    function download() {
      //console.log("asking for download");
    
      // keeping the same image quality
      var data = edited_image_canva.toDataURL("image/png", 1);
    
      // create temporary link  
      var tmpLink = document.createElement('a');
      tmpLink.download = 'edited_image.png'; // set the name of the download file 
      tmpLink.href = data;
    
      // temporarily add link to body and initiate the download  
      document.body.appendChild(tmpLink);
      tmpLink.click();
      document.body.removeChild(tmpLink);
    }
    body {
      text-align: center;
      width: 100%;
      margin: 0 auto;
      padding: 0px;
      font-family: Helvetica, Sans-Serif;
      background-color: #E6E6E6;
    }
    
    #wrapper {
      text-align: center;
      margin: 0 auto;
      padding: 0px;
      width: 995px;
    }
    
    #edit_controls {
      background-color: #A4A4A4;
      float: left;
      width: 500px;
      margin-left: 248px;
    }
    
    #edit_controls li {
      list-style-type: none;
      display: inline-block;
      padding: 0px;
      margin: 10px;
      color: white;
    }
    
    #images_div img {
      width: 80%;
      padding: 20px;
    }
    
    #images_div canvas {
      border: 3px solid #d3d3d3;
    }
    
    button {
      margin: 20px;
    }
    <html>
    
    <head>
      <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    </head>
    
    <body>
      <div id="wrapper">
    
        <!-- filters area -->
        <div id="edit_controls">
          <li>GrayScale<br><input id="grayscale" class="range" type="range" min="0" max="100" value="0"></li>
          <li>Blur<br><input id="blur" class="range" type="range" min="0" max="10" value="0"></li>
          <li>Exposure<br><input id="exposure" class="range" type="range" min="0" max="200" value="100"></li>
          <li>Sepia<br><input id="sepia" class="range" type="range" min="0" max="100" value="0"></li>
          <li>Opacity<br><input id="opacity" class="range" type="range" min="0" max="100" value="100"></li>
        </div>
    
        <!-- images area -->
        <div id="images_div">
          <!-- accepting only image files -->
          <input type="file" accept="image/*" onchange="previewFiles()" style="margin-top: 20px"><br>
          <img src="" id="original_image_preview" alt="Waiting for the image to edit...">
          <br />Edited Image<br /><br />
          <canvas id="edited_image_canva">
              Your browser does not support the HTML5 canvas tag
            </canvas>
          <br />
          <button onclick="download()">Download</button>
        </div>
    
      </div>
    </body>
    
    </html>

    【讨论】:

      猜你喜欢
      • 2021-06-27
      • 2020-05-15
      • 1970-01-01
      • 2021-04-08
      • 1970-01-01
      • 2015-04-10
      • 2015-02-04
      • 1970-01-01
      • 2016-11-18
      相关资源
      最近更新 更多