Skip to content

Commit 61174f6

Browse files
authored
fix(avatar): correct grid rendering for odd sizes and eliminate extra margins (#13)
This PR resolves **Issue #12** which affects avatar rendering when using high or odd `gridSize` values. ### Problem - For odd `gridSize` values (e.g., 9), the center column is skipped during mirroring, causing asymmetry. - For larger even grid sizes (e.g., 10), there's a small margin or padding on the right and bottom of the image. ## What’s Changed - Added support for drawing the center column when `gridSize` is odd - Improved `drawPixel` logic to clamp within image bounds - Ensured the avatar fills the image completely without leaving empty margins
1 parent a106a48 commit 61174f6

File tree

5 files changed

+38
-14
lines changed

5 files changed

+38
-14
lines changed

arts/avatar_2.png

-352 Bytes
Loading

arts/avatar_3.png

-45 Bytes
Loading

arts/avatar_6.png

1.63 KB
Loading

example/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ func main() {
5050
var opts []goavatar.OptFunc
5151

5252
// add size
53-
opts = append(opts, goavatar.WithSize(100))
54-
opts = append(opts, goavatar.WithGridSize(10))
53+
opts = append(opts, goavatar.WithSize(500))
54+
opts = append(opts, goavatar.WithGridSize(13))
5555
image6 := goavatar.Make("nice__user__name", opts...)
5656

5757
// append all the images into the list

goavatar.go

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/hex"
66
"image"
77
"image/color"
8+
"math"
89
)
910

1011
// option contains the configuration for the avatar generator.
@@ -68,11 +69,26 @@ func generateHash(data string) string {
6869
return hex.EncodeToString(hash[:])
6970
}
7071

71-
// drawPixel draws a single pixel and enlarge each pixle into 20x20 block.
72-
func drawPixel(img *image.RGBA, x, y int, c color.Color, pixelW, pixelH int) {
73-
for dx := 0; dx < pixelW; dx++ {
74-
for dy := 0; dy < pixelH; dy++ {
75-
img.Set(x*pixelW+dx, y*pixelH+dy, c)
72+
// drawPixel draws a single pixel block based on proportional scaling to avoid gaps.
73+
func drawPixel(img *image.RGBA, gridX, gridY int, c color.Color, gridSize, imageSize int) {
74+
// Calculate exact scaled bounds
75+
startX := int(math.Round(float64(gridX) * float64(imageSize) / float64(gridSize)))
76+
startY := int(math.Round(float64(gridY) * float64(imageSize) / float64(gridSize)))
77+
endX := int(math.Round(float64(gridX+1) * float64(imageSize) / float64(gridSize)))
78+
endY := int(math.Round(float64(gridY+1) * float64(imageSize) / float64(gridSize)))
79+
80+
// Clamp to image size to avoid out-of-bounds
81+
if endX > img.Bounds().Dx() {
82+
endX = img.Bounds().Dx()
83+
}
84+
if endY > img.Bounds().Dy() {
85+
endY = img.Bounds().Dy()
86+
}
87+
88+
// Fill the block
89+
for y := startY; y < endY; y++ {
90+
for x := startX; x < endX; x++ {
91+
img.Set(x, y, c)
7692
}
7793
}
7894
}
@@ -90,12 +106,10 @@ func Make(input string, opts ...OptFunc) image.Image {
90106
// create a blank image
91107
img := image.NewRGBA(image.Rect(0, 0, o.size, o.size))
92108

93-
pixelSizeX := o.size / o.gridSize // each grid cell width
94-
pixelSizeY := o.size / o.gridSize // each grid cell height
95-
96109
// generate colors
97110
avatarColor := o.fgColor
98111
bgColor := o.bgColor
112+
isOdd := o.gridSize%2 != 0
99113

100114
// generate the pixel pattern
101115
// loop over each pixel in the grid
@@ -106,14 +120,24 @@ func Make(input string, opts ...OptFunc) image.Image {
106120

107121
// image should
108122
if pixelOn {
109-
drawPixel(img, x, y, avatarColor, pixelSizeX, pixelSizeY)
110-
drawPixel(img, o.gridSize-1-x, y, avatarColor, pixelSizeX, pixelSizeY) // mirror the pixel
123+
drawPixel(img, x, y, avatarColor, o.gridSize, o.size)
124+
drawPixel(img, o.gridSize-1-x, y, avatarColor, o.gridSize, o.size) // mirror the pixel
111125
} else {
112-
drawPixel(img, x, y, bgColor, pixelSizeX, pixelSizeY)
113-
drawPixel(img, o.gridSize-1-x, y, bgColor, pixelSizeX, pixelSizeY) // mirror the bg pixel
126+
drawPixel(img, x, y, bgColor, o.gridSize, o.size)
127+
drawPixel(img, o.gridSize-1-x, y, bgColor, o.gridSize, o.size) // mirror the bg pixel
114128
}
115129

116130
}
131+
// Draw the center column if gridSize is odd
132+
if isOdd {
133+
mid := o.gridSize / 2
134+
pixelOn := (hash[y]>>(mid%8))&1 == 1
135+
color := bgColor
136+
if pixelOn {
137+
color = avatarColor
138+
}
139+
drawPixel(img, mid, y, color, o.gridSize, o.size)
140+
}
117141
}
118142

119143
return img

0 commit comments

Comments
 (0)