support subimages and compressed

This commit is contained in:
a 2022-12-19 03:09:29 -06:00
parent 1375ab7a1a
commit 88028a27e4
48 changed files with 150 additions and 71 deletions

BIN
animations/a_0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
animations/a_1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
animations/a_10.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

BIN
animations/a_11.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
animations/a_12.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

BIN
animations/a_13.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
animations/a_14.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
animations/a_15.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
animations/a_16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

BIN
animations/a_17.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
animations/a_18.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

BIN
animations/a_19.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

BIN
animations/a_2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

BIN
animations/a_20.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
animations/a_21.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
animations/a_22.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

BIN
animations/a_23.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

BIN
animations/a_24.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

BIN
animations/a_25.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
animations/a_26.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
animations/a_27.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
animations/a_28.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
animations/a_29.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
animations/a_3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
animations/a_30.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
animations/a_31.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
animations/a_32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
animations/a_33.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
animations/a_34.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
animations/a_35.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
animations/a_36.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
animations/a_37.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
animations/a_4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

BIN
animations/a_5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
animations/a_6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
animations/a_7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
animations/a_8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
animations/a_9.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@ -4,11 +4,12 @@ import (
"bytes" "bytes"
"flag" "flag"
"fmt" "fmt"
"git.tuxpa.in/a/nori/renderer"
"net/http" "net/http"
"os" "os"
"time" "time"
"git.tuxpa.in/a/nori/renderer"
"git.tuxpa.in/a/nori" "git.tuxpa.in/a/nori"
"git.tuxpa.in/a/nori/utils" "git.tuxpa.in/a/nori/utils"
"git.tuxpa.in/a/zlog/log" "git.tuxpa.in/a/zlog/log"
@ -54,7 +55,7 @@ func dump(filename string, output string) {
printIf("reading file '%s'\n", filename) printIf("reading file '%s'\n", filename)
n, err := nori.FromFile(filename) n, err := nori.FromFile(filename)
if err != nil { if err != nil {
log.Panicln("decode: %s", err) log.Panicf("decode: %s", err)
} }
out := new(bytes.Buffer) out := new(bytes.Buffer)
printIf("rendering %d animation(s)\n", n.AnimationCount) printIf("rendering %d animation(s)\n", n.AnimationCount)

BIN
compress.nri Normal file

Binary file not shown.

View File

@ -1,7 +1,6 @@
package nori package nori
import ( import (
"bufio"
"io" "io"
"os" "os"
) )
@ -16,7 +15,7 @@ func FromFile(fp string) (*Nori, error) {
return nil, err return nil, err
} }
defer file.Close() defer file.Close()
return Decode(bufio.NewReader(file)) return Decode(file)
} }
func Decode(r io.Reader) (*Nori, error) { func Decode(r io.Reader) (*Nori, error) {

View File

@ -77,7 +77,7 @@ func (g *GawiSection) Decode(rd io.Reader) error {
g.Images = make([]*Image, int(g.BmpCount)) g.Images = make([]*Image, int(g.BmpCount))
for i := range g.Images { for i := range g.Images {
g.Images[i] = &Image{Bpp: g.Bpp} 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 return err
} }
} }

3
go.mod
View File

@ -5,13 +5,12 @@ go 1.18
require ( require (
git.tuxpa.in/a/zlog v1.32.0 git.tuxpa.in/a/zlog v1.32.0
github.com/disintegration/imaging v1.6.2 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 github.com/phrozen/blend v0.0.0-20210220204729-f26b6cf7a28e
gitlab.com/gfxlabs/gfximg v0.0.5 gitlab.com/gfxlabs/gfximg v0.0.5
) )
require ( 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-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-isatty v0.0.14 // indirect
golang.org/x/image v0.0.0-20211028202545-6944b10bf410 // indirect golang.org/x/image v0.0.0-20211028202545-6944b10bf410 // indirect

3
go.sum
View File

@ -1,7 +1,5 @@
git.tuxpa.in/a/zlog v1.32.0 h1:KKXbRF1x8kJDSzUoGz/pivo+4TVY6xT5sVtdFZ6traY= 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= 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/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 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= 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= 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 h1:jtHE6In6axz0zGPy7YnLIZV9RFdcFEZzpdqoXb52K9s=
gitlab.com/gfxlabs/gfximg v0.0.5/go.mod h1:IAYZwCoqy3JFKwkKafragpfecp5Up6FFIzI7VvK2Zzo= 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-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 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ=
golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=

169
image.go
View File

@ -1,6 +1,7 @@
package nori package nori
import ( import (
"bytes"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"image" "image"
@ -9,8 +10,12 @@ import (
) )
type Image struct { type Image struct {
Bpp uint32 Bpp uint32
Count uint32 Count uint32
SubImages []*SubImage
}
type SubImage struct {
Delay uint32 Delay uint32
OffsetX int32 OffsetX int32
OffsetY int32 OffsetY int32
@ -19,61 +24,28 @@ type Image struct {
Height uint32 Height uint32
Size uint32 Size uint32
Data []byte
Img image.Image Img image.Image
rgb *image.RGBA64
} }
func (i *Image) Decode(rd io.Reader, palette *PaletteSection) error { func (i *SubImage) decode(rd io.Reader, img *Image, size int, g *GawiSection) error {
if err := binary.Read(rd, end, &i.Count); err != nil { switch img.Bpp {
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 {
case 8: case 8:
if palette == nil { if g.Palette == nil {
return fmt.Errorf("bpp = 8, but no palette") 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) b, err := readByte(rd)
if err != nil { if err != nil {
return err return err
} }
col := palette.Palette[b] col := g.Palette.Palette[b]
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 16: case 16:
var bgr uint16 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 { if err := binary.Read(rd, end, &bgr); err != nil {
return err return err
} }
@ -91,12 +63,10 @@ func (i *Image) Decode(rd io.Reader, palette *PaletteSection) error {
red, green, blue, red, green, blue,
alpha, 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: case 24:
i.Data = make([]byte, i.Size) for idx := 0; idx < int(size/3); idx++ {
for idx := 0; idx < int(i.Size/3); idx++ {
rgb := [3]byte{} rgb := [3]byte{}
_, err := io.ReadFull(rd, rgb[:]) _, err := io.ReadFull(rd, rgb[:])
if err != nil { if err != nil {
@ -115,11 +85,108 @@ func (i *Image) Decode(rd io.Reader, palette *PaletteSection) error {
rgb[2], rgb[1], rgb[0], rgb[2], rgb[1], rgb[0],
alpha, alpha,
} }
i.rgb.Set(idx%int(i.Width), idx/int(i.Width), col)
cf.Set(idx%int(i.Width), idx/int(i.Width), col)
} }
return nil
default: 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
} }

BIN
mon1033.nri Executable file

Binary file not shown.

View File

@ -44,5 +44,17 @@ func reflectReader(r io.Reader) io.Reader {
if _, ok := r.(readByteSeeker); ok { if _, ok := r.(readByteSeeker); ok {
return r 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
} }

View File

@ -2,13 +2,14 @@ package nori
import ( import (
"fmt" "fmt"
"image"
"image/color"
"image/draw"
"git.tuxpa.in/a/zlog/log" "git.tuxpa.in/a/zlog/log"
"github.com/disintegration/imaging" "github.com/disintegration/imaging"
"github.com/phrozen/blend" "github.com/phrozen/blend"
"gitlab.com/gfxlabs/gfximg/apng" "gitlab.com/gfxlabs/gfximg/apng"
"image"
"image/color"
"image/draw"
) )
func copyImage(img image.Image) image.Image { 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)) log.Printf("could not find bitmap %d, only have %d", plane.BitmapId, len(g.Images))
} }
bitmap := g.Images[plane.BitmapId] 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 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 { if i == 0 {
canvasRect = rc canvasRect = rc
} else { } else {
@ -45,19 +49,19 @@ func RenderAnimation(n *Nori, num int, f RenderFunc) error {
img := image.NewNRGBA(canvasRect) img := image.NewNRGBA(canvasRect)
for _, plane := range planes { for _, plane := range planes {
bitmap := g.Images[plane.BitmapId] bitmap := g.Images[plane.BitmapId]
drawBitmap := bitmap.Img drawBitmap := bitmap.SubImages[0].Img
transparent := false transparent := false
//flipx //flipx
if plane.RenderFlag&1 != 0 { if plane.RenderFlag&1 != 0 {
if bitmap.Img == drawBitmap { if bitmap.SubImages[0].Img == drawBitmap {
drawBitmap = copyImage(bitmap.Img) drawBitmap = copyImage(bitmap.SubImages[0].Img)
} }
drawBitmap = imaging.FlipH(drawBitmap) drawBitmap = imaging.FlipH(drawBitmap)
} }
//flipy //flipy
if plane.RenderFlag&2 != 0 { if plane.RenderFlag&2 != 0 {
if bitmap.Img == drawBitmap { if bitmap.SubImages[0].Img == drawBitmap {
drawBitmap = copyImage(bitmap.Img) drawBitmap = copyImage(bitmap.SubImages[0].Img)
} }
drawBitmap = imaging.FlipV(drawBitmap) drawBitmap = imaging.FlipV(drawBitmap)
} }