Skip to content

Commit

Permalink
image.NRGBA
Browse files Browse the repository at this point in the history
  • Loading branch information
octu0 committed Feb 10, 2021
1 parent ffcf568 commit f67eb4a
Show file tree
Hide file tree
Showing 6 changed files with 424 additions and 2 deletions.
42 changes: 42 additions & 0 deletions imagepool.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,48 @@ func (b *ImageRGBAPool) Cap() int {
return cap(b.pool)
}

type ImageNRGBAPool struct {
ImageRGBAPool
}

func NewImageNRGBAPool(poolSize int, rect image.Rectangle, funcs ...optionFunc) *ImageNRGBAPool {
opt := newOption()
for _, fn := range funcs {
fn(opt)
}

b := new(ImageNRGBAPool)
b.pool = make(chan []uint8, poolSize)
b.init(rect)

if opt.preload {
b.preload(opt.preloadRate)
}
return b
}

func (b *ImageNRGBAPool) createImageNRGBARef(pix []uint8, pool *ImageNRGBAPool) *ImageNRGBARef {
ref := newImageNRGBARef(pix, &image.NRGBA{
Pix: pix,
Stride: b.stride,
Rect: b.rect,
}, pool)
ref.setFinalizer()
return ref
}

func (b *ImageNRGBAPool) GetRef() *ImageNRGBARef {
var pix []uint8
select {
case pix = <-b.pool:
// reuse exists pool
default:
// create []uint8
pix = make([]uint8, b.length)
}
return b.createImageNRGBARef(pix, b)
}

type ImageYCbCrPool struct {
pool chan []uint8
rect image.Rectangle
Expand Down
134 changes: 134 additions & 0 deletions imagepool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,61 @@ func TestImageRGBAPoolBufSize(t *testing.T) {
})
}

func TestImageNRGBAPoolBufSize(t *testing.T) {
t.Run("getsamecap", func(tt *testing.T) {
rect := image.Rect(0, 0, 100, 100)
pool := NewImageNRGBAPool(10, rect)
img := image.NewNRGBA(rect)

d1 := pool.GetRef()
d2 := pool.GetRef()
if cap(d1.pix) != cap(img.Pix) {
tt.Errorf("buf size = %d", cap(img.Pix))
}
if cap(d2.pix) != cap(img.Pix) {
tt.Errorf("buf size = %d", cap(img.Pix))
}
})
t.Run("getput/smallcap", func(tt *testing.T) {
rect := image.Rect(0, 0, 100, 100)
pool := NewImageNRGBAPool(10, rect)
img := image.NewNRGBA(rect)

r1 := image.Rect(0, 0, 64, 36)
i1 := image.NewNRGBA(r1)
if pool.Put(i1.Pix) {
tt.Errorf("discard small pix")
}

d1 := pool.GetRef()
if cap(d1.pix) != cap(img.Pix) {
tt.Errorf("discard small pix = %d", cap(d1.pix))
}
if len(d1.pix) != len(img.Pix) {
tt.Errorf("discard small pix")
}
})
t.Run("getput/largecap", func(tt *testing.T) {
rect := image.Rect(0, 0, 100, 100)
pool := NewImageNRGBAPool(10, rect)
img := image.NewNRGBA(rect)

r1 := image.Rect(0, 0, 640, 360)
i1 := image.NewNRGBA(r1)
if pool.Put(i1.Pix) != true {
tt.Errorf("allow large pix")
}

d1 := pool.GetRef()
if cap(d1.pix) == cap(img.Pix) {
tt.Errorf("large pix ok")
}
if len(d1.pix) != len(img.Pix) {
tt.Errorf("same len")
}
})
}

func TestImageYCbCrPoolBufSize(t *testing.T) {
t.Run("getsamecap", func(tt *testing.T) {
rect := image.Rect(0, 0, 100, 100)
Expand Down Expand Up @@ -307,6 +362,76 @@ func TestImageRGBAPoolCapLen(t *testing.T) {
})
}

func TestImageNRGBAPoolCapLen(t *testing.T) {
t.Run("getput", func(tt *testing.T) {
r := image.Rect(0, 0, 16, 9)
p := NewImageNRGBAPool(10, r)
if 0 != p.Len() {
tt.Errorf("initial len 0")
}
if 10 != p.Cap() {
tt.Errorf("initial cap 10")
}

data := p.GetRef()
if 0 != p.Len() {
tt.Errorf("initial len 0")
}
if 10 != p.Cap() {
tt.Errorf("initial cap 10")
}
p.Put(data.pix)

if 1 != p.Len() {
tt.Errorf("put one")
}
if 10 != p.Cap() {
tt.Errorf("initial cap 10")
}

d1 := p.GetRef()
if 0 != p.Len() {
tt.Errorf("acquire pool")
}
p.Put(d1.pix)
if 1 != p.Len() {
tt.Errorf("release pool")
}
})
t.Run("maxcap", func(tt *testing.T) {
r := image.Rect(0, 0, 16, 9)
p := NewImageNRGBAPool(10, r)
s := make([]*ImageNRGBARef, 0)
for i := 0; i < 10; i += 1 {
r := p.GetRef()
s = append(s, r)
}
for _, r := range s {
p.Put(r.pix)
}

if 10 != p.Len() {
tt.Errorf("fill-ed pool: %d", p.Len())
}
if 10 != p.Cap() {
tt.Errorf("max capacity = 10")
}

i1 := image.NewNRGBA(r)
d1 := newImageNRGBARef(i1.Pix, i1, p)
i2 := image.NewNRGBA(r)
d2 := newImageNRGBARef(i2.Pix, i2, p)
p.Put(d1.pix)
p.Put(d2.pix)
if 10 != p.Len() {
tt.Errorf("fixed size pool")
}
if 10 != p.Cap() {
tt.Errorf("max capacity = 10")
}
})
}

func TestImageYCbCrPoolCapLen(t *testing.T) {
t.Run("getput", func(tt *testing.T) {
r := image.Rect(0, 0, 16, 9)
Expand Down Expand Up @@ -424,6 +549,15 @@ func TestImageRGBAPoolPreload(t *testing.T) {
}
}

func TestImageNRGBAPoolPreload(t *testing.T) {
r := image.Rect(0, 0, 100, 100)
p := NewImageNRGBAPool(12, r, Preload(true))
l := int(float64(12) * defaultPreloadRate)
if p.Len() != l {
t.Errorf("preloaded buffer = %d", p.Len())
}
}

func TestImageYCbCrPoolPreload(t *testing.T) {
r := image.Rect(0, 0, 100, 100)
p := NewImageYCbCrPool(12, r, image.YCbCrSubsampleRatio420, Preload(true))
Expand Down
60 changes: 58 additions & 2 deletions mimagepool.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,11 @@ func NewMultiImageRGBAPool(funcs ...multiImageBufferPoolOptionFunc) *MultiImageR
}

tuples := uniqImagepoolTuple(mOpt.tuples)
poolFuncs := mOpt.poolFuncs

sortTuples(tuples)
pools := make([]*ImageRGBAPool, len(tuples))
for i, t := range tuples {
pools[i] = NewImageRGBAPool(t.poolSize, t.rect, poolFuncs...)
pools[i] = NewImageRGBAPool(t.poolSize, t.rect, mOpt.poolFuncs...)
}
return &MultiImageRGBAPool{
tuples: tuples,
Expand Down Expand Up @@ -125,6 +124,63 @@ func (b *MultiImageRGBAPool) Put(pix []uint8, r image.Rectangle) bool {
return false
}

type MultiImageNRGBAPool struct {
tuples []imagepoolTuple
pools []*ImageNRGBAPool
}

func NewMultiImageNRGBAPool(funcs ...multiImageBufferPoolOptionFunc) *MultiImageNRGBAPool {
mOpt := newMultiImageBufferPoolOption()
for _, fn := range funcs {
fn(mOpt)
}

tuples := uniqImagepoolTuple(mOpt.tuples)

sortTuples(tuples)
pools := make([]*ImageNRGBAPool, len(tuples))
for i, t := range tuples {
pools[i] = NewImageNRGBAPool(t.poolSize, t.rect, mOpt.poolFuncs...)
}
return &MultiImageNRGBAPool{
tuples: tuples,
pools: pools,
}
}

func (b *MultiImageNRGBAPool) find(r image.Rectangle) (*ImageNRGBAPool, bool) {
if r.Empty() {
return nil, false
}

for i, t := range b.tuples {
if rectIn(t.rect, r) {
return b.pools[i], true
}
}
return nil, false
}

func (b *MultiImageNRGBAPool) GetRef(r image.Rectangle) *ImageNRGBARef {
if pool, ok := b.find(r); ok {
return pool.GetRef()
}

pool := &ImageNRGBAPool{}
pool.init(r)

pix := make([]uint8, pool.length)
return pool.createImageNRGBARef(pix, b.pools[len(b.pools)-1])
}

func (b *MultiImageNRGBAPool) Put(pix []uint8, r image.Rectangle) bool {
if pool, ok := b.find(r); ok {
return pool.Put(pix)
}
// discard
return false
}

type MultiImageYCbCrPool struct {
tuples []imagepoolTuple
pools []*ImageYCbCrPool
Expand Down
Loading

0 comments on commit f67eb4a

Please sign in to comment.