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" <input type="range"
id="blur" id="blur"
class="blur slider is-fullwidth is-primary" 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> </div>
</aside> </aside>
@ -155,7 +155,7 @@
<input type="range" <input type="range"
id="blur" id="blur"
class="blur slider is-fullwidth is-primary" 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> </div>
</div> </div>

31
main.js
View file

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