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 (
"encoding/binary"
"errors"
"fmt"
"io"
@ -29,26 +28,26 @@ type fileHeader struct {
}
type directionHeader struct {
CodedSize uint32
CodedSize uint
HasRawPixelEncoding bool
CompressEqualCells bool
Variable0Bits uint32
WidthBits uint32
HeightBits uint32
OffsetXBits int32
OffsetYBits int32
OptionalBytesBits uint32
CodedBytesBits uint32
Variable0Bits uint
WidthBits uint
HeightBits uint
OffsetXBits uint
OffsetYBits uint
OptionalBytesBits uint
CodedBytesBits uint
}
type frameHeader struct {
Variable0 uint32
Width uint32
Height uint32
OffsetX int32
OffsetY int32
OptionalBytes uint32
CodedBytes uint32
Variable0 uint
Width uint
Height uint
OffsetX int
OffsetY int
OptionalBytes uint
CodedBytes uint
FrameBottomUp bool
Extents extents
}
@ -86,156 +85,46 @@ func NewFromReader(reader io.ReadSeeker) (*Sprite, error) {
return nil, nil
}
func readDirectionHeader(bitReader *streaming.BitReader) (*directionHeader, error) {
var (
dirHead directionHeader
err error
)
func readDirectionHeader(bitReader *streaming.BitReader) *directionHeader {
var dirHead directionHeader
dirHead.CodedSize, err = bitReader.ReadUint32(32)
if err != nil {
return nil, err
dirHead.CodedSize = uint(bitReader.ReadUint(32))
dirHead.HasRawPixelEncoding = bitReader.ReadBool()
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()
if err != nil {
return nil, err
}
func readFrameHeader(bitReader *streaming.BitReader, dirHead directionHeader) *frameHeader {
var frameHead frameHeader
dirHead.CompressEqualCells, err = bitReader.ReadBool()
if err != nil {
return nil, err
}
frameHead.Variable0 = uint(bitReader.ReadUintPacked(int(dirHead.Variable0Bits)))
frameHead.Width = uint(bitReader.ReadUintPacked(int(dirHead.WidthBits)))
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)
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
return &frameHead
}
func readDirection(reader io.ReadSeeker, fileHead fileHeader) error {
bitReader := streaming.NewBitReader(reader)
dirHead, err := readDirectionHeader(bitReader)
if err != nil {
return err
}
frameHead, err := readFrameHeader(bitReader, *dirHead)
if err != nil {
return err
}
dirHead := readDirectionHeader(bitReader)
frameHead := readFrameHeader(bitReader, *dirHead)
fmt.Printf("%+v\n", dirHead)
fmt.Printf("%+v\n", frameHead)
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
import (
"errors"
"io"
)
@ -8,63 +9,65 @@ type BitReader struct {
reader io.Reader
bitOffset int
tailByte byte
err error
}
func NewBitReader(reader io.Reader) *BitReader {
return &BitReader{reader: reader}
}
func (r *BitReader) ReadBool() (bool, error) {
value, err := r.ReadUint64(1)
return value == 1, err
func (r *BitReader) ReadBool() bool {
return r.ReadUint(1) != 0
}
func (r *BitReader) ReadInt8(count int) (int8, error) {
value, err := r.ReadInt64(count)
return int8(value), err
func (r *BitReader) ReadIntPacked(countPacked int) int64 {
if r.err != nil {
return 0
}
func (r *BitReader) ReadUint8(count int) (uint8, error) {
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)
count, err := unpackSize(countPacked)
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)
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) {
@ -135,3 +138,12 @@ func twosComplement(value uint64, bits int) int64 {
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))
test := func(count int, expected uint64) {
value, err := r.ReadUint64(count)
if err != nil {
log.Printf("error: %s\n", err.Error())
t.Fail()
} else if value != expected {
if value := r.ReadUint(count); value != expected {
log.Printf("value: %.16x, expected: %.16x\n", value, expected)
t.Fail()
}
if err := r.Error(); err != nil {
log.Printf("error: %s\n", err.Error())
t.Fail()
}
}
test(0, 0x00)