一、效果
注:狗狗图片源于百度图片,下载格式为 png
二、原理
获取图片的 RGB 数值,通过灰度算法计算灰度值,再将灰度值用字符划分区间,按照灰度值所在的区间输出字符,核心代码:
for j := 0; j < y; j++ {
for i := 0; i < x; i++ {
// 1、获取图片的 RGB 数值
r, g, b, _ := img.At(i, j).RGBA()
//fmt.Println(uint8(r), uint8(g), uint8(b))
// 2、计算图片的灰度值
gray := Gray(uint8(r), uint8(g), uint8(b))
// 3、根据灰度值所在的字符区间输出字符
printPic(gray)
}
fmt.Println("")
}
灰度值算法公式
1、浮点算法:Gray = R * 0.3 + G * 0.59 + B * 0.11
2、整数方法:Gray = (R*30 + G*59 + B*11) / 100
3、移位方法:Gray =( R*76 + G*151 + B*28) >> 8
4、平均值法:Gray =(R + G + B)/ 3
5、仅取绿色:Gray = G
根据灰度值划分字符区间
灰度值介于 0 ~ 255 ,当字符为 18 个时,256 / 18 向下取整为 14,则每个字符区间的差值为 14,例如,0 <= gray <14 时,输出 ‘A’ ,14 <= gray <25 时,输出 ‘B’ ,以此类推。以下提供两个输出方法:
func printPic(gray uint8) {
charArray := []string{"K", "S", "P", "k", "s", "p", ";", "."}
index := math.Round(float64(int(gray) * (len(charArray) + 1) / 255))
if int(index) >= len(charArray) {
fmt.Print(" ")
} else {
fmt.Printf("%s", charArray[int(index)])
}
}
func printPic(gray uint8) {
charArray := []string{"M","N","H","Q","$","O","C","?","7",">","!",":","–",";","."}
index := math.Floor(float64(int(gray) / len(charArray)))
if int(index) >= len(charArray) {
fmt.Print(" ")
} else {
fmt.Printf("%s", charArray[int(index)])
}
}
三、完整代码
package utils
/**
* 图片工具
*
* @author Yushanma
* @since 2022/10/13 18:54
*/
import (
"bufio"
"fmt"
"image"
"image/color"
"image/png"
"log"
"math"
"os"
)
func ReadPic(imgFile string) image.Image {
// 打开图片文件
f, err := os.Open(imgFile)
if err != nil {
log.Fatalln(err)
}
defer f.Close()
// 解析图片
img, fmtName, err := image.Decode(f)
if err != nil {
log.Fatalln(err)
}
//fmt.Printf("Name: %v, Bounds: %+v, Color: %+v", fmtName, img.Bounds(), img.ColorModel())
x := img.Bounds().Size().X
y := img.Bounds().Size().Y
fmt.Println(fmtName, x, y)
out := image.NewRGBA(img.Bounds())
for j := 0; j < y; j++ {
for i := 0; i < x; i++ {
r, g, b, _ := img.At(i, j).RGBA()
//fmt.Println(uint8(r), uint8(g), uint8(b))
gray := Gray(uint8(r), uint8(g), uint8(b))
printPic(gray)
out.Set(i, j, color.RGBA{R: gray, G: gray, B: gray, A: 255})
}
fmt.Println("")
}
SavePic(out)
return img
}
/*
反转,把每个像素点的每个rgb值都与255作差(alpha的值不改变)
r, g, b = 255-r , 255-g , 255-b
*/
func Invert(r, g, b uint8) (uint8, uint8, uint8) {
return 255 - r, 255 - g, 255 - b
}
func Gray(r, g, b uint8) uint8 {
//fmt.Println("\ngray", (r+g+b)/3)
//return (r + g + b) / 3
return g
}
func SavePic(img *image.RGBA) {
f, err := os.Create("D:\\GWorkSpace\\CrazyImg\\data\\out2.png")
if err != nil {
log.Fatalln(err)
}
defer f.Close()
b := bufio.NewWriter(f)
err = png.Encode(b, img)
if err != nil {
log.Fatalln(err)
}
b.Flush()
}
// 输出 V2
func printPic(gray uint8) {
charArray := []string{"K", "S", "P", "k", "s", "p", ";", "."}
index := math.Round(float64(int(gray) * (len(charArray) + 1) / 255))
if int(index) >= len(charArray) {
fmt.Print(" ")
} else {
fmt.Printf("%s", charArray[int(index)])
}
}
package main
import "CrazyImg/utils"
/**
* 主入口
*
* @author Yushanma
* @since 2022/10/13 18:57
*/
func main() {
imgFile := "D:\\GWorkSpace\\CrazyImg\\data\\img0.png"
utils.ReadPic(imgFile)
}
四、TXT查看效果
效果与字体相关,这里使用的是新宋体-粗体-四号。