go根据传入的表头和表内容及文字描述生成base64图片
package table2base64 import ( "bytes" "encoding/base64" "image" "image/color" "image/draw" "image/png" "io" "math/rand" "os" "strconv" "time" "github.com/golang/freetype/truetype" "golang.org/x/image/font" "golang.org/x/image/math/fixed" "icode.baidu.com/baidu/gdp/env" ) const ( DefaultClosWidth int = 103 //默认列宽 DefaultRowsHeight int = 36 //默认行高 DefaultTextRowsHeight int = 20 //默认文字描述行高 ) var ( DefaultTTFFile = "" DefaultTTFFileBOLD = "" ) // 初始化函数 func init() { DefaultTTFFile = env.ConfDir() + "/SIMYOU.TTF" DefaultTTFFileBOLD = env.ConfDir() + "/FZBOLD.TTF" } type DrawString interface { string() string } // TabString 自定义字符串类型 type TabString string // string 方法返回字符串 s 的值 func (s TabString) string() string { return string(s) } // TabNumber 自定义数值类型 type TabNumber float64 // string 方法返回 TabNumber 类型的字符串表示形式 func (n TabNumber) string() string { return strconv.FormatFloat(float64(n), 'f', -1, 64) } type TableContent [][]DrawString type TableImg struct { TTFFile string //字体文件路径 TTFFILEBold string //字体文件路径(粗体) Header []string //表格头 Content [][]interface{} //外部初始化表格内容 TextDesc []string //文字描述 ClosWidth int //列宽 RowsHeight int //行高 TextRowsHeight int //文字描述行高 selfContent TableContent //内部使用表格内容 imgWidth int //图片宽 tableHeight int //表格高 imgHeight int //图片高 cols int //列数 rows int //行数 base64Str string //base64数据 img *image.RGBA //图像资源对象 } // NewTableImg 返回一个TableImg对象 func NewTableImg(tab *TableImg) *TableImg { var c TableContent for _, con := range tab.Content { var cSlice []DrawString for _, cc := range con { value := convertToDrawValue(cc) cSlice = append(cSlice, value) } c = append(c, cSlice) } if tab.TTFFile == "" { tab.TTFFile = DefaultTTFFile } if tab.TTFFILEBold == "" { tab.TTFFILEBold = DefaultTTFFileBOLD } return &TableImg{ TTFFile: tab.TTFFile, TTFFILEBold: tab.TTFFILEBold, Header: tab.Header, Content: tab.Content, ClosWidth: tab.ClosWidth, RowsHeight: tab.RowsHeight, TextDesc: tab.TextDesc, TextRowsHeight: tab.TextRowsHeight, selfContent: c, imgWidth: tab.ClosWidth * len(tab.Header), tableHeight: tab.RowsHeight * (len(tab.Content) + 1), imgHeight: tab.RowsHeight*(len(tab.Content)+1) + tab.TextRowsHeight*(len(tab.TextDesc)+1), cols: len(tab.Header), rows: len(tab.Content) + 1, base64Str: "", img: nil, } } // convertToDrawValue 将一个输入转换为DrawString类型的值 func convertToDrawValue(cc interface{}) DrawString { var value DrawString switch v := cc.(type) { case int: value = TabNumber(v) case int8: value = TabNumber(v) case int16: value = TabNumber(v) case int32: value = TabNumber(v) case int64: value = TabNumber(v) case float32: value = TabNumber(v) case float64: value = TabNumber(v) case string: value = TabString(v) default: value = TabString("") } return value } // GenerateImageGetBase64 生成表格图片并返回base64 func (tab *TableImg) GenerateImageGetBase64() (string, error) { cols := len(tab.Header) rows := len(tab.Content) + 1 // 创建一个新的 RGBA 图片 tab.img = image.NewRGBA(image.Rect(0, 0, tab.imgWidth, tab.imgHeight)) // 以白色作为背景绘制整个图片 draw.Draw(tab.img, tab.img.Bounds(), &image.Uniform{color.White}, image.Point{}, draw.Src) //填充表头背景色 fillArea := image.Rect(0, 0, tab.imgWidth, tab.RowsHeight) draw.Draw(tab.img, fillArea, &image.Uniform{color.RGBA{162, 206, 232, 255}}, image.Point{0, 0}, draw.Src) randSource := rand.NewSource(time.Now().UnixNano()) r := rand.New(randSource) for i := 1; i < rows; i += 3 { fillArea := image.Rect(0, tab.RowsHeight*(i+2), tab.imgWidth, tab.RowsHeight*(i+3)) draw.Draw(tab.img, fillArea, &image.Uniform{color.RGBA{uint8(r.Intn(100) + 150), uint8(r.Intn(100) + 150), uint8(r.Intn(100) + 150), 255}}, image.Point{0, 0}, draw.Src) } //绘制表格线 for i := 0; i <= cols; i++ { x := i * (tab.imgWidth / cols) if x >= tab.imgWidth { x = tab.imgWidth - 1 } tab.drawLine(x, 0, x, tab.tableHeight, color.RGBA{123, 123, 123, 255}) } for i := 0; i <= rows; i++ { y := i * (tab.tableHeight / rows) if y >= tab.tableHeight { y = tab.tableHeight - 1 } tab.drawLine(0, y, tab.imgWidth, y, color.RGBA{123, 123, 123, 255}) } f, err := os.OpenFile(tab.TTFFile, os.O_RDONLY, 0644) // 0644表示文件权限 if err != nil { return "", err } defer f.Close() byteFile, _ := io.ReadAll(f) fBold, err := os.OpenFile(tab.TTFFILEBold, os.O_RDONLY, 0644) // 0644表示文件权限 if err != nil { return "", err } defer fBold.Close() byteFileBold, _ := io.ReadAll(fBold) // 在图片上绘制内容 // 绘制 header 中的内容 for i, h := range tab.Header { if err := tab.drawText(h, (tab.imgWidth/cols)*i+10, 20, byteFile); err != nil { return "", err } } // 绘制 content 中的内容 for i, c := range tab.selfContent { bFile := byteFile if i >= len(tab.selfContent)-3 { bFile = byteFileBold } y := (tab.tableHeight/rows)*(i+1) + 20 for j, item := range c { x := (tab.imgWidth/cols)*j + 10 if err := tab.drawText(item.string(), x, y, bFile); err != nil { return "", err } } } // 绘制 文字描述 中的内容 for i, c := range tab.TextDesc { y := (tab.tableHeight/rows)*(len(tab.selfContent)+1) + 20 y += i * tab.TextRowsHeight if err := tab.drawText(c, 10, y, byteFile); err != nil { return "", err } } // 创建一个内存缓冲区 var buf bytes.Buffer // 将图片编码为 PNG 格式并写入缓冲区 err = png.Encode(&buf, tab.img) if err != nil { return "", err } // 将 PNG 图片转换为 base64 编码的字符串 tab.base64Str = base64.StdEncoding.EncodeToString(buf.Bytes()) return tab.base64Str, nil } // drawText 方法绘制文本到图像上 func (tab *TableImg) drawText(text string, x, y int, fileByte []byte) error { col := color.RGBA{A: 255} point := image.Point{X: x, Y: y} ff, _ := truetype.Parse(fileByte) drawer := &font.Drawer{ Dst: tab.img, Src: image.NewUniform(col), Face: truetype.NewFace(ff, &truetype.Options{ Size: 14, }), Dot: fixed.P(point.X, point.Y), } drawer.DrawString(text) return nil } // drawLine 函数绘制一条直线。 // x0,y0,x1和y1表示起点和终点的坐标值,c为直线颜色。 func (tab *TableImg) drawLine(x0, y0, x1, y1 int, c color.Color) { dx := abs(x1 - x0) dy := abs(y1 - y0) sx, sy := 1, 1 if x0 > x1 { sx = -1 } if y0 > y1 { sy = -1 } err := dx - dy for { tab.img.Set(x0, y0, c) if x0 == x1 && y0 == y1 { break } e2 := 2 * err if e2 > -dy { err -= dy x0 += sx } if e2 < dx { err += dx y0 += sy } } } // abs 函数返回输入整数的绝对值。 func abs(x int) int { if x < 0 { return -x } return x }
用法
base64, _ := table2base64.NewTableImg(&table2base64.TableImg{ Header: header, Content: data, ClosWidth: 115, TextDesc: text, TextRowsHeight: table2base64.DefaultTextRowsHeight, RowsHeight: table2base64.DefaultRowsHeight, TTFFile: table2base64.DefaultTTFFile, }).GenerateImageGetBase64()
发表评论