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>