nori/image.go

124 lines
2.4 KiB
Go
Raw Normal View History

2022-03-25 05:14:03 +00:00
package nori
import (
"encoding/binary"
"fmt"
"image"
"image/color"
"io"
)
type Image struct {
Bpp uint32
Count uint32
Delay uint32
OffsetX int32
OffsetY int32
Width uint32
Height uint32
Size uint32
Data []byte
2022-03-25 07:33:23 +00:00
Img image.Image
2022-03-25 05:14:03 +00:00
}
2022-03-25 21:00:43 +00:00
func (i *Image) Decode(rd io.Reader, palette *PaletteSection) error {
if err := binary.Read(rd, end, &i.Count); err != nil {
return err
}
if i.Count != 1 {
return fmt.Errorf("img count should be 1")
}
if err := binary.Read(rd, end, &i.Size); err != nil {
return err
}
if err := binary.Read(rd, end, &i.Width); err != nil {
return err
}
if err := binary.Read(rd, end, &i.Height); err != nil {
return err
}
if err := binary.Read(rd, end, &i.Delay); err != nil {
return err
}
if err := binary.Read(rd, end, &i.OffsetX); err != nil {
return err
}
if err := binary.Read(rd, end, &i.OffsetY); err != nil {
return err
}
2022-03-25 05:14:03 +00:00
cf := image.NewRGBA64(image.Rect(0, 0, int(i.Width), int(i.Height)))
2022-03-25 07:33:23 +00:00
i.Img = cf
2022-03-25 05:14:03 +00:00
switch i.Bpp {
case 8:
2022-03-25 06:00:01 +00:00
if palette == nil {
return fmt.Errorf("bpp = 8, but no palette")
}
for idx := 0; idx < int(i.Size); idx++ {
2022-03-25 21:00:43 +00:00
b, err := readByte(rd)
2022-03-25 06:00:01 +00:00
if err != nil {
return err
}
col := palette.Palette[b]
cf.Set(idx%int(i.Width), idx/int(i.Width), col)
}
return nil
2022-03-25 05:14:03 +00:00
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)
2022-03-25 10:23:31 +00:00
alpha := uint8(0xff)
2022-03-25 19:38:46 +00:00
if red == 0xff && green == 0x00 && blue == 0xff {
2022-03-25 10:23:31 +00:00
alpha = 0x00
2022-03-25 05:14:03 +00:00
}
2022-03-25 10:28:36 +00:00
if red == 0x00 && blue == 0x00 && green == 0xff {
alpha = 0x00
}
2022-03-25 05:14:03 +00:00
col := &color.RGBA{
red, green, blue,
2022-03-25 10:23:31 +00:00
alpha,
2022-03-25 05:14:03 +00:00
}
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
}
2022-03-25 10:23:31 +00:00
alpha := uint8(0xff)
2022-03-25 05:14:03 +00:00
col := &color.RGBA{
rgb[0], rgb[1], rgb[2],
2022-03-25 10:23:31 +00:00
alpha,
}
2022-03-25 10:28:36 +00:00
if rgb[0] == 0x00 && rgb[1] == 0xff && rgb[2] == 0x00 {
alpha = 0x00
}
2022-03-25 19:38:46 +00:00
if rgb[0] == 0xff && rgb[1] == 0x00 && rgb[2] == 0xff {
2022-03-25 10:23:31 +00:00
alpha = 0x00
2022-03-25 05:14:03 +00:00
}
cf.Set(idx%int(i.Width), idx/int(i.Width), col)
}
return nil
default:
return fmt.Errorf("unsupported bpp, %d", i.Bpp)
}
}