diff --git a/.gitignore b/.gitignore index afc569c..2a01fbc 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ public *.sqlite3 jankifier *.log +*.png diff --git a/go.mod b/go.mod index b225ec3..af9094f 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module lcthw.dev/go/jankifier go 1.25.3 + +require github.com/disintegration/gift v1.2.1 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..89e5a54 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/disintegration/gift v1.2.1 h1:Y005a1X4Z7Uc+0gLpSAsKhWi4qLtsdEcMIbbdvdZ6pc= +github.com/disintegration/gift v1.2.1/go.mod h1:Jh2i7f7Q2BM7Ezno3PhfezbR1xpUg9dUg3/RlKGr4HI= diff --git a/main.go b/main.go index 0ede052..d38b4ce 100644 --- a/main.go +++ b/main.go @@ -1,10 +1,80 @@ package main import ( - "fmt" + // "fmt" + "os" + "image" + "log" + "image/png" + // "image/color" + "github.com/disintegration/gift" + // "math" + "flag" ) +func LoadImage(filename string) image.Image { + reader, err := os.Open(filename) + if err != nil { log.Fatal(err) } + defer reader.Close() + + img, _, err := image.Decode(reader) + if err != nil { log.Fatal(err) } + + return img +} + +func SaveImage(filename string, img image.Image) { + out, err := os.Create(filename) + if err != nil { + log.Fatalf("can't write file %s: %v", filename, err) + } + defer out.Close() + + err = png.Encode(out, img) + if err != nil { + log.Fatalf("can't png encode %s: %v", filename, err) + } +} + +type Opts struct { + InFile string + OutFile string + PixelWidth int +} + +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.Parse() + + return opts +} func main() { - fmt.Println("hello") + opts := ParseOpts() + + src := LoadImage(opts.InFile) + bounds := src.Bounds() + + resize := gift.Resize(bounds.Max.X / opts.PixelWidth, 0, gift.NearestNeighborResampling) + + g := gift.New(resize) + smaller := image.NewNRGBA(g.Bounds(bounds)) + g.Draw(smaller, src) + + upscale := image.NewNRGBA(bounds) + + for y := bounds.Min.Y; y < bounds.Max.Y; y++ { + for x := bounds.Min.X; x < bounds.Max.X; x++ { + from_x := x / opts.PixelWidth + from_y := y / opts.PixelWidth + from := smaller.At(from_x, from_y) + upscale.Set(x, y, from) + } + } + + SaveImage(opts.OutFile, upscale) }