Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | import { DMG_PALETTE } from "consts"; import { hex2GBCrgb } from "shared/lib/helpers/color"; // eslint-disable-next-line no-restricted-globals const workerCtx: Worker = self as unknown as Worker; const indexColour = (g: number) => { Iif (g < 65) { return 3; } Iif (g < 130) { return 2; } Iif (g < 205) { return 1; } return 0; }; interface CacheRecord { canvas: OffscreenCanvas; ctx: OffscreenCanvasRenderingContext2D; img: ImageBitmap; } export interface ColorizedImageResult { id: number; width: number; height: number; canvasImage: ImageBitmap; } const cache: Record<string, CacheRecord> = {}; const TILE_COLOR_PALETTE = 0x7; workerCtx.onmessage = async (evt) => { const id = evt.data.id; const src = evt.data.src; const tiles = evt.data.tiles; const previewAsMono = evt.data.previewAsMono; const palettes = evt.data.palettes; const palettesRGB = palettes.map((colors: string[]) => colors.map(hex2GBCrgb) ); const dmgPalette = DMG_PALETTE.colors.map(hex2GBCrgb); let canvas: OffscreenCanvas; let ctx: OffscreenCanvasRenderingContext2D; let img: ImageBitmap; if (cache[src]) { // Using Cached Data canvas = cache[src].canvas; ctx = cache[src].ctx; img = cache[src].img; } else { // Fetch New Data const imgblob = await fetch(src).then((r) => r.blob()); img = await createImageBitmap(imgblob); canvas = new OffscreenCanvas(img.width, img.height); const tmpCtx = canvas.getContext("2d", { willReadFrequently: true }); Iif (!tmpCtx) { return; } ctx = tmpCtx; cache[src] = { canvas, ctx, img, }; } const width = img.width; const height = img.height; const tileWidth = Math.floor(width / 8); const tileHeight = Math.floor(height / 8); const tilesLength = tileWidth * tileHeight; canvas.width = width; canvas.height = height; ctx.drawImage(img, 0, 0, width, height); const imageData = ctx.getImageData(0, 0, width, height); const data = imageData.data; for (let t = 0; t < tilesLength; t++) { const tX = t % tileWidth; const tY = Math.floor(t / tileWidth); const palette = palettesRGB[tiles[t] & TILE_COLOR_PALETTE] || palettesRGB[0]; const p1X = tX * 8; const p2X = p1X + 8; const p1Y = tY * 8; const p2Y = p1Y + 8; for (let pX = p1X; pX < p2X; pX++) { for (let pY = p1Y; pY < p2Y; pY++) { const index = (pX + pY * width) * 4; const colorIndex = indexColour(data[index + 1]); const color = previewAsMono ? dmgPalette[colorIndex] : palette[colorIndex]; data[index] = color.r; data[index + 1] = color.g; data[index + 2] = color.b; data[index + 3] = 255; } } } ctx.putImageData(imageData, 0, 0); const canvasImage = canvas.transferToImageBitmap(); workerCtx.postMessage({ id, width, height, canvasImage }, [canvasImage]); }; // ----------------------------------------------------------------- export default class W extends Worker { constructor() { super(""); } } |