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 Img image.Image } 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 } 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 { 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) col := &color.RGBA{ rgb[0], rgb[1], rgb[2], alpha, } if rgb[0] == 0x00 && rgb[1] == 0xff && rgb[2] == 0x00 { alpha = 0x00 } if rgb[0] == 0xff && rgb[1] == 0x00 && rgb[2] == 0xff { alpha = 0x00 } cf.Set(idx%int(i.Width), idx/int(i.Width), col) } return nil default: return fmt.Errorf("unsupported bpp, %d", i.Bpp) } }