UNPKG

huefree

Version:

HueFree provides a suite of utility functions specifically designed to facilitate color manipulation and transformation, particularly with an emphasis on accommodating color blindness. It includes methods for converting color representations, applying col

370 lines (321 loc) 16.2 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>HueFree - Library for Color Vision Simulations: visionMethods.js</title> <link type="text/css" rel="stylesheet" href="styles/vendor/prism-custom.css"> <link type="text/css" rel="stylesheet" href="styles/styles.css"> </head> <body> <header class="layout-header"> <h1> <a href="./index.html"> HueFree - Library for Color Vision Simulations </a> </h1> <nav class="layout-nav"> <li class="nav-heading"><a href="global.html">Globals</a></li><li class="nav-item"><span class="nav-item-type type-typedef" title="typedef">T</span><span class="nav-item-name is-typedef"><a href="global.html#ColorVision">ColorVision</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="global.html#applyFilter">applyFilter</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="global.html#changeVision">changeVision</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="global.html#changeVisionRecursive">changeVisionRecursive</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="global.html#colorTransform">colorTransform</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="global.html#deLinearize">deLinearize</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="global.html#getCustomVisions">getCustomVisions</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="global.html#getVisionDetail">getVisionDetail</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="global.html#getVisions">getVisions</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="global.html#linearize">linearize</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="global.html#processPixels">processPixels</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="global.html#rgbToString">rgbToString</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="global.html#stringToRgb">stringToRgb</a></span></li><li class="nav-item"><span class="nav-item-type type-member" title="member">M</span><span class="nav-item-name is-member"><a href="global.html#visions">visions</a></span></li> </nav> </header> <main class="layout-main layout-content--source"> <div class="container"> <p class="page-kind">source</p> <h1 class="page-title">visionMethods.js</h1> <section> <article> <pre id="source" class="source-page line-numbers"><code class="language-js">/* HueFree - Color transformations for color blind visions and more. Copyright (C) 2023, 2024 Piyush Katyal This file is part of HueFree Library. HueFree is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. HueFree is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with HueFree. If not, see &lt;https://www.gnu.org/licenses/>. */ const visions = require("./visions.js"); const color = require("./colorMethods.js"); /** * Retrieves the names of color vision simulations supported by the library or the custom vision object provided by the user. * * @param {Object} [obj=visions] - Optional parameter specifying the object containing color vision definitions. * @returns {string[]} - An array containing the names of the color vision simulations. */ function getVisions(obj = visions) { return Object.keys(obj); } /** * Retrieves detailed information about a specific color vision simulation. * * @param {string} vision - The name of the color vision simulation. * @param {Object} [obj=visions] - Optional parameter specifying the object containing color vision definitions. * @returns {Object | undefined} - An object containing detailed information about the specified color vision simulation, * or undefined if the vision name is not found. */ function getVisionDetail(vision, obj = visions) { return obj[vision]; } /** * Applies color vision simulation transformation to a target element or CSS color string. * * @param {string | Element} target - The CSS color string or DOM element to apply the color vision simulation. * @param {string} visionType - The type of color vision simulation to apply. * @param {Object} [obj=visions] - Optional parameter specifying the object containing color vision definitions. * @returns {string | Element | undefined} - The transformed CSS color string, DOM element with applied styles, * or undefined if the target cannot be processed. */ function changeVision(target, visionType, obj = visions) { if (!obj[visionType]) return; let rgbRegex = /rgba?\(\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)(?:\s*,\s*(-?\d+(?:\.\d+)?))?\s*\)/; if (typeof (target) === "string") { if (target.search(rgbRegex) === -1) return target; if (!obj[visionType].useMap) { let rgbLinear = color.linearize(target); let transMatrix = obj[visionType].transMatrix; let rgbTrans = color.colorTransform(transMatrix, rgbLinear); let sRGB = color.deLinearize(rgbTrans); sRGB = color.rgbToString(sRGB); sRGB = target.replace(rgbRegex, sRGB); return sRGB; } else { let processedValue = obj[visionType].mapColor(color.stringToRgb(target)); processedValue = color.rgbToString(processedValue); processedValue = target.replace(rgbRegex, processedValue); return processedValue; } } else if (typeof Element !== 'undefined' &amp;&amp; target instanceof Element) { if (target.tagName.toLowerCase() === "img") { if (!obj[visionType].useMap) { applyFilter(target, visionType, obj); } else { function loadEventHandler() { changeVision(target, visionType, obj); target.removeEventListener('load', loadEventHandler) } if (target.complete) { processPixels(target, visionType, obj); } else { target.addEventListener('load', loadEventHandler); return; } } } let styles = window.getComputedStyle(target); let stylesLength = styles.length; let colorStyles = []; for (let i = 0; i &lt; stylesLength; ++i) { let key = styles[i]; let value = styles[key]; if (value.search(rgbRegex) == -1) continue; colorStyles.push([key, value]); } for (let property of colorStyles) { let key = property[0]; let value = property[1]; let processedValue = changeVision(value, visionType, obj); target.style[key] = processedValue; } return target; } return; } /** * Recursively applies color vision simulation transformation to all child elements and CSS color strings of a target element. * * @param {string | Element} target - The CSS color string or DOM element to apply the color vision simulation recursively. * @param {string} visionType - The type of color vision simulation to apply. * @param {Object} [obj=visions] - Optional parameter specifying the object containing color vision definitions. * @returns {Element | string | undefined} - The transformed DOM element with applied styles, the transformed CSS color string, * or undefined if the target cannot be processed. */ function changeVisionRecursive(target, visionType, obj = visions) { if (!obj[visionType]) return; let rgbRegex = /rgba?\(\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)(?:\s*,\s*(-?\d+(?:\.\d+)?))?\s*\)/; if (typeof Element !== 'undefined' &amp;&amp; target instanceof Element) { let elementMap = new Map(); let queue = [target]; while (queue.length > 0) { let node = queue.shift(); if (node.nodeType === Node.ELEMENT_NODE) { let styles = window.getComputedStyle(node); let stylesLength = styles.length; let colorStyles = []; for (let i = 0; i &lt; stylesLength; ++i) { let key = styles[i]; let value = styles[key]; if (value.search(rgbRegex) == -1) continue; colorStyles.push([key, value]); } elementMap.set(node, colorStyles); } node.childNodes.forEach(child => queue.push(child)); } elementMap.forEach(function (props, element) { if (element.tagName.toLowerCase() === "img") { changeVision(element, visionType, obj); return; } for (let property of props) { let key = property[0]; let value = property[1]; let processedValue = changeVision(value, visionType, obj); element.style[key] = processedValue; } }); } else if (typeof (target) === "string") { return changeVision(target, visionType, obj); } return target; } /** * Processes each pixel of an image element to simulate color vision deficiency. (Currently not available to public) * * @param {HTMLImageElement} target - The image element to process. * @param {string} visionType - The type of color vision simulation to apply. * @param {Object} [obj=visions] - Optional parameter specifying the object containing color vision definitions. * @returns {HTMLImageElement | null} - The processed image element with simulated color vision deficiency applied, or null if an error occurs. */ function processPixels(target, visionType, obj = visions) { var imageCopy = target.cloneNode(true); var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); canvas.width = target.width; canvas.height = target.height; ctx.drawImage(imageCopy, 0, 0, target.width, target.height); try { var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); var data = imageData.data; for (var i = 0; i &lt; data.length; i += 4) { let srgb = [data[i], data[i + 1], data[i + 2], data[i + 3]]; srgb = color.rgbToString(srgb); srgb = changeVision(srgb, visionType, obj); srgb = color.stringToRgb(srgb); data[i] = srgb[0]; data[i + 1] = srgb[1]; data[i + 2] = srgb[2]; data[i + 3] = srgb[3]; } ctx.putImageData(imageData, 0, 0); target.src = canvas.toDataURL(); return target; } catch (e) { console.error('Error processing image:', e.message); return null; } } /** * Applies an SVG filter to an image element to simulate color vision deficiency. (Currently not available to public) * * @param {HTMLImageElement} target - The image element to apply the filter to. * @param {string} visionType - The type of color vision simulation to apply. * @param {Object} [obj=visions] - Optional parameter specifying the object containing color vision definitions. * @returns {HTMLImageElement} - The image element with the SVG filter applied. */ function applyFilter(target, visionType, obj = visions) { if (!obj[visionType]) return; let timeStamp = new Date().getTime(); let svgId = "_$svgIdTemp_" + timeStamp; let filterId = "_$filterIdTemp_" + timeStamp; function convertMatrix(mat) { let newMat = ` ${mat[0][0]} ${mat[0][1]} ${mat[0][2]} 0 0 ${mat[1][0]} ${mat[1][1]} ${mat[1][2]} 0 0 ${mat[2][0]} ${mat[2][1]} ${mat[2][2]} 0 0 0 0 0 1 0 `; return newMat; }; let matrixValue = convertMatrix(obj[visionType].transMatrix); let svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svg.setAttribute("id", svgId); svg.setAttribute("xmlns", "http://www.w3.org/2000/svg"); svg.setAttribute("width", "0"); svg.setAttribute("height", "0"); let filter = document.createElementNS("http://www.w3.org/2000/svg", "filter"); filter.setAttribute("id", filterId); let feColorMatrix = document.createElementNS("http://www.w3.org/2000/svg", "feColorMatrix"); feColorMatrix.setAttribute("type", "matrix"); feColorMatrix.setAttribute("values", matrixValue); filter.appendChild(feColorMatrix); svg.appendChild(filter); document.body.appendChild(svg); function loadEventHandler() { target.style.filter = "url(#" + filterId + ")"; target.removeEventListener('load', loadEventHandler); } if (target.complete) { target.style.filter = "url(#" + filterId + ")"; } else { target.addEventListener('load', loadEventHandler); } return target; } /** * Creates a custom visions object with specified vision types. The user can then operate elements on this custom object containing user-defined transformations. * * @param {...string} arguments - Vision types to include in the custom visions object. * @returns {Object} - Custom visions object containing specified vision types with default settings. */ function getCustomVisions() { let customVisions = {}; for (let i = 0; i &lt; arguments.length; ++i) { let customVision = { description: null, transMatrix: null, useMap: false, colorMap: null, } customVisions[arguments[i]] = customVision; } customVisions.addVisions = function () { for (let i = 0; i &lt; arguments.length; ++i) { let customVision = { description: null, transMatrix: null, useMap: false, colorMap: null, } customVisions[arguments[i]] = customVision; } }; customVisions.removeVisions = function () { for (let i = 0; i &lt; arguments.length; ++i) { delete customVisions[arguments[i]]; } } return customVisions; } module.exports = { getVisions, getVisionDetail, changeVision, changeVisionRecursive, getCustomVisions };</code></pre> </article> </section> </div> </main> <footer class="layout-footer"> <div class="container"> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.3</a> on Mon Jul 01 2024 23:05:11 GMT+0530 (India Standard Time) </div> </footer> <script src="scripts/prism.dev.js"></script> </body> </html>