golang实现图片颜色反转、图片灰度、转为字符画

来源:互联网 发布:国产视频制作软件 编辑:程序博客网 时间:2024/06/07 06:22

看到网上很多通过字符形成的画,觉得很好玩,于是网上搜索了下原来叫字符画。
见百度百科:https://baike.baidu.com/item/%E5%AD%97%E7%AC%A6%E7%94%BB/1347002

发现了一篇文章手把手教你图片转ASCII码图 这篇文章采用的是javascript编写的,讲了其中的缘由。

大概原理是首先将图片会话处理,然后根据灰白图片后的每个像素的rgb值,转成对应的字符,然后就行程了字符图片。

下面是通过go语言实现的图片转换功能

// imagetool project main.gopackage mainimport (    "bytes"    "fmt"    "image"    "image/color"    "image/gif"    "image/jpeg"    "image/png"    "io/ioutil"    "os"    "strings")//该工具支持将图片色彩反转,图片灰化,图片转为字符画。//author iccboy 2017-9-2func main() {    args := os.Args //获取用户输入的所有参数    if args == nil || len(args) != 4 || !(args[1] == "-r" || args[1] == "-g" || args[1] == "-t") {        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 {        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("    -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_uint8            g_uint8 = 255 - g_uint8            b_uint8 = 255 - b_uint8            newRgba.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}//图片转为字符画func ascllimage(m image.Image, target string) {    bounds := m.Bounds()    dx := bounds.Dx()    dy := bounds.Dy()    arr := []string{"M", "N", "H", "Q", "$", "O", "C", "?", "7", ">", "!", ":", "–", ";", "."}    fileName := target    dstFile, 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 / 18            dstFile.WriteString(arr[num])            if j == dx-1 {                dstFile.WriteString("\n")            }        }    }}

转换后的结果
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
字符画
字符画

从上面的效果可以看出基本功能已经实现,不过还有两个问题需要解决,一个是 gif图片转换后只保留了第一幅图,第二个是“字符画”还并不是字符画,只是一个txt文件,下面一篇文章将优化这个程序,实现gif的字符动画