114 lines
3.4 KiB
Go
114 lines
3.4 KiB
Go
|
|
package skin_renderer
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"image"
|
|||
|
|
"image/color"
|
|||
|
|
"image/draw"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// Minecraft 提供 Minecraft 皮肤渲染的入口方法
|
|||
|
|
// 与 blessing/texture-renderer 的 Minecraft 类保持兼容
|
|||
|
|
type Minecraft struct{}
|
|||
|
|
|
|||
|
|
// NewMinecraft 创建 Minecraft 渲染器实例
|
|||
|
|
func NewMinecraft() *Minecraft {
|
|||
|
|
return &Minecraft{}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// RenderSkin 渲染完整皮肤预览(正面+背面)
|
|||
|
|
// ratio: 缩放比例,默认 7.0
|
|||
|
|
// isAlex: 是否为 Alex 模型(细手臂)
|
|||
|
|
func (m *Minecraft) RenderSkin(skinData []byte, ratio float64, isAlex bool) (image.Image, error) {
|
|||
|
|
vp := 15 // vertical padding
|
|||
|
|
hp := 30 // horizontal padding
|
|||
|
|
ip := 15 // internal padding
|
|||
|
|
|
|||
|
|
// 渲染正面(-45度)
|
|||
|
|
frontRenderer := NewSkinRenderer(ratio, false, -45, -25)
|
|||
|
|
front, err := frontRenderer.Render(skinData, isAlex)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 渲染背面(135度)
|
|||
|
|
backRenderer := NewSkinRenderer(ratio, false, 135, -25)
|
|||
|
|
back, err := backRenderer.Render(skinData, isAlex)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
width := front.Bounds().Dx()
|
|||
|
|
height := front.Bounds().Dy()
|
|||
|
|
|
|||
|
|
// 创建画布
|
|||
|
|
canvas := createEmptyCanvas((hp+width+ip)*2, vp*2+height)
|
|||
|
|
|
|||
|
|
// 绘制背面(左侧)
|
|||
|
|
draw.Draw(canvas, image.Rect(hp, vp, hp+width, vp+height), back, back.Bounds().Min, draw.Over)
|
|||
|
|
|
|||
|
|
// 绘制正面(右侧)
|
|||
|
|
draw.Draw(canvas, image.Rect(hp+width+ip*2, vp, hp+width*2+ip*2, vp+height), front, front.Bounds().Min, draw.Over)
|
|||
|
|
|
|||
|
|
return canvas, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// RenderCape 渲染披风
|
|||
|
|
// height: 输出高度
|
|||
|
|
func (m *Minecraft) RenderCape(capeData []byte, height int) (image.Image, error) {
|
|||
|
|
vp := 20 // vertical padding
|
|||
|
|
hp := 40 // horizontal padding
|
|||
|
|
|
|||
|
|
renderer := NewCapeRenderer()
|
|||
|
|
cape, err := renderer.Render(capeData, height)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
width := cape.Bounds().Dx()
|
|||
|
|
capeHeight := cape.Bounds().Dy()
|
|||
|
|
|
|||
|
|
canvas := createEmptyCanvas(hp*2+width, vp*2+capeHeight)
|
|||
|
|
draw.Draw(canvas, image.Rect(hp, vp, hp+width, vp+capeHeight), cape, cape.Bounds().Min, draw.Over)
|
|||
|
|
|
|||
|
|
return canvas, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Render2DAvatar 渲染 2D 头像
|
|||
|
|
// ratio: 缩放比例,默认 15.0
|
|||
|
|
func (m *Minecraft) Render2DAvatar(skinData []byte, ratio float64) (image.Image, error) {
|
|||
|
|
renderer := NewSkinRendererFull(ratio, true, 0, 0, 0, 0, 0, 0, 0, true)
|
|||
|
|
return renderer.Render(skinData, false)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Render3DAvatar 渲染 3D 头像
|
|||
|
|
// ratio: 缩放比例,默认 15.0
|
|||
|
|
func (m *Minecraft) Render3DAvatar(skinData []byte, ratio float64) (image.Image, error) {
|
|||
|
|
renderer := NewSkinRenderer(ratio, true, 45, -25)
|
|||
|
|
return renderer.Render(skinData, false)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// RenderSkinWithAngle 渲染指定角度的皮肤
|
|||
|
|
func (m *Minecraft) RenderSkinWithAngle(skinData []byte, ratio float64, isAlex bool, hRotation, vRotation float64) (image.Image, error) {
|
|||
|
|
renderer := NewSkinRenderer(ratio, false, hRotation, vRotation)
|
|||
|
|
return renderer.Render(skinData, isAlex)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// RenderHeadWithAngle 渲染指定角度的头像
|
|||
|
|
func (m *Minecraft) RenderHeadWithAngle(skinData []byte, ratio float64, hRotation, vRotation float64) (image.Image, error) {
|
|||
|
|
renderer := NewSkinRenderer(ratio, true, hRotation, vRotation)
|
|||
|
|
return renderer.Render(skinData, false)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// createEmptyCanvas 创建透明画布
|
|||
|
|
func createEmptyCanvas(width, height int) *image.RGBA {
|
|||
|
|
img := image.NewRGBA(image.Rect(0, 0, width, height))
|
|||
|
|
// 填充透明背景
|
|||
|
|
transparent := color.RGBA{0, 0, 0, 0}
|
|||
|
|
for y := 0; y < height; y++ {
|
|||
|
|
for x := 0; x < width; x++ {
|
|||
|
|
img.SetRGBA(x, y, transparent)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return img
|
|||
|
|
}
|