diff options
-rw-r--r-- | index.html | 319 | ||||
-rw-r--r-- | main.js | 252 | ||||
-rw-r--r-- | style.css | 19 |
3 files changed, 354 insertions, 236 deletions
@@ -1,15 +1,15 @@ -<!DOCTYPE html> +<!doctype html> <html lang="en"> <head> - <meta charset="UTF-8"> - <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <link rel="icon" type="image/x-icon" href="assets/favicon.ico"> + <meta charset="UTF-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <link rel="icon" type="image/x-icon" href="assets/favicon.ico" /> <script src="main.js"></script> - <link rel="stylesheet" href="lib/bulma.min.css"> - <link rel="stylesheet" href="lib/bulma-slider.css"> - <link rel="stylesheet" href="lib/fontawesome/css/fontawesome.min.css"> - <link rel="stylesheet" href="lib/fontawesome/css/solid.min.css"> - <link rel="stylesheet" href="style.css"> + <link rel="stylesheet" href="lib/bulma.min.css" /> + <link rel="stylesheet" href="lib/bulma-slider.css" /> + <link rel="stylesheet" href="lib/fontawesome/css/fontawesome.min.css" /> + <link rel="stylesheet" href="lib/fontawesome/css/solid.min.css" /> + <link rel="stylesheet" href="style.css" /> <title>Imagine - Image Editor</title> </head> <body class="import-active"> @@ -21,49 +21,75 @@ <div class="column" id="viewport"> <div class="hero is-fullheight"> <div class="hero-body"> - <div class="container" > + <div class="container"> <!-- viewport that contains canvas/video/import buttons --> - <canvas id="myCanvas" class="is-visible-editor" width="300" height="300"></canvas> - <video id="video" class="is-visible-camera" width="300" height="300"></video> + <canvas + id="myCanvas" + class="is-visible-editor" + width="300" + height="300" + ></canvas> + <video + id="video" + class="is-visible-camera" + width="300" + height="300" + ></video> <div class="container has-text-centered mb-6 is-visible-import"> <h1 class="title is-1">Imagine</h1> <h2 class="subtitle is-3">A simple Image Editor</h2> </div> <div class="columns is-mobile is-visible-import"> <div class="column"> - <button id="take-picture" class="button is-large is-responsive is-fullwidth py-6" > + <button + id="take-picture" + class="button is-large is-responsive is-fullwidth py-6" + > <div class="container"> - <i class="fa-solid fa-6x fa-video mb-4"></i><br> + <i class="fa-solid fa-6x fa-video mb-4"></i><br /> Use Camera </div> </button> </div> <div class="column"> - <label class="button is-large is-responsive is-fullwidth py-6" > - <input class="file-input" type="file" id="upload-image" accept="image/*"> + <label + class="button is-large is-responsive is-fullwidth py-6" + > + <input + class="file-input" + type="file" + id="upload-image" + accept="image/*" + /> <div class="container"> - <i class="fa-solid fa-6x fa-upload mb-4"></i><br> - Choose a file… + <i class="fa-solid fa-6x fa-upload mb-4"></i><br /> + Choose a file… </div> </label> </div> </div> </div> <!-- buttons inside of the viewport --> - <a id="settings-button" href="#settings" class="button is-hidden-desktop is-visible-editor"> - <i class="fa-solid fa-sliders mr-2"></i> Settings + <a + id="settings-button" + href="#settings" + class="button is-hidden-desktop is-visible-editor" + > + <i class="fa-solid fa-sliders mr-2"></i> Settings </a> <button id="back" class="button is-hidden-import"> - <i class="fa-solid fa-arrow-left mr-2"></i> Back + <i class="fa-solid fa-arrow-left mr-2"></i> Back </button> - <button id="cheese" class="button is-large is-visible-camera" > - <i class="fa-solid fa-camera mr-2"></i> Take a Picture + <button id="cheese" class="button is-large is-visible-camera"> + <i class="fa-solid fa-camera mr-2"></i> Take a Picture </button> </div> </div> </div> <!-- settings menu for desktop use --> - <div class="column is-narrow has-background-black-ter is-hidden-mobile is-hidden-tablet-only is-visible-editor"> + <div + class="column is-narrow has-background-black-ter is-hidden-mobile is-hidden-tablet-only is-visible-editor" + > <aside class="menu mr-3"> <h1 class="title">Imagine</h1> <h2 class="subtitle">Image Editor</h2> @@ -71,9 +97,7 @@ <!-- autocomplete off prevents browsers from remebering the value on page reloads --> <form autocomplete="off"> <div class="buttons"> - <button class="button is-primary save-image"> - Save Image - </button> + <button class="button is-primary save-image">Save Image</button> <button class="button is-secondary share-image"> <i class="fa-solid fa-share-from-square fa-fw mr-1"></i> Share @@ -86,9 +110,7 @@ </button> </div> - <p class="menu-label"> - Color Correction - </p> + <p class="menu-label">Color Correction</p> <div class="field"> <label class="label"> @@ -99,10 +121,15 @@ </span> </label> <div class="control"> - <input type="range" - id="brightness" - class="brightness slider is-fullwidth is-primary" - min="0" max="2" value="1" step="0.01"> + <input + type="range" + id="brightness" + class="brightness slider is-fullwidth is-primary" + min="0" + max="2" + value="1" + step="0.01" + /> </div> </div> <div class="field"> @@ -114,10 +141,15 @@ </span> </label> <div class="control"> - <input type="range" - id="saturate" - class="saturate slider is-fullwidth is-primary" - min="0" max="2" value="1" step="0.01"> + <input + type="range" + id="saturate" + class="saturate slider is-fullwidth is-primary" + min="0" + max="2" + value="1" + step="0.01" + /> </div> </div> <div class="field"> @@ -129,10 +161,15 @@ </span> </label> <div class="control"> - <input type="range" - id="contrast" - class="contrast slider is-fullwidth is-primary" - min="0" max="2" value="1" step="0.01"> + <input + type="range" + id="contrast" + class="contrast slider is-fullwidth is-primary" + min="0" + max="2" + value="1" + step="0.01" + /> </div> </div> <div class="field"> @@ -144,16 +181,19 @@ </span> </label> <div class="control"> - <input type="range" - id="hue-rotate" - class="hue-rotate slider is-fullwidth is-primary" - min="-180" max="180" value="0" step="1"> + <input + type="range" + id="hue-rotate" + class="hue-rotate slider is-fullwidth is-primary" + min="-180" + max="180" + value="0" + step="1" + /> </div> </div> - <p class="menu-label"> - Filters - </p> + <p class="menu-label">Filters</p> <div class="field"> <label class="label"> <i class="fa-solid fa-radio fa-fw"></i> @@ -163,10 +203,15 @@ </span> </label> <div class="control"> - <input type="range" - id="grayscale" - class="grayscale slider is-fullwidth is-primary" - min="0" max="1" value="0" step="0.01"> + <input + type="range" + id="grayscale" + class="grayscale slider is-fullwidth is-primary" + min="0" + max="1" + value="0" + step="0.01" + /> </div> </div> <div class="field"> @@ -178,10 +223,15 @@ </span> </label> <div class="control"> - <input type="range" - id="sepia" - class="sepia slider is-fullwidth is-primary" - min="0" max="1" value="0" step="0.01"> + <input + type="range" + id="sepia" + class="sepia slider is-fullwidth is-primary" + min="0" + max="1" + value="0" + step="0.01" + /> </div> </div> <div class="field"> @@ -193,15 +243,18 @@ </span> </label> <div class="control"> - <input type="range" - id="invert" - class="invert slider is-fullwidth is-primary" - min="0" max="1" value="0" step="0.01"> + <input + type="range" + id="invert" + class="invert slider is-fullwidth is-primary" + min="0" + max="1" + value="0" + step="0.01" + /> </div> </div> - <p class="menu-label"> - Blur and Sharpen - </p> + <p class="menu-label">Blur and Sharpen</p> <div class="field"> <label class="label"> <i class="fa-solid fa-water fa-fw"></i> @@ -211,10 +264,15 @@ </span> </label> <div class="control"> - <input type="range" - id="blur" - class="blur slider is-fullwidth is-primary" - min="0" max="1" value="0" step="0.05"> + <input + type="range" + id="blur" + class="blur slider is-fullwidth is-primary" + min="0" + max="1" + value="0" + step="0.05" + /> </div> </div> </form> @@ -222,7 +280,10 @@ </div> </div> <!-- settings menu for mobile use --> - <div id="settings" class="notification is-fullwidth is-hidden-desktop is-visible-editor"> + <div + id="settings" + class="notification is-fullwidth is-hidden-desktop is-visible-editor" + > <!-- #settings is an anhor to scroll to when clicked on the settings-button --> <!-- #top is an anchor provided by the browser to go to the top of the page --> <a href="#top" class="delete"></a> @@ -230,9 +291,7 @@ <!-- autocomplete off prevents browsers from remebering the value on page reloads --> <form autocomplete="off"> <div class="buttons"> - <button class="button is-primary save-image"> - Save Image - </button> + <button class="button is-primary save-image">Save Image</button> <button class="button is-secondary share-image"> <i class="fa-solid fa-share-from-square fa-fw mr-1"></i> Share @@ -245,9 +304,7 @@ </button> </div> - <p class="menu-label"> - Color Correction - </p> + <p class="menu-label">Color Correction</p> <div class="field"> <label class="label"> @@ -258,10 +315,15 @@ </span> </label> <div class="control"> - <input type="range" - id="brightness" - class="brightness slider is-fullwidth is-primary" - min="0" max="2" value="1" step="0.01"> + <input + type="range" + id="brightness" + class="brightness slider is-fullwidth is-primary" + min="0" + max="2" + value="1" + step="0.01" + /> </div> </div> <div class="field"> @@ -273,10 +335,15 @@ </span> </label> <div class="control"> - <input type="range" - id="saturate" - class="saturate slider is-fullwidth is-primary" - min="0" max="2" value="1" step="0.01"> + <input + type="range" + id="saturate" + class="saturate slider is-fullwidth is-primary" + min="0" + max="2" + value="1" + step="0.01" + /> </div> </div> <div class="field"> @@ -288,10 +355,15 @@ </span> </label> <div class="control"> - <input type="range" - id="contrast" - class="contrast slider is-fullwidth is-primary" - min="0" max="2" value="1" step="0.01"> + <input + type="range" + id="contrast" + class="contrast slider is-fullwidth is-primary" + min="0" + max="2" + value="1" + step="0.01" + /> </div> </div> <div class="field"> @@ -303,16 +375,19 @@ </span> </label> <div class="control"> - <input type="range" - id="hue-rotate" - class="hue-rotate slider is-fullwidth is-primary" - min="-180" max="180" value="0" step="1"> + <input + type="range" + id="hue-rotate" + class="hue-rotate slider is-fullwidth is-primary" + min="-180" + max="180" + value="0" + step="1" + /> </div> </div> - <p class="menu-label"> - Filters - </p> + <p class="menu-label">Filters</p> <div class="field"> <label class="label"> <i class="fa-solid fa-radio fa-fw"></i> @@ -322,10 +397,15 @@ </span> </label> <div class="control"> - <input type="range" - id="grayscale" - class="grayscale slider is-fullwidth is-primary" - min="0" max="1" value="0" step="0.01"> + <input + type="range" + id="grayscale" + class="grayscale slider is-fullwidth is-primary" + min="0" + max="1" + value="0" + step="0.01" + /> </div> </div> <div class="field"> @@ -337,10 +417,15 @@ </span> </label> <div class="control"> - <input type="range" - id="sepia" - class="sepia slider is-fullwidth is-primary" - min="0" max="1" value="0" step="0.01"> + <input + type="range" + id="sepia" + class="sepia slider is-fullwidth is-primary" + min="0" + max="1" + value="0" + step="0.01" + /> </div> </div> <div class="field"> @@ -352,15 +437,18 @@ </span> </label> <div class="control"> - <input type="range" - id="invert" - class="invert slider is-fullwidth is-primary" - min="0" max="1" value="0" step="0.01"> + <input + type="range" + id="invert" + class="invert slider is-fullwidth is-primary" + min="0" + max="1" + value="0" + step="0.01" + /> </div> </div> - <p class="menu-label"> - Blur and Sharpen - </p> + <p class="menu-label">Blur and Sharpen</p> <div class="field"> <label class="label"> <i class="fa-solid fa-water fa-fw"></i> @@ -370,10 +458,15 @@ </span> </label> <div class="control"> - <input type="range" - id="blur" - class="blur slider is-fullwidth is-primary" - min="0" max="1" value="0" step="0.05"> + <input + type="range" + id="blur" + class="blur slider is-fullwidth is-primary" + min="0" + max="1" + value="0" + step="0.05" + /> </div> </div> </form> @@ -2,49 +2,64 @@ let canvas; let video; let ctx; /* - * theses settings correspond to a css-filter. you can specify an optional - * filter attribute to modify the value from the input element. - */ + * theses settings correspond to a css-filter. you can specify an optional + * filter attribute to modify the value from the input element. + */ let settings = { "brightness": {}, "saturate": {}, "contrast": {}, - "hue-rotate": { filter: value => value + "deg" }, + "hue-rotate": { filter: (value) => value + "deg" }, "grayscale": {}, "sepia": {}, "invert": {}, - "blur": { filter: value => value * canvas.width / 100 + 'px' } + "blur": { filter: (value) => (value * canvas.width) / 100 + "px" }, }; const img = new Image(); let lensflare_active = false; let cursor = { x: 0, - y: 0 + y: 0, }; // wait for site to be parsed so element can be found -document.addEventListener("DOMContentLoaded", function() { +document.addEventListener("DOMContentLoaded", function () { canvas = document.getElementById("myCanvas"); ctx = canvas.getContext("2d"); video = document.getElementById("video"); - document.getElementById("back").addEventListener("click", () => document.body.className = "import-active"); + document + .getElementById("back") + .addEventListener( + "click", + () => (document.body.className = "import-active"), + ); // bind listeners - document.getElementById("viewport").addEventListener("drop", drop_handler); - document.getElementById("viewport").addEventListener("dragover", event => event.preventDefault()); - document.getElementById("take-picture").addEventListener("click", use_camera); - document.getElementById("cheese").addEventListener("click", take_picture); - document.getElementById("upload-image").addEventListener("change", upload_image) + document + .getElementById("viewport") + .addEventListener("drop", drop_handler); + document + .getElementById("viewport") + .addEventListener("dragover", (event) => event.preventDefault()); + document + .getElementById("take-picture") + .addEventListener("click", use_camera); + document + .getElementById("cheese") + .addEventListener("click", take_picture); + document + .getElementById("upload-image") + .addEventListener("change", upload_image); for (let element of document.getElementsByClassName("save-image")) { - element.addEventListener("click", save_image) + element.addEventListener("click", save_image); } for (let element of document.getElementsByClassName("share-image")) { - element.addEventListener("click", share_image) + element.addEventListener("click", share_image); } for (let element of document.getElementsByClassName("lensflare")) { - element.addEventListener("click", function(event) { + element.addEventListener("click", function (event) { event.preventDefault(); lensflare_active = !lensflare_active; if (lensflare_active) { @@ -56,19 +71,23 @@ document.addEventListener("DOMContentLoaded", function() { }); } - document.getElementById("viewport").addEventListener("mousemove", function(event) { - if (event.buttons === 1 && lensflare_active) { - cursor.x = (event.clientX - canvas.offsetLeft) / canvas.clientWidth - 0.5; - cursor.y = (event.clientY - canvas.offsetTop) / canvas.clientWidth - 0.5; - console.log(cursor); - draw(true); - } - }); + document + .getElementById("viewport") + .addEventListener("mousemove", function (event) { + if (event.buttons === 1 && lensflare_active) { + cursor.x = + (event.clientX - canvas.offsetLeft) / canvas.clientWidth - 0.5; + cursor.y = + (event.clientY - canvas.offsetTop) / canvas.clientWidth - 0.5; + console.log(cursor); + draw(true); + } + }); - window.addEventListener("deviceorientation", function(event) { + window.addEventListener("deviceorientation", function (event) { if (lensflare_active) { - cursor.x = event.gamma / 360 * 4; - cursor.y = (event.beta - 90) / 360 * 4; + cursor.x = (event.gamma / 360) * 4; + cursor.y = ((event.beta - 90) / 360) * 4; console.log(cursor); // draw(true); } @@ -78,22 +97,22 @@ document.addEventListener("DOMContentLoaded", function() { if (lensflare_active) { draw(true); } - requestAnimationFrame(animation) - }; + requestAnimationFrame(animation); + } animation(); - window.addEventListener("resize", () => draw(true)) + window.addEventListener("resize", () => draw(true)); - video.addEventListener("canplay", function() { + video.addEventListener("canplay", function () { const width = 320; let height = video.videoHeight / (video.videoWidth / width); // Firefox currently has a bug where the height can't be read from // the video, so we will make assumptions if this happens. - if (isNaN(height)) { - height = width / (4 / 3); - } + if (isNaN(height)) { + height = width / (4 / 3); + } video.width = width; video.height = height; }); @@ -103,7 +122,7 @@ document.addEventListener("DOMContentLoaded", function() { const elements = [...document.getElementsByClassName(setting)]; settings[setting].elements = elements; // if filter is not definded, use identity function - settings[setting].filter ||= value => value; + settings[setting].filter ||= (value) => value; for (let element of elements) { element.addEventListener("input", settings_apply); } @@ -116,10 +135,10 @@ document.addEventListener("DOMContentLoaded", function() { }); /** - * Reset all inputs of a setting back to the default value - * - * @param {string} setting - key of the settings object to reset - */ + * Reset all inputs of a setting back to the default value + * + * @param {string} setting - key of the settings object to reset + */ function reset_all(setting) { console.log("reseting " + setting); for (let element of settings[setting].elements) { @@ -129,9 +148,9 @@ function reset_all(setting) { } /** - * Request camera access and on succhess, show camera feed on video-element and - * switch to camera-active view - */ + * Request camera access and on succhess, show camera feed on video-element and + * switch to camera-active view + */ function use_camera() { navigator.mediaDevices .getUserMedia({ video: true, audio: false }) @@ -146,9 +165,9 @@ function use_camera() { } /** - * Take a still frame of the video-element showing the camera-feed and load it - * to the img to be rendered by canvas and switch to editor-active view - */ + * Take a still frame of the video-element showing the camera-feed and load it + * to the img to be rendered by canvas and switch to editor-active view + */ function take_picture() { canvas.width = video.width; canvas.height = video.height; @@ -160,9 +179,9 @@ function take_picture() { } /** - * Load selected file by input element to img to be rendered by canvas and - * switch to editor-active view - */ + * Load selected file by input element to img to be rendered by canvas and + * switch to editor-active view + */ function upload_image() { document.body.className = "editor-active"; @@ -173,13 +192,13 @@ function upload_image() { } /** - * Get file that is dropped into the website and load it to img to be rendered - * by canvas and switch to editor-active view. - * - * @param {DragEvent} ev -supplier by event listener - * - * https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/File_drag_and_drop - */ + * Get file that is dropped into the website and load it to img to be rendered + * by canvas and switch to editor-active view. + * + * @param {DragEvent} ev -supplier by event listener + * + * https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/File_drag_and_drop + */ function drop_handler(ev) { ev.preventDefault(); let file; @@ -199,28 +218,28 @@ function drop_handler(ev) { } /** - * Creates a download of the edited image in full resolution by creating a link - * and virtually clicking it. - * - * @param {PointerEvent} event - supplied by event listener - */ + * Creates a download of the edited image in full resolution by creating a link + * and virtually clicking it. + * + * @param {PointerEvent} event - supplied by event listener + */ function save_image(event) { event.preventDefault(); draw(false); const dataUrl = canvas.toDataURL("image/png"); // downloading only works with links but not window.open - const link = document.createElement('a'); + const link = document.createElement("a"); link.href = dataUrl; - link.download = 'imagine.png'; + link.download = "imagine.png"; link.click(); } /** - * Uses the navigator.share API to share the edited image in full reslution. - * - * @param {PointerEvent} event - supplied by event listener - */ + * Uses the navigator.share API to share the edited image in full reslution. + * + * @param {PointerEvent} event - supplied by event listener + */ function share_image(event) { event.preventDefault(); if (!navigator.share) { @@ -230,21 +249,21 @@ function share_image(event) { canvas.toBlob(async (blob) => { if (!blob) return; - const file = new File([blob], 'imagine.png', {type: 'image/png'}); + const file = new File([blob], "imagine.png", { type: "image/png" }); try { - await navigator.share({files: [file]}); + await navigator.share({ files: [file] }); } catch (error) { - console.log('Error sharing:', error); + console.log("Error sharing:", error); } - }, 'image/png'); + }, "image/png"); } /** - * Set all inputs of a setting to the value of the input that changed it. - * - * @param {Event} event - supplied by event listener - */ + * Set all inputs of a setting to the value of the input that changed it. + * + * @param {Event} event - supplied by event listener + */ function settings_apply(event) { const changed_setting = event.target.id; const new_value = event.target.value; @@ -259,12 +278,12 @@ function settings_apply(event) { } /** - * Render a lensflare shader for every pixel on the canvas. - * - * @param {number} pos_x - x position of the lensflare in the range [-0.5,0.5] - * @param {number} pos_y - y position of the lensflare in the range [-0.5,0.5] - * https://www.shadertoy.com/view/ldSXWK - */ + * Render a lensflare shader for every pixel on the canvas. + * + * @param {number} pos_x - x position of the lensflare in the range [-0.5,0.5] + * @param {number} pos_y - y position of the lensflare in the range [-0.5,0.5] + * https://www.shadertoy.com/view/ldSXWK + */ function lensflare(pos_x, pos_y) { const imgdata = ctx.getImageData(0, 0, canvas.width, canvas.height); const pixel_count = imgdata.data.length / 4; @@ -272,8 +291,8 @@ function lensflare(pos_x, pos_y) { for (let i = 0; i < pixel_count; i++) { const x = i % canvas.width; const y = i / canvas.width; - const u = (x / canvas.width - .5) * aspect_ratio; - const v = y / canvas.height - .5; + const u = (x / canvas.width - 0.5) * aspect_ratio; + const v = y / canvas.height - 0.5; const intensity = 1.5 * 255; const uv_len = u * u + v * v; @@ -283,76 +302,81 @@ function lensflare(pos_x, pos_y) { const uvd_pos_x = uvd_x + pos_x; const uvd_pos_y = uvd_y + pos_y; - let temp = uvd_pos_x * uvd_pos_x + uvd_pos_y * uvd_pos_y - const f2 = Math.max(1.0 / (1.0 + 32.0 * temp * .64), .0) * 0.1; - const f22 = Math.max(1.0 / (1.0 + 32.0 * temp * .72), .0) * 0.08; - const f23 = Math.max(1.0 / (1.0 + 32.0 * temp * .81), .0) * 0.06; + let temp = uvd_pos_x * uvd_pos_x + uvd_pos_y * uvd_pos_y; + const f2 = Math.max(1.0 / (1.0 + 32.0 * temp * 0.64), 0.0) * 0.1; + const f22 = Math.max(1.0 / (1.0 + 32.0 * temp * 0.72), 0.0) * 0.08; + const f23 = Math.max(1.0 / (1.0 + 32.0 * temp * 0.81), 0.0) * 0.06; let uvx_x = u * (1 + 0.5) + uvd_x * 0.5; let uvx_y = v * (1 + 0.5) + uvd_y * 0.5; let uvx_pos_x = uvx_x + pos_x; let uvx_pos_y = uvx_y + pos_y; - temp = uvx_pos_x * uvx_pos_x + uvx_pos_y * uvx_pos_y - const f4 = Math.max(0.01 - temp * .16, .0) * 6.0; - const f42 = Math.max(0.01 - temp * .20, .0) * 5.0; - const f43 = Math.max(0.01 - temp * .25, .0) * 3.0; + temp = uvx_pos_x * uvx_pos_x + uvx_pos_y * uvx_pos_y; + const f4 = Math.max(0.01 - temp * 0.16, 0.0) * 6.0; + const f42 = Math.max(0.01 - temp * 0.2, 0.0) * 5.0; + const f43 = Math.max(0.01 - temp * 0.25, 0.0) * 3.0; uvx_x = u * (1 + 0.4) + uvd_x * 0.4; uvx_y = v * (1 + 0.4) + uvd_y * 0.4; uvx_pos_x = uvx_x + pos_x; uvx_pos_y = uvx_y + pos_y; - temp = uvx_pos_x * uvx_pos_x + uvx_pos_y * uvx_pos_y - const f5 = Math.max(0.01 - temp * .04, .0) * 2.0; - const f52 = Math.max(0.01 - temp * .16, .0) * 2.0; - const f53 = Math.max(0.01 - temp * .36, .0) * 2.0; + temp = uvx_pos_x * uvx_pos_x + uvx_pos_y * uvx_pos_y; + const f5 = Math.max(0.01 - temp * 0.04, 0.0) * 2.0; + const f52 = Math.max(0.01 - temp * 0.16, 0.0) * 2.0; + const f53 = Math.max(0.01 - temp * 0.36, 0.0) * 2.0; uvx_x = u * (1 + 0.5) + uvd_x * 0.5; uvx_y = v * (1 + 0.5) + uvd_y * 0.5; uvx_pos_x = uvx_x - pos_x; uvx_pos_y = uvx_y - pos_y; - temp = uvx_pos_x * uvx_pos_x + uvx_pos_y * uvx_pos_y - const f6 = Math.max(0.01 - temp * .9, .0) * 6.0; - const f62 = Math.max(0.01 - temp * .1, .0) * 3.0; - const f63 = Math.max(0.01 - temp * .12, .0) * 5.0; - - imgdata.data[4 * i + 0] += 1.2 * ((f2 + f4 + f5 + f6) * 1.3 - uvd_len * .05) * intensity; - imgdata.data[4 * i + 1] += 1.5 * ((f22 + f42 + f52 + f62) * 1.3 - uvd_len * .05) * intensity; - imgdata.data[4 * i + 2] += 1.3 * ((f23 + f43 + f53 + f63) * 1.3 - uvd_len * .05) * intensity; + temp = uvx_pos_x * uvx_pos_x + uvx_pos_y * uvx_pos_y; + const f6 = Math.max(0.01 - temp * 0.9, 0.0) * 6.0; + const f62 = Math.max(0.01 - temp * 0.1, 0.0) * 3.0; + const f63 = Math.max(0.01 - temp * 0.12, 0.0) * 5.0; + + imgdata.data[4 * i + 0] += + 1.2 * ((f2 + f4 + f5 + f6) * 1.3 - uvd_len * 0.05) * intensity; + imgdata.data[4 * i + 1] += + 1.5 * ((f22 + f42 + f52 + f62) * 1.3 - uvd_len * 0.05) * intensity; + imgdata.data[4 * i + 2] += + 1.3 * ((f23 + f43 + f53 + f63) * 1.3 - uvd_len * 0.05) * intensity; imgdata.data[4 * i + 3] = 255; } ctx.putImageData(imgdata, 0, 0); } /** - * Amply filters and lensflare to the optionally scaled image, to only - * calculate on pixels the user can see. - * - * @param {bool} viewport_scale - render image scaled to viewport or in full - * resolution - */ + * Amply filters and lensflare to the optionally scaled image, to only + * calculate on pixels the user can see. + * + * @param {bool} viewport_scale - render image scaled to viewport or in full + * resolution + */ function draw(viewport_scale) { const filter = Object.entries(settings) - .map(([setting, { elements, filter }]) => `${setting}(${filter(elements[0].value)})`) - .join(" ") + .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. + // 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); ctx.drawImage(img, 0, 0, canvas.width, canvas.height); - ctx.filter = ''; + ctx.filter = ""; if (lensflare_active) { lensflare(cursor.x, cursor.y); } } - @@ -4,8 +4,9 @@ body { padding-top: 100dvh; } -canvas, video { - max-width: 100%; +canvas, +video { + max-width: 100%; max-height: 100%; } @@ -30,21 +31,21 @@ body.import-active .is-hidden-import { } #settings-button { - position: absolute; + position: absolute; right: 30px; - bottom: 30px + bottom: 30px; } #back { - position: absolute; + position: absolute; left: 30px; - top: 30px + top: 30px; } #cheese { - position: absolute; - bottom: 30px; - left: 30px; + position: absolute; + bottom: 30px; + left: 30px; right: 30px; } |