mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-03 23:52:26 -06:00 
			
		
		
		
	* media: add webp support Signed-off-by: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se> * bump exif-terminator to v0.5.0 Signed-off-by: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se> Signed-off-by: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
		
			
				
	
	
		
			403 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			403 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2011 The Go Authors. All rights reserved.
 | 
						|
// Use of this source code is governed by a BSD-style
 | 
						|
// license that can be found in the LICENSE file.
 | 
						|
 | 
						|
// Package vp8 implements a decoder for the VP8 lossy image format.
 | 
						|
//
 | 
						|
// The VP8 specification is RFC 6386.
 | 
						|
package vp8 // import "golang.org/x/image/vp8"
 | 
						|
 | 
						|
// This file implements the top-level decoding algorithm.
 | 
						|
 | 
						|
import (
 | 
						|
	"errors"
 | 
						|
	"image"
 | 
						|
	"io"
 | 
						|
)
 | 
						|
 | 
						|
// limitReader wraps an io.Reader to read at most n bytes from it.
 | 
						|
type limitReader struct {
 | 
						|
	r io.Reader
 | 
						|
	n int
 | 
						|
}
 | 
						|
 | 
						|
// ReadFull reads exactly len(p) bytes into p.
 | 
						|
func (r *limitReader) ReadFull(p []byte) error {
 | 
						|
	if len(p) > r.n {
 | 
						|
		return io.ErrUnexpectedEOF
 | 
						|
	}
 | 
						|
	n, err := io.ReadFull(r.r, p)
 | 
						|
	r.n -= n
 | 
						|
	return err
 | 
						|
}
 | 
						|
 | 
						|
// FrameHeader is a frame header, as specified in section 9.1.
 | 
						|
type FrameHeader struct {
 | 
						|
	KeyFrame          bool
 | 
						|
	VersionNumber     uint8
 | 
						|
	ShowFrame         bool
 | 
						|
	FirstPartitionLen uint32
 | 
						|
	Width             int
 | 
						|
	Height            int
 | 
						|
	XScale            uint8
 | 
						|
	YScale            uint8
 | 
						|
}
 | 
						|
 | 
						|
const (
 | 
						|
	nSegment     = 4
 | 
						|
	nSegmentProb = 3
 | 
						|
)
 | 
						|
 | 
						|
// segmentHeader holds segment-related header information.
 | 
						|
type segmentHeader struct {
 | 
						|
	useSegment     bool
 | 
						|
	updateMap      bool
 | 
						|
	relativeDelta  bool
 | 
						|
	quantizer      [nSegment]int8
 | 
						|
	filterStrength [nSegment]int8
 | 
						|
	prob           [nSegmentProb]uint8
 | 
						|
}
 | 
						|
 | 
						|
const (
 | 
						|
	nRefLFDelta  = 4
 | 
						|
	nModeLFDelta = 4
 | 
						|
)
 | 
						|
 | 
						|
// filterHeader holds filter-related header information.
 | 
						|
type filterHeader struct {
 | 
						|
	simple          bool
 | 
						|
	level           int8
 | 
						|
	sharpness       uint8
 | 
						|
	useLFDelta      bool
 | 
						|
	refLFDelta      [nRefLFDelta]int8
 | 
						|
	modeLFDelta     [nModeLFDelta]int8
 | 
						|
	perSegmentLevel [nSegment]int8
 | 
						|
}
 | 
						|
 | 
						|
// mb is the per-macroblock decode state. A decoder maintains mbw+1 of these
 | 
						|
// as it is decoding macroblocks left-to-right and top-to-bottom: mbw for the
 | 
						|
// macroblocks in the row above, and one for the macroblock to the left.
 | 
						|
type mb struct {
 | 
						|
	// pred is the predictor mode for the 4 bottom or right 4x4 luma regions.
 | 
						|
	pred [4]uint8
 | 
						|
	// nzMask is a mask of 8 bits: 4 for the bottom or right 4x4 luma regions,
 | 
						|
	// and 2 + 2 for the bottom or right 4x4 chroma regions. A 1 bit indicates
 | 
						|
	// that region has non-zero coefficients.
 | 
						|
	nzMask uint8
 | 
						|
	// nzY16 is a 0/1 value that is 1 if the macroblock used Y16 prediction and
 | 
						|
	// had non-zero coefficients.
 | 
						|
	nzY16 uint8
 | 
						|
}
 | 
						|
 | 
						|
// Decoder decodes VP8 bitstreams into frames. Decoding one frame consists of
 | 
						|
// calling Init, DecodeFrameHeader and then DecodeFrame in that order.
 | 
						|
// A Decoder can be re-used to decode multiple frames.
 | 
						|
type Decoder struct {
 | 
						|
	// r is the input bitsream.
 | 
						|
	r limitReader
 | 
						|
	// scratch is a scratch buffer.
 | 
						|
	scratch [8]byte
 | 
						|
	// img is the YCbCr image to decode into.
 | 
						|
	img *image.YCbCr
 | 
						|
	// mbw and mbh are the number of 16x16 macroblocks wide and high the image is.
 | 
						|
	mbw, mbh int
 | 
						|
	// frameHeader is the frame header. When decoding multiple frames,
 | 
						|
	// frames that aren't key frames will inherit the Width, Height,
 | 
						|
	// XScale and YScale of the most recent key frame.
 | 
						|
	frameHeader FrameHeader
 | 
						|
	// Other headers.
 | 
						|
	segmentHeader segmentHeader
 | 
						|
	filterHeader  filterHeader
 | 
						|
	// The image data is divided into a number of independent partitions.
 | 
						|
	// There is 1 "first partition" and between 1 and 8 "other partitions"
 | 
						|
	// for coefficient data.
 | 
						|
	fp  partition
 | 
						|
	op  [8]partition
 | 
						|
	nOP int
 | 
						|
	// Quantization factors.
 | 
						|
	quant [nSegment]quant
 | 
						|
	// DCT/WHT coefficient decoding probabilities.
 | 
						|
	tokenProb   [nPlane][nBand][nContext][nProb]uint8
 | 
						|
	useSkipProb bool
 | 
						|
	skipProb    uint8
 | 
						|
	// Loop filter parameters.
 | 
						|
	filterParams      [nSegment][2]filterParam
 | 
						|
	perMBFilterParams []filterParam
 | 
						|
 | 
						|
	// The eight fields below relate to the current macroblock being decoded.
 | 
						|
	//
 | 
						|
	// Segment-based adjustments.
 | 
						|
	segment int
 | 
						|
	// Per-macroblock state for the macroblock immediately left of and those
 | 
						|
	// macroblocks immediately above the current macroblock.
 | 
						|
	leftMB mb
 | 
						|
	upMB   []mb
 | 
						|
	// Bitmasks for which 4x4 regions of coeff contain non-zero coefficients.
 | 
						|
	nzDCMask, nzACMask uint32
 | 
						|
	// Predictor modes.
 | 
						|
	usePredY16 bool // The libwebp C code calls this !is_i4x4_.
 | 
						|
	predY16    uint8
 | 
						|
	predC8     uint8
 | 
						|
	predY4     [4][4]uint8
 | 
						|
 | 
						|
	// The two fields below form a workspace for reconstructing a macroblock.
 | 
						|
	// Their specific sizes are documented in reconstruct.go.
 | 
						|
	coeff [1*16*16 + 2*8*8 + 1*4*4]int16
 | 
						|
	ybr   [1 + 16 + 1 + 8][32]uint8
 | 
						|
}
 | 
						|
 | 
						|
// NewDecoder returns a new Decoder.
 | 
						|
func NewDecoder() *Decoder {
 | 
						|
	return &Decoder{}
 | 
						|
}
 | 
						|
 | 
						|
// Init initializes the decoder to read at most n bytes from r.
 | 
						|
func (d *Decoder) Init(r io.Reader, n int) {
 | 
						|
	d.r = limitReader{r, n}
 | 
						|
}
 | 
						|
 | 
						|
// DecodeFrameHeader decodes the frame header.
 | 
						|
func (d *Decoder) DecodeFrameHeader() (fh FrameHeader, err error) {
 | 
						|
	// All frame headers are at least 3 bytes long.
 | 
						|
	b := d.scratch[:3]
 | 
						|
	if err = d.r.ReadFull(b); err != nil {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	d.frameHeader.KeyFrame = (b[0] & 1) == 0
 | 
						|
	d.frameHeader.VersionNumber = (b[0] >> 1) & 7
 | 
						|
	d.frameHeader.ShowFrame = (b[0]>>4)&1 == 1
 | 
						|
	d.frameHeader.FirstPartitionLen = uint32(b[0])>>5 | uint32(b[1])<<3 | uint32(b[2])<<11
 | 
						|
	if !d.frameHeader.KeyFrame {
 | 
						|
		return d.frameHeader, nil
 | 
						|
	}
 | 
						|
	// Frame headers for key frames are an additional 7 bytes long.
 | 
						|
	b = d.scratch[:7]
 | 
						|
	if err = d.r.ReadFull(b); err != nil {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	// Check the magic sync code.
 | 
						|
	if b[0] != 0x9d || b[1] != 0x01 || b[2] != 0x2a {
 | 
						|
		err = errors.New("vp8: invalid format")
 | 
						|
		return
 | 
						|
	}
 | 
						|
	d.frameHeader.Width = int(b[4]&0x3f)<<8 | int(b[3])
 | 
						|
	d.frameHeader.Height = int(b[6]&0x3f)<<8 | int(b[5])
 | 
						|
	d.frameHeader.XScale = b[4] >> 6
 | 
						|
	d.frameHeader.YScale = b[6] >> 6
 | 
						|
	d.mbw = (d.frameHeader.Width + 0x0f) >> 4
 | 
						|
	d.mbh = (d.frameHeader.Height + 0x0f) >> 4
 | 
						|
	d.segmentHeader = segmentHeader{
 | 
						|
		prob: [3]uint8{0xff, 0xff, 0xff},
 | 
						|
	}
 | 
						|
	d.tokenProb = defaultTokenProb
 | 
						|
	d.segment = 0
 | 
						|
	return d.frameHeader, nil
 | 
						|
}
 | 
						|
 | 
						|
// ensureImg ensures that d.img is large enough to hold the decoded frame.
 | 
						|
func (d *Decoder) ensureImg() {
 | 
						|
	if d.img != nil {
 | 
						|
		p0, p1 := d.img.Rect.Min, d.img.Rect.Max
 | 
						|
		if p0.X == 0 && p0.Y == 0 && p1.X >= 16*d.mbw && p1.Y >= 16*d.mbh {
 | 
						|
			return
 | 
						|
		}
 | 
						|
	}
 | 
						|
	m := image.NewYCbCr(image.Rect(0, 0, 16*d.mbw, 16*d.mbh), image.YCbCrSubsampleRatio420)
 | 
						|
	d.img = m.SubImage(image.Rect(0, 0, d.frameHeader.Width, d.frameHeader.Height)).(*image.YCbCr)
 | 
						|
	d.perMBFilterParams = make([]filterParam, d.mbw*d.mbh)
 | 
						|
	d.upMB = make([]mb, d.mbw)
 | 
						|
}
 | 
						|
 | 
						|
// parseSegmentHeader parses the segment header, as specified in section 9.3.
 | 
						|
func (d *Decoder) parseSegmentHeader() {
 | 
						|
	d.segmentHeader.useSegment = d.fp.readBit(uniformProb)
 | 
						|
	if !d.segmentHeader.useSegment {
 | 
						|
		d.segmentHeader.updateMap = false
 | 
						|
		return
 | 
						|
	}
 | 
						|
	d.segmentHeader.updateMap = d.fp.readBit(uniformProb)
 | 
						|
	if d.fp.readBit(uniformProb) {
 | 
						|
		d.segmentHeader.relativeDelta = !d.fp.readBit(uniformProb)
 | 
						|
		for i := range d.segmentHeader.quantizer {
 | 
						|
			d.segmentHeader.quantizer[i] = int8(d.fp.readOptionalInt(uniformProb, 7))
 | 
						|
		}
 | 
						|
		for i := range d.segmentHeader.filterStrength {
 | 
						|
			d.segmentHeader.filterStrength[i] = int8(d.fp.readOptionalInt(uniformProb, 6))
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if !d.segmentHeader.updateMap {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	for i := range d.segmentHeader.prob {
 | 
						|
		if d.fp.readBit(uniformProb) {
 | 
						|
			d.segmentHeader.prob[i] = uint8(d.fp.readUint(uniformProb, 8))
 | 
						|
		} else {
 | 
						|
			d.segmentHeader.prob[i] = 0xff
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// parseFilterHeader parses the filter header, as specified in section 9.4.
 | 
						|
func (d *Decoder) parseFilterHeader() {
 | 
						|
	d.filterHeader.simple = d.fp.readBit(uniformProb)
 | 
						|
	d.filterHeader.level = int8(d.fp.readUint(uniformProb, 6))
 | 
						|
	d.filterHeader.sharpness = uint8(d.fp.readUint(uniformProb, 3))
 | 
						|
	d.filterHeader.useLFDelta = d.fp.readBit(uniformProb)
 | 
						|
	if d.filterHeader.useLFDelta && d.fp.readBit(uniformProb) {
 | 
						|
		for i := range d.filterHeader.refLFDelta {
 | 
						|
			d.filterHeader.refLFDelta[i] = int8(d.fp.readOptionalInt(uniformProb, 6))
 | 
						|
		}
 | 
						|
		for i := range d.filterHeader.modeLFDelta {
 | 
						|
			d.filterHeader.modeLFDelta[i] = int8(d.fp.readOptionalInt(uniformProb, 6))
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if d.filterHeader.level == 0 {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	if d.segmentHeader.useSegment {
 | 
						|
		for i := range d.filterHeader.perSegmentLevel {
 | 
						|
			strength := d.segmentHeader.filterStrength[i]
 | 
						|
			if d.segmentHeader.relativeDelta {
 | 
						|
				strength += d.filterHeader.level
 | 
						|
			}
 | 
						|
			d.filterHeader.perSegmentLevel[i] = strength
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		d.filterHeader.perSegmentLevel[0] = d.filterHeader.level
 | 
						|
	}
 | 
						|
	d.computeFilterParams()
 | 
						|
}
 | 
						|
 | 
						|
// parseOtherPartitions parses the other partitions, as specified in section 9.5.
 | 
						|
func (d *Decoder) parseOtherPartitions() error {
 | 
						|
	const maxNOP = 1 << 3
 | 
						|
	var partLens [maxNOP]int
 | 
						|
	d.nOP = 1 << d.fp.readUint(uniformProb, 2)
 | 
						|
 | 
						|
	// The final partition length is implied by the remaining chunk data
 | 
						|
	// (d.r.n) and the other d.nOP-1 partition lengths. Those d.nOP-1 partition
 | 
						|
	// lengths are stored as 24-bit uints, i.e. up to 16 MiB per partition.
 | 
						|
	n := 3 * (d.nOP - 1)
 | 
						|
	partLens[d.nOP-1] = d.r.n - n
 | 
						|
	if partLens[d.nOP-1] < 0 {
 | 
						|
		return io.ErrUnexpectedEOF
 | 
						|
	}
 | 
						|
	if n > 0 {
 | 
						|
		buf := make([]byte, n)
 | 
						|
		if err := d.r.ReadFull(buf); err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
		for i := 0; i < d.nOP-1; i++ {
 | 
						|
			pl := int(buf[3*i+0]) | int(buf[3*i+1])<<8 | int(buf[3*i+2])<<16
 | 
						|
			if pl > partLens[d.nOP-1] {
 | 
						|
				return io.ErrUnexpectedEOF
 | 
						|
			}
 | 
						|
			partLens[i] = pl
 | 
						|
			partLens[d.nOP-1] -= pl
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// We check if the final partition length can also fit into a 24-bit uint.
 | 
						|
	// Strictly speaking, this isn't part of the spec, but it guards against a
 | 
						|
	// malicious WEBP image that is too large to ReadFull the encoded DCT
 | 
						|
	// coefficients into memory, whether that's because the actual WEBP file is
 | 
						|
	// too large, or whether its RIFF metadata lists too large a chunk.
 | 
						|
	if 1<<24 <= partLens[d.nOP-1] {
 | 
						|
		return errors.New("vp8: too much data to decode")
 | 
						|
	}
 | 
						|
 | 
						|
	buf := make([]byte, d.r.n)
 | 
						|
	if err := d.r.ReadFull(buf); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	for i, pl := range partLens {
 | 
						|
		if i == d.nOP {
 | 
						|
			break
 | 
						|
		}
 | 
						|
		d.op[i].init(buf[:pl])
 | 
						|
		buf = buf[pl:]
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// parseOtherHeaders parses header information other than the frame header.
 | 
						|
func (d *Decoder) parseOtherHeaders() error {
 | 
						|
	// Initialize and parse the first partition.
 | 
						|
	firstPartition := make([]byte, d.frameHeader.FirstPartitionLen)
 | 
						|
	if err := d.r.ReadFull(firstPartition); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	d.fp.init(firstPartition)
 | 
						|
	if d.frameHeader.KeyFrame {
 | 
						|
		// Read and ignore the color space and pixel clamp values. They are
 | 
						|
		// specified in section 9.2, but are unimplemented.
 | 
						|
		d.fp.readBit(uniformProb)
 | 
						|
		d.fp.readBit(uniformProb)
 | 
						|
	}
 | 
						|
	d.parseSegmentHeader()
 | 
						|
	d.parseFilterHeader()
 | 
						|
	if err := d.parseOtherPartitions(); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	d.parseQuant()
 | 
						|
	if !d.frameHeader.KeyFrame {
 | 
						|
		// Golden and AltRef frames are specified in section 9.7.
 | 
						|
		// TODO(nigeltao): implement. Note that they are only used for video, not still images.
 | 
						|
		return errors.New("vp8: Golden / AltRef frames are not implemented")
 | 
						|
	}
 | 
						|
	// Read and ignore the refreshLastFrameBuffer bit, specified in section 9.8.
 | 
						|
	// It applies only to video, and not still images.
 | 
						|
	d.fp.readBit(uniformProb)
 | 
						|
	d.parseTokenProb()
 | 
						|
	d.useSkipProb = d.fp.readBit(uniformProb)
 | 
						|
	if d.useSkipProb {
 | 
						|
		d.skipProb = uint8(d.fp.readUint(uniformProb, 8))
 | 
						|
	}
 | 
						|
	if d.fp.unexpectedEOF {
 | 
						|
		return io.ErrUnexpectedEOF
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// DecodeFrame decodes the frame and returns it as an YCbCr image.
 | 
						|
// The image's contents are valid up until the next call to Decoder.Init.
 | 
						|
func (d *Decoder) DecodeFrame() (*image.YCbCr, error) {
 | 
						|
	d.ensureImg()
 | 
						|
	if err := d.parseOtherHeaders(); err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	// Reconstruct the rows.
 | 
						|
	for mbx := 0; mbx < d.mbw; mbx++ {
 | 
						|
		d.upMB[mbx] = mb{}
 | 
						|
	}
 | 
						|
	for mby := 0; mby < d.mbh; mby++ {
 | 
						|
		d.leftMB = mb{}
 | 
						|
		for mbx := 0; mbx < d.mbw; mbx++ {
 | 
						|
			skip := d.reconstruct(mbx, mby)
 | 
						|
			fs := d.filterParams[d.segment][btou(!d.usePredY16)]
 | 
						|
			fs.inner = fs.inner || !skip
 | 
						|
			d.perMBFilterParams[d.mbw*mby+mbx] = fs
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if d.fp.unexpectedEOF {
 | 
						|
		return nil, io.ErrUnexpectedEOF
 | 
						|
	}
 | 
						|
	for i := 0; i < d.nOP; i++ {
 | 
						|
		if d.op[i].unexpectedEOF {
 | 
						|
			return nil, io.ErrUnexpectedEOF
 | 
						|
		}
 | 
						|
	}
 | 
						|
	// Apply the loop filter.
 | 
						|
	//
 | 
						|
	// Even if we are using per-segment levels, section 15 says that "loop
 | 
						|
	// filtering must be skipped entirely if loop_filter_level at either the
 | 
						|
	// frame header level or macroblock override level is 0".
 | 
						|
	if d.filterHeader.level != 0 {
 | 
						|
		if d.filterHeader.simple {
 | 
						|
			d.simpleFilter()
 | 
						|
		} else {
 | 
						|
			d.normalFilter()
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return d.img, nil
 | 
						|
}
 |