diff --git a/config.json b/config.json index b175a06..288059f 100644 --- a/config.json +++ b/config.json @@ -6,8 +6,9 @@ "Width": 0, "Height": 0 }, - "Source": "tests/images/bash_test.png", - "Target": "atkinson.png", + "Source": "tests/images", + "Target": "temp", + "Include": [ ".png", ".jpg" ], "Exceptions": { "temp/painted_*.png": { "PixelWidth": 8, diff --git a/data.go b/data.go index 3e18b5b..336dfde 100644 --- a/data.go +++ b/data.go @@ -6,7 +6,6 @@ import ( "log" ) - type Conversion struct { PixelWidth int ColorDepth int @@ -18,6 +17,7 @@ type Conversion struct { type Settings struct { Source string Target string + Include []string Base Conversion Exceptions map[string]Conversion } @@ -35,5 +35,9 @@ func LoadSettings(path string) Settings { log.Fatalf("json format error:", err) } + if len(settings.Include) == 0 { + log.Fatalf("You must have at least 1 extesion in Include in ", path) + } + return settings } diff --git a/filters/posterize.go b/filters/posterize.go index 80276c7..48747fc 100644 --- a/filters/posterize.go +++ b/filters/posterize.go @@ -14,20 +14,23 @@ const ( AtkinsonDither=2 ) +const ( + BIN_SIZE=math.MaxUint16+1 +) type PosterizeFilter struct { Depth uint16 - Bins [math.MaxUint16]uint16 + Bins [BIN_SIZE]uint16 DitherType int } func Posterize(depth uint16, dither_type int) gift.Filter { var i uint16 - var bins [math.MaxUint16]uint16 - chunk := uint16((math.MaxUint16 + 1) / int(depth)) + var bins [BIN_SIZE]uint16 + chunk := uint16((BIN_SIZE) / int(depth)) // BUG: this was fine with uint8, now it's dumb as hell - for i = 0; i < math.MaxUint16; i++ { + for i = 1; i < math.MaxUint16; i++ { bins[i] = (i / chunk) * chunk } diff --git a/main.go b/main.go index 6b1d3da..5d84f4b 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package main import ( "flag" + "log" ) type Opts struct { @@ -21,6 +22,11 @@ func ParseOpts() Opts { func main() { opts := ParseOpts() - settings := LoadSettings(opts.Config) - JankImage(settings.Base, settings.Source, settings.Target) + config := LoadSettings(opts.Config) + + err := RenderImages(config) + + if err != nil { + log.Fatalf("failed to walk dir %s: %v", config.Source, err) + } } diff --git a/processing.go b/processing.go index 56f6c87..0cb976e 100644 --- a/processing.go +++ b/processing.go @@ -2,8 +2,13 @@ package main import ( "os" + "io/fs" + "fmt" + "path/filepath" + "strings" "image" "log" + "regexp" "image/png" "github.com/disintegration/gift" "lcthw.dev/go/jankifier/filters" @@ -48,3 +53,97 @@ func JankImage(settings Conversion, in_file string, out_file string) { SaveImage(out_file, out_img) } + +func UnfuckedPathSplit(path string) []string { + path = filepath.ToSlash(path) + // WARN: have to use strings.Split because fsnotify uses /, even on windows + return strings.Split(path, "/")[1:] +} + +func SplitPathExt(path string) (string, string, bool) { + split_path := UnfuckedPathSplit(path) + source_name := strings.Join(split_path, "/") // Render wants / even on windows + + ext := filepath.Ext(source_name) + source_name, found := strings.CutSuffix(source_name, ext) + return source_name, ext, found +} + +func RePrefixPath(path string, new_prefix string) string { + split_path := UnfuckedPathSplit(path) + + prefixed_path := append([]string{new_prefix}, split_path...) + + res := filepath.Join(prefixed_path...) + return filepath.ToSlash(res) +} + +func SamePath(a string, b string) bool { + return filepath.ToSlash(a) == filepath.ToSlash(b) +} + +func MkdirPath(target_path string) error { + target_dir := filepath.Dir(target_path) + _, err := os.Stat(target_dir) + + if os.IsNotExist(err) { + log.Println("MAKING: ", target_dir) + err = os.MkdirAll(target_dir, 0750) + + if err != nil { + log.Fatal("making path to %s: %v", target_dir, err) + } + } + + return nil +} + +func Included(config Settings, path string) bool { + _, ext, found := SplitPathExt(path) + if !found { return false } + + for _, include_ext := range config.Include { + if include_ext == ext { + return true + } + } + + return false +} + +func GetConversion(config Settings, path string) Conversion { + for key, conversion := range config.Exceptions { + match, err := regexp.MatchString(key, path) + if err != nil { log.Fatalf("problem matching regex %s: %v", key, err) } + + if match { + return conversion + } + } + + return config.Base +} + +func RenderImages(config Settings) error { + err := filepath.WalkDir(config.Source, + func(path string, d fs.DirEntry, err error) error { + if !d.IsDir() && Included(config, path) { + target := RePrefixPath(path, config.Target) + + err = MkdirPath(target) + if err != nil { + log.Fatalf("failed to make path %s: %v", path, err) + } + + fmt.Println("FILE: ", path, "TARGET:", target) + convert := GetConversion(config, path) + JankImage(convert, path, target) + } else { + fmt.Println("SKIP:", path) + } + + return nil + }) + + return err +}