Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor isPixelActive into calculatePixelIntensity #27

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions stl/geometry/text.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 := calculatePixelIntensity(dc, x, y)
if intensity > 0 {
xPos := config.startX + float64(x)*config.voxelScale/8
zPos := config.startZ - float64(y)*config.voxelScale/8

Expand All @@ -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 {
Expand Down Expand Up @@ -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

Expand All @@ -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,
)

Expand All @@ -241,8 +243,17 @@ 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) bool {
r, _, _, _ := dc.Image().At(x, y).RGBA()
return r > 32768
// 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 {
// 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
}
68 changes: 60 additions & 8 deletions stl/geometry/text_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,25 +110,77 @@ 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) {
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) {
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 intensity", func(t *testing.T) {
dc := gg.NewContext(1, 1)
dc.SetRGB(0.5, 0.5, 0.5) // Gray
dc.Clear()

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) {
// Create a 100x100 image with a radial gradient circle
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)
}
}
})
}
Expand Down
Loading