golang實現圖片顏色反轉、圖片灰度、縮放、轉爲字符畫

看到網上很多通過字符形成的畫,覺得很好玩,於是網上搜索了下原來叫字符畫。
見百度百科:https://baike.baidu.com/item/%E5%AD%97%E7%AC%A6%E7%94%BB/1347002

發現了一篇文章手把手教你圖片轉ASCII碼圖 這篇文章採用的是javascript編寫的,講了其中的緣由。

大概原理是首先將圖片灰化處理,然後根據灰白圖片後的每個像素的rgb值,轉成對應的字符,然後就行程了字符圖片。

下面是通過go語言實現的圖片轉換功能

// imagetool project main.go
package main

import (
    "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 := 200
        if 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_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
}

//圖片縮放, 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 := 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")
            }
        }
    }
}

由於上面映入了code.google.com的組件,需要手動下載包,或者翻qiang了

轉換後的結果
這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述
字符畫
字符畫

從上面的效果可以看出基本功能已經實現,不過還有兩個問題需要解決,一個是 gif圖片轉換後只保留了第一幅圖,第二個是“字符畫”還並不是字符畫,只是一個txt文件,下面一篇文章將優化這個程序,實現gif的字符動畫

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章