看到网上很多通过字符形成的画,觉得很好玩,于是网上搜索了下原来叫字符画。
见百度百科:https://baike.baidu.com/item/%E5%AD%97%E7%AC%A6%E7%94%BB/1347002
发现了一篇文章手把手教你图片转ASCII码图 这篇文章采用的是javascript编写的,讲了其中的缘由。
大概原理是首先将图片灰化处理,然后根据灰白图片后的每个像素的rgb值,转成对应的字符,然后就行程了字符图片。
下面是通过go语言实现的图片转换功能
// imagetool project main.go
package mainimport ("bytes""fmt""image""image/color""image/gif""image/jpeg""image/png""io/ioutil""os""strconv""strings""code.google.com/p/graphics-go/graphics"
)//该工具支持将图片色彩反转,图片灰化,图片转为字符画。
//author iccboy 2017-9-2
func main() {args := os.Args //获取用户输入的所有参数if args == nil || len(args) < 4 || !(args[1] == "-r" || args[1] == "-g" || args[1] == "-t" || args[1] == "-c") {usage()return}fmt.Print("...转换中...")option := args[1]source := args[2]target := args[3]ff, _ := ioutil.ReadFile(source)bbb := bytes.NewBuffer(ff)m, _, _ := image.Decode(bbb)if option == "-r" {newRgba := fzImage(m)f, _ := os.Create(target)defer f.Close()encode(source, f, newRgba)} else if option == "-g" {newGray := hdImage(m)f, _ := os.Create(target)defer f.Close()encode(source, f, newGray)} else if option == "-c" {rectWidth := 200if len(args) > 4 {rectWidth, _ = strconv.Atoi(args[4])}newRgba := rectImage(m, rectWidth)f, _ := os.Create(target)defer f.Close()encode(source, f, newRgba)} else {ascllimage(m, target)}fmt.Println("转换完成...")
}//帮助提示信息
var usage = func() {fmt.Println("输入错误,请按照下面的格式输入:")fmt.Println("使用: imagetool [OPTION] source_image [output]")fmt.Println(" Options is flow:")fmt.Println(" -r 图片颜色翻转")fmt.Println(" -g 图片灰度")fmt.Println(" -c 缩放文本,该参数时,可以传入图片缩放的宽度 如:imagetool -c 1.jpg c1.jpg 100")fmt.Println(" -t 转成文本")}//图片编码
func encode(inputName string, file *os.File, rgba *image.RGBA) {if strings.HasSuffix(inputName, "jpg") || strings.HasSuffix(inputName, "jpeg") {jpeg.Encode(file, rgba, nil)} else if strings.HasSuffix(inputName, "png") {png.Encode(file, rgba)} else if strings.HasSuffix(inputName, "gif") {gif.Encode(file, rgba, nil)} else {fmt.Errorf("不支持的图片格式")}
}//图片色彩反转
func fzImage(m image.Image) *image.RGBA {bounds := m.Bounds()dx := bounds.Dx()dy := bounds.Dy()newRgba := image.NewRGBA(bounds)for i := 0; i < dx; i++ {for j := 0; j < dy; j++ {colorRgb := m.At(i, j)r, g, b, a := colorRgb.RGBA()r_uint8 := uint8(r >> 8)g_uint8 := uint8(g >> 8)b_uint8 := uint8(b >> 8)a_uint8 := uint8(a >> 8)r_uint8 = 255 - r_uint8g_uint8 = 255 - g_uint8b_uint8 = 255 - b_uint8newRgba.SetRGBA(i, j, color.RGBA{r_uint8, g_uint8, b_uint8, a_uint8})}}return newRgba
}//图片灰化处理
func hdImage(m image.Image) *image.RGBA {bounds := m.Bounds()dx := bounds.Dx()dy := bounds.Dy()newRgba := image.NewRGBA(bounds)for i := 0; i < dx; i++ {for j := 0; j < dy; j++ {colorRgb := m.At(i, j)_, g, _, a := colorRgb.RGBA()g_uint8 := uint8(g >> 8)a_uint8 := uint8(a >> 8)newRgba.SetRGBA(i, j, color.RGBA{g_uint8, g_uint8, g_uint8, a_uint8})}}return newRgba
}//图片缩放, add at 2018-9-12
func rectImage(m image.Image, newdx int) *image.RGBA {bounds := m.Bounds()dx := bounds.Dx()dy := bounds.Dy()newRgba := image.NewRGBA(image.Rect(0, 0, newdx, newdx*dy/dx))graphics.Scale(newRgba, m)return newRgba
}//图片转为字符画(简易版)
func ascllimage(m image.Image, target string) {if m.Bounds().Dx() > 300 {m = rectImage(m, 300)}bounds := m.Bounds()dx := bounds.Dx()dy := bounds.Dy()arr := []string{"M", "N", "H", "Q", "$", "O", "C", "?", "7", ">", "!", ":", "–", ";", "."}fileName := targetdstFile, err := os.Create(fileName)if err != nil {fmt.Println(err.Error())return}defer dstFile.Close()for i := 0; i < dy; i++ {for j := 0; j < dx; j++ {colorRgb := m.At(j, i)_, g, _, _ := colorRgb.RGBA()avg := uint8(g >> 8)num := avg / 18dstFile.WriteString(arr[num])if j == dx-1 {dstFile.WriteString("\n")}}}
}
由于上面映入了code.google.com的组件,需要手动下载包,或者翻qiang了
转换后的结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DH3Jdlug-1658063938306)(https://img-blog.csdn.net/20170902202154973?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2Nib3kyMDA5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qwyLgAwN-1658063938309)(https://img-blog.csdn.net/20170902202214908?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2Nib3kyMDA5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E2S3YOex-1658063938310)(https://img-blog.csdn.net/20170902202236139?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2Nib3kyMDA5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l6OwPqWt-1658063938311)(https://img-blog.csdn.net/20170902202510179?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2Nib3kyMDA5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DRykecex-1658063938312)(https://img-blog.csdn.net/20170902202306208?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2Nib3kyMDA5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PKmEyiZD-1658063938313)(https://img-blog.csdn.net/20170902210959233?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2Nib3kyMDA5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jp4a4mNd-1658063938314)(https://img-blog.csdn.net/20170902210834339?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2Nib3kyMDA5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)]
由于上面的图片不知道怎么失效了,重新上传一次图片
从上面的效果可以看出基本功能已经实现,不过还有两个问题需要解决,一个是 gif图片转换后只保留了第一幅图,第二个是“字符画”还并不是字符画,只是一个txt文件,下面一篇文章将优化这个程序,实现gif的字符动画