aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Byron <=>2015-07-20 14:13:18 +1000
committerDaniel Byron <=>2015-07-20 14:13:18 +1000
commited38e7eb0f81267c6e2b520777b8b84705a3cac3 (patch)
tree3157c55f49988e16ab2b12b07af910990ebd4097
parentUpdated readme (diff)
downloadschemer2-ed38e7eb0f81267c6e2b520777b8b84705a3cac3.tar.xz
schemer2-ed38e7eb0f81267c6e2b520777b8b84705a3cac3.zip
Expose advanced image options
Includes a major rewrite of how images are generated, and makes use of many more command line flags. Still needs much testing, however preliminary results look good.
-rw-r--r--image.go226
-rw-r--r--main.go77
2 files changed, 182 insertions, 121 deletions
diff --git a/image.go b/image.go
index 93789e9..d6924b8 100644
--- a/image.go
+++ b/image.go
@@ -10,9 +10,12 @@ import (
"math"
"math/rand"
"os"
+ "sort"
"time"
)
+var imageOutTypes = [...]string{"random", "circles", "rays", "stripes"}
+
func loadImage(filepath string) image.Image {
infile, err := os.Open(filepath)
if err != nil {
@@ -34,6 +37,17 @@ func abs(n int) int {
return -n
}
+func randMinMax(min int, max int) int {
+ if min == max {
+ return min
+ }
+ return rand.Intn(max-min) + min
+}
+
+func randBool() bool {
+ return rand.Intn(2) == 0
+}
+
func colorDifference(col1 color.Color, col2 color.Color, threshold int) bool {
c1 := col1.(color.NRGBA)
c2 := col2.(color.NRGBA)
@@ -101,47 +115,20 @@ func colorsFromImage(filename string) ([]color.Color, error) {
return distinctColors, nil
}
-func imageFromColors(colors []color.Color, w int, h int) image.Image {
+func imageFromColors(colors []color.Color, w int, h int) (image.Image, error) {
rand.Seed(time.Now().UnixNano())
- switch rand.Intn(4) {
- case 0:
- // Circles
- switch rand.Intn(2) {
- case 0:
- return Circles(colors, w, h, false)
- case 1:
- return Circles(colors, w, h, true)
- }
- case 1:
- // Rays
- switch rand.Intn(2) {
- case 0:
- return Rays(colors, w, h, true, rand.Intn(w/24))
- case 1:
- return Rays(colors, w, h, false, rand.Intn(w/24))
- }
- case 2:
- // Horizontal Lines
- switch rand.Intn(2) {
- case 0:
- return HorizontalLines(colors, w, h, false)
- case 1:
- return HorizontalLines(colors, w, h, true)
- }
- case 3:
- // Vertical Lines
- switch rand.Intn(4) {
- case 0:
- return VerticalLines(colors, w, h, false, false)
- case 1:
- return VerticalLines(colors, w, h, true, false)
- case 2:
- return VerticalLines(colors, w, h, false, true)
- case 3:
- return VerticalLines(colors, w, h, true, true)
- }
+ switch *imageOutType {
+ case "random":
+ return randomImage(colors, w, h), nil
+ case "circles":
+ return Circles(colors, w, h, *circleSize, *circleSizeVariance, *circleOverlap, *circleDrawLargestToSmallest, *circleFilled, *circleBorderSize), nil
+ case "rays":
+ return Rays(colors, w, h, *raysSize, *raysSizeVariance, *raysDistributeEvenly, *raysCentered, *raysDrawLargestToSmallest), nil
+ case "stripes":
+ return Lines(colors, w, h, *stripesSize, *stripesSizeVariance, *stripesHorizontal, *stripesEvenSpacing, *stripesSpacing, *stripesOffset), nil
+
}
- return nil
+ return nil, errors.New("Unrecognised ouput image type: " + *imageOutType + "\n")
}
type Circle struct {
@@ -150,18 +137,28 @@ type Circle struct {
size int
}
-func Circles(colors []color.Color, w int, h int, filled bool) image.Image {
+// For sorting circles by size
+type circleBySize []Circle
+
+func (a circleBySize) Len() int { return len(a) }
+func (a circleBySize) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+func (a circleBySize) Less(i, j int) bool { return a[i].size < a[j].size }
+
+func Circles(colors []color.Color, w int, h int, size int, sizevar int, overlap bool, large2small bool, filled bool, bordersize int) image.Image {
img := image.NewNRGBA(image.Rect(0, 0, w, h))
circles := make([]Circle, 0)
for _, c := range colors {
- circle := Circle{c, rand.Intn(w), rand.Intn(h), rand.Intn(w / 2)}
+ circle := Circle{c, rand.Intn(w), rand.Intn(h), randMinMax(size-sizevar, size+sizevar)}
circles = append(circles, circle)
}
bg := colors[0]
- border := rand.Intn(w / 24)
+
+ if large2small {
+ sort.Sort(circleBySize(circles))
+ }
for x := 0; x < w; x++ {
for y := 0; y < h; y++ {
@@ -175,7 +172,7 @@ func Circles(colors []color.Color, w int, h int, filled bool) image.Image {
img.Set(x, y, c.col)
}
} else {
- if int(math.Sqrt(a+b)) < c.size && int(math.Sqrt(a+b)) > (c.size-border) {
+ if int(math.Sqrt(a+b)) < c.size && int(math.Sqrt(a+b)) > (c.size-bordersize) {
img.Set(x, y, c.col)
}
}
@@ -185,80 +182,46 @@ func Circles(colors []color.Color, w int, h int, filled bool) image.Image {
return img
}
-type Stripe struct {
+type Ray struct {
col color.Color
x, y int // Middle point
angle int // 0-180
+ size int
}
-func Rays(colors []color.Color, w int, h int, centered bool, margin int) image.Image {
- img := image.NewNRGBA(image.Rect(0, 0, w, h))
-
- stripes := make([]Stripe, 0)
-
- for _, c := range colors {
- var stripe Stripe
- if centered {
- stripe = Stripe{c, w / 2, h / 2, rand.Intn(180)}
- } else {
- stripe = Stripe{c, rand.Intn(w), rand.Intn(h), rand.Intn(180)}
- }
- stripes = append(stripes, stripe)
- }
-
- bg := colors[0]
-
- for x := 0; x < w; x++ {
- for y := 0; y < h; y++ {
- img.Set(x, y, bg)
- for _, s := range stripes {
- deltaX := float64(x - s.x)
- deltaY := float64(y - s.y)
- angle := math.Atan(deltaY/deltaX) * 180 / math.Pi
- if int(math.Abs(float64(int(angle)-s.angle))) < margin {
- img.Set(x, y, s.col)
- }
- }
- }
- }
- return img
-}
-
-type VerticalLine struct {
- col color.Color
- x int
- w int
-}
+// For sorting rays by size
+type rayBySize []Ray
-type HorizontalLine struct {
- col color.Color
- y int
- h int
-}
+func (a rayBySize) Len() int { return len(a) }
+func (a rayBySize) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+func (a rayBySize) Less(i, j int) bool { return a[i].size < a[j].size }
-func VerticalLines(colors []color.Color, w int, h int, evenlySpaced bool, evenWidth bool) image.Image {
+func Rays(colors []color.Color, w int, h int, size int, sizevar int, evendist bool, centered bool, large2small bool) image.Image {
img := image.NewNRGBA(image.Rect(0, 0, w, h))
- lines := make([]VerticalLine, 0)
-
- var width int
- width = rand.Intn(w / 16)
+ rays := make([]Ray, 0)
- x_index := rand.Intn(w / 2)
+ spacing := 180 / len(colors)
+ current_angle := 0
- var spacing int
- spacing = rand.Intn(w / 32)
+ xpos := w / 2
+ ypos := h / 2
for _, c := range colors {
- if !evenWidth {
- width = rand.Intn(w / 16)
+ var ray Ray
+ if !centered {
+ xpos = rand.Intn(w)
+ ypos = rand.Intn(h)
}
- if !evenlySpaced {
- spacing = rand.Intn(w / 32)
+ if !evendist {
+ current_angle = rand.Intn(180)
}
- x_index += spacing
- lines = append(lines, VerticalLine{c, x_index, width})
- x_index += width
+ ray = Ray{c, xpos, ypos, current_angle, randMinMax(size-sizevar, size+sizevar)}
+
+ if evendist {
+ current_angle += spacing + ray.size
+ }
+ rays = append(rays, ray)
}
bg := colors[0]
@@ -266,33 +229,46 @@ func VerticalLines(colors []color.Color, w int, h int, evenlySpaced bool, evenWi
for x := 0; x < w; x++ {
for y := 0; y < h; y++ {
img.Set(x, y, bg)
- for _, l := range lines {
- if x >= l.x && x < l.x+l.w {
- img.Set(x, y, l.col)
+ for _, r := range rays {
+ deltaX := float64(x - r.x)
+ deltaY := float64(y - r.y)
+ angle := math.Atan(deltaY/deltaX) * 180 / math.Pi
+ if int(math.Abs(float64(int(angle)-r.angle))) < r.size {
+ img.Set(x, y, r.col)
}
}
}
}
-
return img
+}
+type Line struct {
+ col color.Color
+ position int
+ size int
}
-func HorizontalLines(colors []color.Color, w int, h int, evenHeight bool) image.Image {
+func Lines(colors []color.Color, w int, h int, size int, sizevar int, horizontal bool, equalspacing bool, spacingsize int, offset int) image.Image {
img := image.NewNRGBA(image.Rect(0, 0, w, h))
+ var maxsize int
+ if horizontal {
+ maxsize = h
+ } else {
+ maxsize = w
+ }
- lines := make([]HorizontalLine, 0)
+ currentposition := offset
+ spacing := spacingsize
- var height int
- if evenHeight {
- height = rand.Intn(h / 16)
- }
+ lines := make([]Line, 0)
for _, c := range colors {
- if !evenHeight {
- height = rand.Intn(h / 16)
+ line := Line{c, currentposition, randMinMax(size-sizevar, size+sizevar)}
+ lines = append(lines, line)
+ if !equalspacing {
+ spacing = rand.Intn(maxsize / 16)
}
- lines = append(lines, HorizontalLine{c, rand.Intn(h), height})
+ currentposition += line.size + spacing
}
bg := colors[0]
@@ -301,7 +277,14 @@ func HorizontalLines(colors []color.Color, w int, h int, evenHeight bool) image.
for y := 0; y < h; y++ {
img.Set(x, y, bg)
for _, l := range lines {
- if y >= l.y && y < l.y+l.h {
+ var pixelpos int
+ if horizontal {
+ pixelpos = y
+ } else {
+ pixelpos = x
+ }
+
+ if pixelpos > l.position && pixelpos < l.position+l.size {
img.Set(x, y, l.col)
}
}
@@ -309,5 +292,16 @@ func HorizontalLines(colors []color.Color, w int, h int, evenHeight bool) image.
}
return img
+}
+func randomImage(colors []color.Color, w int, h int) image.Image {
+ switch rand.Intn(3) {
+ case 0:
+ return Circles(colors, w, h, rand.Intn(w/2), rand.Intn(w/2), randBool(), randBool(), randBool(), rand.Intn(w/16))
+ case 1:
+ return Rays(colors, w, h, rand.Intn(h/32), rand.Intn(h/32), randBool(), true, randBool())
+ case 2:
+ return Lines(colors, w, h, rand.Intn(h/32), rand.Intn(h/32), randBool(), randBool(), rand.Intn(h/32), rand.Intn(h/2))
+ }
+ return nil
}
diff --git a/main.go b/main.go
index e7ba5e5..4e1971d 100644
--- a/main.go
+++ b/main.go
@@ -15,15 +15,45 @@ const (
)
var (
- threshold *int
outfile *string
infile *string
format_string *string
+
+ // Image input options
+ threshold *int
minBrightness *int
maxBrightness *int
- imageWidth *int
- imageHeight *int
+ // Generic image output options
+ imageWidth *int
+ imageHeight *int
+ imageOutType *string // Eg, "random", "circles", "stripes", etc...
+
+ // Circles image output options
+ circleSize *int
+ circleSizeVariance *int
+ circleOverlap *bool
+ circleDrawLargestToSmallest *bool
+ circleFilled *bool
+ circleBorderSize *int
+
+ // Ray image output options
+ raysSize *int
+ raysSizeVariance *int
+ raysDistributeEvenly *bool
+ raysCentered *bool
+ raysDrawLargestToSmallest *bool
+
+ // Stripes image output options
+ stripesSize *int
+ stripesSizeVariance *int
+ stripesHorizontal *bool
+ stripesEqualSize *bool
+ stripesEvenSpacing *bool
+ stripesSpacing *int
+ stripesOffset *int
+
+ // Show advanced help
advancedoptions *bool
)
@@ -63,14 +93,47 @@ func inputs_outputs() {
}
func main() {
- threshold = flag.Int("threshold", 50, "Threshold for minimum color difference (image input only)")
infile = flag.String("in", "", "Input file")
outfile = flag.String("out", "", "File to write output to.")
format_string = flag.String("format", "", "Format of input and output. Eg. 'image"+format_separator+"xterm'")
+
+ threshold = flag.Int("threshold", 50, "Threshold for minimum color difference (image input only)")
minBrightness = flag.Int("minBright", 0, "Minimum brightness for colors (image input only)")
maxBrightness = flag.Int("maxBright", 200, "Maximum brightness for colors (image input only)")
+
imageHeight = flag.Int("height", 1080, "Height of output image")
imageWidth = flag.Int("width", 1920, "Width of output image")
+ imageOutTypeDesc := "Type of image to generate. Available options: \n"
+ for _, t := range imageOutTypes {
+ imageOutTypeDesc += " "
+ imageOutTypeDesc += t
+ imageOutTypeDesc += "\n"
+ }
+ imageOutType = flag.String("imageOutType", "random", imageOutTypeDesc)
+
+ // Circles image output options
+ circleSize = flag.Int("circleSize", 100, "Size of circles in output image")
+ circleSizeVariance = flag.Int("circleSizeVariance", 50, "Maximum variance in circle size")
+ circleOverlap = flag.Bool("circleOverlap", true, "Allow circles to overlap !!! Unimplemented !!!")
+ circleDrawLargestToSmallest = flag.Bool("circleLargeToSmall", true, "Order circles z-index by size (smaller circles are drawn in front of larger circles)")
+ circleFilled = flag.Bool("circleFilled", false, "Fill circles")
+ circleBorderSize = flag.Int("circleBorderSize", 10, "Border of circles when unfilled")
+
+ // Ray image output options
+ raysSize = flag.Int("raysSize", 16, "Size of rays in output image")
+ raysSizeVariance = flag.Int("raysSizeVariance", 8, "Maximum variance in rays size")
+ raysDistributeEvenly = flag.Bool("raysDistributeEvenly", false, "Distribute rays evenly")
+ raysCentered = flag.Bool("raysCentered", true, "Center rays in middle")
+ raysDrawLargestToSmallest = flag.Bool("raysLargeToSmall", false, "Order rays z-index by size (smaller rays are drawn on top of larger rays)")
+
+ // Stripes image output options
+ stripesSize = flag.Int("stripesSize", 6, "Size of stripes in output image")
+ stripesSizeVariance = flag.Int("stripesSizeVariance", 3, "Maximum variance in stripes size")
+ stripesHorizontal = flag.Bool("stripesHorizontal", false, "Draw stripes horizontally instead of vertically")
+ stripesEvenSpacing = flag.Bool("stripesEvenSpacing", true, "Space all stripes evenly")
+ stripesSpacing = flag.Int("stripesSpacing", 0, "Space stripes by this amount when spacing evenly")
+ stripesOffset = flag.Int("stripesOffset", 0, "Offset stripes by this amount")
+
advancedoptions = flag.Bool("help-advanced", false, "Show advanced command line options")
flag.Usage = flags_usage
@@ -196,7 +259,11 @@ func main() {
}
defer file.Close()
- img := imageFromColors(colors, *imageWidth, *imageHeight) // TODO
+ img, err := imageFromColors(colors, *imageWidth, *imageHeight) // TODO
+ if err != nil {
+ fmt.Printf(err.Error())
+ os.Exit(1)
+ }
png.Encode(file, img)
}