summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--index.html319
-rw-r--r--main.js252
-rw-r--r--style.css19
3 files changed, 354 insertions, 236 deletions
diff --git a/index.html b/index.html
index e72d6fc..e8758eb 100644
--- a/index.html
+++ b/index.html
@@ -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>
diff --git a/main.js b/main.js
index 4c88716..9d286d5 100644
--- a/main.js
+++ b/main.js
@@ -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);
}
}
-
diff --git a/style.css b/style.css
index 4798e74..ba59bf6 100644
--- a/style.css
+++ b/style.css
@@ -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;
}