package picture_service
import (
"errors"
"github.com/nfnt/resize"
"image"
"image/draw"
"image/jpeg"
"image/png"
"log"
"net/http"
"os"
)
type PictureService struct{}
func NewPictureService() *PictureService {
return &PictureService{}
}
func (service *PictureService) PictureMerge(sign string, pic string, newImagePath string, left int, up int, picWidth int, picHeight int, signWidth int, signHeight int) (err error) {
signFile, err := os.Open(sign)
if err != nil {
return
}
defer signFile.Close()
sImage, _, err := image.Decode(signFile)
if err != nil {
return
}
signImage := resize.Resize(uint(signWidth), uint(signHeight), sImage, resize.Lanczos3)
picFile, err := os.Open(pic)
if err != nil {
return
}
defer picFile.Close()
picBytes, err := os.ReadFile(pic)
if err != nil {
return
}
contentType := http.DetectContentType(picBytes)
var picImage image.Image
if contentType == "image/jpeg" || contentType == "image/jpg" {
picImage, err = jpeg.Decode(picFile)
if err != nil {
return
}
} else if contentType == "image/png" {
picImage, err = png.Decode(picFile)
if err != nil {
return
}
} else {
return errors.New("未知圖片型別")
}
// 重置底圖大小
resizePicImage := resize.Resize(uint(picWidth), uint(picHeight), picImage, resize.Lanczos3)
// 新建畫布,邊界與底圖一致
templateImage := image.NewRGBA(resizePicImage.Bounds())
// 將底圖覆蓋畫布上,座標起點為0,0
draw.Draw(templateImage, resizePicImage.Bounds(), resizePicImage, resizePicImage.Bounds().Min, draw.Over)
if err != nil {
log.Panicln(err.Error())
return
}
// 簽章圖片的高、寬的 1/2 就是,簽章圖片中心到右下角距離。文字資訊的中心:向左距離(left),向上距離(up)
// left -寬 = l,up - 高 = h
// 向左移動 l,向上移動 h,就可以讓印章圖的中心點和文字的中心點總是重合,這樣印章就是總是在文字上面
imaCenterLeft := signImage.Bounds().Dx() / 2
imaCenterUp := signImage.Bounds().Dy() / 2
l := left - imaCenterLeft
h := up - imaCenterUp
// 向左移動X減少,向上移動Y減少
offset := image.Pt(templateImage.Bounds().Dx()-signImage.Bounds().Dx()-l, templateImage.Bounds().Dy()-signImage.Bounds().Dy()-h)
draw.Draw(
templateImage,
signImage.Bounds().Add(offset),
signImage,
// 0,0 為起點
image.Point{},
draw.Over)
err = service.savePng(templateImage, newImagePath)
return
}
func (service *PictureService) savePng(pic *image.RGBA, path string) (err error) {
dstFile, err := os.Create(path)
if err != nil {
return
}
defer dstFile.Close()
err = png.Encode(dstFile, pic)
return
}