From 4e0801eb9bc895c9523a7a36bfb9a17b667cdfed Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 19 Jul 2023 23:00:00 +0200 Subject: [PATCH] Add image, Support writing PPM P3 image, Additional checks --- .gitignore | 3 +- README.md | 4 +- hsv.go | 82 +++++++++++++++++++++++++++++++---------- humanshader.png | Bin 0 -> 4337 bytes validator/validator.go | 18 ++++++--- 5 files changed, 80 insertions(+), 27 deletions(-) create mode 100644 humanshader.png diff --git a/.gitignore b/.gitignore index 3f643a0..24ee698 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -/humanshader \ No newline at end of file +/humanshader +*.ppm diff --git a/README.md b/README.md index 70a1d25..9c3dfc7 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ # Human Shader Validator -Validator for [Human Shader](https://humanshader.com/) \ No newline at end of file +Validator for [Human Shader](https://humanshader.com/) + +![Final image of Human Shader](humanshader.png) \ No newline at end of file diff --git a/hsv.go b/hsv.go index 6658283..aeeb926 100644 --- a/hsv.go +++ b/hsv.go @@ -10,24 +10,68 @@ import ( func main() { 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) - val.Calculate(pxX, pxY) - r, g, b := val.GetColor() - fmt.Printf("R: %d\nG: %d\nB: %d\nHEX: #%02X%02X%02X\n", r, g, b, r, g, b) + // TODO: Better argument parsing + if len(args) == 1 || len(args) == 3 || len(args) == 5 { + fmt.Printf("Writing PPM image to %s.\n", args[0]) + 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() } diff --git a/humanshader.png b/humanshader.png new file mode 100644 index 0000000000000000000000000000000000000000..9c4bbc37a0d4c6558390de0b0490c5a14ceba16e GIT binary patch literal 4337 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 literal 0 HcmV?d00001 diff --git a/validator/validator.go b/validator/validator.go index f55b00c..fd55acb 100644 --- a/validator/validator.go +++ b/validator/validator.go @@ -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) if h < 200 { val.print("⇒ h < 200 → %d < 200", h) - val.print("=> Continuing to section B") val.sectionB(u, v, h) } else if v < 0 { val.print("⇒ h < 200 → %d ≮ 200", h) val.print("⇒ v < 0 → %d < 0", v) - val.print("=> Continuing to section C") val.sectionC(u, v, h) } else { val.print("⇒ h < 200 → %d ≮ 200", h) val.print("⇒ v < 0 → %d ≮ 0", v) - val.print("=> Continuing to section D") val.sectionD(x, y) } } func (val *Validator) sectionB(u int, v int, h int) { + val.print("=> Continuing to section B") val.r = 420 val.print("R = %d", val.r) val.b = 520 @@ -77,11 +75,11 @@ func (val *Validator) sectionB(u int, v int, h int) { val.b = val.b + w val.print(" B → B + %d ⇒ B = %d", w, val.b) } - val.print("=> Continuing to section E") val.sectionE() } func (val *Validator) sectionC(u int, v int, h int) { + val.print("=> Continuing to section C") val.r = 150 + 2*v val.print("R = 150 + 2 ⋅ %d = 150 + %d = %d", v, 2*v, val.r) val.b = 50 @@ -112,30 +110,38 @@ func (val *Validator) sectionC(u int, v int, h int) { val.r = val.r + d val.print(" R → R + %d ⇒ R = %d", d, val.r) } - val.print("=> Continuing to section E") val.sectionE() } func (val *Validator) sectionD(x int, y int) { + val.print("=> Continuing to section D") var c int = x + 4*y val.print("c = %d + 4 ⋅ %d", x, y) val.r = 132 + c val.print("R = 132 + %d = %d", c, val.r) val.b = 192 + c val.print("R = 192 + %d = %d", c, val.b) - val.print("=> Continuing to section E") val.sectionE() } func (val *Validator) sectionE() { + val.print("=> Continuing to section E") if val.r > 255 { val.r = 255 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 { val.b = 255 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.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) }