alpha patterns
This commit is contained in:
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user