Initial QSfera import
This commit is contained in:
+138
@@ -0,0 +1,138 @@
|
||||
package webp
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"io"
|
||||
)
|
||||
|
||||
// AnimatedWEBP is the struct of a AnimatedWEBP container and the image data contained within.
|
||||
type AnimatedWEBP struct {
|
||||
Frames []Frame
|
||||
Header ANIMHeader
|
||||
Config image.Config
|
||||
}
|
||||
|
||||
type Frame struct {
|
||||
Header ANMFHeader
|
||||
Frame image.Image
|
||||
}
|
||||
|
||||
type VP8XHeader struct {
|
||||
ICCProfile bool
|
||||
Alpha bool
|
||||
ExifMetadata bool
|
||||
XmpMetadata bool
|
||||
Animation bool
|
||||
CanvasWidth uint32
|
||||
CanvasHeight uint32
|
||||
}
|
||||
|
||||
type ALPHHeader struct {
|
||||
Preprocessing uint8
|
||||
FilteringMethod uint8
|
||||
Compression uint8
|
||||
}
|
||||
|
||||
type ANIMHeader struct {
|
||||
BackgroundColor color.Color
|
||||
LoopCount uint16
|
||||
}
|
||||
|
||||
type ANMFHeader struct {
|
||||
FrameX uint32
|
||||
FrameY uint32
|
||||
FrameWidth uint32
|
||||
FrameHeight uint32
|
||||
FrameDuration uint32
|
||||
AlphaBlend bool
|
||||
DisposalBitSet bool
|
||||
}
|
||||
|
||||
func parseALPHHeader(r io.Reader) ALPHHeader {
|
||||
h := make([]byte, 1)
|
||||
_, _ = io.ReadFull(r, h)
|
||||
|
||||
const (
|
||||
twoBits = byte(3)
|
||||
)
|
||||
|
||||
return ALPHHeader{
|
||||
Preprocessing: h[0] >> 4 & twoBits,
|
||||
FilteringMethod: h[0] >> 2 & twoBits,
|
||||
Compression: h[0] & twoBits,
|
||||
}
|
||||
}
|
||||
|
||||
func parseANIMHeader(r io.Reader) ANIMHeader {
|
||||
h := make([]byte, 6)
|
||||
_, _ = io.ReadFull(r, h)
|
||||
|
||||
loopCount := uint16(h[4]) | uint16(h[5])<<8
|
||||
bg := color.RGBA{
|
||||
R: h[2],
|
||||
G: h[1],
|
||||
B: h[0],
|
||||
A: h[3],
|
||||
}
|
||||
|
||||
return ANIMHeader{
|
||||
BackgroundColor: bg,
|
||||
LoopCount: loopCount,
|
||||
}
|
||||
}
|
||||
|
||||
func parseANMFHeader(r io.Reader) ANMFHeader {
|
||||
h := make([]byte, 16)
|
||||
_, _ = io.ReadFull(r, h)
|
||||
|
||||
const (
|
||||
disposeBit = 1
|
||||
blendBit = 1 << 1
|
||||
)
|
||||
|
||||
return ANMFHeader{
|
||||
FrameX: u24(h[0:3]),
|
||||
FrameY: u24(h[3:6]),
|
||||
FrameWidth: u24(h[6:9]) + 1,
|
||||
FrameHeight: u24(h[9:12]) + 1,
|
||||
FrameDuration: u24(h[12:15]),
|
||||
AlphaBlend: (h[15] & blendBit) == 0,
|
||||
DisposalBitSet: (h[15] & disposeBit) != 0,
|
||||
}
|
||||
}
|
||||
|
||||
func parseVP8XHeader(r io.Reader) VP8XHeader {
|
||||
const (
|
||||
anim = 1 << 1
|
||||
xmp = 1 << 2
|
||||
exif = 1 << 3
|
||||
alpha = 1 << 4
|
||||
icc = 1 << 5
|
||||
)
|
||||
|
||||
h := make([]byte, 10)
|
||||
_, _ = io.ReadFull(r, h)
|
||||
|
||||
widthMinusOne := u24(h[4:])
|
||||
heightMinusOne := u24(h[7:])
|
||||
|
||||
header := VP8XHeader{
|
||||
ICCProfile: h[0]&icc != 0,
|
||||
Alpha: h[0]&alpha != 0,
|
||||
ExifMetadata: h[0]&exif != 0,
|
||||
XmpMetadata: h[0]&xmp != 0,
|
||||
Animation: h[0]&anim != 0,
|
||||
CanvasWidth: widthMinusOne + 1,
|
||||
CanvasHeight: heightMinusOne + 1,
|
||||
}
|
||||
return header
|
||||
}
|
||||
|
||||
func u24(b []byte) uint32 {
|
||||
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16
|
||||
}
|
||||
|
||||
func u32(b []byte) uint32 {
|
||||
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
|
||||
}
|
||||
Reference in New Issue
Block a user