diff --git a/.gitignore b/.gitignore index 5b9c917..9842f0f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,13 @@ -bin/ +bin/cory out/ dist/ +cory *.exe *.out *.bin *test.png + +*.zip diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..31463f1 --- /dev/null +++ b/Makefile @@ -0,0 +1,15 @@ +img_user = a +img_name = cory +img_tag = local + +cory: clean + go build -o ./cory ./cmd/cory + +docker: + DOCKER_BUILDKIT=1 docker build -f server.Dockerfile -t $(img_user)/$(img_name):$(img_tag) . + +server-run: docker + docker run -p 3333:3333 $(img_user)/$(img_name):$(img_tag) --serve + +clean: + rm -rf cory diff --git a/common/nori/render.go b/common/nori/render.go index 35f1e82..d0c8176 100644 --- a/common/nori/render.go +++ b/common/nori/render.go @@ -4,13 +4,29 @@ import ( "fmt" "image" "image/draw" + "strings" "git.tuxpa.in/a/zlog/log" "github.com/phrozen/blend" "gitlab.com/gfxlabs/gfximg/apng" ) -func (n *Nori) RenderAnimation(num int) (*apng.APNG, error) { +func RenderAnimations(n *Nori) ([]*apng.APNG, error) { + apngs := make([]*apng.APNG, 0, len(n.Animations)) + for i := range n.Animations { + a, err := RenderAnimation(n, i) + if err != nil { + if strings.Contains(err.Error(), "no frame") { + continue + } + return nil, err + } + apngs = append(apngs, a) + } + return apngs, nil +} + +func RenderAnimation(n *Nori, num int) (*apng.APNG, error) { g := n.Gawi a := &apng.APNG{ Frames: make([]apng.Frame, 0, len(g.Images)), diff --git a/common/nori/render_test.go b/common/nori/render_test.go index 3179c4d..6db53a7 100644 --- a/common/nori/render_test.go +++ b/common/nori/render_test.go @@ -52,7 +52,7 @@ func writeApng(nori *Nori, name string) error { out := new(bytes.Buffer) os.MkdirAll(fmt.Sprintf("./render_test/%s%s", name, postfix), 0740) for i := range nori.Animations { - a, err := nori.RenderAnimation(i) + a, err := RenderAnimation(nori, i) if err != nil { if strings.Contains(err.Error(), "no frame") { continue diff --git a/common/utils/zip.go b/common/utils/zip.go new file mode 100644 index 0000000..58c373e --- /dev/null +++ b/common/utils/zip.go @@ -0,0 +1,32 @@ +package utils + +import ( + "archive/zip" + "fmt" + "io" + "time" + + "gitlab.com/gfxlabs/gfximg/apng" +) + +func ZipApngs(w io.Writer, xs []*apng.APNG) error { + zw := zip.NewWriter(w) + defer zw.Close() + for i, v := range xs { + header := zip.FileHeader{ + Name: fmt.Sprintf("./animations/a_%d.png", i), + NonUTF8: false, + Method: zip.Deflate, + Modified: time.Now(), + } + hw, err := zw.CreateHeader(&header) + if err != nil { + return err + } + err = apng.Encode(hw, *v) + if err != nil { + return err + } + } + return nil +} diff --git a/common/utils/zip_test.go b/common/utils/zip_test.go new file mode 100644 index 0000000..115af6d --- /dev/null +++ b/common/utils/zip_test.go @@ -0,0 +1,60 @@ +package utils + +import ( + "bytes" + "fmt" + "os" + "testing" + + "git.tuxpa.in/a/gotagonist/common/nori" +) + +func TestParseFile1(t *testing.T) { + nori, err := nori.FromFile("./zip_test/test1.nri") + if err != nil { + t.Errorf("decode: %s", err) + } + t.Logf("\n nori: %+v\n gawi: %+v", nori, nori.Gawi) + + err = writeZip(nori, "test1") + if err != nil { + t.Errorf("export: %s", err) + } +} + +func TestParseFile2(t *testing.T) { + nori, err := nori.FromFile("./zip_test/test2.nri") + if err != nil { + t.Errorf("decode: %s", err) + } + t.Logf("\n nori: %+v\n gawi: %+v", nori, nori.Gawi) + err = writeZip(nori, "test2") + if err != nil { + t.Errorf("export: %s", err) + } +} + +func TestParsePalette(t *testing.T) { + nori, err := nori.FromFile("./zip_test/palette.nri") + 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) + err = writeZip(nori, "palette") + if err != nil { + t.Errorf("export: %s", err) + } +} + +func writeZip(n *nori.Nori, name string) error { + out := new(bytes.Buffer) + frames, err := nori.RenderAnimations(n) + if err != nil { + return err + } + if err := ZipApngs(out, frames); err != nil { + return err + } + os.WriteFile(fmt.Sprintf("./zip_test/%s.zip", name), out.Bytes(), 0740) + return nil +} diff --git a/common/utils/zip_test/palette.nri b/common/utils/zip_test/palette.nri new file mode 100644 index 0000000..93d3ef8 Binary files /dev/null and b/common/utils/zip_test/palette.nri differ diff --git a/common/utils/zip_test/test1.nri b/common/utils/zip_test/test1.nri new file mode 100644 index 0000000..93e2ee3 Binary files /dev/null and b/common/utils/zip_test/test1.nri differ diff --git a/common/utils/zip_test/test2.nri b/common/utils/zip_test/test2.nri new file mode 100644 index 0000000..aa8f861 Binary files /dev/null and b/common/utils/zip_test/test2.nri differ diff --git a/go.mod b/go.mod index 403c6ea..1beb00e 100644 --- a/go.mod +++ b/go.mod @@ -4,12 +4,14 @@ go 1.18 require ( git.tuxpa.in/a/zlog v1.32.0 + 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/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect - github.com/phrozen/blend v0.0.0-20210220204729-f26b6cf7a28e // indirect + gitlab.com/gfxlabs/goutil v1.5.0 // indirect golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect ) diff --git a/go.sum b/go.sum index 629b124..11456b0 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,8 @@ 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/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8= +github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= @@ -12,6 +14,8 @@ 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= +gitlab.com/gfxlabs/goutil v1.5.0 h1:tYjMbDRtK93MPrWrZE4Ub67Ng8rYwTahtb+Bfpf0Spk= +gitlab.com/gfxlabs/goutil v1.5.0/go.mod h1:NGvdG6oTLV2cEX4HKtewdzx/ZIvC+eAS7EbjKy4sXsA= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 h1:foEbQz/B0Oz6YIqu/69kfXPYeFQAuuMYFkjaqXzl5Wo= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..648dc77 --- /dev/null +++ b/readme.md @@ -0,0 +1,34 @@ +# nri file reader + +## about + +common/nori provides structs and decoders for nori file + +## cory + +cmd/cory is command line util for working with nori files + +get a zip file of animations from a nori file + +usage: `./cory -d -f=filename.nri -o=output.zip` + +optionally, use webserver + +start: `./cory -serve` + +example with curl: `curl -X POST --data-binary "@filename.nri" localhost:3333/animations --output output.zip` + +### building cory + +``` +make cory +``` + + +### docker + +oh yeah there's also a docker image for cory lol + +``` +make docker +``` diff --git a/server.Dockerfile b/server.Dockerfile new file mode 100644 index 0000000..fbe968a --- /dev/null +++ b/server.Dockerfile @@ -0,0 +1,7 @@ +from golang:1.18-alpine3.15 as builder +run apk add make curl git +workdir /WORK +copy . . +run make cory +entrypoint ["/WORK/cory"] +cmd ["-serve"]