详解使用JS如何制作简单的ASCII图与单极图(2)

function gray2asc(gray) { /*ASCII--I'mYasic*/ /*32 64 96 128 160 192 224 256*/ gray = 255 - gray; if (gray < 128){ if (gray < 64){ if (gray < 32){ return '\'' } else { return 'c' } } else { if (gray < 96){ return 'i' } else { return 's' } } } else { if (gray < 192){ if (gray < 160){ return 'I' } else { return 'm' } } else { if (gray < 224){ return 'a' } else { return 'Y' } } } }

遍历与显示

上面大概讲解完了对于一个像素点变换为ASCII码的过程,接下来就是遍历和显示了。

遍历

遍历全部像素点并变换为ASCII码基本是不可能的,因为图片稍微大一些计算量就增长很多,所以我们折中一下,对于像素阵列的行与列都进行等间隔采样,最终展示出来的图片分辨率会随着采样间隔减小而增强。另外要注意 data 数组是一维数组,并且每4个元素为一组RGBA数据。相应代码如下

var result = ""; var lineIndex = 0; for (var lineHeight = 0; lineHeight < sourceImg.height; lineHeight += 12){ var lineASC = ""; for (var lineFlag = 0; lineFlag < sourceImg.width; lineFlag += 5){ lineIndex = (lineHeight * sourceImg.width + lineFlag) * 4; var r = imgDataArray[lineIndex]; var g = imgDataArray[lineIndex + 1]; var b = imgDataArray[lineIndex + 2]; lineASC += gray2asc(rgb2gray(r, g, b)); } lineASC += '\n'; result += lineASC; }

显示

最终获得的 result 字符串就是需要展示的ASCII码。但是必须注意,如果直接展示到页面上会因为每一个字符的字符宽度不一样而导致ASCII图“失真”,这里我们可以采用 Monospace 字体来确保字符宽度一致。

制作单极图

其实看完上面部分,就应该知道单极图非常好实现,同样需要获取像素信息并灰度化,只是量化时直接量化为 rgb(0, 0, 0) 和 rgb(255, 255, 255) 两种颜色就可以。

var canvasContext = targetCanvas.getContext("2d"); canvasContext.drawImage(sourceImg, 0, 0); var imgData = canvasContext.getImageData(0 , 0, sourceImg.width, sourceImg.height); var imgDataArray = imgData.data; for (var index = 0; index <= sourceImg.width * sourceImg.height * 4; index += 4){ var red = imgDataArray[index]; var green = imgDataArray[index + 1]; var blue = imgDataArray[index + 2]; var gray = rgb2gray(red, green, blue); if (gray < 128){ imgData.data[index] = 0; imgData.data[index + 1] = 0; imgData.data[index + 2] = 0; } else { imgData.data[index] = 255; imgData.data[index + 1] = 255; imgData.data[index + 2] = 255; } } canvasContext.putImageData(imgData, 0, 0);

别忘了最后要用 putImageData 方法将修改后的像素信息放回 canvas 中进行显示。

ASCII图完整代码

function rgb2gray(r, g, b) { return r * 0.333 + g * 0.333 + b * 0.333; } function gray2asc(gray) { /*ASCII--I'mYasic*/ /*32 64 96 128 160 192 224 256*/ gray = 255 - gray; if (gray < 128){ if (gray < 64){ if (gray < 32){ return '\'' } else { return 'c' } } else { if (gray < 96){ return 'i' } else { return 's' } } } else { if (gray < 192){ if (gray < 160){ return 'I' } else { return 'm' } } else { if (gray < 224){ return 'a' } else { return 'Y' } } } } var img2ASC = function (canvas, sourceImg) { console.log(sourceImg.width + " " + sourceImg.height); var canvasContext = canvas.getContext("2d"); canvasContext.drawImage(sourceImg, 0, 0); var imgData = canvasContext.getImageData(0 , 0, sourceImg.width, sourceImg.height); var imgDataArray = imgData.data; var result = ""; var lineIndex = 0; for (var lineHeight = 0; lineHeight < sourceImg.height; lineHeight += 12){ var lineASC = ""; for (var lineFlag = 0; lineFlag < sourceImg.width; lineFlag += 5){ lineIndex = (lineHeight * sourceImg.width + lineFlag) * 4; var r = imgDataArray[lineIndex]; var g = imgDataArray[lineIndex + 1]; var b = imgDataArray[lineIndex + 2]; lineASC += gray2asc(rgb2gray(r, g, b)); } lineASC += '\n'; result += lineASC; } document.getElementById("result").innerHTML = result; };

单极图完整代码

function rgb2gray(r, g, b) { return r * 0.333 + g * 0.333 + b * 0.333; } function gray2asc(gray) { /*ASCII--I'mYasic*/ /*32 64 96 128 160 192 224 256*/ if (gray < 128){ if (gray < 64){ if (gray < 32){ return '\'' } else { return 'c' } } else { if (gray < 96){ return 'i' } else { return 's' } } } else { if (gray < 192){ if (gray < 160){ return 'I' } else { return 'm' } } else { if (gray < 224){ return 'a' } else { return 'Y' } } } } var monoImg = function (targetCanvas, sourceImg) { targetCanvas.width = sourceImg.width; targetCanvas.height = sourceImg.height; var canvasContext = targetCanvas.getContext("2d"); canvasContext.drawImage(sourceImg, 0, 0); var imgData = canvasContext.getImageData(0 , 0, sourceImg.width, sourceImg.height); var imgDataArray = imgData.data; for (var index = 0; index <= sourceImg.width * sourceImg.height * 4; index += 4){ var red = imgDataArray[index]; var green = imgDataArray[index + 1]; var blue = imgDataArray[index + 2]; var gray = rgb2gray(red, green, blue); if (gray < 128){ imgData.data[index] = 0; imgData.data[index + 1] = 0; imgData.data[index + 2] = 0; } else { imgData.data[index] = 255; imgData.data[index + 1] = 255; imgData.data[index + 2] = 255; } } canvasContext.putImageData(imgData, 0, 0); };

总结

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwyjdw.html