alpha patterns

This commit is contained in:
Dmitry Sergeev
2026-09-18 10:11:07 +03:00
parent 9b194b5591
commit dea2e6a59f
12 changed files with 643 additions and 3 deletions
+92
View File
@@ -0,0 +1,92 @@
package generator
import (
"encoding/binary"
"fmt"
"math"
)
const (
alphaTransparent uint32 = 64
alphaOpaque uint32 = 940
)
func packAlphaBlock(dst []byte, samples [3]uint32) {
const mask uint32 = 0x3ff
word := samples[0]&mask |
(samples[1]&mask)<<10 |
(samples[2]&mask)<<20
binary.LittleEndian.PutUint32(dst, word)
}
func fillAlphaPlane(
dst []byte,
width, height int,
value uint32,
) error {
need := AlphaFrameSize(width, height)
if len(dst) < need {
return fmt.Errorf(
"alpha: destination is too small: got %d bytes, need %d",
len(dst),
need,
)
}
stride := AlphaLineSize(width)
for y := 0; y < height; y++ {
row := dst[y*stride : (y+1)*stride]
for x := 0; x < width; x += 3 {
var samples [3]uint32
for i := range samples {
if x+i < width {
samples[i] = value
}
}
packAlphaBlock(row[x/3*4:], samples)
}
}
return nil
}
func patchAlphaMovingSquare(dst []byte, width, height, frameIndex int) error {
need := AlphaFrameSize(width, height)
if len(dst) < need {
return fmt.Errorf(
"alpha: destination is too small: got %d bytes, need %d",
len(dst),
need,
)
}
bounds := movingSquareBounds(width, height, frameIndex)
firstPixelX := max(0, int(math.Floor(bounds.minX)))
lastPixelX := min(width, int(math.Ceil(bounds.maxX)))
firstBlockX := firstPixelX / 3 * 3
lastBlockX := min(width, (lastPixelX+2)/3*3)
firstY := max(0, int(math.Floor(bounds.minY)))
lastY := min(height, int(math.Ceil(bounds.maxY)))
stride := AlphaLineSize(width)
for y := firstY; y < lastY; y++ {
for blockX := firstBlockX; blockX < lastBlockX; blockX += 3 {
var samples [3]uint32
for i := range samples {
x := blockX + i
switch {
case x >= width:
samples[i] = 0
case bounds.contains(x, y):
samples[i] = alphaTransparent
default:
samples[i] = alphaOpaque
}
}
offset := y*stride + blockX/3*4
packAlphaBlock(dst[offset:], samples)
}
}
return nil
}