diff --git a/tools/utils/images/loading.go b/tools/utils/images/loading.go index 4610a9161..e6290ad7f 100644 --- a/tools/utils/images/loading.go +++ b/tools/utils/images/loading.go @@ -139,25 +139,22 @@ func (self *ImageFrame) Data() (ans []byte) { return } -func ImageFrameFromSerialized(s SerializableImageFrame, data []byte) (*ImageFrame, error) { +func ImageFrameFromSerialized(s SerializableImageFrame, data []byte) (aa *ImageFrame, err error) { ans := ImageFrame{ Width: s.Width, Height: s.Height, Left: s.Left, Top: s.Top, Number: s.Number, Compose_onto: s.Compose_onto, Delay_ms: int32(s.Delay_ms), Is_opaque: s.Is_opaque, } - r := image.Rect(0, 0, s.Width, s.Height) - if s.Is_opaque { - if len(data) != 3*r.Dx()*r.Dy() { - return nil, fmt.Errorf("serialized image data has size: %d != %d", len(data), 3*r.Dy()*r.Dx()) - } - ans.Img = &NRGB{Pix: data, Stride: 3 * r.Dx(), Rect: r} - } else { - if len(data) != 4*r.Dx()*r.Dy() { - return nil, fmt.Errorf("serialized image data has size: %d != %d", len(data), 4*r.Dy()*r.Dx()) - } - ans.Img = &image.NRGBA{Pix: data, Stride: 4 * r.Dx(), Rect: r} + bytes_per_pixel := utils.IfElse(s.Is_opaque, 3, 4) + if expected := bytes_per_pixel * s.Width * s.Height; len(data) != expected { + return nil, fmt.Errorf("serialized image data has size: %d != %d", len(data), expected) } - return &ans, nil + if s.Is_opaque { + ans.Img, err = NewNRGBWithContiguousRGBPixels(data, s.Width, s.Height) + } else { + ans.Img, err = NewNRGBAWithContiguousRGBAPixels(data, s.Width, s.Height) + } + return &ans, err } type ImageData struct { diff --git a/tools/utils/images/to_rgb.go b/tools/utils/images/to_rgb.go index bcaae41c3..ce78db7f3 100644 --- a/tools/utils/images/to_rgb.go +++ b/tools/utils/images/to_rgb.go @@ -170,14 +170,15 @@ func newScannerRGB(img image.Image, opaque_base NRGBColor) *scanner_rgb { } if img, ok := img.(*image.Paletted); ok { s.palette = make([]NRGBColor, max(256, len(img.Palette))) - d := make([]uint8, 3) + d := [3]uint8{0, 0, 0} + ds := d[:] for i := 0; i < len(img.Palette); i++ { r, g, b, a := img.Palette[i].RGBA() switch a { case 0: s.palette[i] = opaque_base default: - blend(d, s.opaque_base, uint8((r*0xffff/a)>>8), uint8((g*0xffff/a)>>8), uint8((b*0xffff/a)>>8), uint8(a>>8)) + blend(ds, s.opaque_base, uint8((r*0xffff/a)>>8), uint8((g*0xffff/a)>>8), uint8((b*0xffff/a)>>8), uint8(a>>8)) s.palette[i] = NRGBColor{d[0], d[1], d[2]} } } @@ -425,3 +426,27 @@ func NewNRGB(r image.Rectangle) *NRGB { Rect: r, } } + +func NewNRGBWithContiguousRGBPixels(p []byte, width, height int) (*NRGB, error) { + const bpp = 3 + if expected := bpp * width * height; expected != len(p) { + return nil, fmt.Errorf("the image width and height dont match the size of the specified pixel data: width=%d height=%d sz=%d != %d", width, height, len(p), expected) + } + return &NRGB{ + Pix: p, + Stride: bpp * width, + Rect: image.Rectangle{image.Point{}, image.Point{width, height}}, + }, nil +} + +func NewNRGBAWithContiguousRGBAPixels(p []byte, width, height int) (*image.NRGBA, error) { + const bpp = 4 + if expected := bpp * width * height; expected != len(p) { + return nil, fmt.Errorf("the image width and height dont match the size of the specified pixel data: width=%d height=%d sz=%d != %d", width, height, len(p), expected) + } + return &image.NRGBA{ + Pix: p, + Stride: bpp * width, + Rect: image.Rectangle{image.Point{}, image.Point{width, height}}, + }, nil +}