From 20d1afa458d1b5069e991b90671ae3c5bf39f529 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Wed, 29 Oct 2025 11:54:06 -0400 Subject: [PATCH] Started the config file format and can process one image with it. --- config.json | 20 ++++++++++++++++ main.go | 69 ++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 67 insertions(+), 22 deletions(-) create mode 100644 config.json diff --git a/config.json b/config.json new file mode 100644 index 0000000..b175a06 --- /dev/null +++ b/config.json @@ -0,0 +1,20 @@ +{ + "Base": { + "PixelWidth": 4, + "ColorDepth": 16, + "DitherType": 2, + "Width": 0, + "Height": 0 + }, + "Source": "tests/images/bash_test.png", + "Target": "atkinson.png", + "Exceptions": { + "temp/painted_*.png": { + "PixelWidth": 8, + "ColorDepth": 4, + "DitherType": 2, + "Width": 256, + "Height": 256 + } + } +} diff --git a/main.go b/main.go index 93a2955..b7c71a0 100644 --- a/main.go +++ b/main.go @@ -3,11 +3,11 @@ package main import ( "os" "image" + "encoding/json" "log" "image/png" "github.com/disintegration/gift" "flag" - "math" "lcthw.dev/go/jankifier/filters" ) @@ -36,44 +36,69 @@ func SaveImage(filename string, img image.Image) { } type Opts struct { - InFile string - OutFile string + Config string + Force bool +} + +type Conversion struct { PixelWidth int ColorDepth int DitherType int + Width int + Height int +} + +type Settings struct { + Source string + Target string + Base Conversion + Exceptions map[string]Conversion +} + +func LoadSettings(path string) Settings { + var settings Settings + + config, err := os.ReadFile(path) + if err != nil { + log.Fatalf("invalid config path: %s", path) + } + + err = json.Unmarshal(config, &settings) + if err != nil { + log.Fatalf("json format error:", err) + } + + return settings } func ParseOpts() Opts { var opts Opts - flag.StringVar(&opts.InFile, "input", "", "input file.png") - flag.StringVar(&opts.OutFile, "output", "", "output file.png") - flag.IntVar(&opts.PixelWidth, "pixel-width", 4, "pixel width") - flag.IntVar(&opts.ColorDepth, "color-depth", 16, "number of colors in the palette") - flag.IntVar(&opts.DitherType, "dither", 0, "0=none, 1=floyd, 2=atkinson") + flag.StringVar(&opts.Config, "config", "config.json", "config file") + flag.BoolVar(&opts.Force, "force", false, "force a full convert") flag.Parse() - if opts.ColorDepth > math.MaxUint8 { - log.Fatalf("color-depth can't be greater than %d", math.MaxUint8); - } - return opts } -func main() { - opts := ParseOpts() - - src := LoadImage(opts.InFile) +func JankImage(settings Conversion, in_file string, out_file string) { + src := LoadImage(in_file) bounds := src.Bounds() - resize := gift.Resize(bounds.Max.X / opts.PixelWidth, 0, gift.NearestNeighborResampling) - posterize := filters.Posterize(uint16(opts.ColorDepth), opts.DitherType) - upscale := filters.Upscale(bounds, opts.PixelWidth) + resize := gift.Resize(bounds.Max.X / settings.PixelWidth, 0, gift.NearestNeighborResampling) + posterize := filters.Posterize(uint16(settings.ColorDepth), settings.DitherType) + upscale := filters.Upscale(bounds, settings.PixelWidth) sharpen := gift.UnsharpMask(1, 1, 0) g := gift.New(resize, posterize, upscale, sharpen) - smaller := image.NewNRGBA(g.Bounds(bounds)) - g.Draw(smaller, src) + out_img := image.NewNRGBA(g.Bounds(bounds)) + g.Draw(out_img, src) + + SaveImage(out_file, out_img) +} - SaveImage(opts.OutFile, smaller) +func main() { + opts := ParseOpts() + settings := LoadSettings(opts.Config) + JankImage(settings.Base, settings.Source, settings.Target) }