110 lines
3.0 KiB
Go
110 lines
3.0 KiB
Go
package webpanimation
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"image"
|
|
"image/draw"
|
|
"io"
|
|
)
|
|
|
|
type WebpAnimation struct {
|
|
WebPAnimEncoderOptions *WebPAnimEncoderOptions
|
|
Width int
|
|
Height int
|
|
loopCount int
|
|
AnimationEncoder *WebPAnimEncoder
|
|
WebPData *WebPData
|
|
WebPMux *WebPMux
|
|
WebPPictures []*WebPPicture
|
|
}
|
|
|
|
// NewWebpAnimation Initialize animation
|
|
func NewWebpAnimation(width, height, loopCount int) *WebpAnimation {
|
|
webpAnimation := &WebpAnimation{loopCount: loopCount, Width: width, Height: height}
|
|
webpAnimation.WebPAnimEncoderOptions = &WebPAnimEncoderOptions{}
|
|
|
|
WebPAnimEncoderOptionsInitInternal(webpAnimation.WebPAnimEncoderOptions)
|
|
|
|
webpAnimation.AnimationEncoder = WebPAnimEncoderNewInternal(width, height, webpAnimation.WebPAnimEncoderOptions)
|
|
return webpAnimation
|
|
}
|
|
|
|
// ReleaseMemory release memory
|
|
func (wpa *WebpAnimation) ReleaseMemory() {
|
|
WebPDataClear(wpa.WebPData)
|
|
WebPMuxDelete(wpa.WebPMux)
|
|
for _, webpPicture := range wpa.WebPPictures {
|
|
WebPPictureFree(webpPicture)
|
|
}
|
|
WebPAnimEncoderDelete(wpa.AnimationEncoder)
|
|
}
|
|
|
|
// AddFrame add frame to animation
|
|
func (wpa *WebpAnimation) AddFrame(img image.Image, timestamp int, webpcfg WebPConfig) error {
|
|
var webPPicture *WebPPicture = nil
|
|
var m *image.RGBA
|
|
if img != nil {
|
|
if v, ok := img.(*image.RGBA); ok {
|
|
m = v
|
|
} else {
|
|
b := img.Bounds()
|
|
m = image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))
|
|
draw.Draw(m, m.Bounds(), img, b.Min, draw.Src)
|
|
}
|
|
|
|
webPPicture = &WebPPicture{}
|
|
wpa.WebPPictures = append(wpa.WebPPictures, webPPicture)
|
|
webPPicture.SetUseArgb(1)
|
|
webPPicture.SetHeight(wpa.Height)
|
|
webPPicture.SetWidth(wpa.Width)
|
|
err := WebPPictureImportRGBA(m.Pix, m.Stride, webPPicture)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
res := WebPAnimEncoderAdd(wpa.AnimationEncoder, webPPicture, timestamp, webpcfg)
|
|
if res == 0 {
|
|
return errors.New("Failed to add frame in animation ecoder")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Encode encode animation
|
|
func (wpa *WebpAnimation) Encode(w io.Writer) error {
|
|
wpa.WebPData = &WebPData{}
|
|
|
|
WebPDataInit(wpa.WebPData)
|
|
|
|
WebPAnimEncoderAssemble(wpa.AnimationEncoder, wpa.WebPData)
|
|
|
|
if wpa.loopCount > 0 {
|
|
wpa.WebPMux = WebPMuxCreateInternal(wpa.WebPData, 1)
|
|
if wpa.WebPMux == nil {
|
|
return errors.New("ERROR: Could not re-mux to add loop count/metadata.")
|
|
}
|
|
WebPDataClear(wpa.WebPData)
|
|
|
|
webPMuxAnimNewParams := WebPMuxAnimParams{}
|
|
muxErr := WebPMuxGetAnimationParams(wpa.WebPMux, &webPMuxAnimNewParams)
|
|
if muxErr != WebpMuxOk {
|
|
return errors.New("Could not fetch loop count")
|
|
}
|
|
webPMuxAnimNewParams.SetLoopCount(wpa.loopCount)
|
|
|
|
muxErr = WebPMuxSetAnimationParams(wpa.WebPMux, &webPMuxAnimNewParams)
|
|
if muxErr != WebpMuxOk {
|
|
return errors.New(fmt.Sprint("Could not update loop count, code:", muxErr))
|
|
}
|
|
|
|
muxErr = WebPMuxAssemble(wpa.WebPMux, wpa.WebPData)
|
|
if muxErr != WebpMuxOk {
|
|
return errors.New("Could not assemble when re-muxing to add")
|
|
}
|
|
|
|
}
|
|
_, err := w.Write(wpa.WebPData.GetBytes())
|
|
return err
|
|
}
|