here u go
This commit is contained in:
parent
4057b3c3c6
commit
0f5e1f4c0a
|
@ -6,6 +6,7 @@ import (
|
|||
"image/draw"
|
||||
|
||||
"git.tuxpa.in/a/zlog/log"
|
||||
"github.com/phrozen/blend"
|
||||
"gitlab.com/gfxlabs/gfximg/apng"
|
||||
)
|
||||
|
||||
|
@ -30,54 +31,89 @@ func (n *Nori) ExportAnimation() (*apng.APNG, error) {
|
|||
a := &apng.APNG{
|
||||
Frames: make([]apng.Frame, 0, len(g.Images)),
|
||||
}
|
||||
images := make([]*image.NRGBA64, 0, len(n.Animations))
|
||||
for i := 0; i < len(n.Animations); i++ {
|
||||
for _, v := range n.Animations[i].Frames {
|
||||
canvasRect := image.Rect(0, 0, 0, 0)
|
||||
for _, plane := range v.Planes {
|
||||
if int(plane.BitmapId) >= len(n.Gawi.Images) {
|
||||
log.Printf("could not find bitmap %d, only have %d", plane.BitmapId, len(n.Gawi.Images))
|
||||
}
|
||||
bitmap := n.Gawi.Images[plane.BitmapId]
|
||||
canvasRect = canvasRect.Union(bitmap.Img.Bounds())
|
||||
}
|
||||
img := image.NewRGBA64(canvasRect)
|
||||
for _, plane := range v.Planes {
|
||||
bitmap := n.Gawi.Images[plane.BitmapId]
|
||||
transparent := false
|
||||
//flipx
|
||||
if plane.RenderFlag&1 != 0 {
|
||||
}
|
||||
//flipy
|
||||
if plane.RenderFlag&2 != 0 {
|
||||
}
|
||||
// is transparent
|
||||
if plane.RenderFlag&0x20 != 0 {
|
||||
transparent = true
|
||||
}
|
||||
_ = transparent
|
||||
switch plane.Blend {
|
||||
case BlendMode_Alpha:
|
||||
case BlendMode_Mul, BlendMode_Mul7:
|
||||
case BlendMode_Add, BlendMode_Add8:
|
||||
case BlendMode_InvertMul, BlendMode_InvertMul5:
|
||||
case BlendMode_None:
|
||||
break
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown blend mode: %d", plane.Blend)
|
||||
}
|
||||
draw.Draw(img,
|
||||
img.Rect,
|
||||
bitmap.Img,
|
||||
image.Point{X: int(plane.PlaneX),
|
||||
Y: int(plane.PlaneY)}, draw.Over)
|
||||
}
|
||||
fr := apng.Frame{
|
||||
Image: g.Images[i].Img,
|
||||
DelayNumerator: uint16(g.Images[i].Delay),
|
||||
DelayDenominator: 1000,
|
||||
}
|
||||
a.Frames = append(a.Frames, fr)
|
||||
if len(n.Animations[i].Frames) < 1 {
|
||||
continue
|
||||
}
|
||||
planes := n.Animations[i].Frames[0].Planes
|
||||
var canvasRect image.Rectangle
|
||||
for _, plane := range planes {
|
||||
if int(plane.BitmapId) >= len(n.Gawi.Images) {
|
||||
log.Printf("could not find bitmap %d, only have %d", plane.BitmapId, len(n.Gawi.Images))
|
||||
}
|
||||
bitmap := n.Gawi.Images[plane.BitmapId]
|
||||
pt := image.Pt(int(plane.PlaneX), int(plane.PlaneY)) // where to put the point
|
||||
rc := bitmap.Img.Bounds()
|
||||
canvasRect = canvasRect.Union(rc.Add(pt))
|
||||
}
|
||||
img := image.NewNRGBA64(canvasRect)
|
||||
for _, plane := range planes {
|
||||
bitmap := n.Gawi.Images[plane.BitmapId]
|
||||
transparent := false
|
||||
//flipx
|
||||
if plane.RenderFlag&1 != 0 {
|
||||
}
|
||||
//flipy
|
||||
if plane.RenderFlag&2 != 0 {
|
||||
}
|
||||
// is transparent
|
||||
if plane.RenderFlag&0x20 != 0 {
|
||||
transparent = true
|
||||
}
|
||||
_ = transparent
|
||||
pt := image.Pt(int(plane.PlaneX), int(plane.PlaneY)) // where to put the point
|
||||
src := bitmap.Img
|
||||
sr := src.Bounds()
|
||||
r := image.Rectangle{pt, pt.Add(sr.Size())}
|
||||
switch plane.Blend {
|
||||
case BlendMode_Alpha:
|
||||
case BlendMode_Mul, BlendMode_Mul7:
|
||||
blend.BlendImage(img, bitmap.Img, blend.Multiply)
|
||||
case BlendMode_Add, BlendMode_Add8:
|
||||
blend.BlendImage(img, bitmap.Img, blend.Add)
|
||||
case BlendMode_InvertMul, BlendMode_InvertMul5:
|
||||
blend.BlendImage(img, bitmap.Img, blend.Multiply)
|
||||
case BlendMode_None:
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown blend mode: %d", plane.Blend)
|
||||
}
|
||||
draw.Draw(img,
|
||||
r,
|
||||
src,
|
||||
sr.Min,
|
||||
draw.Over,
|
||||
)
|
||||
}
|
||||
if len(planes) > 0 {
|
||||
images = append(images, img)
|
||||
|
||||
}
|
||||
}
|
||||
or := images[0].Bounds()
|
||||
for _, realFrame := range images {
|
||||
or = realFrame.Bounds().Union(or)
|
||||
}
|
||||
// TODO: this is bugged
|
||||
for i, realFrame := range images {
|
||||
big := image.NewNRGBA64(or)
|
||||
draw.Draw(
|
||||
big,
|
||||
big.Rect,
|
||||
realFrame,
|
||||
realFrame.Bounds().Min,
|
||||
draw.Src,
|
||||
)
|
||||
fr := apng.Frame{
|
||||
Image: big,
|
||||
DisposeOp: apng.DISPOSE_OP_PREVIOUS,
|
||||
BlendOp: apng.BLEND_OP_OVER,
|
||||
DelayDenominator: 1000,
|
||||
}
|
||||
if g.Images[i].Delay != 0 {
|
||||
fr.DelayNumerator = uint16(g.Images[i].Delay)
|
||||
}
|
||||
a.Frames = append(a.Frames, fr)
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
|
|
|
@ -51,11 +51,13 @@ func (i *Image) Decode(rd *bufio.Reader, palette *PaletteSection) error {
|
|||
red := uint8(((0x7c00 & bgr) >> 10) * 255 / 31)
|
||||
green := uint8(((0x3e0 & bgr) >> 5) * 255 / 31)
|
||||
blue := uint8((0x1f & bgr) * 255 / 31)
|
||||
if red != 0 && blue != 0 && green != 0 {
|
||||
alpha := uint8(0xff)
|
||||
if red == 0xff && blue == 0xff {
|
||||
alpha = 0x00
|
||||
}
|
||||
col := &color.RGBA{
|
||||
red, green, blue,
|
||||
0xff,
|
||||
alpha,
|
||||
}
|
||||
cf.Set(idx%int(i.Width), idx/int(i.Width), col)
|
||||
}
|
||||
|
@ -68,9 +70,13 @@ func (i *Image) Decode(rd *bufio.Reader, palette *PaletteSection) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
alpha := uint8(0xff)
|
||||
col := &color.RGBA{
|
||||
rgb[0], rgb[1], rgb[2],
|
||||
0xff,
|
||||
alpha,
|
||||
}
|
||||
if rgb[0] == 0xff && rgb[2] == 0xff {
|
||||
alpha = 0x00
|
||||
}
|
||||
cf.Set(idx%int(i.Width), idx/int(i.Width), col)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"os"
|
||||
"testing"
|
||||
|
||||
"git.tuxpa.in/a/zlog/log"
|
||||
"gitlab.com/gfxlabs/gfximg/apng"
|
||||
)
|
||||
|
||||
|
@ -59,14 +58,21 @@ func TestParsePalette(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Errorf("export: %s", err)
|
||||
}
|
||||
writeApng(a, "./nori_test/palette.apng")
|
||||
err = writeApng(a, "./nori_test/palette.apng")
|
||||
if err != nil {
|
||||
t.Errorf("export: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func writeApng(a *apng.APNG, fp string) {
|
||||
func writeApng(a *apng.APNG, fp string) error {
|
||||
out := new(bytes.Buffer)
|
||||
err := apng.Encode(out, *a)
|
||||
if err != nil {
|
||||
log.Errorf("fail to encode apng %s", err)
|
||||
return err
|
||||
}
|
||||
os.WriteFile(fp, out.Bytes(), 0740)
|
||||
err = os.WriteFile(fp, out.Bytes(), 0740)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 577 KiB |
Binary file not shown.
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 56 KiB |
Binary file not shown.
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 60 KiB |
1
go.mod
1
go.mod
|
@ -10,5 +10,6 @@ require (
|
|||
require (
|
||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/phrozen/blend v0.0.0-20210220204729-f26b6cf7a28e // indirect
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect
|
||||
)
|
||||
|
|
2
go.sum
2
go.sum
|
@ -6,6 +6,8 @@ github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZb
|
|||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/phrozen/blend v0.0.0-20210220204729-f26b6cf7a28e h1:r8tWFp1HMiodzOwFtEVZ41Q0PuX/G5PWHZS14kAQMoI=
|
||||
github.com/phrozen/blend v0.0.0-20210220204729-f26b6cf7a28e/go.mod h1:8LjAsvtcQgvNmMQZ/iSuduOKYgRA37KcsgPg8ZC6Krc=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
gitlab.com/gfxlabs/gfximg v0.0.5 h1:jtHE6In6axz0zGPy7YnLIZV9RFdcFEZzpdqoXb52K9s=
|
||||
|
|
Loading…
Reference in New Issue