random circles example
This commit is contained in:
24
circle.go
Normal file
24
circle.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package imageutils
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
)
|
||||
|
||||
// go.dev/blog/image-draw#drawing-through-a-mask
|
||||
type Circle struct {
|
||||
image.Point
|
||||
R int
|
||||
}
|
||||
|
||||
func (c Circle) ColorModel() color.Model { return color.AlphaModel }
|
||||
func (c Circle) Bounds() image.Rectangle {
|
||||
return image.Rect(c.Point.X-c.R, c.Point.Y-c.R, c.Point.X+c.R, c.Point.Y+c.R)
|
||||
}
|
||||
func (c Circle) At(x, y int) color.Color {
|
||||
xx, yy, rr := float64(x-c.Point.X)+0.5, float64(y-c.Point.Y)+0.5, float64(c.R)
|
||||
if xx*xx+yy*yy < rr*rr {
|
||||
return color.Opaque
|
||||
}
|
||||
return color.Transparent
|
||||
}
|
||||
18
cmd/jpg2png/jpg2png.go
Normal file
18
cmd/jpg2png/jpg2png.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"image/jpeg"
|
||||
"image/png"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
img, err := jpeg.Decode(os.Stdin)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = png.Encode(os.Stdout, img)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
56
cmd/playground/circles/circles.go
Normal file
56
cmd/playground/circles/circles.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/draw"
|
||||
"image/png"
|
||||
"os"
|
||||
|
||||
iu "git.nkpl.cc/twocookedfaggots/imageutils"
|
||||
)
|
||||
|
||||
func square(side int) image.Rectangle { return image.Rect(0, 0, side, side) }
|
||||
|
||||
func Circles(b image.Rectangle, radius int) chan iu.Circle {
|
||||
ch := make(chan iu.Circle)
|
||||
go func() {
|
||||
defer close(ch)
|
||||
for {
|
||||
x, y := rand.Int()%b.Dx(), rand.Int()%b.Dy()
|
||||
dxdy := b.Dx()*b.Dy()
|
||||
r := rand.Int() % (dxdy/(dxdy/radius))
|
||||
ch <- iu.Circle{image.Point{x, y}, r}
|
||||
}
|
||||
}()
|
||||
return ch
|
||||
}
|
||||
|
||||
// Converts color.Opaque and color.Transparent to color.Black and color.White respectively.
|
||||
var BlackAndWhite = color.ModelFunc(
|
||||
func(c color.Color) color.Color {
|
||||
if color.AlphaModel.Convert(c) == color.Opaque {
|
||||
return color.Black
|
||||
}
|
||||
return color.White
|
||||
},
|
||||
)
|
||||
|
||||
func main() {
|
||||
canvas := image.NewRGBA(square(1024))
|
||||
circles := Circles(canvas.Bounds(), 1024/16)
|
||||
|
||||
// draw n circles
|
||||
for i := 0; i < 100; i++ {
|
||||
c := <-circles
|
||||
draw.DrawMask(
|
||||
canvas, canvas.Bounds(), &image.Uniform{color.White},
|
||||
image.Point{}, c, image.Point{}, draw.Over,
|
||||
)
|
||||
}
|
||||
err := png.Encode(os.Stdout, canvas)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
9
cmd/playground/main.go
Normal file
9
cmd/playground/main.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
iu "git.nkpl.cc/twocookedfaggots/imageutils"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
}
|
||||
BIN
pkg/merge/IMG_0732.jpg
Normal file
BIN
pkg/merge/IMG_0732.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 424 KiB |
BIN
pkg/merge/converted.png
Normal file
BIN
pkg/merge/converted.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 541 KiB |
BIN
pkg/merge/converted_gray.png
Normal file
BIN
pkg/merge/converted_gray.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 615 KiB |
44
pkg/merge/merge.go
Normal file
44
pkg/merge/merge.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
_ "image/jpeg"
|
||||
"image/png"
|
||||
_ "image/png"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Merge struct {
|
||||
first, second image.Image
|
||||
}
|
||||
|
||||
func (m Merge) ColorModel() color.Model { return m.first.ColorModel() }
|
||||
func (m Merge) Bounds() image.Rectangle { return m.first.Bounds() }
|
||||
|
||||
func (m Merge) At(x, y int) color.Color {
|
||||
if (x%2 != 0) && (y%2 != 0) {
|
||||
return m.second.At(x, y)
|
||||
}
|
||||
return m.first.At(x, y)
|
||||
}
|
||||
|
||||
func main() {
|
||||
f1, err := os.Open(os.Args[1])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
f2, err := os.Open(os.Args[2])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
img1, _, err := image.Decode(f1)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
img2, _, err := image.Decode(f2)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
png.Encode(os.Stdout, Merge{img1, img2})
|
||||
}
|
||||
BIN
pkg/merge/merged.png
Normal file
BIN
pkg/merge/merged.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 607 KiB |
152
pkg/merge/palette.go
Normal file
152
pkg/merge/palette.go
Normal file
@@ -0,0 +1,152 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
_ "image/jpeg"
|
||||
"image/png"
|
||||
_ "image/png"
|
||||
"os"
|
||||
|
||||
"slices"
|
||||
)
|
||||
|
||||
func paletteFromImage(img image.Image) (p []color.Color) {
|
||||
for i := 0; i < img.Bounds().Dx(); i++ {
|
||||
p = append(p, img.At(i, 0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
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 = fmt.Errorf("invalid length, must be 7 or 4")
|
||||
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func mean(c1, c2 color.Color) color.Color {
|
||||
r1, g1, b1, _ := c1.RGBA()
|
||||
r2, g2, b2, _ := c2.RGBA()
|
||||
return color.RGBA{
|
||||
uint8((r1 + r2) / 2),
|
||||
uint8((g1 + g2) / 2),
|
||||
uint8((b1 + b2) / 2),
|
||||
0xFF,
|
||||
}
|
||||
}
|
||||
|
||||
type Convert struct {
|
||||
image.Image
|
||||
color.Palette
|
||||
}
|
||||
|
||||
func (c Convert) ColorModel() color.Model { return c.Image.ColorModel() }
|
||||
func (c Convert) Bounds() image.Rectangle { return c.Image.Bounds() }
|
||||
func (c Convert) At(x, y int) color.Color {
|
||||
if isMeanCloser(c.Palette, c.Image.At(x, y)) {
|
||||
first, second := twoClosest(c.Palette, c.Image.At(x, y))
|
||||
// chessboard texture
|
||||
if (x%2 != 0) && (y%2 != 0) || (x%2 == 0) && (y%2 == 0) {
|
||||
return first
|
||||
}
|
||||
return second
|
||||
}
|
||||
return c.Palette.Convert(c.Image.At(x, y))
|
||||
}
|
||||
|
||||
func twoClosest(p color.Palette, c color.Color) (first, second color.Color) {
|
||||
first = p.Convert(c)
|
||||
i := p.Index(c)
|
||||
p2 := slices.Delete(slices.Clone(p), i, i+1)
|
||||
second = p2.Convert(c)
|
||||
return
|
||||
}
|
||||
|
||||
func isMeanCloser(p color.Palette, c color.Color) bool {
|
||||
first, second := twoClosest(p, c)
|
||||
mp := color.Palette{first, mean(first, second), second}
|
||||
i := mp.Index(c)
|
||||
return i == mp.Index(mean(first, second))
|
||||
}
|
||||
|
||||
func main() {
|
||||
paletteFile := flag.String("p", "", "provide palette file")
|
||||
flag.Parse()
|
||||
|
||||
var palette []color.Color
|
||||
|
||||
var colors []string
|
||||
_ = []string{
|
||||
"#ffffec", // soft-white
|
||||
"#ff0000", // red
|
||||
"#00ff00", // green
|
||||
"#0000ff", // blue
|
||||
"#000000", // black
|
||||
}
|
||||
funniPalette := []string{
|
||||
"#ffffec",
|
||||
"#000000",
|
||||
"#4a3544",
|
||||
"#757575",
|
||||
"#8e8e8e",
|
||||
"#666666",
|
||||
"#4c4c4c",
|
||||
"#3b3b3b",
|
||||
"#949494",
|
||||
"#ffffff",
|
||||
"#665361",
|
||||
"#3f3f3f",
|
||||
"#525252",
|
||||
"#838383",
|
||||
"#111111",
|
||||
"#070707",
|
||||
"#b9b9b9",
|
||||
"#dfdfdf",
|
||||
}
|
||||
colors = funniPalette
|
||||
if *paletteFile != "" {
|
||||
f, err := os.Open(*paletteFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
img, _, err := image.Decode(f)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
palette = paletteFromImage(img)
|
||||
} else {
|
||||
palette = func() (p []color.Color) {
|
||||
for _, v := range colors {
|
||||
c, err := parseHexColor(v)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
p = append(p, c)
|
||||
}
|
||||
return
|
||||
}()
|
||||
}
|
||||
img, _, err := image.Decode(os.Stdin)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
palette = append(palette, color.RGBA{88, 88, 88, 0xFF})
|
||||
err = png.Encode(os.Stdout, Convert{img, palette})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
BIN
pkg/merge/palette.png
Normal file
BIN
pkg/merge/palette.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 510 B |
5
pkg/merge/readme.md
Normal file
5
pkg/merge/readme.md
Normal file
@@ -0,0 +1,5 @@
|
||||
experiments with palette and stuff
|
||||
|
||||
---
|
||||
|
||||

|
||||
Submodule pkg/palette deleted from e161720f1c
Reference in New Issue
Block a user