164 lines
		
	
	
	
		
			2.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			164 lines
		
	
	
	
		
			2.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| /*
 | |
| Blurhash toolkit.
 | |
| 
 | |
| base83 decoder/encoder is copied from
 | |
| https://github.com/woltapp/blurhash/blob/master/TypeScript/src/base83.ts,
 | |
| which is MIT Licensed: https://github.com/woltapp/blurhash?tab=MIT-1-ov-file#readme
 | |
| */
 | |
| const digitCharacters = [
 | |
|   "0",
 | |
|   "1",
 | |
|   "2",
 | |
|   "3",
 | |
|   "4",
 | |
|   "5",
 | |
|   "6",
 | |
|   "7",
 | |
|   "8",
 | |
|   "9",
 | |
|   "A",
 | |
|   "B",
 | |
|   "C",
 | |
|   "D",
 | |
|   "E",
 | |
|   "F",
 | |
|   "G",
 | |
|   "H",
 | |
|   "I",
 | |
|   "J",
 | |
|   "K",
 | |
|   "L",
 | |
|   "M",
 | |
|   "N",
 | |
|   "O",
 | |
|   "P",
 | |
|   "Q",
 | |
|   "R",
 | |
|   "S",
 | |
|   "T",
 | |
|   "U",
 | |
|   "V",
 | |
|   "W",
 | |
|   "X",
 | |
|   "Y",
 | |
|   "Z",
 | |
|   "a",
 | |
|   "b",
 | |
|   "c",
 | |
|   "d",
 | |
|   "e",
 | |
|   "f",
 | |
|   "g",
 | |
|   "h",
 | |
|   "i",
 | |
|   "j",
 | |
|   "k",
 | |
|   "l",
 | |
|   "m",
 | |
|   "n",
 | |
|   "o",
 | |
|   "p",
 | |
|   "q",
 | |
|   "r",
 | |
|   "s",
 | |
|   "t",
 | |
|   "u",
 | |
|   "v",
 | |
|   "w",
 | |
|   "x",
 | |
|   "y",
 | |
|   "z",
 | |
|   "#",
 | |
|   "$",
 | |
|   "%",
 | |
|   "*",
 | |
|   "+",
 | |
|   ",",
 | |
|   "-",
 | |
|   ".",
 | |
|   ":",
 | |
|   ";",
 | |
|   "=",
 | |
|   "?",
 | |
|   "@",
 | |
|   "[",
 | |
|   "]",
 | |
|   "^",
 | |
|   "_",
 | |
|   "{",
 | |
|   "|",
 | |
|   "}",
 | |
|   "~",
 | |
| ];
 | |
| 
 | |
| function decode83(str: string) {
 | |
|   let value = 0;
 | |
|   for (let i = 0; i < str.length; i++) {
 | |
|     const c = str[i];
 | |
|     const digit = digitCharacters.indexOf(c);
 | |
|     value = value * 83 + digit;
 | |
|   }
 | |
|   return value;
 | |
| }
 | |
| 
 | |
| function encode83(n: number, length: number): string {
 | |
|   var result = "";
 | |
|   for (let i = 1; i <= length; i++) {
 | |
|     let digit = (Math.floor(n) / Math.pow(83, length - i)) % 83;
 | |
|     result += digitCharacters[Math.floor(digit)];
 | |
|   }
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| /* toColorHex() is modified from
 | |
| https://www.xaymar.com/articles/2020/12/08/fastest-uint8array-to-hex-string-conversion-in-javascript/,
 | |
| licensed BSD-3. */
 | |
| 
 | |
| // Pre-Init
 | |
| const LUT_HEX_4b = [
 | |
|   "0",
 | |
|   "1",
 | |
|   "2",
 | |
|   "3",
 | |
|   "4",
 | |
|   "5",
 | |
|   "6",
 | |
|   "7",
 | |
|   "8",
 | |
|   "9",
 | |
|   "A",
 | |
|   "B",
 | |
|   "C",
 | |
|   "D",
 | |
|   "E",
 | |
|   "F",
 | |
| ];
 | |
| const LUT_HEX_8b = new Array(0x100);
 | |
| for (let n = 0; n < 0x100; n++) {
 | |
|   LUT_HEX_8b[n] = `${LUT_HEX_4b[(n >>> 4) & 0xf]}${LUT_HEX_4b[n & 0xf]}`;
 | |
| }
 | |
| // End Pre-Init
 | |
| function toColorHex(buffer: Uint8ClampedArray): `#${string}` {
 | |
|   let out = "#";
 | |
|   for (let idx = 0, edx = buffer.length; idx < edx; idx++) {
 | |
|     out += LUT_HEX_8b[buffer[idx]];
 | |
|   }
 | |
|   return out as `#${string}`;
 | |
| }
 | |
| 
 | |
| export function averageColor(blurhash: string) {
 | |
|   const v = decode83(blurhash.substring(2, 6)); // 24-bit RGB
 | |
| 
 | |
|   return [v >> 16, (v >> 8) & 255, v & 255] as const;
 | |
| }
 | |
| 
 | |
| export function averageColorHex(blurhash: string) : `#${string}` {
 | |
|   const [r, g, b] = averageColor(blurhash);
 | |
| 
 | |
|   const buf = new Uint8ClampedArray(3);
 | |
|   buf[0] = r;
 | |
|   buf[1] = g;
 | |
|   buf[2] = b;
 | |
| 
 | |
|   return toColorHex(buf);
 | |
| }
 |