├─cmd // 程序入口
├─img // 图片
├─lib // 依赖库
│ └─font
│ └─config
├─res // 输出
└─util // 工具
cmd
package main
import (
"flag"
uuid "github.com/satori/go.uuid"
"mock/lib/font/config"
. "mock/util"
)
func main() {
// 命令行指令
flag.Parse()
// ================== 参数处理
// 处理字符
var charset []string
if len(*Char) == 0 {
charset = []string{"你", "好", "世", "界"}
} else {
for _, v := range *Char {
charset = append(charset, string(v))
}
}
// 输出路径
outPath := ""
if len(*Out) == 0 {
outPath = "../res/" + uuid.NewV4().String() + ".png"
} else {
outPath = "../res/" + *Out + ".png"
}
// 处理方向
horV := "H"
switch *HorV {
default:
horV = "H"
case "V":
horV = "V"
}
// 处理字体
font := config.Font_2
switch *Font {
default:
font = config.Font_2
case "f2":
font = config.Font_2
}
// 生成对联
Generator(charset, outPath, horV, font)
}
lib/config
package config
type TextFont struct {
FontName string // 字体名称
FontSize float64 // 字体大小
X, Y int // 字体渲染位置
}
var Font_1 = TextFont{"方正楷体简体.ttf", 390, 60, 520}
var Font_2 = TextFont{"演示夏行楷.ttf", 390, 0, 550}
util
package util
import (
"flag"
"github.com/golang/freetype"
"image"
"image/color"
"image/png"
"io/ioutil"
"log"
. "mock/lib/font/config"
"os"
)
// charset 中文文字
// horV - H-横排,V-竖排
// out 输出文件名
// font 字体
var (
Char = flag.String("charset", "你好世界", "text (ZH)")
HorV = flag.String("horV", "H", "H | V")
Out = flag.String("out", "", "output file name")
Font = flag.String("font", "f1", "f1 | f2")
)
func Generator(charset []string, outPath string, horV string, textFont TextFont) {
// 打开背景图
bgFile, err := os.OpenFile("./img/bg.png", os.O_RDONLY, 6)
if err != nil {
log.Fatal(err)
}
defer bgFile.Close()
// 解码
i, err := png.Decode(bgFile)
if err != nil {
log.Fatal(err)
}
// 图片的宽度
srcWidth := 640
// 图片的高度
srcHeight := 640
if horV == "H" {
srcWidth = 640 * len(charset)
}
if horV == "V" {
srcHeight = 640 * len(charset)
}
imgFile, _ := os.Create(outPath)
defer imgFile.Close()
img := image.NewRGBA(image.Rect(0, 0, srcWidth, srcHeight))
if horV == "H" {
log.Println("横向生成,渲染背景...")
// 根据字符长度创建背景
for index := 0; index < len(charset); index++ {
// 复制背景图
for y := 0; y < srcHeight; y++ {
for x := index * 640; x < srcWidth; x++ {
if x < 640 {
img.Set(x, y, i.At(x, y))
} else {
img.Set(x, y, i.At(x-index*640, y))
}
}
}
}
}
if horV == "V" {
log.Println("竖向生成,渲染背景...")
// 根据字符长度创建背景
for index := 0; index < len(charset); index++ {
// 复制背景图
for y := index * 640; y < srcHeight; y++ {
for x := 0; x < srcWidth; x++ {
if y < 640 {
img.Set(x, y, i.At(x, y))
} else {
img.Set(x, y, i.At(x, y-index*640))
}
}
}
}
}
// 读取字体数据
fontFileName := "./lib/font/" + textFont.FontName
fontBytes, err := ioutil.ReadFile(fontFileName)
log.Printf("加载字体:%s...", textFont.FontName)
if err != nil {
log.Fatal(err)
}
// 载入字体数据
font, err := freetype.ParseFont(fontBytes)
if err != nil {
log.Println("载入字体失败!", err)
}
f := freetype.NewContext()
// 设置分辨率
f.SetDPI(100)
// 设置字体
f.SetFont(font)
// 设置尺寸
f.SetFontSize(textFont.FontSize)
f.SetClip(img.Bounds())
// 设置输出的图片
f.SetDst(img)
// 设置字体颜色(黑色)
f.SetSrc(image.NewUniform(color.Black))
if horV == "H" {
log.Println("开始绘制对联...")
// 绘制字符
for index := 0; index < len(charset); index++ {
// 设置字体的位置
pt := freetype.Pt(textFont.X+index*640, textFont.Y)
_, err = f.DrawString(charset[index], pt)
if err != nil {
log.Fatal(err)
}
}
}
if horV == "V" {
// 绘制字符
for index := 0; index < len(charset); index++ {
// 设置字体的位置
pt := freetype.Pt(textFont.X, textFont.Y+index*640)
_, err = f.DrawString(charset[index], pt)
if err != nil {
log.Fatal(err)
}
}
}
// 以png 格式写入文件作为输出
err = png.Encode(imgFile, img)
if err != nil {
log.Fatal(err)
}
log.Println("Done.")
}
方正楷体测试
方正楷体、演示夏行楷都是可以免费商用的字体,测试这两种字体为例。
横向对联D:\GoFiles\mock-exls\cmd>go build
D:\GoFiles\mock-exls\cmd>cmd.exe -help
Usage of cmd.exe:
-charset string
text (ZH) (default "你好世界")
-font string
f1 | f2 (default "f1")
-horV string
H | V (default "H")
-out string
output file name
D:\GoFiles\mock-exls\cmd>cmd.exe -charset "既许一人以偏爱"
2022/01/22 16:30:26 横向生成,渲染背景...
2022/01/22 16:30:27 加载字体:方正楷体简体...
2022/01/22 16:30:27 开始绘制对联...
2022/01/22 16:30:27 Done.
D:\GoFiles\mock-exls\cmd>cmd.exe -charset "愿尽余生之慷慨"
2022/01/22 16:31:17 横向生成,渲染背景...
2022/01/22 16:31:18 加载字体:方正楷体简体...
2022/01/22 16:31:18 开始绘制对联...
2022/01/22 16:31:18 Done.
效果
竖向对联
D:\GoFiles\mock-exls\cmd>cmd.exe -charset "算法数据思路清晰" -horV "V"
2022/01/22 16:52:13 竖向生成,渲染背景...
2022/01/22 16:52:14 加载字体:方正楷体简体...
2022/01/22 16:52:14 Done.
D:\GoFiles\mock-exls\cmd>cmd.exe -charset "编译链接一气呵成" -horV "V"
2022/01/22 16:52:45 竖向生成,渲染背景...
2022/01/22 16:52:45 加载字体:方正楷体简体...
2022/01/22 16:52:45 Done.
D:\GoFiles\mock-exls\cmd>cmd.exe -charset "码到功成"
2022/01/22 16:53:30 横向生成,渲染背景...
2022/01/22 16:53:30 加载字体:方正楷体简体...
2022/01/22 16:53:30 开始绘制对联...
2022/01/22 16:53:30 Done.
效果
春联测试
演示夏行楷测试
引用百度AI生成智能春联 工程目录变动
├─cmd
├─img
├─lib
│ └─font
│ └─config
├─res
├─sys // 新增系统变量
└─util
新增百度AI工具类
package util
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"mock/sys"
"net/http"
"strings"
)
// 返回结果
type CoupletsRes struct {
Couplets Couplets `json:"couplets"`
}
type Couplets struct {
First string `json:"first"`
Second string `json:"second"`
Center string `json:"center"`
}
type AccessTokenRes struct {
RefreshToken string `json:"refresh_token"`
ExpiresIn int `json:"expires_in"`
Scope string `json:"scope"`
SessionKey string `json:"session_key"`
AccessToken string `json:"access_token"`
SessionSecret string `json:"session_secret"`
}
func GetAiSpringCouplets(text string, index int) CoupletsRes {
client := http.Client{}
// 请求参数
param := fmt.Sprintf(sys.API_PARAM, text, index)
request, _ := http.NewRequest(http.MethodPost, fmt.Sprintf(sys.URL, sys.ACCESS_TOKEN), strings.NewReader(param))
// 加入 header
request.Header.Add("content-type", "application/json")
r, e := client.Do(request)
if e != nil {
log.Fatal(e)
}
all, e := ioutil.ReadAll(r.Body)
if e != nil {
log.Fatal(e)
}
// 将请求结果反序列化
var coupletsRes CoupletsRes
json.Unmarshal(all, &coupletsRes)
log.Println(string(all))
return coupletsRes
}
func GetAccessToken() AccessTokenRes {
client := http.Client{}
// 请求参数
param := fmt.Sprintf("")
request, _ := http.NewRequest(http.MethodPost, fmt.Sprintf(sys.ACCESS_TOKEN_URL, sys.CLIENT_ID, sys.CLIENT_SECRET), strings.NewReader(param))
r, e := client.Do(request)
if e != nil {
log.Fatal(e)
}
all, e := ioutil.ReadAll(r.Body)
if e != nil {
log.Fatal(e)
}
// 将请求结果反序列化
var accessTokenRes AccessTokenRes
json.Unmarshal(all, &accessTokenRes)
log.Println(string(all))
return accessTokenRes
}
春联工具类修改参数
package util
import (
"flag"
"github.com/golang/freetype"
"image"
"image/color"
"image/png"
"io/ioutil"
"log"
. "mock/lib/font/config"
"os"
)
// charset 中文文字
// horV H-横排,V-竖排
// out 输出文件名
// font 字体
// Mode 模式 customer 为用户输入 ,aiRobot 为百度 AI 生成
// Center 对联主题,仅 aiRobot 模式下可以指定
// Index 对联下标,仅 aiRobot 模式下可以指定
var (
Char = flag.String("charset", "你好世界", "text (ZH)")
HorV = flag.String("horV", "H", "H | V")
Out = flag.String("out", "", "output file name")
Font = flag.String("font", "f1", "f1 | f2")
Mode = flag.String("mode","customer","customer | aiRobot")
Center = flag.String("center","","couplets center")
Index = flag.Int("index",0,"couplets index")
)
func Generator(charset []string, outPath string, horV string, textFont TextFont) {
// 打开背景图
bgFile, err := os.OpenFile("../img/bg.png", os.O_RDONLY, 6)
if err != nil {
log.Fatal(err)
}
defer bgFile.Close()
// 解码
i, err := png.Decode(bgFile)
if err != nil {
log.Fatal(err)
}
// 图片的宽度
srcWidth := 640
// 图片的高度
srcHeight := 640
if horV == "H" {
srcWidth = 640 * len(charset)
}
if horV == "V" {
srcHeight = 640 * len(charset)
}
imgFile, _ := os.Create(outPath)
defer imgFile.Close()
img := image.NewRGBA(image.Rect(0, 0, srcWidth, srcHeight))
if horV == "H" {
log.Println("横向生成,渲染背景...")
// 根据字符长度创建背景
for index := 0; index < len(charset); index++ {
// 复制背景图
for y := 0; y < srcHeight; y++ {
for x := index * 640; x < srcWidth; x++ {
if x < 640 {
img.Set(x, y, i.At(x, y))
} else {
img.Set(x, y, i.At(x-index*640, y))
}
}
}
}
}
if horV == "V" {
log.Println("竖向生成,渲染背景...")
// 根据字符长度创建背景
for index := 0; index < len(charset); index++ {
// 复制背景图
for y := index * 640; y < srcHeight; y++ {
for x := 0; x < srcWidth; x++ {
if y < 640 {
img.Set(x, y, i.At(x, y))
} else {
img.Set(x, y, i.At(x, y-index*640))
}
}
}
}
}
// 读取字体数据
fontFileName := "../lib/font/" + textFont.FontName
fontBytes, err := ioutil.ReadFile(fontFileName)
log.Printf("加载字体:%s...", textFont.FontName)
if err != nil {
log.Fatal(err)
}
// 载入字体数据
font, err := freetype.ParseFont(fontBytes)
if err != nil {
log.Println("载入字体失败!", err)
}
f := freetype.NewContext()
// 设置分辨率
f.SetDPI(100)
// 设置字体
f.SetFont(font)
// 设置尺寸
f.SetFontSize(textFont.FontSize)
f.SetClip(img.Bounds())
// 设置输出的图片
f.SetDst(img)
// 设置字体颜色(黑色)
f.SetSrc(image.NewUniform(color.Black))
if horV == "H" {
log.Println("开始绘制对联...")
// 绘制字符
for index := 0; index < len(charset); index++ {
// 设置字体的位置
pt := freetype.Pt(textFont.X+index*640, textFont.Y)
_, err = f.DrawString(charset[index], pt)
if err != nil {
log.Fatal(err)
}
}
}
if horV == "V" {
// 绘制字符
for index := 0; index < len(charset); index++ {
// 设置字体的位置
pt := freetype.Pt(textFont.X, textFont.Y+index*640)
_, err = f.DrawString(charset[index], pt)
if err != nil {
log.Fatal(err)
}
}
}
// 以png 格式写入文件作为输出
err = png.Encode(imgFile, img)
if err != nil {
log.Fatal(err)
}
log.Println("Done.")
}
系统变量
package sys
var ACCESS_TOKEN = ""
var CLIENT_ID = ""
var CLIENT_SECRET = ""
// api 请求参数
var API_PARAM = `
{
"text": "%s",
"index": %d
}`
// 百度 AI 接口
var URL = "https://aip.baidubce.com/rpc/2.0/creation/v1/couplets?access_token=%s"
var ACCESS_TOKEN_URL = "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=%s&client_secret=%s"
程序入口修改
package main
import (
"flag"
uuid "github.com/satori/go.uuid"
"mock/lib/font/config"
. "mock/util"
)
func main() {
// 命令行指令
flag.Parse()
// ================== 参数处理
// 处理字符
var charset []string
if len(*Char) == 0 {
charset = []string{"你", "好", "世", "界"}
} else {
for _, v := range *Char {
charset = append(charset, string(v))
}
}
// 输出路径
outPath := ""
if len(*Out) == 0 {
outPath = "../res/" + uuid.NewV4().String() + ".png"
} else {
outPath = "../res/" + *Out + ".png"
}
// 处理方向
horV := "H"
switch *HorV {
default:
horV = "H"
case "V":
horV = "V"
}
// 处理字体
font := config.Font_1
switch *Font {
default:
font = config.Font_1
case "f2":
font = config.Font_2
}
switch *Mode {
default:
// 手动输入生成对联
Generator(charset, outPath, horV, font)
case "aiRobot":
// 百度 AI 生成对联
couplets := GetAiSpringCouplets(*Center, *Index).Couplets
center := couplets.Center
first := couplets.First
second := couplets.Second
for i := 0; i < 3; i++ {
charset = nil
if i == 0 {
for _, v := range center {
charset = append(charset, string(v))
}
} else if i == 1 {
for _, v := range first {
charset = append(charset, string(v))
}
} else {
for _, v := range second {
charset = append(charset, string(v))
}
}
outPath = "../res/" + uuid.NewV4().String() + ".png"
Generator(charset, outPath, horV, font)
}
}
}
智能版测试
D:\GoFiles\mock-exls\cmd>go build
D:\GoFiles\mock-exls\cmd>cmd.exe -help
Usage of cmd.exe:
-center string
couplets center
-charset string
text (ZH) (default "你好世界")
-font string
f1 | f2 (default "f1")
-horV string
H | V (default "H")
-index int
couplets index
-mode string
customer | aiRobot (default "customer")
-out string
output file name
D:\GoFiles\mock-exls\cmd>cmd.exe -mode "aiRobot" -center "千云祥集" -index 0
2022/01/23 18:11:29 {"couplets":{"center":"千云祥集","first":"万里祥光辉栋宇","second":"百年集色映梅花"},"log_id":1485193458259264015}
2022/01/23 18:11:29 横向生成,渲染背景...
2022/01/23 18:11:29 加载字体:方正楷体简体.ttf...
2022/01/23 18:11:29 开始绘制对联...
2022/01/23 18:11:29 Done.
2022/01/23 18:11:29 横向生成,渲染背景...
2022/01/23 18:11:29 加载字体:方正楷体简体.ttf...
2022/01/23 18:11:29 开始绘制对联...
2022/01/23 18:11:30 Done.
2022/01/23 18:11:30 横向生成,渲染背景...
2022/01/23 18:11:30 加载字体:方正楷体简体.ttf...
2022/01/23 18:11:30 开始绘制对联...
2022/01/23 18:11:30 Done.
参考:百度AI智能春联文档
新春祝福新的一年,祝愿大家身体健康,万事如意,依旧不失对新生活的憧憬和热爱,怀揣理想主义,迸发心中花火,活出滚烫人生。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)