使用Golang将多张图片合并为GIF动态图

发表时间: 2024-01-26 22:29

在Go语言实际开发中,会遇到将几张图片合成gif动态图情况,这里整理了两种实现方式

方式1

使用第三方库有
https://github.com/disintegration/imaging

支持图片格式 ".jpg",".jpeg",".gif",".png",".bmp",".webp"

package mainimport (    "errors"    "fmt"    "github.com/disintegration/imaging"    "golang.org/x/image/webp"    "image/draw"    "image"    "image/color/palette"    "image/gif"    "os"    "path/filepath")func main() {    imgArr := []string{"./img/1.jpeg","./img/2.png","./img/3.jpg","./img/4.jpg","./img/5.gif","./img/7.bmp"}    delay:=100//设置延迟    //新建gif结构体    outGif := &gif.GIF{}    for _, img := range imgArr {        //图像解码        inGif, err:=imageDecode(img)        //如果是 jpg jpeg  gif bmp png 类型,可替换imageDecode        //inGif, err:=imaging.Open(img)        if err!=nil {            fmt.Println("图像解码失败",err)            continue        }        //修改图片大小        inGif=imaging.Resize(inGif,500,500,imaging.Lanczos)        bounds := inGif.Bounds()        //创建一个新的image.Paletted对象用于存储带有调色板的图像        palettedImg := image.NewPaletted(bounds, palette.Plan9)        //将原始图像绘制到 palettedImg        draw.Draw(palettedImg, bounds, inGif, bounds.Min, draw.Src)        outGif.Image = append(outGif.Image, palettedImg)        outGif.Delay = append(outGif.Delay, delay)    }    f, _ := os.OpenFile("output.gif", os.O_WRONLY|os.O_CREATE, 0600)    defer f.Close()    gif.EncodeAll(f, outGif)}//图像解码func imageDecode(file string) (image.Image,error) {    f, err := os.Open(file)    if err!=nil {        return nil, err    }    defer f.Close()    ext:=filepath.Ext(file)    switch ext {    case ".jpg",".jpeg",".gif",".png",".bmp":        return  imaging.Decode(f)    case ".webp":        return webp.Decode(f)    default:        return nil,errors.New("图片格式错误")    }}

方式2

不通过第三方库 支持图片格式 ".jpg",".jpeg",".gif",".png",".bmp",".webp"

package mainimport (    "errors"    "fmt"    "golang.org/x/image/bmp"    "golang.org/x/image/draw"    "golang.org/x/image/webp"    "image"    "image/color/palette"    "image/gif"    "image/jpeg"    "image/png"    "os"    "path/filepath")func main() {    imgArr := []string{"./img/1.jpeg","./img/2.png","./img/3.jpg","./img/4.jpg","./img/5.gif","./img/7.bmp"}    delay:=100//设置延迟    //新建gif结构体    outGif := &gif.GIF{}    for _, img := range imgArr {        //图像解码        inGif,err:=imageDecode(img)        if err!=nil {            fmt.Println("图像解码失败",err)            continue        }        //缩放        dst := image.NewRGBA(image.Rect(0, 0, 640, 640))        resize(dst,inGif)        bounds := dst.Bounds()        //创建一个新的image.Paletted对象用于存储带有调色板的图像        palettedImg := image.NewPaletted(bounds, palette.Plan9)        //将原始图像绘制到 palettedImg        draw.Draw(palettedImg, bounds, dst, bounds.Min, draw.Src)        outGif.Image = append(outGif.Image, palettedImg)        outGif.Delay = append(outGif.Delay, delay)    }    f, _ := os.OpenFile("output.gif", os.O_WRONLY|os.O_CREATE, 0600)    defer f.Close()    gif.EncodeAll(f, outGif)}//图像解码func imageDecode(file string) (image.Image,error) {    f, err := os.Open(file)    if err!=nil {        return nil, err    }    defer f.Close()    ext:=filepath.Ext(file)    switch ext {    case ".jpg",".jpeg":        return jpeg.Decode(f)    case ".png":        return png.Decode(f)    case ".bmp":        return bmp.Decode(f)    case ".gif":        return gif.Decode(f)    case ".webp":        return webp.Decode(f)    default:        return nil,errors.New("图片格式错误")    }}//不等比例缩放到指定大小,func resize(dst *image.RGBA, src image.Image) error {    sw, sh := src.Bounds().Dx(), src.Bounds().Dy()    dw, dh := dst.Bounds().Dx(), dst.Bounds().Dy()    scaleW, scaleH := float64(sw)/float64(dw), float64(sh)/float64(dh)    for y := 0; y < dh; y++ {        for x := 0; x < dw; x++ {            dst.Set(x, y, src.At(int(float64(x)*scaleW), int(float64(y)*scaleH)))        }    }    return nil}

总结

  • 这里实现了几种常见的图片格式合成gif动画,有其他的图片格式需求的可修改imageDecode方法增加
  • disintegration/imaging 第三方库可以实现图片滤镜、设置大小、模糊、锐化、亮度、对比度、饱和度、伽玛校正等功能