diff --git a/animations/a_0.png b/animations/a_0.png new file mode 100644 index 0000000..ee6dc1b Binary files /dev/null and b/animations/a_0.png differ diff --git a/animations/a_1.png b/animations/a_1.png new file mode 100644 index 0000000..ee6dc1b Binary files /dev/null and b/animations/a_1.png differ diff --git a/animations/a_10.png b/animations/a_10.png new file mode 100644 index 0000000..98b5e21 Binary files /dev/null and b/animations/a_10.png differ diff --git a/animations/a_11.png b/animations/a_11.png new file mode 100644 index 0000000..ed11f2c Binary files /dev/null and b/animations/a_11.png differ diff --git a/animations/a_12.png b/animations/a_12.png new file mode 100644 index 0000000..b9ebc66 Binary files /dev/null and b/animations/a_12.png differ diff --git a/animations/a_13.png b/animations/a_13.png new file mode 100644 index 0000000..148dc30 Binary files /dev/null and b/animations/a_13.png differ diff --git a/animations/a_14.png b/animations/a_14.png new file mode 100644 index 0000000..0239309 Binary files /dev/null and b/animations/a_14.png differ diff --git a/animations/a_15.png b/animations/a_15.png new file mode 100644 index 0000000..ee6dc1b Binary files /dev/null and b/animations/a_15.png differ diff --git a/animations/a_16.png b/animations/a_16.png new file mode 100644 index 0000000..aa6df6d Binary files /dev/null and b/animations/a_16.png differ diff --git a/animations/a_17.png b/animations/a_17.png new file mode 100644 index 0000000..b0c744c Binary files /dev/null and b/animations/a_17.png differ diff --git a/animations/a_18.png b/animations/a_18.png new file mode 100644 index 0000000..4c99973 Binary files /dev/null and b/animations/a_18.png differ diff --git a/animations/a_19.png b/animations/a_19.png new file mode 100644 index 0000000..4140516 Binary files /dev/null and b/animations/a_19.png differ diff --git a/animations/a_2.png b/animations/a_2.png new file mode 100644 index 0000000..98b5e21 Binary files /dev/null and b/animations/a_2.png differ diff --git a/animations/a_20.png b/animations/a_20.png new file mode 100644 index 0000000..1ba427c Binary files /dev/null and b/animations/a_20.png differ diff --git a/animations/a_21.png b/animations/a_21.png new file mode 100644 index 0000000..1d2a420 Binary files /dev/null and b/animations/a_21.png differ diff --git a/animations/a_22.png b/animations/a_22.png new file mode 100644 index 0000000..66be67a Binary files /dev/null and b/animations/a_22.png differ diff --git a/animations/a_23.png b/animations/a_23.png new file mode 100644 index 0000000..253200b Binary files /dev/null and b/animations/a_23.png differ diff --git a/animations/a_24.png b/animations/a_24.png new file mode 100644 index 0000000..cdce141 Binary files /dev/null and b/animations/a_24.png differ diff --git a/animations/a_25.png b/animations/a_25.png new file mode 100644 index 0000000..a0f7062 Binary files /dev/null and b/animations/a_25.png differ diff --git a/animations/a_26.png b/animations/a_26.png new file mode 100644 index 0000000..ee6dc1b Binary files /dev/null and b/animations/a_26.png differ diff --git a/animations/a_27.png b/animations/a_27.png new file mode 100644 index 0000000..ed11f2c Binary files /dev/null and b/animations/a_27.png differ diff --git a/animations/a_28.png b/animations/a_28.png new file mode 100644 index 0000000..f8c2c3f Binary files /dev/null and b/animations/a_28.png differ diff --git a/animations/a_29.png b/animations/a_29.png new file mode 100644 index 0000000..ee6dc1b Binary files /dev/null and b/animations/a_29.png differ diff --git a/animations/a_3.png b/animations/a_3.png new file mode 100644 index 0000000..ed11f2c Binary files /dev/null and b/animations/a_3.png differ diff --git a/animations/a_30.png b/animations/a_30.png new file mode 100644 index 0000000..ee6dc1b Binary files /dev/null and b/animations/a_30.png differ diff --git a/animations/a_31.png b/animations/a_31.png new file mode 100644 index 0000000..ed11f2c Binary files /dev/null and b/animations/a_31.png differ diff --git a/animations/a_32.png b/animations/a_32.png new file mode 100644 index 0000000..f8c2c3f Binary files /dev/null and b/animations/a_32.png differ diff --git a/animations/a_33.png b/animations/a_33.png new file mode 100644 index 0000000..ee6dc1b Binary files /dev/null and b/animations/a_33.png differ diff --git a/animations/a_34.png b/animations/a_34.png new file mode 100644 index 0000000..ee6dc1b Binary files /dev/null and b/animations/a_34.png differ diff --git a/animations/a_35.png b/animations/a_35.png new file mode 100644 index 0000000..ed11f2c Binary files /dev/null and b/animations/a_35.png differ diff --git a/animations/a_36.png b/animations/a_36.png new file mode 100644 index 0000000..f8c2c3f Binary files /dev/null and b/animations/a_36.png differ diff --git a/animations/a_37.png b/animations/a_37.png new file mode 100644 index 0000000..ee6dc1b Binary files /dev/null and b/animations/a_37.png differ diff --git a/animations/a_4.png b/animations/a_4.png new file mode 100644 index 0000000..b9ebc66 Binary files /dev/null and b/animations/a_4.png differ diff --git a/animations/a_5.png b/animations/a_5.png new file mode 100644 index 0000000..f8c2c3f Binary files /dev/null and b/animations/a_5.png differ diff --git a/animations/a_6.png b/animations/a_6.png new file mode 100644 index 0000000..0239309 Binary files /dev/null and b/animations/a_6.png differ diff --git a/animations/a_7.png b/animations/a_7.png new file mode 100644 index 0000000..ee6dc1b Binary files /dev/null and b/animations/a_7.png differ diff --git a/animations/a_8.png b/animations/a_8.png new file mode 100644 index 0000000..ee6dc1b Binary files /dev/null and b/animations/a_8.png differ diff --git a/animations/a_9.png b/animations/a_9.png new file mode 100644 index 0000000..ee6dc1b Binary files /dev/null and b/animations/a_9.png differ diff --git a/_cmd/cory-bin/main.go b/cmd/cory-bin/main.go similarity index 98% rename from _cmd/cory-bin/main.go rename to cmd/cory-bin/main.go index 7643f3c..72b95cf 100644 --- a/_cmd/cory-bin/main.go +++ b/cmd/cory-bin/main.go @@ -4,11 +4,12 @@ import ( "bytes" "flag" "fmt" - "git.tuxpa.in/a/nori/renderer" "net/http" "os" "time" + "git.tuxpa.in/a/nori/renderer" + "git.tuxpa.in/a/nori" "git.tuxpa.in/a/nori/utils" "git.tuxpa.in/a/zlog/log" @@ -54,7 +55,7 @@ func dump(filename string, output string) { printIf("reading file '%s'\n", filename) n, err := nori.FromFile(filename) if err != nil { - log.Panicln("decode: %s", err) + log.Panicf("decode: %s", err) } out := new(bytes.Buffer) printIf("rendering %d animation(s)\n", n.AnimationCount) diff --git a/compress.nri b/compress.nri new file mode 100644 index 0000000..2e1daca Binary files /dev/null and b/compress.nri differ diff --git a/decode.go b/decode.go index 362c847..2fc1588 100644 --- a/decode.go +++ b/decode.go @@ -1,7 +1,6 @@ package nori import ( - "bufio" "io" "os" ) @@ -16,7 +15,7 @@ func FromFile(fp string) (*Nori, error) { return nil, err } defer file.Close() - return Decode(bufio.NewReader(file)) + return Decode(file) } func Decode(r io.Reader) (*Nori, error) { diff --git a/gawi.go b/gawi.go index 40ea080..dd3e065 100644 --- a/gawi.go +++ b/gawi.go @@ -77,7 +77,7 @@ func (g *GawiSection) Decode(rd io.Reader) error { 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 { + if err := g.Images[i].Decode(rd, g); err != nil { return err } } diff --git a/go.mod b/go.mod index 63cc2a4..effca3c 100644 --- a/go.mod +++ b/go.mod @@ -5,13 +5,12 @@ go 1.18 require ( git.tuxpa.in/a/zlog v1.32.0 github.com/disintegration/imaging v1.6.2 + github.com/go-chi/chi/v5 v5.0.7 github.com/phrozen/blend v0.0.0-20210220204729-f26b6cf7a28e gitlab.com/gfxlabs/gfximg v0.0.5 ) require ( - github.com/chai2010/webp v1.1.1 // indirect - github.com/go-chi/chi/v5 v5.0.7 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect golang.org/x/image v0.0.0-20211028202545-6944b10bf410 // indirect diff --git a/go.sum b/go.sum index 0ff64b1..66f7973 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,5 @@ git.tuxpa.in/a/zlog v1.32.0 h1:KKXbRF1x8kJDSzUoGz/pivo+4TVY6xT5sVtdFZ6traY= git.tuxpa.in/a/zlog v1.32.0/go.mod h1:vUa2Qhu6DLPLqmfRy99FiPqaY2eb6/KQjtMekW3UNnA= -github.com/chai2010/webp v1.1.1 h1:jTRmEccAJ4MGrhFOrPMpNGIJ/eybIgwKpcACsrTEapk= -github.com/chai2010/webp v1.1.1/go.mod h1:0XVwvZWdjjdxpUEIf7b9g9VkHFnInUSYujwqTLEuldU= github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= @@ -18,7 +16,6 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= gitlab.com/gfxlabs/gfximg v0.0.5 h1:jtHE6In6axz0zGPy7YnLIZV9RFdcFEZzpdqoXb52K9s= gitlab.com/gfxlabs/gfximg v0.0.5/go.mod h1:IAYZwCoqy3JFKwkKafragpfecp5Up6FFIzI7VvK2Zzo= -golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ= golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= diff --git a/image.go b/image.go index 97a9df8..663e270 100644 --- a/image.go +++ b/image.go @@ -1,6 +1,7 @@ package nori import ( + "bytes" "encoding/binary" "fmt" "image" @@ -9,8 +10,12 @@ import ( ) type Image struct { - Bpp uint32 - Count uint32 + Bpp uint32 + Count uint32 + SubImages []*SubImage +} + +type SubImage struct { Delay uint32 OffsetX int32 OffsetY int32 @@ -19,61 +24,28 @@ type Image struct { Height uint32 Size uint32 - Data []byte Img image.Image + rgb *image.RGBA64 } -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 { +func (i *SubImage) decode(rd io.Reader, img *Image, size int, g *GawiSection) error { + switch img.Bpp { case 8: - if palette == nil { + if g.Palette == nil { return fmt.Errorf("bpp = 8, but no palette") } - for idx := 0; idx < int(i.Size); idx++ { + for idx := 0; idx < int(size); idx++ { b, err := readByte(rd) if err != nil { return err } - col := palette.Palette[b] - cf.Set(idx%int(i.Width), idx/int(i.Width), col) + col := g.Palette.Palette[b] + i.rgb.Set(idx%int(i.Width), idx/int(i.Width), col) } - return nil case 16: var bgr uint16 - for idx := 0; idx < int(i.Size/2); idx++ { + for idx := 0; idx < int(size/2); idx++ { if err := binary.Read(rd, end, &bgr); err != nil { return err } @@ -91,12 +63,10 @@ func (i *Image) Decode(rd io.Reader, palette *PaletteSection) error { red, green, blue, alpha, } - cf.Set(idx%int(i.Width), idx/int(i.Width), col) + i.rgb.Set(idx%int(i.Width), idx/int(i.Width), col) } - return nil case 24: - i.Data = make([]byte, i.Size) - for idx := 0; idx < int(i.Size/3); idx++ { + for idx := 0; idx < int(size/3); idx++ { rgb := [3]byte{} _, err := io.ReadFull(rd, rgb[:]) if err != nil { @@ -115,11 +85,108 @@ func (i *Image) Decode(rd io.Reader, palette *PaletteSection) error { rgb[2], rgb[1], rgb[0], alpha, } - - cf.Set(idx%int(i.Width), idx/int(i.Width), col) + i.rgb.Set(idx%int(i.Width), idx/int(i.Width), col) } - return nil default: - return fmt.Errorf("unsupported bpp, %d", i.Bpp) + return fmt.Errorf("unsupported bpp, %d", img.Bpp) } + + return nil +} + +func (i *SubImage) decodeCompressed(rd io.Reader, img *Image, g *GawiSection) error { + var u16 uint16 + ob := new(bytes.Buffer) + for k := 0; k < int(i.Height); k++ { + pixelCount := 0 + if err := binary.Read(rd, end, &u16); err != nil { + return fmt.Errorf("compressed size: %w", err) + } + want := make([]byte, int(u16)-2) + if _, err := io.ReadFull(rd, want); err != nil { + return fmt.Errorf("compressed want (%d): %w", u16, err) + } + buf := bytes.NewBuffer(want) + for buf.Len() > 0 { + var paddingSize, foregroundSize uint16 + if err := binary.Read(buf, end, &paddingSize); err != nil { + return fmt.Errorf("padding size: %w", err) + } + if err := binary.Read(buf, end, &foregroundSize); err != nil { + return fmt.Errorf("foreground size: %w", err) + } + for x := 0; x < int(paddingSize); x++ { + switch img.Bpp { + case 8: + ob.Write([]byte{0}) + case 16: + ob.Write([]byte{0x1f, 0x7c}) + case 24: + ob.Write([]byte{0xff, 0, 0xff}) + default: + ob.Write([]byte{0}) + } + } + foregroundBytes := make([]byte, int(foregroundSize)*(int(g.Bpp)/8)) + if _, err := io.ReadFull(buf, foregroundBytes); err != nil { + return fmt.Errorf("foreground bytes: %w", err) + } + for y := 0; y < len(foregroundBytes); y++ { + ob.WriteByte(foregroundBytes[y]) + } + pixelCount = pixelCount + int(paddingSize) + int(foregroundSize) + } + if pixelCount != int(i.Width) { + return fmt.Errorf("scanline has fewer pixels than the width (expected %d, got %d)", i.Width, pixelCount) + } + } + return i.decode(ob, img, ob.Len(), g) +} + +func (i *SubImage) Decode(rd io.Reader, img *Image, g *GawiSection) error { + cf := image.NewRGBA64(image.Rect(0, 0, int(i.Width), int(i.Height))) + i.rgb = cf + i.Img = i.rgb + if g.IsCompressed { + return i.decodeCompressed(rd, img, g) + } + return i.decode(rd, img, int(i.Size), g) +} + +func (img *Image) Decode(rd io.Reader, g *GawiSection) error { + if err := binary.Read(rd, end, &img.Count); err != nil { + return err + } + img.SubImages = make([]*SubImage, 0, img.Count) + for k := 0; k < int(img.Count); k++ { + i := &SubImage{} + img.SubImages = append(img.SubImages, i) + 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 + } + if err := i.Decode(rd, img, g); err != nil { + return err + } + } + return nil } diff --git a/mon1033.nri b/mon1033.nri new file mode 100755 index 0000000..8218228 Binary files /dev/null and b/mon1033.nri differ diff --git a/reader.go b/reader.go index 1b7f777..01f6aca 100644 --- a/reader.go +++ b/reader.go @@ -44,5 +44,17 @@ func reflectReader(r io.Reader) io.Reader { if _, ok := r.(readByteSeeker); ok { return r } - return bufio.NewReader(r) + return fileByteReader{ + ReadSeeker: r.(io.ReadSeeker), + } +} + +type fileByteReader struct { + io.ReadSeeker +} + +func (o *fileByteReader) ReadByte() (byte, error) { + b := [1]byte{} + _, err := o.Read(b[:]) + return b[0], err } diff --git a/render.go b/render.go index cb9d6ee..5bc4dd0 100644 --- a/render.go +++ b/render.go @@ -2,13 +2,14 @@ package nori import ( "fmt" + "image" + "image/color" + "image/draw" + "git.tuxpa.in/a/zlog/log" "github.com/disintegration/imaging" "github.com/phrozen/blend" "gitlab.com/gfxlabs/gfximg/apng" - "image" - "image/color" - "image/draw" ) func copyImage(img image.Image) image.Image { @@ -34,8 +35,11 @@ func RenderAnimation(n *Nori, num int, f RenderFunc) error { log.Printf("could not find bitmap %d, only have %d", plane.BitmapId, len(g.Images)) } bitmap := g.Images[plane.BitmapId] + if len(bitmap.SubImages) == 0 { + return fmt.Errorf("no subimages in bitmap") + } pt := image.Pt(int(plane.PlaneX), int(plane.PlaneY)) // where to put the point - rc := bitmap.Img.Bounds().Add(pt) // translate rectangle to put in the global canvas + rc := bitmap.SubImages[0].Img.Bounds().Add(pt) // translate rectangle to put in the global canvas if i == 0 { canvasRect = rc } else { @@ -45,19 +49,19 @@ func RenderAnimation(n *Nori, num int, f RenderFunc) error { img := image.NewNRGBA(canvasRect) for _, plane := range planes { bitmap := g.Images[plane.BitmapId] - drawBitmap := bitmap.Img + drawBitmap := bitmap.SubImages[0].Img transparent := false //flipx if plane.RenderFlag&1 != 0 { - if bitmap.Img == drawBitmap { - drawBitmap = copyImage(bitmap.Img) + if bitmap.SubImages[0].Img == drawBitmap { + drawBitmap = copyImage(bitmap.SubImages[0].Img) } drawBitmap = imaging.FlipH(drawBitmap) } //flipy if plane.RenderFlag&2 != 0 { - if bitmap.Img == drawBitmap { - drawBitmap = copyImage(bitmap.Img) + if bitmap.SubImages[0].Img == drawBitmap { + drawBitmap = copyImage(bitmap.SubImages[0].Img) } drawBitmap = imaging.FlipV(drawBitmap) }