This commit is contained in:
Alex Yatskov 2019-02-10 08:55:14 -08:00
parent 000d804f04
commit 7da7f57001
3 changed files with 100 additions and 198 deletions

View File

@ -2,7 +2,6 @@ package dcc
import ( import (
"encoding/binary" "encoding/binary"
"errors"
"fmt" "fmt"
"io" "io"
@ -29,26 +28,26 @@ type fileHeader struct {
} }
type directionHeader struct { type directionHeader struct {
CodedSize uint32 CodedSize uint
HasRawPixelEncoding bool HasRawPixelEncoding bool
CompressEqualCells bool CompressEqualCells bool
Variable0Bits uint32 Variable0Bits uint
WidthBits uint32 WidthBits uint
HeightBits uint32 HeightBits uint
OffsetXBits int32 OffsetXBits uint
OffsetYBits int32 OffsetYBits uint
OptionalBytesBits uint32 OptionalBytesBits uint
CodedBytesBits uint32 CodedBytesBits uint
} }
type frameHeader struct { type frameHeader struct {
Variable0 uint32 Variable0 uint
Width uint32 Width uint
Height uint32 Height uint
OffsetX int32 OffsetX int
OffsetY int32 OffsetY int
OptionalBytes uint32 OptionalBytes uint
CodedBytes uint32 CodedBytes uint
FrameBottomUp bool FrameBottomUp bool
Extents extents Extents extents
} }
@ -86,156 +85,46 @@ func NewFromReader(reader io.ReadSeeker) (*Sprite, error) {
return nil, nil return nil, nil
} }
func readDirectionHeader(bitReader *streaming.BitReader) (*directionHeader, error) { func readDirectionHeader(bitReader *streaming.BitReader) *directionHeader {
var ( var dirHead directionHeader
dirHead directionHeader
err error
)
dirHead.CodedSize, err = bitReader.ReadUint32(32) dirHead.CodedSize = uint(bitReader.ReadUint(32))
if err != nil { dirHead.HasRawPixelEncoding = bitReader.ReadBool()
return nil, err dirHead.CompressEqualCells = bitReader.ReadBool()
dirHead.Variable0Bits = uint(bitReader.ReadUint(4))
dirHead.WidthBits = uint(bitReader.ReadUint(4))
dirHead.HeightBits = uint(bitReader.ReadUint(4))
dirHead.OffsetXBits = uint(bitReader.ReadInt(4))
dirHead.OffsetYBits = uint(bitReader.ReadInt(4))
dirHead.OptionalBytesBits = uint(bitReader.ReadUint(4))
dirHead.CodedBytesBits = uint(bitReader.ReadUint(4))
return &dirHead
} }
dirHead.HasRawPixelEncoding, err = bitReader.ReadBool() func readFrameHeader(bitReader *streaming.BitReader, dirHead directionHeader) *frameHeader {
if err != nil { var frameHead frameHeader
return nil, err
}
dirHead.CompressEqualCells, err = bitReader.ReadBool() frameHead.Variable0 = uint(bitReader.ReadUintPacked(int(dirHead.Variable0Bits)))
if err != nil { frameHead.Width = uint(bitReader.ReadUintPacked(int(dirHead.WidthBits)))
return nil, err frameHead.Height = uint(bitReader.ReadUintPacked(int(dirHead.HeightBits)))
} frameHead.OffsetX = int(bitReader.ReadIntPacked(int(dirHead.OffsetXBits)))
frameHead.OffsetY = int(bitReader.ReadIntPacked(int(dirHead.OffsetYBits)))
frameHead.OptionalBytes = uint(bitReader.ReadUintPacked(int(dirHead.OptionalBytesBits)))
frameHead.CodedBytes = uint(bitReader.ReadUintPacked(int(dirHead.CodedBytesBits)))
frameHead.FrameBottomUp = bitReader.ReadBool()
dirHead.Variable0Bits, err = bitReader.ReadUint32(4) return &frameHead
if err != nil {
return nil, err
}
dirHead.WidthBits, err = bitReader.ReadUint32(4)
if err != nil {
return nil, err
}
dirHead.HeightBits, err = bitReader.ReadUint32(4)
if err != nil {
return nil, err
}
dirHead.OffsetXBits, err = bitReader.ReadInt32(4)
if err != nil {
return nil, err
}
dirHead.OffsetYBits, err = bitReader.ReadInt32(4)
if err != nil {
return nil, err
}
dirHead.OptionalBytesBits, err = bitReader.ReadUint32(4)
if err != nil {
return nil, err
}
dirHead.CodedBytesBits, err = bitReader.ReadUint32(4)
if err != nil {
return nil, err
}
return &dirHead, nil
}
func readFrameHeader(bitReader *streaming.BitReader, dirHead directionHeader) (*frameHeader, error) {
var (
frameHead frameHeader
err error
)
frameHead.Variable0, err = readPackedUint32(bitReader, int(dirHead.Variable0Bits))
if err != nil {
return nil, err
}
frameHead.Width, err = readPackedUint32(bitReader, int(dirHead.WidthBits))
if err != nil {
return nil, err
}
frameHead.Height, err = readPackedUint32(bitReader, int(dirHead.HeightBits))
if err != nil {
return nil, err
}
frameHead.OffsetX, err = readPackedInt32(bitReader, int(dirHead.OffsetXBits))
if err != nil {
return nil, err
}
frameHead.OffsetY, err = readPackedInt32(bitReader, int(dirHead.OffsetYBits))
if err != nil {
return nil, err
}
frameHead.OptionalBytes, err = readPackedUint32(bitReader, int(dirHead.OptionalBytesBits))
if err != nil {
return nil, err
}
frameHead.CodedBytes, err = readPackedUint32(bitReader, int(dirHead.CodedBytesBits))
if err != nil {
return nil, err
}
frameHead.FrameBottomUp, err = bitReader.ReadBool()
if err != nil {
return nil, err
}
return &frameHead, nil
} }
func readDirection(reader io.ReadSeeker, fileHead fileHeader) error { func readDirection(reader io.ReadSeeker, fileHead fileHeader) error {
bitReader := streaming.NewBitReader(reader) bitReader := streaming.NewBitReader(reader)
dirHead, err := readDirectionHeader(bitReader) dirHead := readDirectionHeader(bitReader)
if err != nil { frameHead := readFrameHeader(bitReader, *dirHead)
return err
}
frameHead, err := readFrameHeader(bitReader, *dirHead)
if err != nil {
return err
}
fmt.Printf("%+v\n", dirHead) fmt.Printf("%+v\n", dirHead)
fmt.Printf("%+v\n", frameHead) fmt.Printf("%+v\n", frameHead)
return nil return nil
} }
func readPackedInt32(reader *streaming.BitReader, packedSize int) (int32, error) {
width, err := unpackSize(packedSize)
if err != nil {
return 0, err
}
return reader.ReadInt32(width)
}
func readPackedUint32(reader *streaming.BitReader, packedSize int) (uint32, error) {
width, err := unpackSize(packedSize)
if err != nil {
return 0, err
}
return reader.ReadUint32(width)
}
func unpackSize(packedSize int) (int, error) {
sizes := []int{0, 1, 2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 26, 28, 30, 32}
if packedSize >= len(sizes) {
return 0, errors.New("invalid packed size")
}
return sizes[packedSize], nil
}

View File

@ -1,6 +1,7 @@
package streaming package streaming
import ( import (
"errors"
"io" "io"
) )
@ -8,63 +9,65 @@ type BitReader struct {
reader io.Reader reader io.Reader
bitOffset int bitOffset int
tailByte byte tailByte byte
err error
} }
func NewBitReader(reader io.Reader) *BitReader { func NewBitReader(reader io.Reader) *BitReader {
return &BitReader{reader: reader} return &BitReader{reader: reader}
} }
func (r *BitReader) ReadBool() (bool, error) { func (r *BitReader) ReadBool() bool {
value, err := r.ReadUint64(1) return r.ReadUint(1) != 0
return value == 1, err
} }
func (r *BitReader) ReadInt8(count int) (int8, error) { func (r *BitReader) ReadIntPacked(countPacked int) int64 {
value, err := r.ReadInt64(count) if r.err != nil {
return int8(value), err return 0
} }
func (r *BitReader) ReadUint8(count int) (uint8, error) { count, err := unpackSize(countPacked)
value, err := r.ReadUint64(count)
return uint8(value), err
}
func (r *BitReader) ReadInt16(count int) (int16, error) {
value, err := r.ReadInt64(count)
return int16(value), err
}
func (r *BitReader) ReadUint16(count int) (uint16, error) {
value, err := r.ReadUint64(count)
return uint16(value), err
}
func (r *BitReader) ReadInt32(count int) (int32, error) {
value, err := r.ReadInt64(count)
return int32(value), err
}
func (r *BitReader) ReadUint32(count int) (uint32, error) {
value, err := r.ReadUint64(count)
return uint32(value), err
}
func (r *BitReader) ReadInt64(count int) (int64, error) {
value, err := r.ReadUint64(count)
if err != nil { if err != nil {
return 0, err r.err = err
return 0
} }
return twosComplement(value, count), nil return r.ReadInt(count)
}
func (r *BitReader) ReadInt(count int) int64 {
return twosComplement(r.ReadUint(count), count)
}
func (r *BitReader) ReadUintPacked(countPacked int) uint64 {
if r.err != nil {
return 0
}
count, err := unpackSize(countPacked)
if err != nil {
r.err = err
return 0
}
return r.ReadUint(count)
}
func (r *BitReader) ReadUint(count int) uint64 {
if r.err != nil {
return 0
} }
func (r *BitReader) ReadUint64(count int) (uint64, error) {
buffer, bitOffset, err := r.readBytes(count) buffer, bitOffset, err := r.readBytes(count)
if err != nil { if err != nil {
return 0, err r.err = err
return 0
} }
return readBits(buffer, bitOffset, count), nil return readBits(buffer, bitOffset, count)
}
func (r *BitReader) Error() error {
return r.err
} }
func (r *BitReader) readBytes(count int) ([]byte, int, error) { func (r *BitReader) readBytes(count int) ([]byte, int, error) {
@ -135,3 +138,12 @@ func twosComplement(value uint64, bits int) int64 {
return -int64(valueMask & (^value + 1)) return -int64(valueMask & (^value + 1))
} }
} }
func unpackSize(sizePacked int) (int, error) {
sizes := []int{0, 1, 2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 26, 28, 30, 32}
if sizePacked >= len(sizes) {
return 0, errors.New("invalid packed size")
}
return sizes[sizePacked], nil
}

View File

@ -21,14 +21,15 @@ func TestBitReader(t *testing.T) {
r := NewBitReader(bytes.NewReader(data)) r := NewBitReader(bytes.NewReader(data))
test := func(count int, expected uint64) { test := func(count int, expected uint64) {
value, err := r.ReadUint64(count) if value := r.ReadUint(count); value != expected {
if err != nil {
log.Printf("error: %s\n", err.Error())
t.Fail()
} else if value != expected {
log.Printf("value: %.16x, expected: %.16x\n", value, expected) log.Printf("value: %.16x, expected: %.16x\n", value, expected)
t.Fail() t.Fail()
} }
if err := r.Error(); err != nil {
log.Printf("error: %s\n", err.Error())
t.Fail()
}
} }
test(0, 0x00) test(0, 0x00)