github.com/gop9/olt@v0.0.0-20200202132135-d956aad50b08/framework/drawfillover_test.go (about)

     1  package framework
     2  
     3  import (
     4  	"image"
     5  	"testing"
     6  )
     7  
     8  func drawFillOver_Normal(dst *image.RGBA, r image.Rectangle, sr, sg, sb, sa uint32) {
     9  	const m = 1<<16 - 1
    10  	// The 0x101 is here for the same reason as in drawRGBA.
    11  	a := (m - sa) * 0x101
    12  	i0 := dst.PixOffset(r.Min.X, r.Min.Y)
    13  	i1 := i0 + r.Dx()*4
    14  	for y := r.Min.Y; y != r.Max.Y; y++ {
    15  		for i := i0; i < i1; i += 4 {
    16  			dr := &dst.Pix[i+0]
    17  			dg := &dst.Pix[i+1]
    18  			db := &dst.Pix[i+2]
    19  			da := &dst.Pix[i+3]
    20  
    21  			*dr = uint8((uint32(*dr)*a/m + sr) >> 8)
    22  			*dg = uint8((uint32(*dg)*a/m + sg) >> 8)
    23  			*db = uint8((uint32(*db)*a/m + sb) >> 8)
    24  			*da = uint8((uint32(*da)*a/m + sa) >> 8)
    25  		}
    26  		i0 += dst.Stride
    27  		i1 += dst.Stride
    28  	}
    29  }
    30  
    31  func drawFillOver_NoPtr(dst *image.RGBA, r image.Rectangle, sr, sg, sb, sa uint32) {
    32  	const m = 1<<16 - 1
    33  	// The 0x101 is here for the same reason as in drawRGBA.
    34  	a := (m - sa) * 0x101
    35  	i0 := dst.PixOffset(r.Min.X, r.Min.Y)
    36  	i1 := i0 + r.Dx()*4
    37  	for y := r.Min.Y; y != r.Max.Y; y++ {
    38  		for i := i0; i < i1; i += 4 {
    39  			dst.Pix[i+0] = uint8((uint32(dst.Pix[i+0])*a/m + sr) >> 8)
    40  			dst.Pix[i+1] = uint8((uint32(dst.Pix[i+1])*a/m + sg) >> 8)
    41  			dst.Pix[i+2] = uint8((uint32(dst.Pix[i+2])*a/m + sb) >> 8)
    42  			dst.Pix[i+3] = uint8((uint32(dst.Pix[i+3])*a/m + sa) >> 8)
    43  		}
    44  		i0 += dst.Stride
    45  		i1 += dst.Stride
    46  	}
    47  }
    48  
    49  func drawFillOver_SIMD(dst *image.RGBA, r image.Rectangle, sr, sg, sb, sa uint32) {
    50  	const m = 1<<16 - 1
    51  	a := (m - sa) * 0x101
    52  	adivm := a / m
    53  	i0 := dst.PixOffset(r.Min.X, r.Min.Y)
    54  	i1 := i0 + r.Dx()*4
    55  	drawFillOver_SIMD_internal(&dst.Pix[0], i0, i1, dst.Stride, r.Max.Y-r.Min.Y, adivm, sr, sg, sb, sa)
    56  }
    57  
    58  func clearImg(b *image.RGBA) {
    59  	for i := 0; i < len(b.Pix); i += 4 {
    60  		b.Pix[i+0] = 50
    61  		b.Pix[i+1] = 50
    62  		b.Pix[i+2] = 50
    63  		b.Pix[i+3] = 255
    64  	}
    65  }
    66  
    67  func checkUniform(t *testing.T, b *image.RGBA, tgtr, tgtg, tgtb, tgta uint8) {
    68  	ok := true
    69  	for i := 0; i < len(b.Pix); i += 4 {
    70  		if b.Pix[i+0] != tgtr {
    71  			ok = false
    72  			t.Errorf("mismatch at pixel %d (red) %d %d\n", i/4, b.Pix[i+0], tgtr)
    73  		}
    74  		if b.Pix[i+1] != tgtg {
    75  			ok = false
    76  			t.Errorf("mismatch at pixel %d (green) %d %d\n", i/4, b.Pix[i+1], tgtg)
    77  		}
    78  		if b.Pix[i+2] != tgtb {
    79  			ok = false
    80  			t.Errorf("mismatch at pixel %d (blue) %d %d\n", i/4, b.Pix[i+2], tgtb)
    81  		}
    82  		if b.Pix[i+3] != tgta {
    83  			ok = false
    84  			t.Errorf("mismatch at pixel %d (alpha) %d %d\n", i/4, b.Pix[i+3], tgta)
    85  		}
    86  		if !ok {
    87  			t.Fatal("previous errors")
    88  		}
    89  	}
    90  	outr, outg, outb, outa := b.Pix[0], b.Pix[1], b.Pix[2], b.Pix[3]
    91  	t.Logf("color %d %d %d %d\n", outr, outg, outb, outa)
    92  }
    93  
    94  type fillOverFunc func(b *image.RGBA, r image.Rectangle, sr, sg, sb, sa uint32)
    95  
    96  func testFillOver(t *testing.T, b *image.RGBA, fo fillOverFunc) {
    97  	clearImg(b)
    98  	fo(b, b.Bounds(), 12850, 14906, 15677, 57825)
    99  	checkUniform(t, b, 56, 64, 67, 255)
   100  }
   101  
   102  func TestDrawFillOver(t *testing.T) {
   103  	b := image.NewRGBA(image.Rect(0, 0, 2550, 1400))
   104  	testFillOver(t, b, drawFillOver_Normal)
   105  	testFillOver(t, b, drawFillOver_NoPtr)
   106  	testFillOver(t, b, drawFillOver_SIMD)
   107  }
   108  
   109  func benchFillOver(bnc *testing.B, fo fillOverFunc) {
   110  	bnc.StopTimer()
   111  	b := image.NewRGBA(image.Rect(0, 0, 2550, 1400))
   112  
   113  	for n := 0; n < bnc.N; n++ {
   114  		clearImg(b)
   115  		bnc.StartTimer()
   116  		fo(b, b.Bounds(), 12850, 14906, 15677, 57825)
   117  		bnc.StopTimer()
   118  	}
   119  
   120  }
   121  
   122  // go test -bench=DrawFillOver -run=NONE -v
   123  
   124  func BenchmarkDrawFillOverNormal(bnc *testing.B) { // 18734046 ns/op
   125  	benchFillOver(bnc, drawFillOver_Normal)
   126  }
   127  
   128  func BenchmarkDrawFillOverNoPtr(bnc *testing.B) { // 19357654 ns/op
   129  	benchFillOver(bnc, drawFillOver_NoPtr)
   130  }
   131  
   132  func BenchmarkDrawFillOverSIMD(bnc *testing.B) { // 4644812 ns/op
   133  	benchFillOver(bnc, drawFillOver_SIMD)
   134  }