limage - xcf/rle.go
1 package xcf
2
3 import (
4 "errors"
5 "io"
6
7 "vimagination.zapto.org/byteio"
8 "vimagination.zapto.org/memio"
9 )
10
11 type rle struct {
12 Reader *byteio.StickyBigEndianReader
13 repeatByte bool
14 data uint8
15 count uint16
16 }
17
18 func (r *rle) Read(p []byte) (int, error) {
19 var n int
20 for len(p) > 0 && r.Reader.Err == nil {
21 if r.count == 0 {
22 m := r.Reader.ReadUint8()
23 if r.Reader.Err != nil {
24 return n, r.Reader.Err
25 }
26 if m < 127 {
27 r.repeatByte = true
28 r.count = uint16(m) + 1
29 r.data = r.Reader.ReadUint8()
30 } else if m == 127 {
31 r.repeatByte = true
32 r.count = r.Reader.ReadUint16()
33 r.data = r.Reader.ReadUint8()
34 } else if m == 128 {
35 r.repeatByte = false
36 r.count = r.Reader.ReadUint16()
37 } else {
38 r.repeatByte = false
39 r.count = 256 - uint16(m)
40 }
41 if r.Reader.Err != nil {
42 if r.Reader.Err == io.EOF {
43 r.Reader.Err = io.ErrUnexpectedEOF
44 }
45 return n, r.Reader.Err
46 }
47 }
48 c := int(r.count)
49 if len(p) < c {
50 c = len(p)
51 }
52 if r.repeatByte {
53 for i := 0; i < c; i++ {
54 p[i] = r.data
55 }
56 } else {
57 r.Reader.Read(p[:c])
58 }
59 r.count -= uint16(c)
60 p = p[c:]
61 n += c
62 }
63 if r.count != 0 && r.Reader.Err == nil {
64 return n, ErrInvalidRLE
65 }
66 return n, r.Reader.Err
67 }
68
69 const minRunLength = 3
70
71 func (w *writer) WriteRLE(data []byte) {
72 if len(data) == 0 {
73 return
74 }
75 var run, written int
76 last := data[0]
77 for n, b := range data {
78 if b == last {
79 run++
80 } else {
81 if run > minRunLength {
82 w.WriteRLEData(data[written:n-run], run, last)
83 written = n
84 }
85 run = 1
86 }
87 last = b
88 }
89 if run <= minRunLength && run < len(data) {
90 run = 0
91 }
92 w.WriteRLEData(data[written:len(data)-run], run, last)
93 }
94
95 func (w *writer) WriteRLEData(data []byte, run int, last byte) {
96 if len(data) > 0 {
97 r := false
98 if len(data) <= minRunLength {
99 r = true
100 for _, b := range data {
101 if b != data[0] {
102 r = false
103 break
104 }
105 }
106 }
107 if r {
108 w.WriteRLEData(nil, len(data), data[0])
109 } else {
110 if len(data) < 128 {
111 w.WriteUint8(255 - uint8(len(data)-1))
112 } else {
113 w.WriteUint8(128)
114 w.WriteUint16(uint16(len(data)))
115 }
116 w.Write(data)
117 }
118 }
119 if run > 0 {
120 if run < 128 {
121 w.WriteUint8(uint8(run - 1))
122 } else {
123 w.WriteUint8(127)
124 w.WriteUint16(uint16(run))
125 }
126 w.WriteUint8(last)
127 }
128 }
129
130 func (d *decoder) readRLE(count int, buf *memio.Buffer) error {
131 bw := byteio.BigEndianWriter{Writer: buf}
132 for count > 0 {
133 c := d.reader.ReadUint8()
134 bw.WriteUint8(c)
135 if c < 127 {
136 count -= int(c) + 1
137 bw.WriteUint8(d.ReadUint8())
138 } else if c == 127 {
139 p := d.ReadUint16()
140 bw.WriteUint16(p)
141 count -= int(p)
142 bw.WriteUint8(d.ReadUint8())
143 } else if c == 128 {
144 p := d.ReadUint16()
145 bw.WriteUint16(p)
146 count -= int(p)
147 io.CopyN(buf, d, int64(p))
148 } else {
149 count -= 256 - int(c)
150 io.CopyN(buf, d, 256-int64(c))
151 }
152 }
153 if count < 0 {
154 return ErrInvalidRLE
155 }
156 return nil
157 }
158
159 // Errors
160 var (
161 ErrInvalidRLE = errors.New("invalid RLE data")
162 )
163