This commit is contained in:
elee 2022-03-25 02:33:23 -05:00
parent 47850d7b13
commit 4057b3c3c6
6 changed files with 135 additions and 44 deletions

View File

@ -13,7 +13,7 @@ type Frame struct {
CoordinateCount uint32
Coordinates [][2]uint32
Unknown1 string
Sound_effect string
SoundEffect string
Unknown2 string
Camp CampSection
}
@ -23,8 +23,17 @@ type CampSection struct {
Extra string
}
type Plane struct {
BitmapId uint32
PlaneX int32
PlaneY int32
Opacity uint32
Blend BlendMode
FlagParam uint32
RenderFlag uint32
}
type Animation struct {
Title string
Title [32]byte
// std::vector<uint32> frame_offsets
FrameCount uint32
@ -32,9 +41,15 @@ type Animation struct {
}
func (a *Animation) Decode(rd *bufio.Reader, version int) 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 {
return err
}
a.Frames = make([]*Frame, int(a.FrameCount))
for i := range a.Frames {
cf := &Frame{}
@ -42,29 +57,31 @@ func (a *Animation) Decode(rd *bufio.Reader, version int) error {
if err := binary.Read(rd, end, &cf.Duration); 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
}
@ -75,7 +92,10 @@ func (a *Animation) Decode(rd *bufio.Reader, version int) error {
}
cf.Coordinates = make([][2]uint32, cf.CoordinateCount)
for i := range cf.Coordinates {
if err := binary.Read(rd, end, cf.Coordinates[i]); err != nil {
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
}
}
@ -112,9 +132,9 @@ func (a *Animation) Decode(rd *bufio.Reader, version int) error {
if err := binary.Read(rd, end, &cast); err != nil {
return err
}
if version > 303 && (cast > 1) {
if version >= 303 && (cast > 0) {
cf.Camp = CampSection{}
if err := binary.Read(rd, end, &cf.Camp.Params); err != nil {
if err := binary.Read(rd, end, cf.Camp.Params[:]); err != nil {
return err
}
sz := int(cf.Camp.Params[1]) * int(cf.Camp.Params[2])
@ -122,17 +142,10 @@ func (a *Animation) Decode(rd *bufio.Reader, version int) error {
if _, err := io.ReadFull(rd, cf.Camp.Array); err != nil {
return err
}
if _, err := rd.Discard(20); err != nil {
return err
}
}
}
return nil
}
type Plane struct {
Bitmap_id uint32
PlaneX int32
PlaneY int32
Opacity uint32
Blend BlendMode
FlagParam uint32
RenderFlag uint32
}

View File

@ -1,15 +1,22 @@
package nori
import "gitlab.com/gfxlabs/gfximg/apng"
import (
"fmt"
"image"
"image/draw"
func (n *Nori) ExportAnimation() *apng.APNG {
"git.tuxpa.in/a/zlog/log"
"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].Frame,
Image: g.Images[i].Img,
DelayNumerator: uint16(g.Images[i].Delay),
DelayDenominator: 1000,
}
@ -17,3 +24,60 @@ func (n *Nori) ExportAnimation() *apng.APNG {
}
return a
}
func (n *Nori) ExportAnimation() (*apng.APNG, error) {
g := n.Gawi
a := &apng.APNG{
Frames: make([]apng.Frame, 0, len(g.Images)),
}
for i := 0; i < len(n.Animations); i++ {
for _, v := range n.Animations[i].Frames {
canvasRect := image.Rect(0, 0, 0, 0)
for _, plane := range v.Planes {
if int(plane.BitmapId) >= len(n.Gawi.Images) {
log.Printf("could not find bitmap %d, only have %d", plane.BitmapId, len(n.Gawi.Images))
}
bitmap := n.Gawi.Images[plane.BitmapId]
canvasRect = canvasRect.Union(bitmap.Img.Bounds())
}
img := image.NewRGBA64(canvasRect)
for _, plane := range v.Planes {
bitmap := n.Gawi.Images[plane.BitmapId]
transparent := false
//flipx
if plane.RenderFlag&1 != 0 {
}
//flipy
if plane.RenderFlag&2 != 0 {
}
// is transparent
if plane.RenderFlag&0x20 != 0 {
transparent = true
}
_ = transparent
switch plane.Blend {
case BlendMode_Alpha:
case BlendMode_Mul, BlendMode_Mul7:
case BlendMode_Add, BlendMode_Add8:
case BlendMode_InvertMul, BlendMode_InvertMul5:
case BlendMode_None:
break
default:
return nil, fmt.Errorf("unknown blend mode: %d", plane.Blend)
}
draw.Draw(img,
img.Rect,
bitmap.Img,
image.Point{X: int(plane.PlaneX),
Y: int(plane.PlaneY)}, draw.Over)
}
fr := apng.Frame{
Image: g.Images[i].Img,
DelayNumerator: uint16(g.Images[i].Delay),
DelayDenominator: 1000,
}
a.Frames = append(a.Frames, fr)
}
}
return a, nil
}

View File

@ -22,13 +22,12 @@ type Image struct {
Size uint32
Data []byte
Frame image.Image
Img image.Image
}
func (i *Image) Decode(rd *bufio.Reader, palette *PaletteSection) error {
cf := image.NewRGBA64(image.Rect(0, 0, int(i.Width), int(i.Height)))
i.Frame = cf
i.Img = cf
switch i.Bpp {
case 8:
if palette == nil {
@ -80,4 +79,3 @@ func (i *Image) Decode(rd *bufio.Reader, palette *PaletteSection) error {
return fmt.Errorf("unsupported bpp, %d", i.Bpp)
}
}

View File

@ -12,43 +12,53 @@ import (
func TestParseFile1(t *testing.T) {
rd, err := os.OpenFile("./nori_test/test1.nri", os.O_RDONLY, 0666)
if err != nil {
t.Fatalf("open file: %s", err)
t.Errorf("open file: %s", err)
}
nori, err := NewReader(rd).Decode()
if err != nil {
t.Fatalf("decode: %s", err)
t.Errorf("decode: %s", err)
}
t.Logf("\n nori: %+v", nori)
t.Logf("\n gawi: %+v", nori.Gawi)
a, err := nori.ExportAnimation()
if err != nil {
t.Errorf("export: %s", err)
}
t.Logf("\n nori: %+v\n gawi: %+v", nori, nori.Gawi)
a := nori.ExportAnimation()
writeApng(a, "./nori_test/test1.apng")
}
func TestParseFile2(t *testing.T) {
rd, err := os.OpenFile("./nori_test/test2.nri", os.O_RDONLY, 0666)
if err != nil {
t.Fatalf("open file: %s", err)
t.Errorf("open file: %s", err)
}
nori, err := NewReader(rd).Decode()
if err != nil {
t.Fatalf("decode: %s", err)
t.Errorf("decode: %s", err)
}
t.Logf("\n nori: %+v\n gawi: %+v", nori, nori.Gawi)
a := nori.ExportAnimation()
a, err := nori.ExportAnimation()
if err != nil {
t.Errorf("export: %s", err)
}
writeApng(a, "./nori_test/test2.apng")
}
func TestParsePalette(t *testing.T) {
rd, err := os.OpenFile("./nori_test/palette.nri", os.O_RDONLY, 0666)
if err != nil {
t.Logf("open file: %s", err)
t.Fail()
t.Errorf("open file: %s", err)
}
nori, err := NewReader(rd).Decode()
if err != nil {
t.Errorf("decode: %s", err)
}
t.Logf("\n nori: %+v\n gawi: %+v\n palette: %+v\n", nori, nori.Gawi, nori.Gawi.Palette)
a := nori.ExportAnimation()
a, err := nori.ExportAnimation()
if err != nil {
t.Errorf("export: %s", err)
}
writeApng(a, "./nori_test/palette.apng")
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 969 KiB

After

Width:  |  Height:  |  Size: 1.9 MiB

View File

@ -26,28 +26,28 @@ func NewReader(rd io.Reader) *Reader {
func (n *Reader) Decode() (*Nori, error) {
if _, err := io.ReadFull(n, n.nori.lastSignature[:]); err != nil {
return nil, err
return n.nori, err
}
if sig, target := string(n.nori.lastSignature[:]), "NORI"; sig != target {
return nil, fmt.Errorf("expected header %s, got %s", target, sig)
return n.nori, fmt.Errorf("expected header %s, got %s", target, sig)
}
if err := binary.Read(n, end, &n.nori.Version); err != nil {
return nil, err
return n.nori, err
}
if err := binary.Read(n, end, n.nori.Params[:]); err != nil {
return nil, err
return n.nori, err
}
if err := binary.Read(n, end, &n.nori.AnimationCount); err != nil {
return nil, err
return n.nori, err
}
if err := binary.Read(n, end, &n.nori.SizeNoGawi); err != nil {
return nil, err
return n.nori, err
}
if err := binary.Read(n, end, &n.nori.TotalSize); err != nil {
return nil, err
return n.nori, err
}
if err := n.decodeGawi(); err != nil {
return nil, err
return n.nori, err
}
return n.nori, nil
}
@ -117,6 +117,12 @@ func (n *Reader) decodeGawi() error {
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
}