support subimages and compressed

This commit is contained in:
a 2022-12-19 03:09:29 -06:00
parent 1375ab7a1a
commit 88028a27e4
48 changed files with 150 additions and 71 deletions

BIN
animations/a_0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
animations/a_1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
animations/a_10.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

BIN
animations/a_11.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
animations/a_12.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

BIN
animations/a_13.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
animations/a_14.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
animations/a_15.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
animations/a_16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

BIN
animations/a_17.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
animations/a_18.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

BIN
animations/a_19.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

BIN
animations/a_2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

BIN
animations/a_20.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
animations/a_21.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
animations/a_22.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

BIN
animations/a_23.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

BIN
animations/a_24.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

BIN
animations/a_25.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
animations/a_26.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
animations/a_27.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
animations/a_28.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
animations/a_29.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
animations/a_3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
animations/a_30.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
animations/a_31.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
animations/a_32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
animations/a_33.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
animations/a_34.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
animations/a_35.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
animations/a_36.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
animations/a_37.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
animations/a_4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

BIN
animations/a_5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
animations/a_6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
animations/a_7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
animations/a_8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
animations/a_9.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@ -4,11 +4,12 @@ import (
"bytes"
"flag"
"fmt"
"git.tuxpa.in/a/nori/renderer"
"net/http"
"os"
"time"
"git.tuxpa.in/a/nori/renderer"
"git.tuxpa.in/a/nori"
"git.tuxpa.in/a/nori/utils"
"git.tuxpa.in/a/zlog/log"
@ -54,7 +55,7 @@ func dump(filename string, output string) {
printIf("reading file '%s'\n", filename)
n, err := nori.FromFile(filename)
if err != nil {
log.Panicln("decode: %s", err)
log.Panicf("decode: %s", err)
}
out := new(bytes.Buffer)
printIf("rendering %d animation(s)\n", n.AnimationCount)

BIN
compress.nri Normal file

Binary file not shown.

View File

@ -1,7 +1,6 @@
package nori
import (
"bufio"
"io"
"os"
)
@ -16,7 +15,7 @@ func FromFile(fp string) (*Nori, error) {
return nil, err
}
defer file.Close()
return Decode(bufio.NewReader(file))
return Decode(file)
}
func Decode(r io.Reader) (*Nori, error) {

View File

@ -77,7 +77,7 @@ func (g *GawiSection) Decode(rd io.Reader) error {
g.Images = make([]*Image, int(g.BmpCount))
for i := range g.Images {
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
}
}

3
go.mod
View File

@ -5,13 +5,12 @@ go 1.18
require (
git.tuxpa.in/a/zlog v1.32.0
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
gitlab.com/gfxlabs/gfximg v0.0.5
)
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-isatty v0.0.14 // indirect
golang.org/x/image v0.0.0-20211028202545-6944b10bf410 // indirect

3
go.sum
View File

@ -1,7 +1,5 @@
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=
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/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
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=
gitlab.com/gfxlabs/gfximg v0.0.5 h1:jtHE6In6axz0zGPy7YnLIZV9RFdcFEZzpdqoXb52K9s=
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-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ=
golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=

203
image.go
View File

@ -1,6 +1,7 @@
package nori
import (
"bytes"
"encoding/binary"
"fmt"
"image"
@ -11,6 +12,10 @@ import (
type Image struct {
Bpp uint32
Count uint32
SubImages []*SubImage
}
type SubImage struct {
Delay uint32
OffsetX int32
OffsetY int32
@ -19,19 +24,143 @@ type Image struct {
Height uint32
Size uint32
Data []byte
Img image.Image
rgb *image.RGBA64
}
func (i *Image) Decode(rd io.Reader, palette *PaletteSection) error {
if err := binary.Read(rd, end, &i.Count); err != nil {
func (i *SubImage) decode(rd io.Reader, img *Image, size int, g *GawiSection) error {
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
}
if i.Count != 1 {
return fmt.Errorf("img count should be 1")
col := g.Palette.Palette[b]
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 {
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 {
return err
}
cf := image.NewRGBA64(image.Rect(0, 0, int(i.Width), int(i.Height)))
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 {
if err := i.Decode(rd, img, g); err != nil {
return err
}
col := palette.Palette[b]
cf.Set(idx%int(i.Width), idx/int(i.Width), col)
}
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)
}
}

BIN
mon1033.nri Executable file

Binary file not shown.

View File

@ -44,5 +44,17 @@ func reflectReader(r io.Reader) io.Reader {
if _, ok := r.(readByteSeeker); ok {
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
}

View File

@ -2,13 +2,14 @@ package nori
import (
"fmt"
"image"
"image/color"
"image/draw"
"git.tuxpa.in/a/zlog/log"
"github.com/disintegration/imaging"
"github.com/phrozen/blend"
"gitlab.com/gfxlabs/gfximg/apng"
"image"
"image/color"
"image/draw"
)
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))
}
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
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 {
canvasRect = rc
} else {
@ -45,19 +49,19 @@ func RenderAnimation(n *Nori, num int, f RenderFunc) error {
img := image.NewNRGBA(canvasRect)
for _, plane := range planes {
bitmap := g.Images[plane.BitmapId]
drawBitmap := bitmap.Img
drawBitmap := bitmap.SubImages[0].Img
transparent := false
//flipx
if plane.RenderFlag&1 != 0 {
if bitmap.Img == drawBitmap {
drawBitmap = copyImage(bitmap.Img)
if bitmap.SubImages[0].Img == drawBitmap {
drawBitmap = copyImage(bitmap.SubImages[0].Img)
}
drawBitmap = imaging.FlipH(drawBitmap)
}
//flipy
if plane.RenderFlag&2 != 0 {
if bitmap.Img == drawBitmap {
drawBitmap = copyImage(bitmap.Img)
if bitmap.SubImages[0].Img == drawBitmap {
drawBitmap = copyImage(bitmap.SubImages[0].Img)
}
drawBitmap = imaging.FlipV(drawBitmap)
}