Can’t download a canvas image with filters on it

  canvas, html, html5-canvas, javascript

I have a page where users can put on themselves images some filters like hue-rotate, blur, invert, saturate and sepia. After, they can dowload it by pressing Save picture button. The problem is picture downloads but without any filters on it. I use canvas and adding filter with CanvasRenderingContext2D.filter. When i check with console.log() my ctx.filter there are filters that i accepted on it. I tried to redraw file with drawImage() function when Save picture button is pressed, it downloads with filters, but here is another problem, current img that User put on page become with filters even when filters reset. I mean picture seems like user have downloaded on page picture with filters already on it. Any suggestions? Below code and picture of page:

window.addEventListener("DOMContentLoaded", () => {
  const filters = document.querySelectorAll(".filters input"),
    btnReset = document.querySelector(".btn.btn-reset"),
    btns = document.querySelectorAll(".btn-container .btn"),
    btnContainer = document.querySelector(".btn-container"),
    btnLoadPicture = document.querySelector(".btn.btn-load #btnInput");
  const canvas = document.querySelector("canvas"),
    ctx = canvas.getContext("2d"),
    saveBtn = document.querySelector(".btn.btn-save");
  const img = new Image();

  // filter change

  function handleUpdate() {
    const suffix = this.dataset.sizing || "";
    document.documentElement.style.setProperty(
      `--${this.name}`,
      this.value + suffix
    );
    this.nextElementSibling.value = this.value;
    filterDownload();
  }
  function filterDownload() {
    let hold = "";
    for (let i = 0; i < filters.length; i++) {
      hold =
        hold +
        filters[i].name +
        "(" +
        filters[i].value +
        filters[i].dataset.sizing +
        ")";
    }
    ctx.filter = hold;
    console.log(ctx);
  }
  
  // load button function

  canvas.dataMaxWidth = canvas.width;
  canvas.dataMaxHeight = canvas.height;
  btnLoadPicture.addEventListener(
    "change",
    (e) => {
      const reader = new FileReader();
      const file = e.target.files[0];

      img.onload = function () {
        let scaled = getScaledDim(
          img,
          ctx.canvas.dataMaxWidth,
          ctx.canvas.dataMaxHeight
        );
        ctx.canvas.width = scaled.width;
        ctx.canvas.height = scaled.height;
        ctx.drawImage(img, 0, 0, ctx.canvas.width, ctx.canvas.height);
      };
      reader.onloadend = function () {
        img.src = reader.result;
      };
      reader.readAsDataURL(file);
      e.target.value = "";
      hideButton();
      highlightButton(2);
    },
    false
  );
  function getScaledDim(img, maxWidth, maxHeight) {
    let scaled = {
      ratio: img.width / img.height,
      width: img.width,
      height: img.height,
    };
    if (scaled.width > maxWidth) {
      scaled.width = maxWidth;
      scaled.height = scaled.width / scaled.ratio;
    }
    if (scaled.height > maxHeight) {
      scaled.height = maxHeight;
      scaled.width = scaled.height / scaled.ratio;
    }
    return scaled;
  }

  // canvas

  let i = 0;
  function setImage() {
    img.setAttribute("crossOrigin", "anonymous");
    const index = i % images.length;
    let currentTime = new Date();
    if (currentTime.getHours() == 6 || currentTime.getHours() < 12) {
      const imageSrc = imageBaseMorning + images[index];
      img.src = imageSrc;
      i++;
    } else if (currentTime.getHours() == 12 || currentTime.getHours() < 18) {
      const imageSrc = imageBaseDay + images[index];
      img.src = imageSrc;
      i++;
    } else if (currentTime.getHours() == 18 || currentTime.getHours() < 24) {
      const imageSrc = imageBaseEvening + images[index];
      img.src = imageSrc;
      i++;
    } else if (currentTime.getHours() == 0 || currentTime.getHours() < 6) {
      const imageSrc = imageBaseNight + images[index];
      img.src = imageSrc;
      i++;
    }

    img.onload = () => {
      canvas.width = img.width;
      canvas.height = img.height;
      ctx.drawImage(img, 0, 0);
    };
  }
  setImage();

  // Save picture function
  saveBtn.addEventListener("click", saveButton);

  function saveButton() {
    const link = document.createElement("a");
    link.download = "download.png";
    link.href = canvas.toDataURL();
    link.style.display = "none";
    link.click();
    link.remove();

  }
});

HTML:

<main class="main">
  <div class="filters">
    <label>
      Blur:
      <input
        name="blur"
        data-sizing="px"
        type="range"
        min="0"
        max="10"
        value="0"
        id="blur"
      />
      <output name="result" for="blur">0</output>
    </label>

    <label>
      Invert:
      <input
        name="invert"
        data-sizing="%"
        type="range"
        min="0"
        max="100"
        value="0"
        id="invert"
      />
      <output name="result">0</output>
    </label>

    <label>
      Sepia:
      <input
        name="sepia"
        data-sizing="%"
        type="range"
        min="0"
        max="100"
        value="0"
        id="sepia"
      />
      <output name="result">0</output>
    </label>

    <label>
      Saturate:
      <input
        name="saturate"
        data-sizing="%"
        type="range"
        min="0"
        max="200"
        value="100"
        id="saturate"
      />
      <output name="result">100</output>
    </label>

    <label>
      Hue rotate:
      <input
        name="hue-rotate"
        data-sizing="deg"
        type="range"
        min="0"
        max="360"
        value="0"
        id="hue"
      />
      <output name="result">0</output>
    </label>
  </div>
  <div class="editor">
    <div class="btn-container">
      <button class="btn btn-reset">Reset</button>
      <button class="btn btn-next btn-active">Next picture</button>
      <label class="btn btn-load" for="btnInput">
        Load picture
        <input
          class="btn-load--input"
          id="btnInput"
          name="upload"
          type="file"
          placeholder="Load picture"
        />
      </label>
      <button class="btn btn-save">Save picture</button>
    </div>
    <canvas width="1600" height="900"></canvas>
  </div>
</main>

enter image description here

Source: Ask Javascript Questions

LEAVE A COMMENT