fix: scale image to viewport to not waste computation on pixels the user can't see

This commit is contained in:
Orangerot 2024-12-08 04:19:51 +01:00
parent 9fdb7856ed
commit f2b10db055
2 changed files with 24 additions and 11 deletions

View file

@ -95,7 +95,7 @@
<input type="range"
id="blur"
class="blur slider is-fullwidth is-primary"
min="0" max="20" value="0" step="1">
min="0" max="1" value="0" step="0.05">
</div>
</div>
</aside>
@ -155,7 +155,7 @@
<input type="range"
id="blur"
class="blur slider is-fullwidth is-primary"
min="0" max="20" value="0" step="1">
min="0" max="1" value="0" step="0.05">
</div>
</div>
</div>

31
main.js
View file

@ -5,7 +5,7 @@ let settings = {
brightness: {},
saturate: {},
contrast: {},
blur: {prefix: 'px'}
blur: {filter: value => value * canvas.width / 100 + 'px'}
};
const img = new Image();
@ -19,14 +19,17 @@ document.addEventListener("DOMContentLoaded", function() {
document.getElementById("take-picture").addEventListener("click", take_picture);
document.getElementById("upload-image").addEventListener("change", upload_image)
document.getElementById("save").addEventListener("click", save_image)
document.getElementById("share").addEventListener("click", share_image)
window.addEventListener("resize", () => draw(true))
for (let setting in settings) {
// make an array out of an iterable
const elements = [...document.getElementsByClassName(setting)];
settings[setting].elements = elements;
// if filter is not definded, use identity function
settings[setting].filter ||= value => value;
for (let element of elements) {
element.addEventListener("input", settings_apply);
}
@ -46,14 +49,12 @@ function upload_image() {
console.log(this.files[0]);
img.src = URL.createObjectURL(this.files[0]);
img.onload = function() {
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
}
img.onload = () => draw(true);
}
function save_image() {
draw(false);
const dataUrl = canvas.toDataURL("image/png");
// downloading only works with links but not window.open
const link = document.createElement('a');
@ -76,12 +77,24 @@ function settings_apply(event) {
element.value = new_value;
}
draw(true);
}
function draw(viewport_scale) {
const filter = Object.entries(settings)
.map(([setting, {elements, prefix}]) => `${setting}(${elements[0].value}${prefix || ""})`)
.map(([setting, {elements, filter}]) => `${setting}(${filter(elements[0].value)})`)
.join(" ")
// set the resolution to the original and then scale down to the viewport to
// only calculate the filter on pixels the user can see.
canvas.height = img.naturalHeight;
canvas.width = img.naturalWidth;
if (viewport_scale) {
canvas.height = canvas.clientHeight;
canvas.width = canvas.clientWidth;
}
ctx.filter = filter
console.log(filter);
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
}