/bs/io.go
package bs
// I! O! Let's go!
// I! O! Let's go!
// I! O! Let's go!
// I! O! Let's go!
// - with apologies to The Ramones
import (
"io"
"log"
"fmt"
"errors"
"image/png"
"bytex64.net/code/bitsmash/packet"
"bytex64.net/code/bitsmash/ac"
)
func (self *BitSmash) packetType(n int) int {
switch self.packetList[n].(type) {
case *packet.RLEPacket:
return 0
case *packet.BinaryPatternPacket:
return 1
case *packet.DirectPacket:
return 2
case *packet.RepeatPacket:
return 3
}
return -1
}
func (self *BitSmash) ReadFrom(file io.Reader) error {
var header [5]byte
n, err := file.Read(header[:])
if n < 5 {
log.Fatal("Short read on header")
} else if err != nil {
return err
}
self.size = sizes[int(header[0]) & 0x7]
self.palette = (int(header[0]) >> 3) & 0xF
n_packets := int(header[1]) + (int(header[2] & 0x3) << 8) + 1
self.packetList = make([]packet.Packet, n_packets)
// The transparent bit is the 17th bit of the palette map
self.paletteMap = uint32(header[3]) + (uint32(header[4]) << 8) + (uint32(header[0] & 0x80) << 9);
decoder, err := ac.NewDecoder(file)
if err != nil {
return err
}
self.codecManagerInit(decoder)
for i := 0; i < n_packets; i++ {
var pkt packet.Packet // Packet! PACKET! PACKET!!!
packet_type := decoder.Decode(packet.CONTEXT_PACKET_TYPE)
switch packet_type {
case 0:
pkt = packet.DecodeRLE(decoder)
case 1:
pkt = packet.DecodeBinaryPattern(decoder)
case 2:
pkt = packet.DecodeDirect(decoder)
case 3:
pkt = packet.DecodeRepeat(decoder)
}
self.packetList[i] = pkt
}
return nil
}
func (self *BitSmash) WriteTo(file io.Writer) error {
n_packets := len(self.packetList)
if n_packets > 1024 {
fmt.Println("Too many packets:", n_packets)
return errors.New("Too many packets")
}
var header [5]byte
transparent := 0
if (self.paletteMap & 0x10000 > 0) {
transparent = 1
}
header[0] = byte(sizeIndex(self.size) + (self.palette << 3) + (transparent << 7))
header[1] = byte((n_packets - 1) & 0xFF)
header[2] = byte(((n_packets - 1) >> 8) & 0x3)
header[3] = byte(self.paletteMap & 0xFF)
header[4] = byte(self.paletteMap >> 8)
file.Write(header[:])
encoder, err := ac.NewEncoder(file)
if err != nil {
return err
}
self.codecManagerInit(encoder)
for i, p := range(self.packetList) {
encoder.Encode(packet.CONTEXT_PACKET_TYPE, uint32(self.packetType(i)))
p.Encode(encoder)
}
encoder.Finish()
return nil
}
func (self *BitSmash) WriteImage(file io.Writer) error {
image := self.toImage()
return png.Encode(file, image)
}