diff --git a/encoding.go b/encoding.go index ff98b91..de08f3e 100644 --- a/encoding.go +++ b/encoding.go @@ -326,53 +326,34 @@ func readTightLength(c Conn) (int, error) { } func (enc *RawEncoding) Write(c Conn, rect *Rectangle) error { - buf := bPool.Get().(*bytes.Buffer) - buf.Reset() - defer bPool.Put(buf) - n := 0 - for _, c := range enc.Colors { - bytes, err := c.Marshal() - if err != nil { - return err - } - n += len(bytes) - - if err := binary.Write(buf, binary.BigEndian, bytes); err != nil { - return err + var err error + for _, clr := range enc.Colors { + if err = clr.Write(c); err != nil { + break } } - - _, err := buf.WriteTo(c) return err } // Read implements the Encoding interface. func (enc *RawEncoding) Read(c Conn, rect *Rectangle) error { - buf := bPool.Get().(*bytes.Buffer) - buf.Reset() - defer bPool.Put(buf) + var err error pf := c.PixelFormat() cm := c.ColorMap() - bytesPerPixel := int(pf.BPP / 8) - n := rect.Area() * bytesPerPixel - data := make([]byte, n) - if err := binary.Read(c, binary.BigEndian, &data); err != nil { - return err - } - buf.Write(data) colors := make([]Color, rect.Area()) +Loop: for y := uint16(0); y < rect.Height; y++ { for x := uint16(0); x < rect.Width; x++ { color := NewColor(pf, cm) - if err := color.Unmarshal(buf.Next(bytesPerPixel)); err != nil { - return err + if err = color.Read(c); err != nil { + break Loop } colors[int(y)*int(rect.Width)+int(x)] = *color } } enc.Colors = colors - return nil + return err } func (*RawEncoding) Type() EncodingType { return EncRaw } diff --git a/image.go b/image.go index 6c1d806..1c46937 100644 --- a/image.go +++ b/image.go @@ -39,6 +39,28 @@ func NewRectangle() *Rectangle { return &Rectangle{} } +func (clr *Color) Write(c Conn) error { + var err error + order := clr.pf.order() + pixel := clr.cmIndex + if clr.pf.TrueColor == 1 { + pixel = uint32(clr.R) << clr.pf.RedShift + pixel |= uint32(clr.G) << clr.pf.GreenShift + pixel |= uint32(clr.B) << clr.pf.BlueShift + } + + switch clr.pf.BPP { + case 8: + err = binary.Write(c, order, byte(pixel)) + case 16: + err = binary.Write(c, order, uint16(pixel)) + case 32: + err = binary.Write(c, order, uint32(pixel)) + } + + return err +} + // Marshal implements the Marshaler interface. func (c *Color) Marshal() ([]byte, error) { order := c.pf.order() @@ -65,6 +87,42 @@ func (c *Color) Marshal() ([]byte, error) { return bytes, nil } +func (clr *Color) Read(c Conn) error { + order := clr.pf.order() + var pixel uint32 + + switch clr.pf.BPP { + case 8: + var px uint8 + if err := binary.Read(c, order, &px); err != nil { + return err + } + pixel = uint32(px) + case 16: + var px uint16 + if err := binary.Read(c, order, &px); err != nil { + return err + } + pixel = uint32(px) + case 32: + var px uint32 + if err := binary.Read(c, order, &px); err != nil { + return err + } + pixel = uint32(px) + } + + if clr.pf.TrueColor == 1 { + clr.R = uint16((pixel >> clr.pf.RedShift) & uint32(clr.pf.RedMax)) + clr.G = uint16((pixel >> clr.pf.GreenShift) & uint32(clr.pf.GreenMax)) + clr.B = uint16((pixel >> clr.pf.BlueShift) & uint32(clr.pf.BlueMax)) + } else { + *clr = clr.cm[pixel] + clr.cmIndex = pixel + } + return nil +} + // Unmarshal implements the Unmarshaler interface. func (c *Color) Unmarshal(data []byte) error { if len(data) == 0 {