75 lines
1.7 KiB
Go
75 lines
1.7 KiB
Go
package generator
|
|
|
|
import "math"
|
|
|
|
const movingSquareSize = 150
|
|
|
|
type baseColorFunc func(x, y, width, height int) YCbCr10
|
|
|
|
type squareBounds struct {
|
|
minX float64
|
|
maxX float64
|
|
minY float64
|
|
maxY float64
|
|
}
|
|
|
|
func movingSquareBounds(width, height, frameIndex int) squareBounds {
|
|
const half = float64(movingSquareSize) / 2
|
|
centerX := float64(width) / 2
|
|
centerY := float64(height) / 2
|
|
time := float64(frameIndex) / 25.0
|
|
offset := math.Sin(time*0.5) * (centerX - half)
|
|
return squareBounds{
|
|
minX: centerX - half + offset,
|
|
maxX: centerX + half + offset,
|
|
minY: centerY - half,
|
|
maxY: centerY + half,
|
|
}
|
|
}
|
|
|
|
func (b squareBounds) contains(x, y int) bool {
|
|
return float64(x) >= b.minX && float64(x) < b.maxX &&
|
|
float64(y) >= b.minY && float64(y) < b.maxY
|
|
}
|
|
|
|
func patchMovingSquare(
|
|
dst []byte,
|
|
width, height, frameIndex int,
|
|
baseColor baseColorFunc,
|
|
) error {
|
|
bounds := movingSquareBounds(width, height, frameIndex)
|
|
|
|
firstPixelX := max(0, int(math.Floor(bounds.minX)))
|
|
lastPixelX := min(width, int(math.Ceil(bounds.maxX)))
|
|
firstBlockX := firstPixelX / 6 * 6
|
|
lastBlockX := min(width, (lastPixelX+5)/6*6)
|
|
firstY := max(0, int(math.Floor(bounds.minY)))
|
|
lastY := min(height, int(math.Ceil(bounds.maxY)))
|
|
stride := V210LineSize(width)
|
|
|
|
for y := firstY; y < lastY; y++ {
|
|
for x := firstBlockX; x < lastBlockX; x += 6 {
|
|
var pixels [6]YCbCr10
|
|
for i := range pixels {
|
|
px := x + i
|
|
color := baseColor(px, y, width, height)
|
|
if bounds.contains(px, y) {
|
|
color = invertStudioRange(color)
|
|
}
|
|
pixels[i] = color
|
|
}
|
|
offset := y*stride + x/6*16
|
|
packV210Block(dst[offset:offset+16], pixels)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func invertStudioRange(color YCbCr10) YCbCr10 {
|
|
return YCbCr10{
|
|
Y: 1004 - color.Y,
|
|
Cb: 1024 - color.Cb,
|
|
Cr: 1024 - color.Cr,
|
|
}
|
|
}
|