You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
299 lines
6.3 KiB
299 lines
6.3 KiB
package share_img
|
|
|
|
import (
|
|
"fmt"
|
|
"image"
|
|
"image/color"
|
|
"image/draw"
|
|
_ "image/jpeg"
|
|
"image/png"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"recook/configs"
|
|
"recook/internal/back"
|
|
"recook/internal/static_path"
|
|
"runtime"
|
|
|
|
"github.com/astaxie/beego"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/golang/freetype"
|
|
"github.com/golang/freetype/truetype"
|
|
farmhash "github.com/leemcloughlin/gofarmhash"
|
|
)
|
|
|
|
const (
|
|
fontDPI float64 = 72 // 屏幕每英寸的分辨率
|
|
|
|
)
|
|
|
|
var (
|
|
PingFangFont *truetype.Font
|
|
PingFangScRegular = "/qr_resource/PingFang-SC-Regular.ttf"
|
|
DefaultBackImage = "/qr_resource/default.png"
|
|
)
|
|
|
|
func init() {
|
|
dir, _ := os.Executable()
|
|
exPath := filepath.Dir(dir)
|
|
if runtime.GOOS != "linux" {
|
|
PingFangScRegular = "." + PingFangScRegular
|
|
DefaultBackImage = "." + DefaultBackImage
|
|
exPath = ""
|
|
}
|
|
|
|
fontBytes, err := ioutil.ReadFile(exPath + PingFangScRegular)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
PingFangFont, err = freetype.ParseFont(fontBytes)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
beego.SetLogFuncCall(true)
|
|
|
|
}
|
|
|
|
type shareImage struct {
|
|
File string
|
|
QrSize int
|
|
X int
|
|
Y int
|
|
}
|
|
|
|
func GetSharePhoto(c *gin.Context) {
|
|
share_code := c.Param("code")
|
|
url := fmt.Sprintf(`https://testh5.reecook.cn/#/user/appRegister/%s`, share_code)
|
|
if configs.IsProductionEnv() {
|
|
url = fmt.Sprintf(`https://h5.reecook.cn/#/user/appRegister/%s`, share_code)
|
|
}
|
|
|
|
dir, _ := os.Executable()
|
|
exPath := filepath.Dir(dir)
|
|
if runtime.GOOS != "linux" {
|
|
exPath = ""
|
|
}
|
|
|
|
//这边加个for 循环
|
|
//var imgBgArr = []string{"/qr_resource/default1.png", "/qr_resource/default2.png", "/qr_resource/default3.png"}
|
|
imgBgArr := []shareImage{{"/qr_resource/default1.jpg", 191, 725, 1334}, {"/qr_resource/default2.png", 115, 421, 874}, {"/qr_resource/default3.png", 254, 335, 1191}}
|
|
|
|
var imgBgArrs []string
|
|
|
|
urlImg1 := "https://testcdn.reecook.cn/static"
|
|
if configs.IsProductionEnv() {
|
|
urlImg1 = "https://cdn.reecook.cn/static"
|
|
}
|
|
|
|
for i, imgbg := range imgBgArr {
|
|
|
|
back_img := exPath + imgbg.File
|
|
// 判断文件是否存在
|
|
path, err := Merge(back_img, share_code, url, i, imgbg)
|
|
if err != nil {
|
|
beego.Error(err)
|
|
return
|
|
}
|
|
/* 允许追加空切片 */
|
|
imgBgArrs = append(imgBgArrs, urlImg1+path)
|
|
|
|
//img, err := imaging.Open(path)
|
|
//if err != nil {
|
|
// beego.Error(err)
|
|
// return
|
|
//}
|
|
//buffer := new(bytes.Buffer)
|
|
//if err := png.Encode(buffer, img); err != nil {
|
|
// http.Err(c, "png转码出错")
|
|
// return
|
|
//}
|
|
|
|
}
|
|
|
|
//上面生成多张
|
|
back.Suc(c, "操作成功", &imgBgArrs)
|
|
|
|
//c.Data(200, "image/png", buffer.Bytes())
|
|
}
|
|
|
|
// 判断所给路径文件/文件夹是否存在
|
|
func Exists(path string) bool {
|
|
_, err := os.Stat(path) //os.Stat获取文件信息
|
|
if err != nil {
|
|
if os.IsExist(err) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func GetFileName(back_img, code, url string, number int) (filename, save_path string, show_path string, err error) {
|
|
filename = fmt.Sprintf("%s_%d_%d.png", "shareInvite", farmhash.Hash64([]byte(fmt.Sprintf("%s_%s", back_img, code))), number)
|
|
save_path = filepath.Join(static_path.Dir.Root, static_path.Dir.Photo, filename)
|
|
show_path = filepath.Join(static_path.Dir.Photo, filename)
|
|
return filename, save_path, show_path, nil
|
|
}
|
|
|
|
func Merge(back_img, code, url string, number int, imgTemp shareImage) (path string, err error) {
|
|
_, save_path, show_path, err := GetFileName(back_img, code, url, number)
|
|
beego.Info(save_path)
|
|
if Exists(save_path) {
|
|
//不使用缓存
|
|
return show_path, nil
|
|
}
|
|
|
|
imgb, err := os.Open(back_img)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
img, _, _ := image.Decode(imgb)
|
|
defer imgb.Close()
|
|
|
|
//share_img, err := GetShareCodeImage(code)
|
|
//if err != nil {
|
|
// panic(err)
|
|
//}
|
|
|
|
qr_img, err := QrForShare(url, imgTemp.QrSize)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
b := img.Bounds()
|
|
m := image.NewRGBA(b)
|
|
// // share add
|
|
//offset_share := image.Pt(340, 1081)
|
|
//draw.Draw(m, b, img, image.ZP, draw.Src)
|
|
//不显示邀请码
|
|
//draw.Draw(m, share_img.Bounds().Add(offset_share), share_img, image.ZP, draw.Over)
|
|
|
|
// qr add
|
|
offset := image.Pt(imgTemp.X, imgTemp.Y)
|
|
draw.Draw(m, b, img, image.ZP, draw.Src)
|
|
draw.Draw(m, qr_img.Bounds().Add(offset), qr_img, image.ZP, draw.Over)
|
|
|
|
// res_path := fmt.Sprintf("%s/%s_%s", save_path, DefaultBackImage, code)
|
|
imgw, _ := os.Create(save_path)
|
|
png.Encode(imgw, m)
|
|
//jpeg.Encode(imgw, m, &jpeg.Options{jpeg.DefaultQuality})
|
|
defer imgw.Close()
|
|
|
|
return show_path, nil
|
|
}
|
|
|
|
func GetShareCodeImage(code string) (image.Image, error) {
|
|
text := "邀请码:" + code
|
|
fontSize := 32
|
|
dx := getEachTextWidth(text) * int(fontSize) / 1000
|
|
dy := fontSize
|
|
// 新建一个 指定大小的 RGBA位图
|
|
img := image.NewNRGBA(image.Rect(0, 0, dx, dy+10))
|
|
// 画背景
|
|
for y := 0; y < dy+20; y++ {
|
|
for x := 0; x < dx; x++ {
|
|
// 设置某个点的颜色,依次是 RGBA
|
|
img.Set(x, y, color.RGBA{0, 0, 0, 0})
|
|
}
|
|
}
|
|
|
|
c := freetype.NewContext()
|
|
c.SetDPI(fontDPI)
|
|
c.SetFont(PingFangFont)
|
|
c.SetFontSize(float64(fontSize))
|
|
c.SetClip(img.Bounds())
|
|
c.SetDst(img)
|
|
|
|
c.SetSrc(image.NewUniform(color.RGBA{255, 255, 255, 255}))
|
|
|
|
pt := freetype.Pt(0, fontSize) // 字出现的位置
|
|
|
|
_, err := c.DrawString(text, pt)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return img, nil
|
|
|
|
}
|
|
|
|
func getEachTextWidth(word string) int {
|
|
word_runes := []rune(word)
|
|
width := 0
|
|
for _, v := range word_runes {
|
|
if v, ok := number_map[string(v)]; ok {
|
|
width += v
|
|
} else {
|
|
width += number_map["base"]
|
|
}
|
|
}
|
|
return width
|
|
}
|
|
|
|
var number_map = map[string]int{
|
|
"base": 1000,
|
|
" ": 500,
|
|
"0": 880,
|
|
"1": 510,
|
|
"2": 780,
|
|
"3": 800,
|
|
"4": 880,
|
|
"5": 820,
|
|
"6": 840,
|
|
"7": 740,
|
|
"8": 870,
|
|
"9": 840,
|
|
"A": 960,
|
|
"B": 900,
|
|
"C": 810,
|
|
"D": 910,
|
|
"E": 800,
|
|
"F": 780,
|
|
"G": 940,
|
|
"H": 930,
|
|
"I": 500,
|
|
"J": 440,
|
|
"K": 820,
|
|
"L": 630,
|
|
"M": 1140,
|
|
"N": 880,
|
|
"O": 910,
|
|
"P": 870,
|
|
"Q": 900,
|
|
"R": 920,
|
|
"S": 870,
|
|
"T": 780,
|
|
"U": 910,
|
|
"V": 910,
|
|
"W": 1110,
|
|
"X": 910,
|
|
"Y": 860,
|
|
"Z": 880,
|
|
"a": 790,
|
|
"b": 810,
|
|
"c": 710,
|
|
"d": 820,
|
|
"e": 860,
|
|
"f": 580,
|
|
"g": 840,
|
|
"h": 780,
|
|
"i": 330,
|
|
"j": 440,
|
|
"k": 760,
|
|
"l": 330,
|
|
"m": 990,
|
|
"n": 830,
|
|
"o": 830,
|
|
"p": 880,
|
|
"q": 830,
|
|
"r": 540,
|
|
"s": 800,
|
|
"t": 590,
|
|
"u": 830,
|
|
"v": 810,
|
|
"w": 950,
|
|
"x": 830,
|
|
"y": 860,
|
|
"z": 800,
|
|
}
|