diff --git a/cmd/dither/main.go b/cmd/dither/main.go new file mode 100644 index 0000000..46b0402 --- /dev/null +++ b/cmd/dither/main.go @@ -0,0 +1,22 @@ +package main + +import ( + "flag" + "image" + + "git.nkpl.cc/twocookedfaggots/imageutils/pkg/dithering" + "git.nkpl.cc/twocookedfaggots/imageutils/util" +) + +var factor = flag.Float64("n", 0.75, "dithering effect 'magic' number") + +func main() { + flag.Parse() + + println(*factor) + if err := util.ProcessStdio(func(img image.Image) image.Image { + return dithering.Dithering{img, *factor} + }); err != nil { + panic(err) + } +} diff --git a/cmd/negate/negate.go b/cmd/negate/negate.go new file mode 100644 index 0000000..f7bbdf1 --- /dev/null +++ b/cmd/negate/negate.go @@ -0,0 +1,39 @@ +package main + +import ( + "image" + "image/color" + + "git.nkpl.cc/twocookedfaggots/imageutils/util" +) + +func NegateRGBA(c color.RGBA) color.RGBA { + c.R = 255 - c.R + c.G = 255 - c.G + c.B = 255 - c.B + return c +} + +type Negate struct{ image.Image } + +func (n Negate) ColorModel() color.Model { return n.Image.ColorModel() } +func (n Negate) Bounds() image.Rectangle { return n.Image.Bounds() } +func (n Negate) At(x, y int) color.Color { + c := n.Image.At(x, y) + r, g, b, a := c.RGBA() + RGBAColor := color.RGBA{ + R: uint8(r >> 8), + G: uint8(g >> 8), + B: uint8(b >> 8), + A: uint8(a >> 8), + } + return NegateRGBA(RGBAColor) +} + +func main() { + if err := util.ProcessStdio(func(img image.Image) image.Image { + return Negate{img} + }); err != nil { + panic(err) + } +} diff --git a/cmd/scale/main.go b/cmd/scale/main.go new file mode 100644 index 0000000..2e1e316 --- /dev/null +++ b/cmd/scale/main.go @@ -0,0 +1,20 @@ +package main + +import ( + "flag" + "image" + + "git.nkpl.cc/twocookedfaggots/imageutils" + "git.nkpl.cc/twocookedfaggots/imageutils/util" +) + +var scale = flag.Int("n", 2, "rescale by factor") + +func main() { + flag.Parse() + if err := util.ProcessStdio(func(img image.Image) image.Image { + return imageutils.Scale(img, *scale) + }); err != nil { + panic(err) + } +} diff --git a/pkg/center/main.go b/pkg/center/main.go new file mode 100644 index 0000000..1cfe847 --- /dev/null +++ b/pkg/center/main.go @@ -0,0 +1,18 @@ +package center + +type Into struct { + Src, Dst image.Image +} + +func (i Into) Bounds() image.Rectangle { return i.Dst.Bounds() } +func (i Into) ColorModel() color.Model { return i.Dst.ColorModel } +func (i Into) At(x, y int) color.Color { + x1, y1 := (i.Dst.Bounds().Dx()/2)-(i.Src.Bounds().Dx()/2), + (i.Dst.Bounds().Dy()/2)-(i.Src.Bounds().Dy()/2) + r := image.Rect(x1, y1, + x1+i.Src.Bounds().Dx(), y1+i.Src.Bounds().Dy()) + if (image.Point{x, y}).In(r) { + return i.Src.At(x-x1,y-y2) + } + return i.Dst.At(x, y) +} diff --git a/pkg/clock/README.md b/pkg/clock/README.md new file mode 100644 index 0000000..6ebc997 --- /dev/null +++ b/pkg/clock/README.md @@ -0,0 +1,8 @@ +залил как есть. +любая кринжовая хуйня которая здесь найдется... просто зайбейте на это хуй, не обращайте внимания + +запускается значится так: +заходите в cmd и... +> go run . + +заходите в бровз и пишите адрес с портом diff --git a/pkg/clock/clock.go b/pkg/clock/clock.go new file mode 100644 index 0000000..4a786d6 --- /dev/null +++ b/pkg/clock/clock.go @@ -0,0 +1,82 @@ +//go:build draft +package clock + +import ( + "image" + "image/color" + "image/png" + "io" + "strconv" + "time" + + "git.niplace.ru/XoxJlopeZi4BB/clock/letter" + "git.niplace.ru/XoxJlopeZi4BB/imageutils" +) + + + +var img1, img2 = letter.Render(letter.Nums[6]), letter.Render(letter.Nums[9]) + +func DownRightBlank(img image.Image) image.Image { + clr := color.White + img = letter.Blank(img, clr, imageutils.Down) + return letter.Blank(img, clr, imageutils.Right) +} + +func LeftUpBlank(img image.Image) image.Image { + clr := color.White + img = letter.Blank(img, clr, imageutils.Left) + return letter.Blank(img, clr, imageutils.Up) +} + +func RenderNum(n int) image.Image { + var img image.Image = image.NewRGBA(image.Rect(0, 0, 0, 0)) + s := strconv.Itoa(n) + for i := range s { + n, err := strconv.Atoi(string(s[i])) + if err != nil { + panic(err) + } + + num := letter.Render(letter.Nums[n]) + num = DownRightBlank(num) + img = imageutils.Concat(img, num, imageutils.Right) + } + img = LeftUpBlank(img) + return img +} + +func RenderTime(t time.Time) image.Image { + hour := RenderNum(t.Hour()) + if t.Hour() < 10 { + hour = imageutils.Concat( + DownRightBlank(letter.Empty), hour, imageutils.Right) + } + minute := RenderNum(t.Minute()) + if t.Minute() < 10 { + minute = imageutils.Concat( + DownRightBlank(letter.Empty), minute, imageutils.Right) + } + + img := imageutils.Concat(hour, minute, imageutils.Down) + return img +} + +func Margin(img image.Image, length int) image.Image { + for i := 0; i < length; i++ { + img = LeftUpBlank(DownRightBlank(img)) + } + return img +} + +func Time(w io.Writer) { + t := time.Now() + img := RenderTime(t) + img = Margin(img, 3) + img = imageutils.Scale(img, 1<<6) + + err := png.Encode(w, img) + if err != nil { + panic(err) + } +} diff --git a/pkg/clock/clock_test.go b/pkg/clock/clock_test.go new file mode 100644 index 0000000..266e692 --- /dev/null +++ b/pkg/clock/clock_test.go @@ -0,0 +1,13 @@ +//go:build ignore +package clock + +import ( + "io" + "testing" +) + +func BenchmarkNumber(b *testing.B) { + for i := 0; i < b.N; i++ { + Numbers(io.Discard) + } +} diff --git a/pkg/clock/cmd/main.go b/pkg/clock/cmd/main.go new file mode 100644 index 0000000..00a960a --- /dev/null +++ b/pkg/clock/cmd/main.go @@ -0,0 +1,22 @@ +package main + +import ( + "net/http" + + "git.niplace.ru/XoxJlopeZi4BB/clock" +) + +func main() { + addrwithport := ":8080" + http.HandleFunc("/", + func(w http.ResponseWriter, req *http.Request) { + clock.Time(w) + }, + ) + + println("this thingy running on", addrwithport) + err := http.ListenAndServe(addrwithport, nil) + if err != nil { + panic(err) + } +} diff --git a/pkg/clock/digit/digit.go b/pkg/clock/digit/digit.go new file mode 100644 index 0000000..7f773b0 --- /dev/null +++ b/pkg/clock/digit/digit.go @@ -0,0 +1,22 @@ +package main + +import ( + "fmt" + "time" +) + +func main() { + d, err := time.ParseDuration("1s") + if err != nil { + panic(err) + } + t := time.Tick(d) + go func() { + fmt.Printf("\033[2J\033[H") + for { + <-t + fmt.Printf("\r%s", time.Now().Format(time.TimeOnly)) + } + }() + select {} +} diff --git a/pkg/clock/go.mod b/pkg/clock/go.mod new file mode 100644 index 0000000..0df2c6b --- /dev/null +++ b/pkg/clock/go.mod @@ -0,0 +1,5 @@ +module git.niplace.ru/XoxJlopeZi4BB/clock + +go 1.25.3 + +require git.niplace.ru/XoxJlopeZi4BB/imageutils v0.0.0-20241224134015-2709034fc322 diff --git a/pkg/clock/go.sum b/pkg/clock/go.sum new file mode 100644 index 0000000..697048c --- /dev/null +++ b/pkg/clock/go.sum @@ -0,0 +1,4 @@ +git.niplace.ru/XoxJlopeZi4BB/imageutils v0.0.0-20241224134015-2709034fc322 h1:jefEdqKZ/JKnmky9LipaS/UH0phAhz/56ORHIjmHREk= +git.niplace.ru/XoxJlopeZi4BB/imageutils v0.0.0-20241224134015-2709034fc322/go.mod h1:QieEgSGk9ZYISDv5XyMMktQXi/2qlTmdHuxTlt1Xfq8= +github.com/potassium5703/texture v0.0.0-20240820054037-fce43fc4b0f0 h1:sowjIIVme5ovcdB0kjP3w+4xbVNrlOPdx7Up4LIGJz8= +github.com/potassium5703/texture v0.0.0-20240820054037-fce43fc4b0f0/go.mod h1:KwM7hMpZhr3XySWuK/SZ7s1BXVQe8p1IyZftYg9KtWY= diff --git a/pkg/clock/letter/image.go b/pkg/clock/letter/image.go new file mode 100644 index 0000000..b0004aa --- /dev/null +++ b/pkg/clock/letter/image.go @@ -0,0 +1,106 @@ +package letter + +import ( + "embed" + "encoding/csv" + "image" + "image/color" + "image/draw" + "io" + + "git.niplace.ru/XoxJlopeZi4BB/imageutils" +) + +type Letter string + +//go:embed map.csv +var fs embed.FS +var mapFile = func() io.Reader { + f, err := fs.Open("map.csv") + if err != nil { + panic(err) + } + return f +}() + +var Letters = func(r io.Reader) (m map[string]string) { + records, err := csv.NewReader(r).ReadAll() + if err != nil { + panic(err) + } + for _, v := range records { + if len(v) < 2 { + panic("csv file isn's key-value pair") + } + m[v[0]] = v[1] + } + return m +}(mapFile) + +// implements image.Image interface. +func (l Letter) ColorModel() color.Model { + return color.Alpha16Model +} + +// implements image.Image interface. +func (l Letter) Bounds() image.Rectangle { + return image.Rect(0, 0, 3, 3) +} + +// implements image.Image interface. +func (l Letter) At(x, y int) color.Color { + if len(l) != 9 { + panic("len(Letter) != 9") + } + target := l[x+y*3] + if target != '1' { + return color.Opaque + } + return color.Transparent +} + +func Render(l Letter) image.Image { + img := image.NewRGBA(l.Bounds()) + draw.Draw(img, l.Bounds(), image.White, image.ZP, draw.Src) + draw.Draw(img, l.Bounds(), l, image.ZP, draw.Over) + return img +} + +type blank struct { + image.Image + color.Color + imageutils.Side +} + +func (b blank) ColorModel() color.Model { return b.Image.ColorModel() } + +func (b blank) Bounds() image.Rectangle { + rect := image.Rectangle{} + switch b.Side { + case imageutils.Left: + fallthrough + case imageutils.Right: + rect = image.Rectangle{ + image.ZP, + image.Point{ + 1, b.Image.Bounds().Dy(), + }, + } + case imageutils.Up: + fallthrough + case imageutils.Down: + rect = image.Rectangle{ + image.ZP, + image.Point{ + b.Image.Bounds().Dx(), 1, + }, + } + } + return rect +} + +func (b blank) At(x, y int) color.Color { return b.Color } + +func Blank(img image.Image, clr color.Color, side imageutils.Side) image.Image { + return imageutils.Concat(img, blank{img, clr, side}, side) +} diff --git a/pkg/clock/letter/map.csv b/pkg/clock/letter/map.csv new file mode 100644 index 0000000..8f33882 --- /dev/null +++ b/pkg/clock/letter/map.csv @@ -0,0 +1,11 @@ +0, 111101111 +1, 010010010 +2, 110010011 +3, 111011111 +4, 101111001 +5, 011010110 +6, 001111111 +7, 111001001 +8, 011111111 +9, 111111001 +:, 010000010 diff --git a/pkg/clock/string.go b/pkg/clock/string.go new file mode 100644 index 0000000..70ab50f --- /dev/null +++ b/pkg/clock/string.go @@ -0,0 +1,35 @@ +package clock + +import ( + "git.nkpl.cc/twocookedfaggots/imageutils/clock/letter" +) + +var blank = Letter("000000000") + +type String struct { + S string +} + +func (s String) Bounds() image.Rectangle { + splitted := strings.Split(s.S, '\n') + max := 0 + for _, v := range splitted { + max = max(len(v), max) + } + x, y := max*4+1, len(splitted)*4+1 + return image.Rect(0,0,x,y) +} + +func (s String) ColorModel() color.Model { return color.Alpha16Model } +func (s String) At(x, y int) color.Color { + splitted := string.Split(s.S, '\n') + if y/4 > len(splitted) { + return blank.At(0, 0) + } + if x/4 > len(splitted[y/4]) { + return blank.At(0, 0) + } + c := splitted[y/4][x/4] + return Letter(c).At(x%4, y%4) +} + diff --git a/pkg/dithering/grid.go b/pkg/dithering/grid.go index 5c29717..8f11335 100644 --- a/pkg/dithering/grid.go +++ b/pkg/dithering/grid.go @@ -9,6 +9,7 @@ const side = 16 type grid struct { color.Gray + Factor float64 } func (_ grid) ColorModel() color.Model { @@ -20,7 +21,7 @@ func (_ grid) Bounds() image.Rectangle { } func (g grid) At(x, y int) color.Color { - n := uint8(g.Gray.Y * 10) + n := uint8(float64(g.Gray.Y) * g.Factor) if n == 0 { return color.Black @@ -52,12 +53,13 @@ func (g uniformGrid) At(x, y int) color.Color { type Dithering struct { image.Image + Factor float64 } 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)}}. + return uniformGrid{grid{c.(color.Gray), d.Factor}}. At(x, y) } diff --git a/pkg/mesh/mesh.go b/pkg/mesh/mesh.go index b2a6fc5..be5a51e 100644 --- a/pkg/mesh/mesh.go +++ b/pkg/mesh/mesh.go @@ -13,6 +13,8 @@ import ( "golang.org/x/image/font" "golang.org/x/image/font/gofont/gomono" "golang.org/x/image/math/fixed" + + "git.nkpl.cc/twocookedfaggots/imageutils/pkg/mesh/wallpaper" // "github.com/droyo/styx" // "io/fs" ) @@ -42,22 +44,22 @@ func render(img image.Image) draw.Image { } func main() { -// x := flag.Int("x", 2, "use to grid by x axis") -// y := flag.Int("y", 2, "use to grid by y axis") + // x := flag.Int("x", 2, "use to grid by x axis") + // y := flag.Int("y", 2, "use to grid by y axis") flag.Parse() // now flags is ready to use img, err := png.Decode(os.Stdin) if err != nil { panic(err) } -// Mesh{ // our image modifyer -// Image: img, -// X: *x, -// Y: *y, -// }, + // Mesh{ // our image modifyer + // Image: img, + // X: *x, + // Y: *y, + // }, dst := render( - img, + img, ) f, err := truetype.Parse(gomono.TTF) @@ -75,16 +77,16 @@ func main() { Src: image.NewUniform(color.Black), Face: face, Dot: fixed.Point26_6{fixed.Int26_6(img.Bounds().Dx() / - 9*64, + 9 * 64, ), fixed.Int26_6(img.Bounds().Dy() / - 5*64, + 5 * 64, ), }, } d.DrawString(time.Now().Format(time.Kitchen)) - err = png.Encode(os.Stdout, dst) + err = wallpaper.Wallpaper(dst) if err != nil { panic(err) } diff --git a/pkg/mesh/test_cmd.go b/pkg/mesh/test_cmd.go new file mode 100644 index 0000000..ea5d4df --- /dev/null +++ b/pkg/mesh/test_cmd.go @@ -0,0 +1,23 @@ +package main + +import ( + "os" + "os/exec" +) + +func main() { + f, err := os.Open("/home/potassium/documents/wallpaper/8.png") + if err != nil { + panic(err) + } + cmd := exec.Command( + "swaybg", + "--image", "/dev/stdin", + ) + cmd.Stderr = os.Stderr + cmd.Stdin = f + err = cmd.Run() + if err != nil { + panic(err) + } +} diff --git a/pkg/mesh/wallpaper/swaybg.go b/pkg/mesh/wallpaper/swaybg.go new file mode 100644 index 0000000..69c8060 --- /dev/null +++ b/pkg/mesh/wallpaper/swaybg.go @@ -0,0 +1,37 @@ +package wallpaper + +import ( + "bytes" + "image" + "image/png" + "os" + "os/exec" +) + +var err error + +func Wallpaper(img image.Image) error { + /* + cmd := exec.Command( + "swaybg", + "--image", "/dev/stdin", + "--mode", "fill", + ) + */ + cmd := exec.Command("imv", "/dev/stdin") + + var buf = new(bytes.Buffer) + err := png.Encode(buf, img) + if err != nil { + panic(err) + } + + cmd.Stderr = os.Stdout + cmd.Stdin = buf + + err = cmd.Run() + if err != nil { + return err + } + return nil +} diff --git a/pkg/negate/negate.go b/pkg/negate/negate.go index 3608fb0..f99a96e 100644 --- a/pkg/negate/negate.go +++ b/pkg/negate/negate.go @@ -5,6 +5,8 @@ import ( "image/color" "image/png" "os" + + "git.nkpl.cc/twocookedfaggots/imageutils/util" ) func NegateRGBA(c color.RGBA) color.RGBA { @@ -30,15 +32,10 @@ func (n Negate) At(x, y int) color.Color { return NegateRGBA(RGBAColor) } -func check(err error) { - if err != nil { +func main() { + if err := util.ProcessStdio(func(img image.Image) image.Image { + return Negate{img} + }); err != nil { panic(err) } } - -func main() { - img, err := png.Decode(os.Stdin) - check(err) - err = png.Encode(os.Stdout, Negate{img}) - check(err) -} diff --git a/scale.go b/scale.go index 332e37a..7c6039e 100644 --- a/scale.go +++ b/scale.go @@ -38,7 +38,7 @@ func (r rescaled) At(x, y int) color.Color { // Scale scales image.Image to a given scale // and then returns image.Image. // For now it will work only with positive integers. -func Scale(scale int, img image.Image) image.Image { +func Scale(img image.Image, scale int) image.Image { if scale < 1 { scale = 1 }