{"version":3,"file":"AsciiEffect.cjs","sources":["../../src/effects/AsciiEffect.js"],"sourcesContent":["/**\n * Ascii generation is based on https://github.com/hassadee/jsascii/blob/master/jsascii.js\n *\n * 16 April 2012 - @blurspline\n */\n\nclass AsciiEffect {\n constructor(renderer, charSet = ' .:-=+*#%@', options = {}) {\n // ' .,:;=|iI+hHOE#`$';\n // darker bolder character set from https://github.com/saw/Canvas-ASCII-Art/\n // ' .\\'`^\",:;Il!i~+_-?][}{1)(|/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$'.split('');\n\n // Some ASCII settings\n\n const fResolution = options['resolution'] || 0.15 // Higher for more details\n const iScale = options['scale'] || 1\n const bColor = options['color'] || false // nice but slows down rendering!\n const bAlpha = options['alpha'] || false // Transparency\n const bBlock = options['block'] || false // blocked characters. like good O dos\n const bInvert = options['invert'] || false // black is white, white is black\n const strResolution = options['strResolution'] || 'low'\n\n let width, height\n\n const domElement = document.createElement('div')\n domElement.style.cursor = 'default'\n\n const oAscii = document.createElement('table')\n domElement.appendChild(oAscii)\n\n let iWidth, iHeight\n let oImg\n\n this.setSize = function (w, h) {\n width = w\n height = h\n\n renderer.setSize(w, h)\n\n initAsciiSize()\n }\n\n this.render = function (scene, camera) {\n renderer.render(scene, camera)\n asciifyImage(oAscii)\n }\n\n this.domElement = domElement\n\n // Throw in ascii library from https://github.com/hassadee/jsascii/blob/master/jsascii.js (MIT License)\n\n function initAsciiSize() {\n iWidth = Math.floor(width * fResolution)\n iHeight = Math.floor(height * fResolution)\n\n oCanvas.width = iWidth\n oCanvas.height = iHeight\n // oCanvas.style.display = \"none\";\n // oCanvas.style.width = iWidth;\n // oCanvas.style.height = iHeight;\n\n oImg = renderer.domElement\n\n if (oImg.style.backgroundColor) {\n oAscii.rows[0].cells[0].style.backgroundColor = oImg.style.backgroundColor\n oAscii.rows[0].cells[0].style.color = oImg.style.color\n }\n\n oAscii.cellSpacing = 0\n oAscii.cellPadding = 0\n\n const oStyle = oAscii.style\n oStyle.whiteSpace = 'pre'\n oStyle.margin = '0px'\n oStyle.padding = '0px'\n oStyle.letterSpacing = fLetterSpacing + 'px'\n oStyle.fontFamily = strFont\n oStyle.fontSize = fFontSize + 'px'\n oStyle.lineHeight = fLineHeight + 'px'\n oStyle.textAlign = 'left'\n oStyle.textDecoration = 'none'\n }\n\n const aDefaultCharList = ' .,:;i1tfLCG08@'.split('')\n const aDefaultColorCharList = ' CGO08@'.split('')\n const strFont = 'courier new, monospace'\n\n const oCanvasImg = renderer.domElement\n\n const oCanvas = document.createElement('canvas')\n if (!oCanvas.getContext) {\n return\n }\n\n const oCtx = oCanvas.getContext('2d')\n if (!oCtx.getImageData) {\n return\n }\n\n let aCharList = bColor ? aDefaultColorCharList : aDefaultCharList\n\n if (charSet) aCharList = charSet\n\n // Setup dom\n\n const fFontSize = (2 / fResolution) * iScale\n const fLineHeight = (2 / fResolution) * iScale\n\n // adjust letter-spacing for all combinations of scale and resolution to get it to fit the image width.\n\n let fLetterSpacing = 0\n\n if (strResolution == 'low') {\n switch (iScale) {\n case 1:\n fLetterSpacing = -1\n break\n case 2:\n case 3:\n fLetterSpacing = -2.1\n break\n case 4:\n fLetterSpacing = -3.1\n break\n case 5:\n fLetterSpacing = -4.15\n break\n }\n }\n\n if (strResolution == 'medium') {\n switch (iScale) {\n case 1:\n fLetterSpacing = 0\n break\n case 2:\n fLetterSpacing = -1\n break\n case 3:\n fLetterSpacing = -1.04\n break\n case 4:\n case 5:\n fLetterSpacing = -2.1\n break\n }\n }\n\n if (strResolution == 'high') {\n switch (iScale) {\n case 1:\n case 2:\n fLetterSpacing = 0\n break\n case 3:\n case 4:\n case 5:\n fLetterSpacing = -1\n break\n }\n }\n\n // can't get a span or div to flow like an img element, but a table works?\n\n // convert img element to ascii\n\n function asciifyImage(oAscii) {\n oCtx.clearRect(0, 0, iWidth, iHeight)\n oCtx.drawImage(oCanvasImg, 0, 0, iWidth, iHeight)\n const oImgData = oCtx.getImageData(0, 0, iWidth, iHeight).data\n\n // Coloring loop starts now\n let strChars = ''\n\n // console.time('rendering');\n\n for (let y = 0; y < iHeight; y += 2) {\n for (let x = 0; x < iWidth; x++) {\n const iOffset = (y * iWidth + x) * 4\n\n const iRed = oImgData[iOffset]\n const iGreen = oImgData[iOffset + 1]\n const iBlue = oImgData[iOffset + 2]\n const iAlpha = oImgData[iOffset + 3]\n let iCharIdx\n\n let fBrightness\n\n fBrightness = (0.3 * iRed + 0.59 * iGreen + 0.11 * iBlue) / 255\n // fBrightness = (0.3*iRed + 0.5*iGreen + 0.3*iBlue) / 255;\n\n if (iAlpha == 0) {\n // should calculate alpha instead, but quick hack :)\n //fBrightness *= (iAlpha / 255);\n fBrightness = 1\n }\n\n iCharIdx = Math.floor((1 - fBrightness) * (aCharList.length - 1))\n\n if (bInvert) {\n iCharIdx = aCharList.length - iCharIdx - 1\n }\n\n // good for debugging\n //fBrightness = Math.floor(fBrightness * 10);\n //strThisChar = fBrightness;\n\n let strThisChar = aCharList[iCharIdx]\n\n if (strThisChar === undefined || strThisChar == ' ') strThisChar = ' '\n\n if (bColor) {\n strChars +=\n \"\" +\n strThisChar +\n ''\n } else {\n strChars += strThisChar\n }\n }\n\n strChars += '
'\n }\n\n oAscii.innerHTML = `