ciallorize
Version:
Ciallorize your bundled js into ascii art.
119 lines (100 loc) • 3.41 kB
JavaScript
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('')
}