diff --git a/pkg/dithering/8x8grid.go b/pkg/dithering/8x8grid.go index bfd6fba..6d311a7 100644 --- a/pkg/dithering/8x8grid.go +++ b/pkg/dithering/8x8grid.go @@ -18,16 +18,19 @@ func (_ grid) Bounds() image.Rectangle { } func (g grid) At(x, y int) color.Color { - step := int(64 / (g.Gray.Y / 4)) - if (y*8+x)%step == 0 { + n := g.Gray.Y / 4 + if n == 0 { return color.Black } - return color.White + step := int(64 / n) + if (y*8+x)%step == 0 { + return color.White + } + return color.Black } type uniformGrid struct { image.Image - image.Rectangle } func (g uniformGrid) ColorModel() color.Model { @@ -35,9 +38,23 @@ func (g uniformGrid) ColorModel() color.Model { } func (g uniformGrid) Bounds() image.Rectangle { - return g.Rectangle + // just need to return something + return g.Image.Bounds() } func (g uniformGrid) At(x, y int) color.Color { - return color.Color(nil) + dx, dy := g.Image.Bounds().Dx(), g.Image.Bounds().Dy() + return g.Image.At(x%dx, y%dy) +} + +type Dithering struct { + image.Image +} + +func (d Dithering) ColorModel() color.Model { return color.GrayModel } +func (d Dithering) Bounds() image.Rectangle { return d.Image.Bounds() } +func (d Dithering) At(x, y int) color.Color { + c := color.GrayModel.Convert(d.Image.At(x, y)) + return uniformGrid{grid{c.(color.Gray)}}. + At(x, y) } diff --git a/pkg/dithering/8x8grid_test.go b/pkg/dithering/8x8grid_test.go index 09200c5..8e300cd 100644 --- a/pkg/dithering/8x8grid_test.go +++ b/pkg/dithering/8x8grid_test.go @@ -1,9 +1,11 @@ package dithering import ( + "image" "image/color" "image/png" "math/rand" + "os" "os/exec" "testing" "time" @@ -11,25 +13,61 @@ import ( "git.nkpl.cc/twocookedfaggots/imageutils" ) -func TestGrid(t *testing.T) { +func init() { rand.Seed(time.Now().UnixNano()) +} +func callImage(img image.Image) { + for y := 0; y < img.Bounds().Dy(); y++ { + for x := 0; x < img.Bounds().Dx(); x++ { + _ = img.At(x, y) + } + } +} + +func TestGrid(t *testing.T) { command := exec.Command("imv", "-") w, err := command.StdinPipe() if err != nil { - t.Error(err) + t.Fatal(err) } - img := imageutils.Scale(1<<6, grid{color.Gray{uint8(rand.Int() % 64)}}) - - go func() { - err = png.Encode(w, img) - if err != nil { - t.Error(err) - } - }() - err = command.Start() if err != nil { - t.Error(err) + t.Fatal(err) + } + + n := uint8(rand.Int() % 256) + t.Log(n) + img := imageutils.Scale(1<<6, grid{color.Gray{n}}) + err = png.Encode(w, img) + if err != nil { + t.Fatal(err) + } + + callImage(grid{color.Gray{4}}) + callImage(grid{color.Gray{0}}) +} + +func TestDithering(t *testing.T) { + r, err := os.Open("/home/potassium/documents/wallpaper/8.png") + if err != nil { + t.Fatal(err) + } + defer r.Close() + + w, err := os.Create("sample.png") + if err != nil { + t.Fatal(err) + } + defer w.Close() + + img, err := png.Decode(r) + if err != nil { + t.Fatal(err) + } + + err = png.Encode(w, Dithering{img}) + if err != nil { + t.Fatal(err) } } diff --git a/pkg/dithering/cmd/main.go b/pkg/dithering/cmd/main.go new file mode 100644 index 0000000..6ae3cb7 --- /dev/null +++ b/pkg/dithering/cmd/main.go @@ -0,0 +1,15 @@ +package main + +import ( + "git.nkpl.cc/twocookedfaggots/imageutils/pkg/dithering" + "git.nkpl.cc/twocookedfaggots/imageutils/util" +) + +func main() { + err := util.ProcessStdio(func(img image.Image) image.Image { + return dithering.Dithering{img} + }) + if err != nil { + panic(err) + } +} diff --git a/pkg/dithering/sample.png b/pkg/dithering/sample.png new file mode 100644 index 0000000..bcc389e Binary files /dev/null and b/pkg/dithering/sample.png differ diff --git a/pkg/hex.go b/pkg/hex.go deleted file mode 100644 index 65aa065..0000000 --- a/pkg/hex.go +++ /dev/null @@ -1,32 +0,0 @@ -package imageutils - -import ( - "fmt" - "image/color" - "errors" -) - -var ParseHexColorErr = errors.New("invalid length, must be 7 or 4") - -func ParseHexColor(s string) (c color.RGBA, err error) { - c.A = 0xff - switch len(s) { - case 7: - _, err = fmt.Sscanf(s, "#%02x%02x%02x", &c.R, &c.G, &c.B) - case 4: - _, err = fmt.Sscanf(s, "#%1x%1x%1x", &c.R, &c.G, &c.B) - // Double the hex digits: - c.R *= 17 - c.G *= 17 - c.B *= 17 - default: - err = ParseHexColorErr - - } - return -} - -func ColorToHex(c color.Color) string { - r, g, b, _ := color.NRGBAModel.Convert(c).RGBA() - return fmt.Sprintf("#%02x%02x%02x", byte(r), byte(g), byte(b)) -} diff --git a/pkg/hex_test.go b/pkg/hex_test.go deleted file mode 100644 index 6a0123c..0000000 --- a/pkg/hex_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package imageutils - -import ( - "fmt" - "image/png" - "os" - "path/filepath" - "testing" -) - -// Returns path of first occured file -// with png extension in user's home directory. -func firstPNG(root string) (filename string, - err error) { - var fn filepath.WalkFunc = func(path string, - info os.FileInfo, - fileErr error) error { - if fileErr != nil { - return fileErr - } - if !info.IsDir() && - filepath.Ext(path) == ".png" { - filename = path - return nil - } - return nil - } - err = filepath.Walk(root, fn) - return -} - -func TestColorToHex(t *testing.T) { - root := os.Getenv("HOME") - path, err := firstPNG(root) - if err != nil { - t.Fatal(err) - } - f, err := os.Open(path) - if err != nil { - t.Fatal(err) - } - img, err := png.Decode(f) - if err != nil { - t.Fatal(err) - } - fmt.Println(ColorToHex(img.At(0, 0))) -} diff --git a/util/stdio.go b/util/stdio.go new file mode 100644 index 0000000..3b0757b --- /dev/null +++ b/util/stdio.go @@ -0,0 +1,14 @@ +package imageutils + +// ProcessImage takes input png image from stdin, processes it with f and outputs it to stdout. +func ProcessStdio(f func(image.Image) image.Image) { + img, err := png.Decode(os.Stdin) + if err != nil { + return err + } + err = png.Encode(os.Stdout, f(img)) + if err != nil { + return err + } + return err +}