support subimages and compressed
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 7.0 KiB |
After Width: | Height: | Size: 7.8 KiB |
After Width: | Height: | Size: 7.4 KiB |
After Width: | Height: | Size: 7.8 KiB |
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 6.2 KiB |
After Width: | Height: | Size: 8.7 KiB |
After Width: | Height: | Size: 8.8 KiB |
After Width: | Height: | Size: 6.1 KiB |
After Width: | Height: | Size: 7.0 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 53 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 54 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 7.8 KiB |
After Width: | Height: | Size: 7.8 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 7.8 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 7.8 KiB |
After Width: | Height: | Size: 7.8 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 7.8 KiB |
After Width: | Height: | Size: 7.8 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 7.4 KiB |
After Width: | Height: | Size: 7.8 KiB |
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 5.8 KiB |
|
@ -4,11 +4,12 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"git.tuxpa.in/a/nori/renderer"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.tuxpa.in/a/nori/renderer"
|
||||||
|
|
||||||
"git.tuxpa.in/a/nori"
|
"git.tuxpa.in/a/nori"
|
||||||
"git.tuxpa.in/a/nori/utils"
|
"git.tuxpa.in/a/nori/utils"
|
||||||
"git.tuxpa.in/a/zlog/log"
|
"git.tuxpa.in/a/zlog/log"
|
||||||
|
@ -54,7 +55,7 @@ func dump(filename string, output string) {
|
||||||
printIf("reading file '%s'\n", filename)
|
printIf("reading file '%s'\n", filename)
|
||||||
n, err := nori.FromFile(filename)
|
n, err := nori.FromFile(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicln("decode: %s", err)
|
log.Panicf("decode: %s", err)
|
||||||
}
|
}
|
||||||
out := new(bytes.Buffer)
|
out := new(bytes.Buffer)
|
||||||
printIf("rendering %d animation(s)\n", n.AnimationCount)
|
printIf("rendering %d animation(s)\n", n.AnimationCount)
|
|
@ -1,7 +1,6 @@
|
||||||
package nori
|
package nori
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
@ -16,7 +15,7 @@ func FromFile(fp string) (*Nori, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
return Decode(bufio.NewReader(file))
|
return Decode(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Decode(r io.Reader) (*Nori, error) {
|
func Decode(r io.Reader) (*Nori, error) {
|
||||||
|
|
2
gawi.go
|
@ -77,7 +77,7 @@ func (g *GawiSection) Decode(rd io.Reader) error {
|
||||||
g.Images = make([]*Image, int(g.BmpCount))
|
g.Images = make([]*Image, int(g.BmpCount))
|
||||||
for i := range g.Images {
|
for i := range g.Images {
|
||||||
g.Images[i] = &Image{Bpp: g.Bpp}
|
g.Images[i] = &Image{Bpp: g.Bpp}
|
||||||
if err := g.Images[i].Decode(rd, g.Palette); err != nil {
|
if err := g.Images[i].Decode(rd, g); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
3
go.mod
|
@ -5,13 +5,12 @@ go 1.18
|
||||||
require (
|
require (
|
||||||
git.tuxpa.in/a/zlog v1.32.0
|
git.tuxpa.in/a/zlog v1.32.0
|
||||||
github.com/disintegration/imaging v1.6.2
|
github.com/disintegration/imaging v1.6.2
|
||||||
|
github.com/go-chi/chi/v5 v5.0.7
|
||||||
github.com/phrozen/blend v0.0.0-20210220204729-f26b6cf7a28e
|
github.com/phrozen/blend v0.0.0-20210220204729-f26b6cf7a28e
|
||||||
gitlab.com/gfxlabs/gfximg v0.0.5
|
gitlab.com/gfxlabs/gfximg v0.0.5
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/chai2010/webp v1.1.1 // indirect
|
|
||||||
github.com/go-chi/chi/v5 v5.0.7 // indirect
|
|
||||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410 // indirect
|
golang.org/x/image v0.0.0-20211028202545-6944b10bf410 // indirect
|
||||||
|
|
3
go.sum
|
@ -1,7 +1,5 @@
|
||||||
git.tuxpa.in/a/zlog v1.32.0 h1:KKXbRF1x8kJDSzUoGz/pivo+4TVY6xT5sVtdFZ6traY=
|
git.tuxpa.in/a/zlog v1.32.0 h1:KKXbRF1x8kJDSzUoGz/pivo+4TVY6xT5sVtdFZ6traY=
|
||||||
git.tuxpa.in/a/zlog v1.32.0/go.mod h1:vUa2Qhu6DLPLqmfRy99FiPqaY2eb6/KQjtMekW3UNnA=
|
git.tuxpa.in/a/zlog v1.32.0/go.mod h1:vUa2Qhu6DLPLqmfRy99FiPqaY2eb6/KQjtMekW3UNnA=
|
||||||
github.com/chai2010/webp v1.1.1 h1:jTRmEccAJ4MGrhFOrPMpNGIJ/eybIgwKpcACsrTEapk=
|
|
||||||
github.com/chai2010/webp v1.1.1/go.mod h1:0XVwvZWdjjdxpUEIf7b9g9VkHFnInUSYujwqTLEuldU=
|
|
||||||
github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
|
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
|
||||||
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
|
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
|
||||||
|
@ -18,7 +16,6 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
||||||
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||||
gitlab.com/gfxlabs/gfximg v0.0.5 h1:jtHE6In6axz0zGPy7YnLIZV9RFdcFEZzpdqoXb52K9s=
|
gitlab.com/gfxlabs/gfximg v0.0.5 h1:jtHE6In6axz0zGPy7YnLIZV9RFdcFEZzpdqoXb52K9s=
|
||||||
gitlab.com/gfxlabs/gfximg v0.0.5/go.mod h1:IAYZwCoqy3JFKwkKafragpfecp5Up6FFIzI7VvK2Zzo=
|
gitlab.com/gfxlabs/gfximg v0.0.5/go.mod h1:IAYZwCoqy3JFKwkKafragpfecp5Up6FFIzI7VvK2Zzo=
|
||||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U=
|
|
||||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ=
|
golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ=
|
||||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||||
|
|
203
image.go
|
@ -1,6 +1,7 @@
|
||||||
package nori
|
package nori
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
|
@ -11,6 +12,10 @@ import (
|
||||||
type Image struct {
|
type Image struct {
|
||||||
Bpp uint32
|
Bpp uint32
|
||||||
Count uint32
|
Count uint32
|
||||||
|
SubImages []*SubImage
|
||||||
|
}
|
||||||
|
|
||||||
|
type SubImage struct {
|
||||||
Delay uint32
|
Delay uint32
|
||||||
OffsetX int32
|
OffsetX int32
|
||||||
OffsetY int32
|
OffsetY int32
|
||||||
|
@ -19,19 +24,143 @@ type Image struct {
|
||||||
Height uint32
|
Height uint32
|
||||||
|
|
||||||
Size uint32
|
Size uint32
|
||||||
Data []byte
|
|
||||||
|
|
||||||
Img image.Image
|
Img image.Image
|
||||||
|
rgb *image.RGBA64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) Decode(rd io.Reader, palette *PaletteSection) error {
|
func (i *SubImage) decode(rd io.Reader, img *Image, size int, g *GawiSection) error {
|
||||||
if err := binary.Read(rd, end, &i.Count); err != nil {
|
switch img.Bpp {
|
||||||
|
case 8:
|
||||||
|
if g.Palette == nil {
|
||||||
|
return fmt.Errorf("bpp = 8, but no palette")
|
||||||
|
}
|
||||||
|
for idx := 0; idx < int(size); idx++ {
|
||||||
|
b, err := readByte(rd)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if i.Count != 1 {
|
col := g.Palette.Palette[b]
|
||||||
return fmt.Errorf("img count should be 1")
|
i.rgb.Set(idx%int(i.Width), idx/int(i.Width), col)
|
||||||
|
}
|
||||||
|
case 16:
|
||||||
|
var bgr uint16
|
||||||
|
for idx := 0; idx < int(size/2); idx++ {
|
||||||
|
if err := binary.Read(rd, end, &bgr); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
red := uint8(((0x7c00 & bgr) >> 10) * 255 / 31)
|
||||||
|
green := uint8(((0x3e0 & bgr) >> 5) * 255 / 31)
|
||||||
|
blue := uint8((0x1f & bgr) * 255 / 31)
|
||||||
|
alpha := uint8(0xff)
|
||||||
|
if red == 0xff && green == 0x00 && blue == 0xff {
|
||||||
|
alpha = 0x00
|
||||||
|
}
|
||||||
|
if red == 0x00 && blue == 0x00 && green == 0xff {
|
||||||
|
alpha = 0x00
|
||||||
|
}
|
||||||
|
col := &color.RGBA{
|
||||||
|
red, green, blue,
|
||||||
|
alpha,
|
||||||
|
}
|
||||||
|
i.rgb.Set(idx%int(i.Width), idx/int(i.Width), col)
|
||||||
|
}
|
||||||
|
case 24:
|
||||||
|
for idx := 0; idx < int(size/3); idx++ {
|
||||||
|
rgb := [3]byte{}
|
||||||
|
_, err := io.ReadFull(rd, rgb[:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
alpha := uint8(0xff)
|
||||||
|
|
||||||
|
if rgb[2] == 0x00 && rgb[1] == 0xff && rgb[0] == 0x00 {
|
||||||
|
alpha = 0x00
|
||||||
|
}
|
||||||
|
if rgb[2] == 0xff && rgb[1] == 0x00 && rgb[0] == 0xff {
|
||||||
|
alpha = 0x00
|
||||||
}
|
}
|
||||||
|
|
||||||
|
col := &color.RGBA{
|
||||||
|
rgb[2], rgb[1], rgb[0],
|
||||||
|
alpha,
|
||||||
|
}
|
||||||
|
i.rgb.Set(idx%int(i.Width), idx/int(i.Width), col)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unsupported bpp, %d", img.Bpp)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *SubImage) decodeCompressed(rd io.Reader, img *Image, g *GawiSection) error {
|
||||||
|
var u16 uint16
|
||||||
|
ob := new(bytes.Buffer)
|
||||||
|
for k := 0; k < int(i.Height); k++ {
|
||||||
|
pixelCount := 0
|
||||||
|
if err := binary.Read(rd, end, &u16); err != nil {
|
||||||
|
return fmt.Errorf("compressed size: %w", err)
|
||||||
|
}
|
||||||
|
want := make([]byte, int(u16)-2)
|
||||||
|
if _, err := io.ReadFull(rd, want); err != nil {
|
||||||
|
return fmt.Errorf("compressed want (%d): %w", u16, err)
|
||||||
|
}
|
||||||
|
buf := bytes.NewBuffer(want)
|
||||||
|
for buf.Len() > 0 {
|
||||||
|
var paddingSize, foregroundSize uint16
|
||||||
|
if err := binary.Read(buf, end, &paddingSize); err != nil {
|
||||||
|
return fmt.Errorf("padding size: %w", err)
|
||||||
|
}
|
||||||
|
if err := binary.Read(buf, end, &foregroundSize); err != nil {
|
||||||
|
return fmt.Errorf("foreground size: %w", err)
|
||||||
|
}
|
||||||
|
for x := 0; x < int(paddingSize); x++ {
|
||||||
|
switch img.Bpp {
|
||||||
|
case 8:
|
||||||
|
ob.Write([]byte{0})
|
||||||
|
case 16:
|
||||||
|
ob.Write([]byte{0x1f, 0x7c})
|
||||||
|
case 24:
|
||||||
|
ob.Write([]byte{0xff, 0, 0xff})
|
||||||
|
default:
|
||||||
|
ob.Write([]byte{0})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foregroundBytes := make([]byte, int(foregroundSize)*(int(g.Bpp)/8))
|
||||||
|
if _, err := io.ReadFull(buf, foregroundBytes); err != nil {
|
||||||
|
return fmt.Errorf("foreground bytes: %w", err)
|
||||||
|
}
|
||||||
|
for y := 0; y < len(foregroundBytes); y++ {
|
||||||
|
ob.WriteByte(foregroundBytes[y])
|
||||||
|
}
|
||||||
|
pixelCount = pixelCount + int(paddingSize) + int(foregroundSize)
|
||||||
|
}
|
||||||
|
if pixelCount != int(i.Width) {
|
||||||
|
return fmt.Errorf("scanline has fewer pixels than the width (expected %d, got %d)", i.Width, pixelCount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i.decode(ob, img, ob.Len(), g)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *SubImage) Decode(rd io.Reader, img *Image, g *GawiSection) error {
|
||||||
|
cf := image.NewRGBA64(image.Rect(0, 0, int(i.Width), int(i.Height)))
|
||||||
|
i.rgb = cf
|
||||||
|
i.Img = i.rgb
|
||||||
|
if g.IsCompressed {
|
||||||
|
return i.decodeCompressed(rd, img, g)
|
||||||
|
}
|
||||||
|
return i.decode(rd, img, int(i.Size), g)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (img *Image) Decode(rd io.Reader, g *GawiSection) error {
|
||||||
|
if err := binary.Read(rd, end, &img.Count); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
img.SubImages = make([]*SubImage, 0, img.Count)
|
||||||
|
for k := 0; k < int(img.Count); k++ {
|
||||||
|
i := &SubImage{}
|
||||||
|
img.SubImages = append(img.SubImages, i)
|
||||||
if err := binary.Read(rd, end, &i.Size); err != nil {
|
if err := binary.Read(rd, end, &i.Size); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -55,71 +184,9 @@ func (i *Image) Decode(rd io.Reader, palette *PaletteSection) error {
|
||||||
if err := binary.Read(rd, end, &i.OffsetY); err != nil {
|
if err := binary.Read(rd, end, &i.OffsetY); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cf := image.NewRGBA64(image.Rect(0, 0, int(i.Width), int(i.Height)))
|
if err := i.Decode(rd, img, g); err != nil {
|
||||||
i.Img = cf
|
|
||||||
switch i.Bpp {
|
|
||||||
case 8:
|
|
||||||
if palette == nil {
|
|
||||||
return fmt.Errorf("bpp = 8, but no palette")
|
|
||||||
}
|
|
||||||
for idx := 0; idx < int(i.Size); idx++ {
|
|
||||||
b, err := readByte(rd)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
col := palette.Palette[b]
|
|
||||||
cf.Set(idx%int(i.Width), idx/int(i.Width), col)
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
case 16:
|
|
||||||
var bgr uint16
|
|
||||||
for idx := 0; idx < int(i.Size/2); idx++ {
|
|
||||||
if err := binary.Read(rd, end, &bgr); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
red := uint8(((0x7c00 & bgr) >> 10) * 255 / 31)
|
|
||||||
green := uint8(((0x3e0 & bgr) >> 5) * 255 / 31)
|
|
||||||
blue := uint8((0x1f & bgr) * 255 / 31)
|
|
||||||
alpha := uint8(0xff)
|
|
||||||
if red == 0xff && green == 0x00 && blue == 0xff {
|
|
||||||
alpha = 0x00
|
|
||||||
}
|
|
||||||
if red == 0x00 && blue == 0x00 && green == 0xff {
|
|
||||||
alpha = 0x00
|
|
||||||
}
|
|
||||||
col := &color.RGBA{
|
|
||||||
red, green, blue,
|
|
||||||
alpha,
|
|
||||||
}
|
|
||||||
cf.Set(idx%int(i.Width), idx/int(i.Width), col)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
case 24:
|
|
||||||
i.Data = make([]byte, i.Size)
|
|
||||||
for idx := 0; idx < int(i.Size/3); idx++ {
|
|
||||||
rgb := [3]byte{}
|
|
||||||
_, err := io.ReadFull(rd, rgb[:])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
alpha := uint8(0xff)
|
|
||||||
|
|
||||||
if rgb[2] == 0x00 && rgb[1] == 0xff && rgb[0] == 0x00 {
|
|
||||||
alpha = 0x00
|
|
||||||
}
|
|
||||||
if rgb[2] == 0xff && rgb[1] == 0x00 && rgb[0] == 0xff {
|
|
||||||
alpha = 0x00
|
|
||||||
}
|
|
||||||
|
|
||||||
col := &color.RGBA{
|
|
||||||
rgb[2], rgb[1], rgb[0],
|
|
||||||
alpha,
|
|
||||||
}
|
|
||||||
|
|
||||||
cf.Set(idx%int(i.Width), idx/int(i.Width), col)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("unsupported bpp, %d", i.Bpp)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
14
reader.go
|
@ -44,5 +44,17 @@ func reflectReader(r io.Reader) io.Reader {
|
||||||
if _, ok := r.(readByteSeeker); ok {
|
if _, ok := r.(readByteSeeker); ok {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
return bufio.NewReader(r)
|
return fileByteReader{
|
||||||
|
ReadSeeker: r.(io.ReadSeeker),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type fileByteReader struct {
|
||||||
|
io.ReadSeeker
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *fileByteReader) ReadByte() (byte, error) {
|
||||||
|
b := [1]byte{}
|
||||||
|
_, err := o.Read(b[:])
|
||||||
|
return b[0], err
|
||||||
}
|
}
|
||||||
|
|
22
render.go
|
@ -2,13 +2,14 @@ package nori
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"image"
|
||||||
|
"image/color"
|
||||||
|
"image/draw"
|
||||||
|
|
||||||
"git.tuxpa.in/a/zlog/log"
|
"git.tuxpa.in/a/zlog/log"
|
||||||
"github.com/disintegration/imaging"
|
"github.com/disintegration/imaging"
|
||||||
"github.com/phrozen/blend"
|
"github.com/phrozen/blend"
|
||||||
"gitlab.com/gfxlabs/gfximg/apng"
|
"gitlab.com/gfxlabs/gfximg/apng"
|
||||||
"image"
|
|
||||||
"image/color"
|
|
||||||
"image/draw"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func copyImage(img image.Image) image.Image {
|
func copyImage(img image.Image) image.Image {
|
||||||
|
@ -34,8 +35,11 @@ func RenderAnimation(n *Nori, num int, f RenderFunc) error {
|
||||||
log.Printf("could not find bitmap %d, only have %d", plane.BitmapId, len(g.Images))
|
log.Printf("could not find bitmap %d, only have %d", plane.BitmapId, len(g.Images))
|
||||||
}
|
}
|
||||||
bitmap := g.Images[plane.BitmapId]
|
bitmap := g.Images[plane.BitmapId]
|
||||||
|
if len(bitmap.SubImages) == 0 {
|
||||||
|
return fmt.Errorf("no subimages in bitmap")
|
||||||
|
}
|
||||||
pt := image.Pt(int(plane.PlaneX), int(plane.PlaneY)) // where to put the point
|
pt := image.Pt(int(plane.PlaneX), int(plane.PlaneY)) // where to put the point
|
||||||
rc := bitmap.Img.Bounds().Add(pt) // translate rectangle to put in the global canvas
|
rc := bitmap.SubImages[0].Img.Bounds().Add(pt) // translate rectangle to put in the global canvas
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
canvasRect = rc
|
canvasRect = rc
|
||||||
} else {
|
} else {
|
||||||
|
@ -45,19 +49,19 @@ func RenderAnimation(n *Nori, num int, f RenderFunc) error {
|
||||||
img := image.NewNRGBA(canvasRect)
|
img := image.NewNRGBA(canvasRect)
|
||||||
for _, plane := range planes {
|
for _, plane := range planes {
|
||||||
bitmap := g.Images[plane.BitmapId]
|
bitmap := g.Images[plane.BitmapId]
|
||||||
drawBitmap := bitmap.Img
|
drawBitmap := bitmap.SubImages[0].Img
|
||||||
transparent := false
|
transparent := false
|
||||||
//flipx
|
//flipx
|
||||||
if plane.RenderFlag&1 != 0 {
|
if plane.RenderFlag&1 != 0 {
|
||||||
if bitmap.Img == drawBitmap {
|
if bitmap.SubImages[0].Img == drawBitmap {
|
||||||
drawBitmap = copyImage(bitmap.Img)
|
drawBitmap = copyImage(bitmap.SubImages[0].Img)
|
||||||
}
|
}
|
||||||
drawBitmap = imaging.FlipH(drawBitmap)
|
drawBitmap = imaging.FlipH(drawBitmap)
|
||||||
}
|
}
|
||||||
//flipy
|
//flipy
|
||||||
if plane.RenderFlag&2 != 0 {
|
if plane.RenderFlag&2 != 0 {
|
||||||
if bitmap.Img == drawBitmap {
|
if bitmap.SubImages[0].Img == drawBitmap {
|
||||||
drawBitmap = copyImage(bitmap.Img)
|
drawBitmap = copyImage(bitmap.SubImages[0].Img)
|
||||||
}
|
}
|
||||||
drawBitmap = imaging.FlipV(drawBitmap)
|
drawBitmap = imaging.FlipV(drawBitmap)
|
||||||
}
|
}
|
||||||
|
|