From 7c0a465c8227d7fa442aa4a09894829e107dcbcc Mon Sep 17 00:00:00 2001 From: Chris Reddington <791642+chrisreddington@users.noreply.github.com> Date: Mon, 9 Dec 2024 09:10:46 +0000 Subject: [PATCH 1/4] Enhance text rendering with grayscale values Update text rendering to use grayscale values for embossing height. --- stl/geometry/text.go | 14 ++++++++------ stl/geometry/text_test.go | 15 +++++++++++++-- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/stl/geometry/text.go b/stl/geometry/text.go index 65e83d0..3e4b2a5 100644 --- a/stl/geometry/text.go +++ b/stl/geometry/text.go @@ -135,7 +135,8 @@ func renderText(config textRenderConfig) ([]types.Triangle, error) { for y := 0; y < config.contextHeight; y++ { for x := 0; x < config.contextWidth; x++ { - if isPixelActive(dc, x, y) { + intensity := isPixelActive(dc, x, y) + if intensity > 0 { xPos := config.startX + float64(x)*config.voxelScale/8 zPos := config.startZ - float64(y)*config.voxelScale/8 @@ -144,7 +145,7 @@ func renderText(config textRenderConfig) ([]types.Triangle, error) { config.startY, zPos, config.voxelScale/2, - config.depth, + config.depth*intensity, config.voxelScale/2, ) if err != nil { @@ -216,7 +217,8 @@ func renderImage(config imageRenderConfig) ([]types.Triangle, error) { for y := height - 1; y >= 0; y-- { for x := 0; x < width; x++ { r, _, _, a := img.At(x, y).RGBA() - if a > 32768 && r > 32768 { + intensity := float64(r) / 65535.0 + if a > 32768 && intensity > 0 { xPos := config.startX + float64(x)*config.voxelScale*scale zPos := config.startZ + float64(height-1-y)*config.voxelScale*scale @@ -225,7 +227,7 @@ func renderImage(config imageRenderConfig) ([]types.Triangle, error) { config.startY, zPos, config.voxelScale*scale, - config.depth, + config.depth*intensity, config.voxelScale*scale, ) @@ -242,7 +244,7 @@ func renderImage(config imageRenderConfig) ([]types.Triangle, error) { } // isPixelActive checks if a pixel is active (white) in the given context. -func isPixelActive(dc *gg.Context, x, y int) bool { +func isPixelActive(dc *gg.Context, x, y int) float64 { r, _, _, _ := dc.Image().At(x, y).RGBA() - return r > 32768 + return float64(r) / 65535.0 } diff --git a/stl/geometry/text_test.go b/stl/geometry/text_test.go index c1500a7..685c097 100644 --- a/stl/geometry/text_test.go +++ b/stl/geometry/text_test.go @@ -117,7 +117,7 @@ func TestIsPixelActive(t *testing.T) { dc.SetRGB(1, 1, 1) // White dc.Clear() - if !isPixelActive(dc, 0, 0) { + if isPixelActive(dc, 0, 0) <= 0 { t.Error("Expected white pixel to be active") } }) @@ -127,10 +127,21 @@ func TestIsPixelActive(t *testing.T) { dc.SetRGB(0, 0, 0) // Black dc.Clear() - if isPixelActive(dc, 0, 0) { + if isPixelActive(dc, 0, 0) > 0 { t.Error("Expected black pixel to be inactive") } }) + + t.Run("verify grayscale pixel detection", func(t *testing.T) { + dc := gg.NewContext(1, 1) + dc.SetRGB(0.5, 0.5, 0.5) // Gray + dc.Clear() + + intensity := isPixelActive(dc, 0, 0) + if intensity <= 0 || intensity >= 1 { + t.Errorf("Expected grayscale pixel to have intensity between 0 and 1, got %f", intensity) + } + }) } // createTestPNG creates a temporary PNG file for testing From 5f03efb029d9c4aaee903ddb8743a6beeabe15ca Mon Sep 17 00:00:00 2001 From: Chris Reddington <791642+chrisreddington@users.noreply.github.com> Date: Mon, 9 Dec 2024 10:08:07 +0000 Subject: [PATCH 2/4] Refactor pixel intensity calculation and update related tests --- stl/geometry/text.go | 10 ++++--- stl/geometry/text_test.go | 60 ++++++++++++++++++++++++++++++++------- 2 files changed, 56 insertions(+), 14 deletions(-) diff --git a/stl/geometry/text.go b/stl/geometry/text.go index 3e4b2a5..4dc7db2 100644 --- a/stl/geometry/text.go +++ b/stl/geometry/text.go @@ -135,7 +135,7 @@ func renderText(config textRenderConfig) ([]types.Triangle, error) { for y := 0; y < config.contextHeight; y++ { for x := 0; x < config.contextWidth; x++ { - intensity := isPixelActive(dc, x, y) + intensity := calculatePixelIntensity(dc, x, y) if intensity > 0 { xPos := config.startX + float64(x)*config.voxelScale/8 zPos := config.startZ - float64(y)*config.voxelScale/8 @@ -243,8 +243,10 @@ func renderImage(config imageRenderConfig) ([]types.Triangle, error) { return triangles, nil } -// isPixelActive checks if a pixel is active (white) in the given context. -func isPixelActive(dc *gg.Context, x, y int) float64 { +// calculatePixelIntensity returns the intensity of a pixel at the given coordinates +// as a float64 value between 0.0 (black) and 1.0 (white). +func calculatePixelIntensity(dc *gg.Context, x, y int) float64 { r, _, _, _ := dc.Image().At(x, y).RGBA() - return float64(r) / 65535.0 + intensity := float64(r) / 65535.0 + return intensity } diff --git a/stl/geometry/text_test.go b/stl/geometry/text_test.go index 685c097..c65c591 100644 --- a/stl/geometry/text_test.go +++ b/stl/geometry/text_test.go @@ -110,38 +110,78 @@ func TestRenderImage(t *testing.T) { }) } -// TestIsPixelActive verifies pixel activity detection -func TestIsPixelActive(t *testing.T) { - t.Run("verify white pixel detection", func(t *testing.T) { +// TestCalculatePixelIntensity verifies pixel intensity calculation +func TestCalculatePixelIntensity(t *testing.T) { + t.Run("verify white pixel intensity", func(t *testing.T) { dc := gg.NewContext(1, 1) dc.SetRGB(1, 1, 1) // White dc.Clear() - if isPixelActive(dc, 0, 0) <= 0 { - t.Error("Expected white pixel to be active") + if calculatePixelIntensity(dc, 0, 0) <= 0 { + t.Error("Expected white pixel to have positive intensity") } }) - t.Run("verify black pixel detection", func(t *testing.T) { + t.Run("verify black pixel intensity", func(t *testing.T) { dc := gg.NewContext(1, 1) dc.SetRGB(0, 0, 0) // Black dc.Clear() - if isPixelActive(dc, 0, 0) > 0 { - t.Error("Expected black pixel to be inactive") + if calculatePixelIntensity(dc, 0, 0) > 0 { + t.Error("Expected black pixel to have zero intensity") } }) - t.Run("verify grayscale pixel detection", func(t *testing.T) { + t.Run("verify grayscale pixel intensity", func(t *testing.T) { dc := gg.NewContext(1, 1) dc.SetRGB(0.5, 0.5, 0.5) // Gray dc.Clear() - intensity := isPixelActive(dc, 0, 0) + intensity := calculatePixelIntensity(dc, 0, 0) if intensity <= 0 || intensity >= 1 { t.Errorf("Expected grayscale pixel to have intensity between 0 and 1, got %f", intensity) } }) + + t.Run("verify gradient circle intensity", func(t *testing.T) { + size := 100 + dc := gg.NewContext(size, size) + dc.SetRGB(0, 0, 0) + dc.Clear() + + // Draw a single circle with gradient + centerX, centerY := float64(size/2), float64(size/2) + radius := float64(size / 2) + + // Create radial gradient + gradient := gg.NewRadialGradient(centerX, centerY, 0, centerX, centerY, radius) + gradient.AddColorStop(0, color.White) + gradient.AddColorStop(1, color.Black) + + dc.SetFillStyle(gradient) + dc.DrawCircle(centerX, centerY, radius) + dc.Fill() + + // Test points at different distances from center + testPoints := []struct { + x, y int + minRange float64 + maxRange float64 + }{ + {size / 2, size / 2, 0.9, 1.0}, // Center (highest intensity) + {size / 4, size / 4, 0.3, 0.7}, // Quarter way (medium intensity) + {size - 1, size - 1, 0.0, 0.1}, // Corner (lowest intensity) + } + + for _, pt := range testPoints { + intensity := calculatePixelIntensity(dc, pt.x, pt.y) + t.Logf("Pixel at (%d,%d) has intensity %f", pt.x, pt.y, intensity) + if intensity < pt.minRange || intensity > pt.maxRange { + t.Errorf("Pixel at (%d,%d) has intensity %f, expected between %f and %f", + pt.x, pt.y, intensity, pt.minRange, pt.maxRange) + } + } + }) } // createTestPNG creates a temporary PNG file for testing From e0e664ca7ac4e24bef3ece94071c809e76956b1b Mon Sep 17 00:00:00 2001 From: Chris Reddington <791642+chrisreddington@users.noreply.github.com> Date: Mon, 9 Dec 2024 10:25:17 +0000 Subject: [PATCH 3/4] Refactor pixel intensity calculation to use grayscale conversion --- stl/geometry/text.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/stl/geometry/text.go b/stl/geometry/text.go index 4dc7db2..acd360c 100644 --- a/stl/geometry/text.go +++ b/stl/geometry/text.go @@ -246,7 +246,14 @@ func renderImage(config imageRenderConfig) ([]types.Triangle, error) { // calculatePixelIntensity returns the intensity of a pixel at the given coordinates // as a float64 value between 0.0 (black) and 1.0 (white). func calculatePixelIntensity(dc *gg.Context, x, y int) float64 { - r, _, _, _ := dc.Image().At(x, y).RGBA() - intensity := float64(r) / 65535.0 + // Get RGB values from pixel + r, g, b, _ := dc.Image().At(x, y).RGBA() + + // Convert to grayscale + gray := 0.299*float64(r) + 0.587*float64(g) + 0.114*float64(b) + + // Normalize to 0-1 range (RGBA values are in 0-65535 range) + intensity := gray / 65535.0 + return intensity } From 45c9da2d7a7aaeb844ba44e36f27d8e18c084731 Mon Sep 17 00:00:00 2001 From: Chris Reddington <791642+chrisreddington@users.noreply.github.com> Date: Mon, 9 Dec 2024 10:35:35 +0000 Subject: [PATCH 4/4] Add comment to re-trigger workflow for CodeQL check --- stl/geometry/text_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/stl/geometry/text_test.go b/stl/geometry/text_test.go index c65c591..598cd97 100644 --- a/stl/geometry/text_test.go +++ b/stl/geometry/text_test.go @@ -144,6 +144,7 @@ func TestCalculatePixelIntensity(t *testing.T) { }) t.Run("verify gradient circle intensity", func(t *testing.T) { + // Create a 100x100 image with a radial gradient circle size := 100 dc := gg.NewContext(size, size) dc.SetRGB(0, 0, 0)