dither/main.go

94 lines
1.9 KiB
Go

package main
import (
"fmt"
"image"
_ "image/jpeg"
"image/png"
"math/rand"
"os"
"time"
)
func main() {
if len(os.Args) == 1 || len(os.Args) > 4 || os.Args[1] == "help" {
fmt.Printf(`usage: %s <path/to/image.ext> <dither_option> <path/to/output.png>
Supported dither options are: noop; naive; randomnoise; bayer{0,1}; bayer{0,1}n
Supported input image formats are jpg, png
`, os.Args[0])
os.Exit(0)
}
filename := os.Args[1]
ditherer := os.Args[2]
outfile := os.Args[3]
i, codex, err := loadImage(filename)
if err != nil {
fmt.Printf("error loading %s; %v\n", filename, err)
os.Exit(255)
}
fmt.Printf("loaded %s using %s\n", filename, codex)
t := time.Now()
var new image.Image
switch ditherer {
case "noop":
new = apply(i, noOp)
case "naive":
new = apply(i, naiveBW)
case "randomnoise":
rand.Seed(time.Now().UnixNano())
new = apply(i, randomNoise)
case "bayer0":
new = apply(i, bayerDithering(0, false))
case "bayer0n":
new = apply(i, bayerDithering(0, true))
case "bayer1":
new = apply(i, bayerDithering(1, false))
case "bayer1n":
new = apply(i, bayerDithering(1, true))
case "simpleerror":
new = apply(i, simpleErrorDiffusion())
default:
fmt.Printf("unknown ditherer option: %s\n", ditherer)
os.Exit(2)
}
fmt.Printf("dithering took %s\n", time.Since(t))
err = saveImage(outfile, new)
if err != nil {
fmt.Printf("error saving %s; %v\n", outfile, err)
os.Exit(255)
}
fmt.Printf("saved output to %s\n", outfile)
}
func loadImage(filename string) (image.Image, string, error) {
r, err := os.Open(filename)
if err != nil {
return nil, "", err
}
return image.Decode(r)
}
func saveImage(filename string, img image.Image) error {
f, err := os.Create(filename)
if err != nil {
return err
}
if err := png.Encode(f, img); err != nil {
f.Close()
return err
}
if err := f.Close(); err != nil {
return err
}
return nil
}