手机版

详细讲解如何用JS制作简单的ASCII图片和单极性图片

时间:2021-09-05 来源:互联网 编辑:宝哥软件园 浏览:

ASCII图表

当终端执行各种命令时,经常会看到一些“图片”显示在终端上。从远处看像一张图片,近看像ASCII码。它们大致是这样的

我们今天要做的就是用JS把给定的图片转换成这个由ASCII字符组成的“ASCII图片”。我们先来看看最终的效果,假设我们给定的图片是这样的。

这是代码处理的结果,用I 'mYasic的8个字符表示,轮廓还是可以区分的。

单层图

另一张图片是单极性图片,也就是黑白图片,或者就是那张图片,输出如下

基础知识

这两种图相对简单,只需要以下知识

HTML5中Canvas像素的RGB值;JS中的Canvas相关API制作ASCII图片

一般来说,在电脑中,我们看到的大多数图片都是由像素组成的,每个像素都是由RGBA组成的。在css中,rgba(255,255,255,255,0)是一组rgba值,即RGB原色和Alpha透明度。当然,一张图片不仅包含所有的像素数据,还包括一些描述信息,也称为图片简介。这部分小到几KB,大到几百KB,经常在图片压缩中处理。

然后,对于图片中的每个像素,只要我们改变它对应的RGBA值,最终的图片就会改变。修改哪些像素,修改哪些RGBA,将决定最终的画面风格,这也是很多滤镜采用的机制。

基于以上理论知识,我们有了制作ASCII图的想法。事实上,ASCII图片通过计算RGBA值将图片中的一个像素分成几个给定的量化值。这里,因为我们用I 'mYasic的8个字符来表示,所以需要把它分成8组值,每组用一个ASCII字符来表示,最后就可以形成一个完整的ASCII图片。

下一步是具体的代码实现。

获取图片的像素信息

通过Canvas API中的getImageData()方法,我们可以得到一个对象,这个对象的属性包含一个一维数组数据,它是每四个元素组成的一个组,表示一个Canvas中指定范围内的所有像素信息,依次为RED、GREEN、BLUE和ALPHA。所以我们可以先把图片放到画布上,然后调用这个方法来获取像素。

但是,我想知道为什么数据是一维数组,通常处理后的图像是二维图像。如果像素信息用二维数组表示,读码和处理会方便得多,也更容易理解。您甚至可以使用三维数组将RGBA信息放在一维中。

获取图片像素信息的代码如下

var canvasContext=canvas . getcontext(' 2d ');canvascontext . draw image(source img,0,0);var img data=canvascontext . getimagedata(0,0,sourceImg.width,sourceimg . height);var imgDataArray=imgData.data那么某个像素的RGBA值可以通过这种方式获得

var r=imgdata array[LineIndex];var g=imgdata array[LineIndex 1];var b=imgdata array[LineIndex 2];var a=imgdata array[LineIndex 3];其中lineIndex是遍历每个像素的参考变量。

图像灰度化

灰度化,即获取像素的灰度值。每个像素包含RGBA的四种信息,我们需要把所有像素的RGBA值分成八组,所以需要统一RGBA值,最后得到一个值Y,对应像素的RGBA值满足Y=R=G=B,所以这里不考虑透明度Alpha。因为RGB值相等,所以像素颜色在白色和黑色之间是灰色的,所以这个过程也称为灰度化。

灰度算法有很多种,这里我们采用最简单的方法,即

Y=(R G B) * 1/3

相应的代码如下

函数rgb2gray(r,g,b){ return r * 0.333g * 0.333 b * 0.333;}灰度量化

灰色化后,图片大致是这样的,可以看到颜色都变成了灰色。

那么下一步就是关键的“量化”过程。也就是说,我们需要把这些不同灰度的值分成8组,每组给一个ASCII字符作为标记。当然,选择的ASCII字符要有一定的规则,即从暗到亮对应的字符都是简单的。量化过程是将0-255的范围分成8个区间,依次判断灰度值在哪个区间。代码如下。

由于图像中的像素数量巨大,为了效率,可以采用“二值决策”的方法来提高决策速度。

函数gray 2 ASC(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码,因为图片稍大时计算量会增加很多,所以我们通过等间隔采样像素阵列的行和列来折中,显示的图片分辨率会随着采样间隔的减小而增加。另外需要注意的是,数据数组是一维数组,每四个元素就是一组RGBA数据。相应的代码如下

var结果=' ';var LineIndex=0;for(var line height=0;line height source IMg . height;line height=12){ var linesc=' ';for(var line flag=0;line flag source IMg . width;line flag=5){ line index=(line height * sourceimg . width line flag)* 4;var r=imgdata array[LineIndex];var g=imgdata array[LineIndex 1];var b=imgdata array[LineIndex 2];linesc=gray 2 ASC(RGB 2 gray(r,g,b));} lineASC=' \ n结果=lineASC}显示

结果字符串是要显示的ASCII码。但是,必须注意的是,如果直接显示在页面上,ASCII图形会“失真”,因为每个字符的字符宽度不同。在这里,我们可以使用Monospace字体来确保字符宽度一致。

制作单极地图

其实看完上面的部分,应该知道单极性图非常容易实现,也需要获取像素信息并进行灰度化,但是可以直接量化为rgb(0,0,0)和rgb(255,255,255)。

var canvasContext=targetcanvas . getcontext(' 2d ');canvascontext . draw image(source img,0,0);var img data=canvascontext . getimagedata(0,0,sourceImg.width,sourceimg . height);var imgDataArray=imgData.datafor (var索引=0;index=source img . width * source img . height * 4;index=4){ var red=imgdata array[index];var green=imgdata array[索引1];var blue=imgdata array[索引2];var gray=rgb2gray(红、绿、蓝);if(gray 128){ imgdata . data[index]=0;imgdata . data[索引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方法将修改后的像素信息放回画布中进行显示。

ASCII图的完整代码

函数rgb2gray(r,g,b){ return r * 0.333g * 0.333 b * 0.333;}函数gray 2 ASC(gray){/* ASCII-I ' mya sic *//* 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 img2s=function(canvas,sourceImg)varget context(' 2d ');canvascontext。绘制图像(源img,0,0);var img data=canvascontext。getimagedata(0,0,sourceImg.width,sourceImg。高度);var IMgdata array=IMgdata . data var结果=' ';var LineIndex=0;for(变行高=0;行高来源IMg。身高;行高=12){ var linesc=' ';for(var行标志=0;行标志源IMg。宽度;行标志=5){行索引=(行高* sourceimg。宽度线条标志)* 4;var r=imgdata数组[LineIndex];var g=imgdata数组[LineIndex 1];var b=imgdata数组[LineIndex 2];linesc=gray 2 ASC(RGB 2 gray(r,g,b));} lineASC=' \ n结果=lineASC }文档。getelementbyid(' result ').innerHTML=结果;};单极图完整代码

函数rgb2gray(r,g,b){ return r * 0.333g * 0.333 b * 0.333;}函数gray 2 ASC(gray){/* ASCII-I ' mya sic *//* 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 ' } target canvas高度=源img。身高;var canvasContext=targetcanvas。get context(' 2d ');canvascontext。绘制图像(源img,0,0);var img data=canvascontext。getimagedata(0,0,sourceImg.width,sourceImg。高度);var imgdata array=imgdata . data for(var索引=0;索引=源img。宽度*源img。身高* 4;index=4){ var red=imgdata数组[index];var green=imgdata数组[索引1];var blue=imgdata数组[索引2];var gray=rgb2gray(红、绿、蓝);if(gray 128){ imgdata。数据[索引]=0;imgdata。数据[索引1]=0;imgdata。数据[索引2]=0;} else { imgdata。数据[索引]=255;imgdata。数据[索引1]=255;imgdata。数据[索引2]=255;} } canvascontext。putimagedata(imgData,0,0);};总结

这一篇博客主要讲了利用射流研究…中的画布应用编程接口进行一些简单的像素化操作,但其实还有很多地方可以继续改进。比如一般单极图出来后很多地方会有噪点,也就是一些碍眼的白点和黑点,可以通过一些方式"去掉噪点",就留在以后写吧!以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

版权声明:详细讲解如何用JS制作简单的ASCII图片和单极性图片是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。