Add image, Support writing PPM P3 image, Additional checks
This commit is contained in:
parent
32d9ef18eb
commit
4e0801eb9b
5 changed files with 80 additions and 27 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1 +1,2 @@
|
||||||
/humanshader
|
/humanshader
|
||||||
|
*.ppm
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
# Human Shader Validator
|
# Human Shader Validator
|
||||||
|
|
||||||
Validator for [Human Shader](https://humanshader.com/)
|
Validator for [Human Shader](https://humanshader.com/)
|
||||||
|
|
||||||
|
![Final image of Human Shader](humanshader.png)
|
82
hsv.go
82
hsv.go
|
@ -10,24 +10,68 @@ import (
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
args := os.Args[1:]
|
args := os.Args[1:]
|
||||||
var pxX int
|
|
||||||
var pxY int
|
|
||||||
if len(args) == 2 {
|
|
||||||
pxX, _ = strconv.Atoi(args[0])
|
|
||||||
pxY, _ = strconv.Atoi(args[1])
|
|
||||||
} else {
|
|
||||||
fmt.Print("Pixel x coordinate: ")
|
|
||||||
input := bufio.NewScanner(os.Stdin)
|
|
||||||
input.Scan()
|
|
||||||
pxX, _ = strconv.Atoi(input.Text())
|
|
||||||
fmt.Print("Pixel y coordinate: ")
|
|
||||||
input = bufio.NewScanner(os.Stdin)
|
|
||||||
input.Scan()
|
|
||||||
pxY, _ = strconv.Atoi(input.Text())
|
|
||||||
}
|
|
||||||
|
|
||||||
val := hsv.NewValidator(true)
|
// TODO: Better argument parsing
|
||||||
val.Calculate(pxX, pxY)
|
if len(args) == 1 || len(args) == 3 || len(args) == 5 {
|
||||||
r, g, b := val.GetColor()
|
fmt.Printf("Writing PPM image to %s.\n", args[0])
|
||||||
fmt.Printf("R: %d\nG: %d\nB: %d\nHEX: #%02X%02X%02X\n", r, g, b, r, g, b)
|
if len(args) == 3 || len(args) == 5 {
|
||||||
|
width, _ := strconv.Atoi(args[1])
|
||||||
|
height, _ := strconv.Atoi(args[2])
|
||||||
|
if len(args) == 5 {
|
||||||
|
startx, _ := strconv.Atoi(args[3])
|
||||||
|
starty, _ := strconv.Atoi(args[4])
|
||||||
|
writePPM(args[0], width, height, startx, starty)
|
||||||
|
} else {
|
||||||
|
writePPM(args[0], width, height, 0, 0)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
writePPM(args[0], 71, 40, 0, 0)
|
||||||
|
}
|
||||||
|
fmt.Println("Done")
|
||||||
|
} else if len(args) == 2 {
|
||||||
|
pxX, _ := strconv.Atoi(args[0])
|
||||||
|
pxY, _ := strconv.Atoi(args[1])
|
||||||
|
fmt.Println()
|
||||||
|
printPixel(pxX, pxY)
|
||||||
|
} else {
|
||||||
|
input := bufio.NewScanner(os.Stdin)
|
||||||
|
fmt.Print("Pixel x coordinate: ")
|
||||||
|
input.Scan()
|
||||||
|
pxX, _ := strconv.Atoi(input.Text())
|
||||||
|
fmt.Print("Pixel y coordinate: ")
|
||||||
|
input.Scan()
|
||||||
|
pxY, _ := strconv.Atoi(input.Text())
|
||||||
|
fmt.Println()
|
||||||
|
printPixel(pxX, pxY)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printPixel(x int, y int) {
|
||||||
|
val := hsv.NewValidator(true)
|
||||||
|
val.Calculate(x, y)
|
||||||
|
r, g, b := val.GetColor()
|
||||||
|
fmt.Printf("\nR: %d\nG: %d\nB: %d\nHEX: #%02X%02X%02X\n", r, g, b, r, g, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writePPM(path string, width int, height int, startx int, starty int) {
|
||||||
|
f, err := os.Create(path)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
bw := bufio.NewWriter(f)
|
||||||
|
bw.WriteString("P3\n")
|
||||||
|
bw.WriteString(fmt.Sprintf("%d %d\n", width, height))
|
||||||
|
bw.WriteString("255\n")
|
||||||
|
for y := startx; y < startx+height; y++ {
|
||||||
|
for x := starty; x < starty+width; x++ {
|
||||||
|
v := hsv.NewValidator(false)
|
||||||
|
v.Calculate(x, y)
|
||||||
|
r, g, b := v.GetColor()
|
||||||
|
bw.WriteString(fmt.Sprintf("%d %d %d ", r, g, b))
|
||||||
|
}
|
||||||
|
bw.WriteString("\n")
|
||||||
|
}
|
||||||
|
bw.Flush()
|
||||||
}
|
}
|
||||||
|
|
BIN
humanshader.png
Normal file
BIN
humanshader.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
|
@ -26,22 +26,20 @@ func (val *Validator) Calculate(x int, y int) {
|
||||||
val.print("h = %d² + %d² = %d + %d = %d", u, v, u*u, v*v, h)
|
val.print("h = %d² + %d² = %d + %d = %d", u, v, u*u, v*v, h)
|
||||||
if h < 200 {
|
if h < 200 {
|
||||||
val.print("⇒ h < 200 → %d < 200", h)
|
val.print("⇒ h < 200 → %d < 200", h)
|
||||||
val.print("=> Continuing to section B")
|
|
||||||
val.sectionB(u, v, h)
|
val.sectionB(u, v, h)
|
||||||
} else if v < 0 {
|
} else if v < 0 {
|
||||||
val.print("⇒ h < 200 → %d ≮ 200", h)
|
val.print("⇒ h < 200 → %d ≮ 200", h)
|
||||||
val.print("⇒ v < 0 → %d < 0", v)
|
val.print("⇒ v < 0 → %d < 0", v)
|
||||||
val.print("=> Continuing to section C")
|
|
||||||
val.sectionC(u, v, h)
|
val.sectionC(u, v, h)
|
||||||
} else {
|
} else {
|
||||||
val.print("⇒ h < 200 → %d ≮ 200", h)
|
val.print("⇒ h < 200 → %d ≮ 200", h)
|
||||||
val.print("⇒ v < 0 → %d ≮ 0", v)
|
val.print("⇒ v < 0 → %d ≮ 0", v)
|
||||||
val.print("=> Continuing to section D")
|
|
||||||
val.sectionD(x, y)
|
val.sectionD(x, y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (val *Validator) sectionB(u int, v int, h int) {
|
func (val *Validator) sectionB(u int, v int, h int) {
|
||||||
|
val.print("=> Continuing to section B")
|
||||||
val.r = 420
|
val.r = 420
|
||||||
val.print("R = %d", val.r)
|
val.print("R = %d", val.r)
|
||||||
val.b = 520
|
val.b = 520
|
||||||
|
@ -77,11 +75,11 @@ func (val *Validator) sectionB(u int, v int, h int) {
|
||||||
val.b = val.b + w
|
val.b = val.b + w
|
||||||
val.print(" B → B + %d ⇒ B = %d", w, val.b)
|
val.print(" B → B + %d ⇒ B = %d", w, val.b)
|
||||||
}
|
}
|
||||||
val.print("=> Continuing to section E")
|
|
||||||
val.sectionE()
|
val.sectionE()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (val *Validator) sectionC(u int, v int, h int) {
|
func (val *Validator) sectionC(u int, v int, h int) {
|
||||||
|
val.print("=> Continuing to section C")
|
||||||
val.r = 150 + 2*v
|
val.r = 150 + 2*v
|
||||||
val.print("R = 150 + 2 ⋅ %d = 150 + %d = %d", v, 2*v, val.r)
|
val.print("R = 150 + 2 ⋅ %d = 150 + %d = %d", v, 2*v, val.r)
|
||||||
val.b = 50
|
val.b = 50
|
||||||
|
@ -112,30 +110,38 @@ func (val *Validator) sectionC(u int, v int, h int) {
|
||||||
val.r = val.r + d
|
val.r = val.r + d
|
||||||
val.print(" R → R + %d ⇒ R = %d", d, val.r)
|
val.print(" R → R + %d ⇒ R = %d", d, val.r)
|
||||||
}
|
}
|
||||||
val.print("=> Continuing to section E")
|
|
||||||
val.sectionE()
|
val.sectionE()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (val *Validator) sectionD(x int, y int) {
|
func (val *Validator) sectionD(x int, y int) {
|
||||||
|
val.print("=> Continuing to section D")
|
||||||
var c int = x + 4*y
|
var c int = x + 4*y
|
||||||
val.print("c = %d + 4 ⋅ %d", x, y)
|
val.print("c = %d + 4 ⋅ %d", x, y)
|
||||||
val.r = 132 + c
|
val.r = 132 + c
|
||||||
val.print("R = 132 + %d = %d", c, val.r)
|
val.print("R = 132 + %d = %d", c, val.r)
|
||||||
val.b = 192 + c
|
val.b = 192 + c
|
||||||
val.print("R = 192 + %d = %d", c, val.b)
|
val.print("R = 192 + %d = %d", c, val.b)
|
||||||
val.print("=> Continuing to section E")
|
|
||||||
val.sectionE()
|
val.sectionE()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (val *Validator) sectionE() {
|
func (val *Validator) sectionE() {
|
||||||
|
val.print("=> Continuing to section E")
|
||||||
if val.r > 255 {
|
if val.r > 255 {
|
||||||
val.r = 255
|
val.r = 255
|
||||||
val.print("⇒ R > 255 → R = %d", val.r)
|
val.print("⇒ R > 255 → R = %d", val.r)
|
||||||
}
|
}
|
||||||
|
if val.r < 0 {
|
||||||
|
val.r = 0
|
||||||
|
val.print("⇒ R < 0 → R = %d", val.r)
|
||||||
|
}
|
||||||
if val.b > 255 {
|
if val.b > 255 {
|
||||||
val.b = 255
|
val.b = 255
|
||||||
val.print("⇒ B > 255 → B = %d", val.b)
|
val.print("⇒ B > 255 → B = %d", val.b)
|
||||||
}
|
}
|
||||||
|
if val.b < 0 {
|
||||||
|
val.b = 0
|
||||||
|
val.print("⇒ B < 0 → B = %d", val.b)
|
||||||
|
}
|
||||||
val.g = val.mod(7*val.r+3*val.b, 1)
|
val.g = val.mod(7*val.r+3*val.b, 1)
|
||||||
val.print("G = (7 + %d + 3 ⋅ %d) | 1 = (%d + %d) | 1 = %d | 1 = %d", val.r, val.b, 7+val.r, 3*val.b, 7*val.r+3*val.b, val.g)
|
val.print("G = (7 + %d + 3 ⋅ %d) | 1 = (%d + %d) | 1 = %d | 1 = %d", val.r, val.b, 7+val.r, 3*val.b, 7*val.r+3*val.b, val.g)
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue