package main import ( "bytes" "encoding/json" "flag" "fmt" "log" "log/slog" "os" "path/filepath" "runtime/pprof" "strings" "time" "anime.bike/slogutil/slogenv" "anime.bike/stint" "git.tuxpa.in/a/nori/renderer" "gitlab.com/gfxlabs/gfximg/apng" "golang.org/x/sync/errgroup" "git.tuxpa.in/a/nori" "git.tuxpa.in/a/nori/utils" ) var ( dumpPtr = flag.Bool("d", false, "dump nri file to zip") silentPtr = flag.Bool("s", false, "silent") bulkDumpPtr = flag.Bool("b", false, "bulk dump nris from a folder") jsonDumpPtr = flag.Bool("j", false, "bulk dump nri animation names from a folder") directoryPtr = flag.String("dir", "nri", "directory to bulk dump from") destinationPtr = flag.String("dest", "", "directory to bulk dump to") filePtr = flag.String("f", "example.nri", "file to load") outputPtr = flag.String("o", "output.zip", "output zip file") cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file") ) func init() { slog.SetDefault(slog.New(stint.NewHandler(os.Stderr, &stint.Options{ AddSource: true, Level: slogenv.EnvLevel(), }))) } func main() { flag.Parse() if len(os.Args) < 2 { flag.PrintDefaults() } if *cpuprofile != "" { f, err := os.Create(*cpuprofile) if err != nil { panic(err) } pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() } if *dumpPtr { filename := *filePtr output := *outputPtr if _, err := os.Stat(filename); err != nil { printIf("could not find file %s\n", filename) return } dump(filename, output) return } dir := *directoryPtr dest := *destinationPtr if dest == "" { dest = dir } printIf("output: %s\n", dest) if *bulkDumpPtr || *jsonDumpPtr { files, err := os.ReadDir(dir) if err != nil { printIf("%s: %s\n", dir, err) return } egg := errgroup.Group{} egg.SetLimit(12) for _, ff := range files { f := ff if strings.HasSuffix(f.Name(), ".nri") { egg.Go(func() error { if *bulkDumpPtr { if err := dump_nozip(dir+"/"+f.Name(), dest); err != nil { return err } } if *jsonDumpPtr { if err := dump_nozip(dir+"/"+f.Name(), dest); err != nil { return dump_anim_json(dir+"/"+f.Name(), dest) } } return nil }) } } if err := egg.Wait(); err != nil { log.Panicf("oh fuck: %s\n", err) return } } } func printIf(s string, args ...interface{}) { if !*silentPtr { fmt.Printf(s, args...) } } func dump_anim_json(filename string, destination string) error { n, err := nori.FromFile(filename) if err != nil { return fmt.Errorf("decode: %s", err) } names, err := nori.GetAnimationNames(n) if err != nil { return fmt.Errorf("animation: %s", err) } json, err := json.Marshal(names) if err != nil { return fmt.Errorf("could not marshal json: %s\n", err) } baseName := filepath.Base(strings.TrimSuffix(filename, filepath.Ext(filename))) output := fmt.Sprintf("%s/%s.json", destination, baseName) return os.WriteFile(output, json, 0o740) } func dump_nozip(filename string, destination string) error { start := time.Now() n, err := nori.FromFile(filename) if err != nil { return fmt.Errorf("decode: %s", err) } // printIf("rendering %d animation(s)\n", n.AnimationCount) animations, err := renderer.RenderAnimationsApng(n) if err != nil { return fmt.Errorf("animation: %s", err) } baseName := filepath.Base(strings.TrimSuffix(filename, filepath.Ext(filename))) for i, v := range animations { output := fmt.Sprintf(destination+"/%s_%d.png", baseName, i) // printIf("saving to %s \n", output) f, fErr := os.OpenFile(output, os.O_CREATE, 0740) if fErr != nil { return fErr } defer f.Close() if err := apng.Encode(f, *v); err != nil { return err } } // //if err := utils.ZipApngs(out, animations); err != nil { // return fmt.Errorf("zipping: %s", err) //} printIf("done in %v \n", time.Now().Sub(start)) //os.WriteFile(output, out.Bytes(), 0740) return nil } func dump(filename string, output string) error { start := time.Now() n, err := nori.FromFile(filename) if err != nil { return fmt.Errorf("decode: %s", err) } out := new(bytes.Buffer) printIf("rendering %d animation(s)\n", n.AnimationCount) animations, err := renderer.RenderAnimationsApng(n) if err != nil { return fmt.Errorf("animation: %s", err) } printIf("saving to %s \n", output) if err := utils.ZipApngs(out, animations); err != nil { return fmt.Errorf("zipping: %s", err) } printIf("done in %v \n", time.Now().Sub(start)) os.WriteFile(output, out.Bytes(), 0740) return nil }