Skip to content

Commit f67eb4a

Browse files
committed
image.NRGBA
1 parent ffcf568 commit f67eb4a

File tree

6 files changed

+424
-2
lines changed

6 files changed

+424
-2
lines changed

imagepool.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,48 @@ func (b *ImageRGBAPool) Cap() int {
9999
return cap(b.pool)
100100
}
101101

102+
type ImageNRGBAPool struct {
103+
ImageRGBAPool
104+
}
105+
106+
func NewImageNRGBAPool(poolSize int, rect image.Rectangle, funcs ...optionFunc) *ImageNRGBAPool {
107+
opt := newOption()
108+
for _, fn := range funcs {
109+
fn(opt)
110+
}
111+
112+
b := new(ImageNRGBAPool)
113+
b.pool = make(chan []uint8, poolSize)
114+
b.init(rect)
115+
116+
if opt.preload {
117+
b.preload(opt.preloadRate)
118+
}
119+
return b
120+
}
121+
122+
func (b *ImageNRGBAPool) createImageNRGBARef(pix []uint8, pool *ImageNRGBAPool) *ImageNRGBARef {
123+
ref := newImageNRGBARef(pix, &image.NRGBA{
124+
Pix: pix,
125+
Stride: b.stride,
126+
Rect: b.rect,
127+
}, pool)
128+
ref.setFinalizer()
129+
return ref
130+
}
131+
132+
func (b *ImageNRGBAPool) GetRef() *ImageNRGBARef {
133+
var pix []uint8
134+
select {
135+
case pix = <-b.pool:
136+
// reuse exists pool
137+
default:
138+
// create []uint8
139+
pix = make([]uint8, b.length)
140+
}
141+
return b.createImageNRGBARef(pix, b)
142+
}
143+
102144
type ImageYCbCrPool struct {
103145
pool chan []uint8
104146
rect image.Rectangle

imagepool_test.go

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,61 @@ func TestImageRGBAPoolBufSize(t *testing.T) {
168168
})
169169
}
170170

171+
func TestImageNRGBAPoolBufSize(t *testing.T) {
172+
t.Run("getsamecap", func(tt *testing.T) {
173+
rect := image.Rect(0, 0, 100, 100)
174+
pool := NewImageNRGBAPool(10, rect)
175+
img := image.NewNRGBA(rect)
176+
177+
d1 := pool.GetRef()
178+
d2 := pool.GetRef()
179+
if cap(d1.pix) != cap(img.Pix) {
180+
tt.Errorf("buf size = %d", cap(img.Pix))
181+
}
182+
if cap(d2.pix) != cap(img.Pix) {
183+
tt.Errorf("buf size = %d", cap(img.Pix))
184+
}
185+
})
186+
t.Run("getput/smallcap", func(tt *testing.T) {
187+
rect := image.Rect(0, 0, 100, 100)
188+
pool := NewImageNRGBAPool(10, rect)
189+
img := image.NewNRGBA(rect)
190+
191+
r1 := image.Rect(0, 0, 64, 36)
192+
i1 := image.NewNRGBA(r1)
193+
if pool.Put(i1.Pix) {
194+
tt.Errorf("discard small pix")
195+
}
196+
197+
d1 := pool.GetRef()
198+
if cap(d1.pix) != cap(img.Pix) {
199+
tt.Errorf("discard small pix = %d", cap(d1.pix))
200+
}
201+
if len(d1.pix) != len(img.Pix) {
202+
tt.Errorf("discard small pix")
203+
}
204+
})
205+
t.Run("getput/largecap", func(tt *testing.T) {
206+
rect := image.Rect(0, 0, 100, 100)
207+
pool := NewImageNRGBAPool(10, rect)
208+
img := image.NewNRGBA(rect)
209+
210+
r1 := image.Rect(0, 0, 640, 360)
211+
i1 := image.NewNRGBA(r1)
212+
if pool.Put(i1.Pix) != true {
213+
tt.Errorf("allow large pix")
214+
}
215+
216+
d1 := pool.GetRef()
217+
if cap(d1.pix) == cap(img.Pix) {
218+
tt.Errorf("large pix ok")
219+
}
220+
if len(d1.pix) != len(img.Pix) {
221+
tt.Errorf("same len")
222+
}
223+
})
224+
}
225+
171226
func TestImageYCbCrPoolBufSize(t *testing.T) {
172227
t.Run("getsamecap", func(tt *testing.T) {
173228
rect := image.Rect(0, 0, 100, 100)
@@ -307,6 +362,76 @@ func TestImageRGBAPoolCapLen(t *testing.T) {
307362
})
308363
}
309364

365+
func TestImageNRGBAPoolCapLen(t *testing.T) {
366+
t.Run("getput", func(tt *testing.T) {
367+
r := image.Rect(0, 0, 16, 9)
368+
p := NewImageNRGBAPool(10, r)
369+
if 0 != p.Len() {
370+
tt.Errorf("initial len 0")
371+
}
372+
if 10 != p.Cap() {
373+
tt.Errorf("initial cap 10")
374+
}
375+
376+
data := p.GetRef()
377+
if 0 != p.Len() {
378+
tt.Errorf("initial len 0")
379+
}
380+
if 10 != p.Cap() {
381+
tt.Errorf("initial cap 10")
382+
}
383+
p.Put(data.pix)
384+
385+
if 1 != p.Len() {
386+
tt.Errorf("put one")
387+
}
388+
if 10 != p.Cap() {
389+
tt.Errorf("initial cap 10")
390+
}
391+
392+
d1 := p.GetRef()
393+
if 0 != p.Len() {
394+
tt.Errorf("acquire pool")
395+
}
396+
p.Put(d1.pix)
397+
if 1 != p.Len() {
398+
tt.Errorf("release pool")
399+
}
400+
})
401+
t.Run("maxcap", func(tt *testing.T) {
402+
r := image.Rect(0, 0, 16, 9)
403+
p := NewImageNRGBAPool(10, r)
404+
s := make([]*ImageNRGBARef, 0)
405+
for i := 0; i < 10; i += 1 {
406+
r := p.GetRef()
407+
s = append(s, r)
408+
}
409+
for _, r := range s {
410+
p.Put(r.pix)
411+
}
412+
413+
if 10 != p.Len() {
414+
tt.Errorf("fill-ed pool: %d", p.Len())
415+
}
416+
if 10 != p.Cap() {
417+
tt.Errorf("max capacity = 10")
418+
}
419+
420+
i1 := image.NewNRGBA(r)
421+
d1 := newImageNRGBARef(i1.Pix, i1, p)
422+
i2 := image.NewNRGBA(r)
423+
d2 := newImageNRGBARef(i2.Pix, i2, p)
424+
p.Put(d1.pix)
425+
p.Put(d2.pix)
426+
if 10 != p.Len() {
427+
tt.Errorf("fixed size pool")
428+
}
429+
if 10 != p.Cap() {
430+
tt.Errorf("max capacity = 10")
431+
}
432+
})
433+
}
434+
310435
func TestImageYCbCrPoolCapLen(t *testing.T) {
311436
t.Run("getput", func(tt *testing.T) {
312437
r := image.Rect(0, 0, 16, 9)
@@ -424,6 +549,15 @@ func TestImageRGBAPoolPreload(t *testing.T) {
424549
}
425550
}
426551

552+
func TestImageNRGBAPoolPreload(t *testing.T) {
553+
r := image.Rect(0, 0, 100, 100)
554+
p := NewImageNRGBAPool(12, r, Preload(true))
555+
l := int(float64(12) * defaultPreloadRate)
556+
if p.Len() != l {
557+
t.Errorf("preloaded buffer = %d", p.Len())
558+
}
559+
}
560+
427561
func TestImageYCbCrPoolPreload(t *testing.T) {
428562
r := image.Rect(0, 0, 100, 100)
429563
p := NewImageYCbCrPool(12, r, image.YCbCrSubsampleRatio420, Preload(true))

mimagepool.go

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,11 @@ func NewMultiImageRGBAPool(funcs ...multiImageBufferPoolOptionFunc) *MultiImageR
7979
}
8080

8181
tuples := uniqImagepoolTuple(mOpt.tuples)
82-
poolFuncs := mOpt.poolFuncs
8382

8483
sortTuples(tuples)
8584
pools := make([]*ImageRGBAPool, len(tuples))
8685
for i, t := range tuples {
87-
pools[i] = NewImageRGBAPool(t.poolSize, t.rect, poolFuncs...)
86+
pools[i] = NewImageRGBAPool(t.poolSize, t.rect, mOpt.poolFuncs...)
8887
}
8988
return &MultiImageRGBAPool{
9089
tuples: tuples,
@@ -125,6 +124,63 @@ func (b *MultiImageRGBAPool) Put(pix []uint8, r image.Rectangle) bool {
125124
return false
126125
}
127126

127+
type MultiImageNRGBAPool struct {
128+
tuples []imagepoolTuple
129+
pools []*ImageNRGBAPool
130+
}
131+
132+
func NewMultiImageNRGBAPool(funcs ...multiImageBufferPoolOptionFunc) *MultiImageNRGBAPool {
133+
mOpt := newMultiImageBufferPoolOption()
134+
for _, fn := range funcs {
135+
fn(mOpt)
136+
}
137+
138+
tuples := uniqImagepoolTuple(mOpt.tuples)
139+
140+
sortTuples(tuples)
141+
pools := make([]*ImageNRGBAPool, len(tuples))
142+
for i, t := range tuples {
143+
pools[i] = NewImageNRGBAPool(t.poolSize, t.rect, mOpt.poolFuncs...)
144+
}
145+
return &MultiImageNRGBAPool{
146+
tuples: tuples,
147+
pools: pools,
148+
}
149+
}
150+
151+
func (b *MultiImageNRGBAPool) find(r image.Rectangle) (*ImageNRGBAPool, bool) {
152+
if r.Empty() {
153+
return nil, false
154+
}
155+
156+
for i, t := range b.tuples {
157+
if rectIn(t.rect, r) {
158+
return b.pools[i], true
159+
}
160+
}
161+
return nil, false
162+
}
163+
164+
func (b *MultiImageNRGBAPool) GetRef(r image.Rectangle) *ImageNRGBARef {
165+
if pool, ok := b.find(r); ok {
166+
return pool.GetRef()
167+
}
168+
169+
pool := &ImageNRGBAPool{}
170+
pool.init(r)
171+
172+
pix := make([]uint8, pool.length)
173+
return pool.createImageNRGBARef(pix, b.pools[len(b.pools)-1])
174+
}
175+
176+
func (b *MultiImageNRGBAPool) Put(pix []uint8, r image.Rectangle) bool {
177+
if pool, ok := b.find(r); ok {
178+
return pool.Put(pix)
179+
}
180+
// discard
181+
return false
182+
}
183+
128184
type MultiImageYCbCrPool struct {
129185
tuples []imagepoolTuple
130186
pools []*ImageYCbCrPool

0 commit comments

Comments
 (0)