应用滤镜后如何下载图像? [复制]

Posted

技术标签:

【中文标题】应用滤镜后如何下载图像? [复制]【英文标题】: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.rotationdeg) 
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>

【问题讨论】:

【参考方案1】:

乔·卡维亚,

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

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

我从这个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;]

注意:当我尝试在 *** 编辑器中运行示例时 [下面这个] 我无法真正下载图像,但如果您在 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" >
      <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>

【讨论】:

以上是关于应用滤镜后如何下载图像? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

在ps 里面怎么用滤镜

如何在不使用滤镜的情况下使图像变暗? [复制]

在 iOS 中应用模糊滤镜时如何从图像中删除黑色阴影矩形?

如何在 iOS SDK 中的选定图像区域上应用滤镜/颜色

如何用华为图像服务快速实现滤镜功能

如何在位图上应用不同的图像效果(滤镜),如棕褐色、黑白、模糊等? [关闭]