organized
|
@ -1,151 +1,38 @@
|
|||
package nori
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
)
|
||||
|
||||
type Frame struct {
|
||||
Duration uint32
|
||||
PlaneCount uint32
|
||||
Planes []*Plane
|
||||
CoordinateCount uint32
|
||||
Coordinates [][2]uint32
|
||||
Unknown1 string
|
||||
SoundEffect string
|
||||
Unknown2 string
|
||||
Camp CampSection
|
||||
}
|
||||
type CampSection struct {
|
||||
Params [7]uint32
|
||||
Array []byte
|
||||
Extra string
|
||||
}
|
||||
|
||||
type Plane struct {
|
||||
BitmapId uint32
|
||||
PlaneX int32
|
||||
PlaneY int32
|
||||
Opacity uint32
|
||||
Blend BlendMode
|
||||
FlagParam uint32
|
||||
RenderFlag uint32
|
||||
}
|
||||
type Animation struct {
|
||||
Title [32]byte
|
||||
|
||||
// std::vector<uint32> frame_offsets
|
||||
FrameCount uint32
|
||||
Frames []*Frame
|
||||
Version int
|
||||
}
|
||||
|
||||
func (a *Animation) Decode(rd *bufio.Reader, version int) error {
|
||||
func NewAnimation(version int) *Animation {
|
||||
return &Animation{Version: version}
|
||||
}
|
||||
|
||||
func (a *Animation) Decode(rd io.Reader) error {
|
||||
if err := binary.Read(rd, end, a.Title[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(rd, end, &a.FrameCount); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := rd.Discard(4 * int(a.FrameCount)); err != nil {
|
||||
if err := discardN(rd, 4*int(a.FrameCount)); err != nil {
|
||||
return err
|
||||
}
|
||||
a.Frames = make([]*Frame, int(a.FrameCount))
|
||||
for i := range a.Frames {
|
||||
cf := &Frame{}
|
||||
a.Frames[i] = cf
|
||||
if err := binary.Read(rd, end, &cf.Duration); err != nil {
|
||||
a.Frames[i] = NewFrame(a.Version)
|
||||
if err := a.Frames[i].Decode(rd); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(rd, end, &cf.PlaneCount); err != nil {
|
||||
return err
|
||||
}
|
||||
cf.Planes = make([]*Plane, int(cf.PlaneCount))
|
||||
for i := range cf.Planes {
|
||||
cp := &Plane{}
|
||||
cf.Planes[i] = cp
|
||||
if err := binary.Read(rd, end, &cp.BitmapId); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(rd, end, &cp.PlaneX); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(rd, end, &cp.PlaneY); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(rd, end, &cp.Opacity); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(rd, end, &cp.RenderFlag); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(rd, end, &cp.Blend); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(rd, end, &cp.FlagParam); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if version != 300 {
|
||||
if err := binary.Read(rd, end, &cf.CoordinateCount); err != nil {
|
||||
return err
|
||||
}
|
||||
cf.Coordinates = make([][2]uint32, cf.CoordinateCount)
|
||||
for i := range cf.Coordinates {
|
||||
if err := binary.Read(rd, end, &cf.Coordinates[i][0]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(rd, end, &cf.Coordinates[i][1]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
switch version {
|
||||
case 300, 301:
|
||||
if _, err := rd.Discard(144); err != nil {
|
||||
return err
|
||||
}
|
||||
case 302, 303:
|
||||
if _, err := rd.Discard(96); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if version >= 302 {
|
||||
// entry blocks
|
||||
if _, err := rd.Discard(28 * 6); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// unknown1
|
||||
if _, err := rd.Discard(44); err != nil {
|
||||
return err
|
||||
}
|
||||
//sound_effect
|
||||
if _, err := rd.Discard(18); err != nil {
|
||||
return err
|
||||
}
|
||||
// unknown2
|
||||
if _, err := rd.Discard(18); err != nil {
|
||||
return err
|
||||
}
|
||||
var cast uint32
|
||||
if err := binary.Read(rd, end, &cast); err != nil {
|
||||
return err
|
||||
}
|
||||
if version >= 303 && (cast > 0) {
|
||||
cf.Camp = CampSection{}
|
||||
if err := binary.Read(rd, end, cf.Camp.Params[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
sz := int(cf.Camp.Params[1]) * int(cf.Camp.Params[2])
|
||||
cf.Camp.Array = make([]byte, sz)
|
||||
if _, err := io.ReadFull(rd, cf.Camp.Array); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := rd.Discard(20); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package nori
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
type BlendMode uint32
|
||||
|
||||
var (
|
||||
|
@ -16,3 +18,5 @@ var (
|
|||
BlendMode_Mul7 BlendMode = 7
|
||||
BlendMode_Add8 BlendMode = 8
|
||||
)
|
||||
|
||||
var end = binary.LittleEndian
|
|
@ -0,0 +1,26 @@
|
|||
package nori
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
func New() *Nori {
|
||||
return &Nori{}
|
||||
}
|
||||
|
||||
func FromFile(fp string) (*Nori, error) {
|
||||
file, err := os.Open(fp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
return Decode(bufio.NewReader(file))
|
||||
}
|
||||
|
||||
func Decode(r io.Reader) (*Nori, error) {
|
||||
nori := New()
|
||||
err := nori.Decode(r)
|
||||
return nori, err
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
package nori
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
)
|
||||
|
||||
type Frame struct {
|
||||
Duration uint32
|
||||
PlaneCount uint32
|
||||
Planes []*Plane
|
||||
CoordinateCount uint32
|
||||
Coordinates [][2]uint32
|
||||
Unknown1 string
|
||||
SoundEffect string
|
||||
Unknown2 string
|
||||
HasCamp bool
|
||||
Camp struct {
|
||||
Params [7]uint32
|
||||
Array []byte
|
||||
Extra string
|
||||
}
|
||||
|
||||
Version int
|
||||
}
|
||||
|
||||
func NewFrame(version int) *Frame {
|
||||
return &Frame{Version: version}
|
||||
}
|
||||
|
||||
func (f *Frame) Decode(rd io.Reader) error {
|
||||
if err := binary.Read(rd, end, &f.Duration); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(rd, end, &f.PlaneCount); err != nil {
|
||||
return err
|
||||
}
|
||||
f.Planes = make([]*Plane, int(f.PlaneCount))
|
||||
for i := range f.Planes {
|
||||
f.Planes[i] = &Plane{}
|
||||
if err := f.Planes[i].Decode(rd); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if f.Version != 300 {
|
||||
if err := binary.Read(rd, end, &f.CoordinateCount); err != nil {
|
||||
return err
|
||||
}
|
||||
f.Coordinates = make([][2]uint32, f.CoordinateCount)
|
||||
for i := range f.Coordinates {
|
||||
if err := binary.Read(rd, end, f.Coordinates[i][:]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
switch f.Version {
|
||||
case 300, 301:
|
||||
if err := discardN(rd, 144); err != nil {
|
||||
return err
|
||||
}
|
||||
case 302, 303:
|
||||
if err := discardN(rd, 96); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if f.Version >= 302 {
|
||||
// entry blocks
|
||||
if err := discardN(rd, 28*6); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// unknown1
|
||||
if err := discardN(rd, 44); err != nil {
|
||||
return err
|
||||
}
|
||||
//sound_effect
|
||||
if err := discardN(rd, 18); err != nil {
|
||||
return err
|
||||
}
|
||||
// unknown2
|
||||
if err := discardN(rd, 18); err != nil {
|
||||
return err
|
||||
}
|
||||
var cast uint32
|
||||
if err := binary.Read(rd, end, &cast); err != nil {
|
||||
return err
|
||||
}
|
||||
// camp
|
||||
f.HasCamp = (f.Version >= 303 && (cast > 0))
|
||||
if f.HasCamp {
|
||||
if err := binary.Read(rd, end, f.Camp.Params[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
sz := int(f.Camp.Params[1]) * int(f.Camp.Params[2])
|
||||
f.Camp.Array = make([]byte, sz)
|
||||
if _, err := io.ReadFull(rd, f.Camp.Array); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := discardN(rd, 20); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
package nori
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
type GawiSection struct {
|
||||
Version uint32
|
||||
Bpp uint32
|
||||
IsCompressed bool
|
||||
Params [4]uint32
|
||||
BmpCount uint32
|
||||
Size uint32
|
||||
|
||||
HasPalette bool
|
||||
Palette *PaletteSection
|
||||
Images []*Image
|
||||
|
||||
lastSignature [4]byte
|
||||
}
|
||||
|
||||
func (g *GawiSection) Decode(rd io.Reader) error {
|
||||
if _, err := io.ReadFull(rd, g.lastSignature[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if sig, target := string(g.lastSignature[:]), "GAWI"; sig != target {
|
||||
return fmt.Errorf("bad sig: want %s, got %s", target, sig)
|
||||
}
|
||||
if err := binary.Read(rd, end, &g.Version); err != nil {
|
||||
return err
|
||||
}
|
||||
if g.Version != 300 {
|
||||
return fmt.Errorf("bad ver: want 300, got %d", g.Version)
|
||||
}
|
||||
if err := binary.Read(rd, end, &g.Bpp); err != nil {
|
||||
return err
|
||||
}
|
||||
good := false
|
||||
for _, v := range [3]uint32{8, 16, 24} {
|
||||
if g.Bpp == v {
|
||||
good = true
|
||||
}
|
||||
}
|
||||
if !good {
|
||||
return fmt.Errorf("bad bpp: %d", g.Bpp)
|
||||
}
|
||||
var container uint32
|
||||
if err := binary.Read(rd, end, &container); err != nil {
|
||||
return err
|
||||
}
|
||||
g.IsCompressed = (container == 1)
|
||||
if err := binary.Read(rd, end, &container); err != nil {
|
||||
return err
|
||||
}
|
||||
g.HasPalette = (container > 0)
|
||||
|
||||
if err := binary.Read(rd, end, g.Params[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(rd, end, &g.BmpCount); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(rd, end, &g.Size); err != nil {
|
||||
return err
|
||||
}
|
||||
if g.HasPalette {
|
||||
g.Palette = &PaletteSection{}
|
||||
if err := g.Palette.Decode(rd); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := discardN(rd, 4*int(g.BmpCount)); err != nil {
|
||||
return err
|
||||
}
|
||||
g.Images = make([]*Image, int(g.BmpCount))
|
||||
for i := range g.Images {
|
||||
g.Images[i] = &Image{Bpp: g.Bpp}
|
||||
if err := g.Images[i].Decode(rd, g.Palette); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
package nori
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"image"
|
||||
|
@ -25,7 +24,37 @@ type Image struct {
|
|||
Img image.Image
|
||||
}
|
||||
|
||||
func (i *Image) Decode(rd *bufio.Reader, palette *PaletteSection) error {
|
||||
func (i *Image) Decode(rd io.Reader, palette *PaletteSection) error {
|
||||
if err := binary.Read(rd, end, &i.Count); err != nil {
|
||||
return err
|
||||
}
|
||||
if i.Count != 1 {
|
||||
return fmt.Errorf("img count should be 1")
|
||||
}
|
||||
|
||||
if err := binary.Read(rd, end, &i.Size); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := binary.Read(rd, end, &i.Width); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := binary.Read(rd, end, &i.Height); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := binary.Read(rd, end, &i.Delay); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := binary.Read(rd, end, &i.OffsetX); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := binary.Read(rd, end, &i.OffsetY); err != nil {
|
||||
return err
|
||||
}
|
||||
cf := image.NewRGBA64(image.Rect(0, 0, int(i.Width), int(i.Height)))
|
||||
i.Img = cf
|
||||
switch i.Bpp {
|
||||
|
@ -34,7 +63,7 @@ func (i *Image) Decode(rd *bufio.Reader, palette *PaletteSection) error {
|
|||
return fmt.Errorf("bpp = 8, but no palette")
|
||||
}
|
||||
for idx := 0; idx < int(i.Size); idx++ {
|
||||
b, err := rd.ReadByte()
|
||||
b, err := readByte(rd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1,29 +1,10 @@
|
|||
package nori
|
||||
|
||||
import "image/color"
|
||||
|
||||
type PaletteSection struct {
|
||||
Version uint32
|
||||
Params [4]uint32
|
||||
Divided bool
|
||||
DataLength uint32
|
||||
Palette [256]color.Color
|
||||
MainBound [2]uint32
|
||||
}
|
||||
|
||||
type GawiSection struct {
|
||||
Version uint32
|
||||
Bpp uint32
|
||||
IsCompressed bool
|
||||
Params [4]uint32
|
||||
BmpCount uint32
|
||||
Size uint32
|
||||
|
||||
HasPalette bool
|
||||
Palette *PaletteSection
|
||||
// std::vector<uint32> bmp_offsets
|
||||
Images []*Image
|
||||
}
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
type Nori struct {
|
||||
Version uint32
|
||||
|
@ -34,7 +15,47 @@ type Nori struct {
|
|||
|
||||
Gawi *GawiSection
|
||||
Animations []*Animation
|
||||
AnimationByKey map[string]*Animation
|
||||
//AnimationByKey map[string]*Animation
|
||||
|
||||
lastSignature [4]byte
|
||||
}
|
||||
|
||||
func (n *Nori) Decode(r io.Reader) error {
|
||||
rd := reflectReader(r)
|
||||
n.Gawi = &GawiSection{}
|
||||
if _, err := io.ReadFull(rd, n.lastSignature[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if sig, target := string(n.lastSignature[:]), "NORI"; sig != target {
|
||||
return fmt.Errorf("expected header %s, got %s", target, sig)
|
||||
}
|
||||
if err := binary.Read(rd, end, &n.Version); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(rd, end, n.Params[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(rd, end, &n.AnimationCount); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(rd, end, &n.SizeNoGawi); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(rd, end, &n.TotalSize); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := n.Gawi.Decode(rd); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := discardN(rd, 4*int(n.AnimationCount)); err != nil {
|
||||
return err
|
||||
}
|
||||
n.Animations = make([]*Animation, n.AnimationCount)
|
||||
for i := range n.Animations {
|
||||
n.Animations[i] = NewAnimation(int(n.Version))
|
||||
if err := n.Animations[i].Decode(rd); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
package nori
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"image/color"
|
||||
"io"
|
||||
)
|
||||
|
||||
type PaletteSection struct {
|
||||
Version uint32
|
||||
Params [4]uint32
|
||||
Divided bool
|
||||
DataLength uint32
|
||||
Palette [256]color.Color
|
||||
MainBound [2]uint32
|
||||
|
||||
lastSignature [4]byte
|
||||
}
|
||||
|
||||
func (p *PaletteSection) Decode(rd io.Reader) error {
|
||||
if _, err := io.ReadFull(rd, p.lastSignature[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if sig, target := string(p.lastSignature[:]), "PAL_"; sig != target {
|
||||
return fmt.Errorf("bad sig: want %s, got %s", target, sig)
|
||||
}
|
||||
p.Palette = [256]color.Color{}
|
||||
if err := binary.Read(rd, end, &p.Version); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(rd, end, p.Params[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
var cast uint32
|
||||
if err := binary.Read(rd, end, &cast); err != nil {
|
||||
return err
|
||||
}
|
||||
p.Divided = (cast > 0)
|
||||
if err := binary.Read(rd, end, &p.DataLength); err != nil {
|
||||
return err
|
||||
}
|
||||
for i := 0; i < 256; i++ {
|
||||
rgb := [3]byte{}
|
||||
_, err := io.ReadFull(rd, rgb[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
alpha := uint8(0xff)
|
||||
if rgb[0] == 0x00 && rgb[1] == 0xff && rgb[2] == 0x00 {
|
||||
alpha = 0x00
|
||||
}
|
||||
if rgb[0] == 0xff && rgb[1] == 0x00 && rgb[2] == 0xff {
|
||||
alpha = 0x00
|
||||
}
|
||||
p.Palette[i] = &color.RGBA{
|
||||
rgb[0], rgb[1], rgb[2],
|
||||
alpha,
|
||||
}
|
||||
}
|
||||
if p.Divided {
|
||||
if err := binary.Read(rd, end, p.MainBound[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package nori
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
)
|
||||
|
||||
type Plane struct {
|
||||
BitmapId uint32
|
||||
PlaneX int32
|
||||
PlaneY int32
|
||||
Opacity uint32
|
||||
Blend BlendMode
|
||||
FlagParam uint32
|
||||
RenderFlag uint32
|
||||
}
|
||||
|
||||
func (p *Plane) Decode(r io.Reader) error {
|
||||
if err := binary.Read(r, end, &p.BitmapId); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(r, end, &p.PlaneX); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(r, end, &p.PlaneY); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(r, end, &p.Opacity); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(r, end, &p.RenderFlag); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(r, end, &p.Blend); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(r, end, &p.FlagParam); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -1,219 +0,0 @@
|
|||
package nori
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"image/color"
|
||||
"io"
|
||||
)
|
||||
|
||||
var end = binary.LittleEndian
|
||||
|
||||
type Reader struct {
|
||||
nori *Nori
|
||||
|
||||
r *bufio.Reader
|
||||
}
|
||||
|
||||
func NewReader(rd io.Reader) *Reader {
|
||||
o := &Reader{
|
||||
nori: &Nori{},
|
||||
r: bufio.NewReader(rd),
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func (n *Reader) Decode() (*Nori, error) {
|
||||
if _, err := io.ReadFull(n, n.nori.lastSignature[:]); err != nil {
|
||||
return n.nori, err
|
||||
}
|
||||
if sig, target := string(n.nori.lastSignature[:]), "NORI"; sig != target {
|
||||
return n.nori, fmt.Errorf("expected header %s, got %s", target, sig)
|
||||
}
|
||||
if err := binary.Read(n, end, &n.nori.Version); err != nil {
|
||||
return n.nori, err
|
||||
}
|
||||
if err := binary.Read(n, end, n.nori.Params[:]); err != nil {
|
||||
return n.nori, err
|
||||
}
|
||||
if err := binary.Read(n, end, &n.nori.AnimationCount); err != nil {
|
||||
return n.nori, err
|
||||
}
|
||||
if err := binary.Read(n, end, &n.nori.SizeNoGawi); err != nil {
|
||||
return n.nori, err
|
||||
}
|
||||
if err := binary.Read(n, end, &n.nori.TotalSize); err != nil {
|
||||
return n.nori, err
|
||||
}
|
||||
if err := n.decodeGawi(); err != nil {
|
||||
return n.nori, err
|
||||
}
|
||||
return n.nori, nil
|
||||
}
|
||||
|
||||
func (n *Reader) decodeGawi() error {
|
||||
g := &GawiSection{}
|
||||
n.nori.Gawi = g
|
||||
if _, err := io.ReadFull(n, n.nori.lastSignature[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if sig, target := string(n.nori.lastSignature[:]), "GAWI"; sig != target {
|
||||
return fmt.Errorf("bad sig: want %s, got %s", target, sig)
|
||||
}
|
||||
if err := binary.Read(n, end, &g.Version); err != nil {
|
||||
return err
|
||||
}
|
||||
if g.Version != 300 {
|
||||
return fmt.Errorf("bad ver: want 300, got %d", g.Version)
|
||||
}
|
||||
if err := binary.Read(n, end, &g.Bpp); err != nil {
|
||||
return err
|
||||
}
|
||||
good := false
|
||||
for _, v := range [3]uint32{8, 16, 24} {
|
||||
if g.Bpp == v {
|
||||
good = true
|
||||
}
|
||||
}
|
||||
if !good {
|
||||
return fmt.Errorf("bad bpp: %d", g.Bpp)
|
||||
}
|
||||
var container uint32
|
||||
if err := binary.Read(n, end, &container); err != nil {
|
||||
return err
|
||||
}
|
||||
g.IsCompressed = (container == 1)
|
||||
if err := binary.Read(n, end, &container); err != nil {
|
||||
return err
|
||||
}
|
||||
g.HasPalette = (container > 0)
|
||||
|
||||
if err := binary.Read(n, end, g.Params[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(n, end, &g.BmpCount); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(n, end, &g.Size); err != nil {
|
||||
return err
|
||||
}
|
||||
if g.HasPalette {
|
||||
if err := n.decodePalette(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if _, err := n.r.Discard(4 * int(g.BmpCount)); err != nil {
|
||||
return err
|
||||
}
|
||||
g.Images = make([]*Image, int(g.BmpCount))
|
||||
for i := range g.Images {
|
||||
g.Images[i] = &Image{Bpp: g.Bpp}
|
||||
if err := n.decodeImage(g.Images[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if _, err := n.r.Discard(4 * int(n.nori.AnimationCount)); err != nil {
|
||||
return err
|
||||
}
|
||||
n.nori.Animations = make([]*Animation, n.nori.AnimationCount)
|
||||
for i := range n.nori.Animations {
|
||||
n.nori.Animations[i] = &Animation{}
|
||||
if err := n.nori.Animations[i].Decode(n.r, int(n.nori.Version)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *Reader) decodePalette() error {
|
||||
if _, err := io.ReadFull(n, n.nori.lastSignature[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if sig, target := string(n.nori.lastSignature[:]), "PAL_"; sig != target {
|
||||
return fmt.Errorf("bad sig: want %s, got %s", target, sig)
|
||||
}
|
||||
cp := &PaletteSection{
|
||||
Palette: [256]color.Color{},
|
||||
}
|
||||
n.nori.Gawi.Palette = cp
|
||||
if err := binary.Read(n, end, &cp.Version); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(n, end, cp.Params[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
var cast uint32
|
||||
if err := binary.Read(n, end, &cast); err != nil {
|
||||
return err
|
||||
}
|
||||
cp.Divided = (cast > 0)
|
||||
if err := binary.Read(n, end, &cp.DataLength); err != nil {
|
||||
return err
|
||||
}
|
||||
for i := 0; i < 256; i++ {
|
||||
rgb := [3]byte{}
|
||||
_, err := io.ReadFull(n, rgb[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
alpha := uint8(0xff)
|
||||
if rgb[0] == 0x00 && rgb[1] == 0xff && rgb[2] == 0x00 {
|
||||
alpha = 0x00
|
||||
}
|
||||
if rgb[0] == 0xff && rgb[1] == 0x00 && rgb[2] == 0xff {
|
||||
alpha = 0x00
|
||||
}
|
||||
cp.Palette[i] = &color.RGBA{
|
||||
rgb[0], rgb[1], rgb[2],
|
||||
alpha,
|
||||
}
|
||||
}
|
||||
|
||||
if cp.Divided {
|
||||
if err := binary.Read(n, end, cp.MainBound[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (n *Reader) decodeImage(img *Image) error {
|
||||
if err := binary.Read(n, end, &img.Count); err != nil {
|
||||
return err
|
||||
}
|
||||
if img.Count != 1 {
|
||||
return fmt.Errorf("img count should be 1")
|
||||
}
|
||||
|
||||
if err := binary.Read(n, end, &img.Size); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := binary.Read(n, end, &img.Width); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := binary.Read(n, end, &img.Height); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := binary.Read(n, end, &img.Delay); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := binary.Read(n, end, &img.OffsetX); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := binary.Read(n, end, &img.OffsetY); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := img.Decode(n.r, n.nori.Gawi.Palette); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *Reader) Read(b []byte) (int, error) {
|
||||
return n.r.Read(b)
|
||||
}
|
|
@ -10,23 +10,7 @@ import (
|
|||
"gitlab.com/gfxlabs/gfximg/apng"
|
||||
)
|
||||
|
||||
func (n *Nori) ShowAnimation() *apng.APNG {
|
||||
g := n.Gawi
|
||||
a := &apng.APNG{
|
||||
Frames: make([]apng.Frame, 0, len(g.Images)),
|
||||
}
|
||||
for i := 0; i < len(g.Images); i++ {
|
||||
fr := apng.Frame{
|
||||
Image: g.Images[i].Img,
|
||||
DelayNumerator: uint16(g.Images[i].Delay),
|
||||
DelayDenominator: 1000,
|
||||
}
|
||||
a.Frames = append(a.Frames, fr)
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
func (n *Nori) ExportAnimation(num int) (*apng.APNG, error) {
|
||||
func (n *Nori) RenderAnimation(num int) (*apng.APNG, error) {
|
||||
g := n.Gawi
|
||||
a := &apng.APNG{
|
||||
Frames: make([]apng.Frame, 0, len(g.Images)),
|
|
@ -11,11 +11,7 @@ import (
|
|||
)
|
||||
|
||||
func TestParseFile1(t *testing.T) {
|
||||
rd, err := os.OpenFile("./nori_test/test1.nri", os.O_RDONLY, 0666)
|
||||
if err != nil {
|
||||
t.Errorf("open file: %s", err)
|
||||
}
|
||||
nori, err := NewReader(rd).Decode()
|
||||
nori, err := FromFile("./render_test/test1.nri")
|
||||
if err != nil {
|
||||
t.Errorf("decode: %s", err)
|
||||
}
|
||||
|
@ -28,11 +24,7 @@ func TestParseFile1(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestParseFile2(t *testing.T) {
|
||||
rd, err := os.OpenFile("./nori_test/test2.nri", os.O_RDONLY, 0666)
|
||||
if err != nil {
|
||||
t.Errorf("open file: %s", err)
|
||||
}
|
||||
nori, err := NewReader(rd).Decode()
|
||||
nori, err := FromFile("./render_test/test2.nri")
|
||||
if err != nil {
|
||||
t.Errorf("decode: %s", err)
|
||||
}
|
||||
|
@ -44,11 +36,7 @@ func TestParseFile2(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestParsePalette(t *testing.T) {
|
||||
rd, err := os.OpenFile("./nori_test/palette.nri", os.O_RDONLY, 0666)
|
||||
if err != nil {
|
||||
t.Errorf("open file: %s", err)
|
||||
}
|
||||
nori, err := NewReader(rd).Decode()
|
||||
nori, err := FromFile("./render_test/palette.nri")
|
||||
if err != nil {
|
||||
t.Errorf("decode: %s", err)
|
||||
}
|
||||
|
@ -62,9 +50,9 @@ func TestParsePalette(t *testing.T) {
|
|||
func writeApng(nori *Nori, name string) error {
|
||||
postfix := ".example"
|
||||
out := new(bytes.Buffer)
|
||||
os.MkdirAll(fmt.Sprintf("./nori_test/%s%s", name, postfix), 0740)
|
||||
os.MkdirAll(fmt.Sprintf("./render_test/%s%s", name, postfix), 0740)
|
||||
for i := range nori.Animations {
|
||||
a, err := nori.ExportAnimation(i)
|
||||
a, err := nori.RenderAnimation(i)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "no frame") {
|
||||
continue
|
||||
|
@ -75,7 +63,7 @@ func writeApng(nori *Nori, name string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.WriteFile(fmt.Sprintf("./nori_test/%s%s/animation_%d.png", name, postfix, i), out.Bytes(), 0740)
|
||||
err = os.WriteFile(fmt.Sprintf("./render_test/%s%s/animation_%d.png", name, postfix, i), out.Bytes(), 0740)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 80 KiB |
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 80 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 609 B After Width: | Height: | Size: 609 B |
Before Width: | Height: | Size: 609 B After Width: | Height: | Size: 609 B |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |