196 lines
3.9 KiB
Go
196 lines
3.9 KiB
Go
// Package image ...
|
|
//
|
|
// Description : GIF相关操作
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 2021-11-29 12:43 下午
|
|
package image
|
|
|
|
import (
|
|
"errors"
|
|
"image"
|
|
"image/color"
|
|
"image/color/palette"
|
|
"image/draw"
|
|
"image/gif"
|
|
"image/jpeg"
|
|
"image/png"
|
|
"os"
|
|
|
|
"git.zhangdeman.cn/zhangdeman/gopkg/util"
|
|
)
|
|
|
|
var (
|
|
// GIF ...
|
|
GIF *GIFConvert
|
|
)
|
|
|
|
func init() {
|
|
GIF = &GIFConvert{}
|
|
}
|
|
|
|
// GIFConvert gif转换
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 12:44 下午 2021/11/29
|
|
type GIFConvert struct {
|
|
}
|
|
|
|
// Generate 生成
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 2:13 下午 2021/11/29
|
|
func (g *GIFConvert) Generate(sourceImageList []string, savePath string) error {
|
|
if len(sourceImageList) == 0 {
|
|
return errors.New("source image list is empty")
|
|
}
|
|
var (
|
|
err error
|
|
formatImgList []ImgInfo
|
|
disposals []byte
|
|
images []*image.Paletted
|
|
// 播放速度设置 , 100 次多少秒
|
|
delays []int
|
|
)
|
|
if formatImgList, err = g.checkImageType(sourceImageList); nil != err {
|
|
return err
|
|
}
|
|
|
|
for _, imgInfo := range formatImgList {
|
|
img, gErr := g.loadImage(imgInfo)
|
|
if nil != gErr {
|
|
return gErr
|
|
}
|
|
cp := g.getPalette(img)
|
|
//cp:=append(palette.WebSafe,color.Transparent)
|
|
disposals = append(disposals, gif.DisposalBackground) //透明图片需要设置
|
|
p := image.NewPaletted(image.Rect(0, 0, 640, 996), cp)
|
|
draw.Draw(p, p.Bounds(), img, image.ZP, draw.Src)
|
|
images = append(images, p)
|
|
delays = append(delays, 100)
|
|
}
|
|
gifInstance := &gif.GIF{
|
|
Image: images,
|
|
Delay: delays,
|
|
LoopCount: -1,
|
|
Disposal: disposals,
|
|
}
|
|
f, fErr := os.Create(savePath)
|
|
if fErr != nil {
|
|
return fErr
|
|
}
|
|
defer func() { _ = f.Close() }()
|
|
return gif.EncodeAll(f, gifInstance)
|
|
}
|
|
|
|
// checkImageType 检测图片类型
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 2:16 下午 2021/11/29
|
|
func (g *GIFConvert) checkImageType(sourceImageList []string) ([]ImgInfo, error) {
|
|
result := make([]ImgInfo, 0)
|
|
for _, item := range sourceImageList {
|
|
imgType := util.GetFileType(item)
|
|
if len(imgType) == 0 {
|
|
return result, errors.New(item + " parse img type fail!")
|
|
}
|
|
result = append(result, ImgInfo{
|
|
Path: item,
|
|
Type: imgType,
|
|
})
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
// loadImage 加载图片内容
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 2:52 下午 2021/11/29
|
|
func (g *GIFConvert) loadImage(imgInfo ImgInfo) (image.Image, error) {
|
|
var (
|
|
err error
|
|
f *os.File
|
|
)
|
|
if f, err = os.Open(imgInfo.Path); nil != err {
|
|
return nil, err
|
|
}
|
|
|
|
defer func() {
|
|
_ = f.Close()
|
|
}()
|
|
|
|
switch imgInfo.Type {
|
|
case TypePNG:
|
|
if img, imgErr := png.Decode(f); nil != err {
|
|
return nil, imgErr
|
|
} else {
|
|
return img, nil
|
|
}
|
|
case TypeJPEG:
|
|
fallthrough
|
|
case TypeJPG:
|
|
if img, imgErr := jpeg.Decode(f); nil != err {
|
|
return nil, imgErr
|
|
} else {
|
|
return img, nil
|
|
}
|
|
case TypeGIF:
|
|
if img, imgErr := gif.Decode(f); nil != err {
|
|
return nil, imgErr
|
|
} else {
|
|
return img, nil
|
|
}
|
|
default:
|
|
return nil, errors.New(imgInfo.Type + " is not support!")
|
|
}
|
|
}
|
|
|
|
// getPalette ...
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 3:01 下午 2021/11/29
|
|
func (g *GIFConvert) getPalette(m image.Image) color.Palette {
|
|
p := color.Palette{color.RGBA{0x00, 0x00, 0x00, 0x00}}
|
|
p9 := color.Palette(palette.Plan9)
|
|
b := m.Bounds()
|
|
black := false
|
|
for y := b.Min.Y; y < b.Max.Y; y++ {
|
|
for x := b.Min.X; x < b.Max.X; x++ {
|
|
c := m.At(x, y)
|
|
cc := p9.Convert(c)
|
|
if cc == p9[0] {
|
|
black = true
|
|
}
|
|
if g.isInPalette(p, cc) == -1 {
|
|
p = append(p, cc)
|
|
}
|
|
}
|
|
}
|
|
if len(p) < 256 && black == true {
|
|
p[0] = color.RGBA{0x00, 0x00, 0x00, 0x00} // transparent
|
|
p = append(p, p9[0])
|
|
}
|
|
return p
|
|
}
|
|
|
|
// isInPalette ...
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 3:01 下午 2021/11/29
|
|
func (g *GIFConvert) isInPalette(p color.Palette, c color.Color) int {
|
|
ret := -1
|
|
for i, v := range p {
|
|
if v == c {
|
|
return i
|
|
}
|
|
}
|
|
return ret
|
|
}
|