huh
This commit is contained in:
parent
47850d7b13
commit
4057b3c3c6
|
@ -13,7 +13,7 @@ type Frame struct {
|
||||||
CoordinateCount uint32
|
CoordinateCount uint32
|
||||||
Coordinates [][2]uint32
|
Coordinates [][2]uint32
|
||||||
Unknown1 string
|
Unknown1 string
|
||||||
Sound_effect string
|
SoundEffect string
|
||||||
Unknown2 string
|
Unknown2 string
|
||||||
Camp CampSection
|
Camp CampSection
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,17 @@ type CampSection struct {
|
||||||
Extra string
|
Extra string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Plane struct {
|
||||||
|
BitmapId uint32
|
||||||
|
PlaneX int32
|
||||||
|
PlaneY int32
|
||||||
|
Opacity uint32
|
||||||
|
Blend BlendMode
|
||||||
|
FlagParam uint32
|
||||||
|
RenderFlag uint32
|
||||||
|
}
|
||||||
type Animation struct {
|
type Animation struct {
|
||||||
Title string
|
Title [32]byte
|
||||||
|
|
||||||
// std::vector<uint32> frame_offsets
|
// std::vector<uint32> frame_offsets
|
||||||
FrameCount uint32
|
FrameCount uint32
|
||||||
|
@ -32,9 +41,15 @@ type Animation struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Animation) Decode(rd *bufio.Reader, version int) error {
|
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 {
|
if err := binary.Read(rd, end, &a.FrameCount); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if _, err := rd.Discard(4 * int(a.FrameCount)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
a.Frames = make([]*Frame, int(a.FrameCount))
|
a.Frames = make([]*Frame, int(a.FrameCount))
|
||||||
for i := range a.Frames {
|
for i := range a.Frames {
|
||||||
cf := &Frame{}
|
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 {
|
if err := binary.Read(rd, end, &cf.Duration); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := binary.Read(rd, end, &cf.PlaneCount); err != nil {
|
if err := binary.Read(rd, end, &cf.PlaneCount); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cf.Planes = make([]*Plane, int(cf.PlaneCount))
|
cf.Planes = make([]*Plane, int(cf.PlaneCount))
|
||||||
for i := range cf.Planes {
|
for i := range cf.Planes {
|
||||||
cp := &Plane{}
|
cp := &Plane{}
|
||||||
cf.Planes[i] = cp
|
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 {
|
if err := binary.Read(rd, end, &cp.PlaneX); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := binary.Read(rd, end, &cp.PlaneY); err != nil {
|
if err := binary.Read(rd, end, &cp.PlaneY); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := binary.Read(rd, end, &cp.Opacity); err != nil {
|
if err := binary.Read(rd, end, &cp.Opacity); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := binary.Read(rd, end, &cp.RenderFlag); err != nil {
|
if err := binary.Read(rd, end, &cp.RenderFlag); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := binary.Read(rd, end, &cp.Blend); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err := binary.Read(rd, end, &cp.FlagParam); err != nil {
|
if err := binary.Read(rd, end, &cp.FlagParam); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -75,7 +92,10 @@ func (a *Animation) Decode(rd *bufio.Reader, version int) error {
|
||||||
}
|
}
|
||||||
cf.Coordinates = make([][2]uint32, cf.CoordinateCount)
|
cf.Coordinates = make([][2]uint32, cf.CoordinateCount)
|
||||||
for i := range cf.Coordinates {
|
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
|
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 {
|
if err := binary.Read(rd, end, &cast); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if version > 303 && (cast > 1) {
|
if version >= 303 && (cast > 0) {
|
||||||
cf.Camp = CampSection{}
|
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
|
return err
|
||||||
}
|
}
|
||||||
sz := int(cf.Camp.Params[1]) * int(cf.Camp.Params[2])
|
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 {
|
if _, err := io.ReadFull(rd, cf.Camp.Array); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if _, err := rd.Discard(20); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type Plane struct {
|
|
||||||
Bitmap_id uint32
|
|
||||||
PlaneX int32
|
|
||||||
PlaneY int32
|
|
||||||
Opacity uint32
|
|
||||||
Blend BlendMode
|
|
||||||
FlagParam uint32
|
|
||||||
RenderFlag uint32
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,15 +1,22 @@
|
||||||
package nori
|
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
|
g := n.Gawi
|
||||||
a := &apng.APNG{
|
a := &apng.APNG{
|
||||||
Frames: make([]apng.Frame, 0, len(g.Images)),
|
Frames: make([]apng.Frame, 0, len(g.Images)),
|
||||||
}
|
}
|
||||||
for i := 0; i < len(g.Images); i++ {
|
for i := 0; i < len(g.Images); i++ {
|
||||||
fr := apng.Frame{
|
fr := apng.Frame{
|
||||||
Image: g.Images[i].Frame,
|
Image: g.Images[i].Img,
|
||||||
DelayNumerator: uint16(g.Images[i].Delay),
|
DelayNumerator: uint16(g.Images[i].Delay),
|
||||||
DelayDenominator: 1000,
|
DelayDenominator: 1000,
|
||||||
}
|
}
|
||||||
|
@ -17,3 +24,60 @@ func (n *Nori) ExportAnimation() *apng.APNG {
|
||||||
}
|
}
|
||||||
return a
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -22,13 +22,12 @@ type Image struct {
|
||||||
Size uint32
|
Size uint32
|
||||||
Data []byte
|
Data []byte
|
||||||
|
|
||||||
Frame image.Image
|
Img image.Image
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (i *Image) Decode(rd *bufio.Reader, palette *PaletteSection) error {
|
func (i *Image) Decode(rd *bufio.Reader, palette *PaletteSection) error {
|
||||||
cf := image.NewRGBA64(image.Rect(0, 0, int(i.Width), int(i.Height)))
|
cf := image.NewRGBA64(image.Rect(0, 0, int(i.Width), int(i.Height)))
|
||||||
i.Frame = cf
|
i.Img = cf
|
||||||
switch i.Bpp {
|
switch i.Bpp {
|
||||||
case 8:
|
case 8:
|
||||||
if palette == nil {
|
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)
|
return fmt.Errorf("unsupported bpp, %d", i.Bpp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,43 +12,53 @@ import (
|
||||||
func TestParseFile1(t *testing.T) {
|
func TestParseFile1(t *testing.T) {
|
||||||
rd, err := os.OpenFile("./nori_test/test1.nri", os.O_RDONLY, 0666)
|
rd, err := os.OpenFile("./nori_test/test1.nri", os.O_RDONLY, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("open file: %s", err)
|
t.Errorf("open file: %s", err)
|
||||||
}
|
}
|
||||||
nori, err := NewReader(rd).Decode()
|
nori, err := NewReader(rd).Decode()
|
||||||
if err != nil {
|
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")
|
writeApng(a, "./nori_test/test1.apng")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseFile2(t *testing.T) {
|
func TestParseFile2(t *testing.T) {
|
||||||
rd, err := os.OpenFile("./nori_test/test2.nri", os.O_RDONLY, 0666)
|
rd, err := os.OpenFile("./nori_test/test2.nri", os.O_RDONLY, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("open file: %s", err)
|
t.Errorf("open file: %s", err)
|
||||||
}
|
}
|
||||||
nori, err := NewReader(rd).Decode()
|
nori, err := NewReader(rd).Decode()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("decode: %s", err)
|
t.Errorf("decode: %s", err)
|
||||||
}
|
}
|
||||||
t.Logf("\n nori: %+v\n gawi: %+v", nori, nori.Gawi)
|
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")
|
writeApng(a, "./nori_test/test2.apng")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParsePalette(t *testing.T) {
|
func TestParsePalette(t *testing.T) {
|
||||||
rd, err := os.OpenFile("./nori_test/palette.nri", os.O_RDONLY, 0666)
|
rd, err := os.OpenFile("./nori_test/palette.nri", os.O_RDONLY, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Logf("open file: %s", err)
|
t.Errorf("open file: %s", err)
|
||||||
t.Fail()
|
|
||||||
}
|
}
|
||||||
nori, err := NewReader(rd).Decode()
|
nori, err := NewReader(rd).Decode()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("decode: %s", err)
|
t.Errorf("decode: %s", err)
|
||||||
}
|
}
|
||||||
t.Logf("\n nori: %+v\n gawi: %+v\n palette: %+v\n", nori, nori.Gawi, nori.Gawi.Palette)
|
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")
|
writeApng(a, "./nori_test/palette.apng")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 969 KiB After Width: | Height: | Size: 1.9 MiB |
|
@ -26,28 +26,28 @@ func NewReader(rd io.Reader) *Reader {
|
||||||
|
|
||||||
func (n *Reader) Decode() (*Nori, error) {
|
func (n *Reader) Decode() (*Nori, error) {
|
||||||
if _, err := io.ReadFull(n, n.nori.lastSignature[:]); err != nil {
|
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 {
|
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 {
|
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 {
|
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 {
|
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 {
|
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 {
|
if err := binary.Read(n, end, &n.nori.TotalSize); err != nil {
|
||||||
return nil, err
|
return n.nori, err
|
||||||
}
|
}
|
||||||
if err := n.decodeGawi(); err != nil {
|
if err := n.decodeGawi(); err != nil {
|
||||||
return nil, err
|
return n.nori, err
|
||||||
}
|
}
|
||||||
return n.nori, nil
|
return n.nori, nil
|
||||||
}
|
}
|
||||||
|
@ -117,6 +117,12 @@ func (n *Reader) decodeGawi() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
n.nori.Animations = make([]*Animation, n.nori.AnimationCount)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue