UNPKG

ciallorize

Version:

Ciallorize your bundled js into ascii art.

119 lines (100 loc) 3.41 kB
const sharp = require('sharp'); const compareAST = require('./compare_ast'); module.exports = async (sequence, mask_path, options = { fontWidthToHeightRatio: 16/40, characterCompensation: 0.95 }) => { const image = await sharp(mask_path) .grayscale() .raw() .toBuffer({ resolveWithObject: true }); const width = image.info.width; const height = image.info.height; let black_pixels = 0; let white_pixels = 0; const threshold = 0xFF / 2; for(let i of image.data){ if(i < threshold){ black_pixels++; }else{ white_pixels++; } } // console.log(`Black pixels: ${black_pixels}`); // console.log(`White pixels: ${white_pixels}`); const fontConstant = options.fontWidthToHeightRatio; // 英文字符的宽:高 const characterCount = Math.round(sequence.join('').length * options.characterCompensation); const k = Math.sqrt(black_pixels / characterCount * fontConstant); const targetWidth = Math.floor(width / k); const targetHeight = Math.floor(height / k * fontConstant); // console.log(`characterCount: ${characterCount}`); const resizedImage = await sharp(image.data, { raw: { width: width, height: height, channels: 1 } }) .resize(targetWidth, targetHeight, {fit:'fill'}) .grayscale() .raw() .toBuffer({ resolveWithObject: true }) // console.log(resizedImage); const lines = [] for(let row=0;row<resizedImage.info.height;row++){ let line = [] for(let col=0;col<resizedImage.info.width;col++){ let pixel = resizedImage.data[row*resizedImage.info.width+col] if(pixel < threshold){ line.push(1) }else{ line.push(0) } } lines.push(line) } function getTokenWidth(token){ return token.length } function consumeLine(previousLines, line, sequence, seqIdx){ let rowIdx = 0 let code = '' while(rowIdx<line.length){ if(seqIdx==sequence.length){ break } if(line[rowIdx]==0){ code += ' ' rowIdx++ }else{ code += sequence[seqIdx] rowIdx+= getTokenWidth(sequence[seqIdx]) seqIdx++ } } function validate(){ const crrCode = previousLines.join('\n') + '\n' + code + '\n' + sequence.slice(seqIdx).join('') try{ return compareAST(crrCode, sequence.join('')) }catch{ return false } } while(!validate()){ code += sequence[seqIdx] seqIdx++ } return {code, seqIdx} } const resultLines = [] let seqIdx = 0 for(let row=0;row<lines.length;row++){ let line = lines[row] let {code, seqIdx: nextSeqIdx} = consumeLine(resultLines, line, sequence, seqIdx) resultLines.push(code) seqIdx = nextSeqIdx } return resultLines.join('\n')+sequence.slice(seqIdx).join('') }