• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mlange-42 / arche-pixel / 6787797515

07 Nov 2023 04:59PM CUT coverage: 83.59%. First build
6787797515

push

github

web-flow
CI tests, 2nd attempt (#45)

* Destroy window on UI finalization
* Enable full tests with window creation using `xvfb`
* Add coverage report and badge

Commits:
* run tests with xvfb
* destroy the window on finalization
* add TestMain to run all tests on the main thread
* enable window creation in all tests
* add coveralls step to CI tests
* add coveralls badge, update changelog

3 of 3 new or added lines in 1 file covered. (100.0%)

1355 of 1621 relevant lines covered (83.59%)

164130.5 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.71
/plot/rgb_image.go
1
package plot
2

3
import (
4
        "fmt"
5
        "image/color"
6

7
        pixel "github.com/gopxl/pixel/v2"
8
        "github.com/gopxl/pixel/v2/backends/opengl"
9
        "github.com/mlange-42/arche-model/observer"
10
        "github.com/mlange-42/arche-pixel/window"
11
        "github.com/mlange-42/arche/ecs"
12
)
13

14
// ImageRGB drawer.
15
//
16
// Draws an image from a Matrix observer per RGB color channel.
17
// The image is scaled to the canvas extent, with preserved aspect ratio.
18
// Does not add plot axes etc.
19
type ImageRGB struct {
20
        Scale    float64               // Spatial scaling: cell size in screen pixels. Optional, default auto.
21
        Observer observer.MatrixLayers // Observer providing data for color channels.
22
        Layers   []int                 // Layer indices. Optional, defaults to [0, 1, 2]. Use -1 to ignore a channel.
23
        Min      []float64             // Minimum value for channel color mapping. Optional, default [0, 0, 0].
24
        Max      []float64             // Maximum value for channel color mapping. Optional, default [1, 1, 1].
25
        slope    []float64
26
        dataLen  int
27
        picture  *pixel.PictureData
28
}
29

30
// Initialize the drawer.
31
func (i *ImageRGB) Initialize(w *ecs.World, win *opengl.Window) {
1✔
32
        i.Observer.Initialize(w)
1✔
33

1✔
34
        if i.Layers == nil {
2✔
35
                i.Layers = []int{0, 1, 2}
1✔
36
        } else if len(i.Layers) != 3 {
1✔
37
                panic("rgb image plot Layers must be of length 3")
×
38
        }
39

40
        layers := i.Observer.Layers()
1✔
41
        for _, l := range i.Layers {
4✔
42
                if l >= 0 && layers <= l {
3✔
43
                        panic(fmt.Sprintf("layer index %d out of range", l))
×
44
                }
45
        }
46

47
        if i.Min == nil {
1✔
48
                i.Min = []float64{0, 0, 0}
×
49
        }
×
50
        if i.Max == nil {
1✔
51
                i.Max = []float64{1, 1, 1}
×
52
        }
×
53
        if len(i.Min) != 3 {
1✔
54
                panic("RgbImage plot needs exactly 3 Min values")
×
55
        }
56
        if len(i.Max) != 3 {
1✔
57
                panic("RgbImage plot needs exactly 3 Max values")
×
58
        }
59

60
        i.slope = []float64{
1✔
61
                1.0 / (i.Max[0] - i.Min[0]),
1✔
62
                1.0 / (i.Max[1] - i.Min[1]),
1✔
63
                1.0 / (i.Max[2] - i.Min[2]),
1✔
64
        }
1✔
65

1✔
66
        width, height := i.Observer.Dims()
1✔
67
        i.dataLen = width * height
1✔
68
        i.picture = pixel.MakePictureData(pixel.R(0, 0, float64(width), float64(height)))
1✔
69
}
70

71
// Update the drawer.
72
func (i *ImageRGB) Update(w *ecs.World) {
100✔
73
        i.Observer.Update(w)
100✔
74
}
100✔
75

76
// UpdateInputs handles input events of the previous frame update.
77
func (i *ImageRGB) UpdateInputs(w *ecs.World, win *opengl.Window) {}
100✔
78

79
// Draw the drawer.
80
func (i *ImageRGB) Draw(w *ecs.World, win *opengl.Window) {
100✔
81
        cannels := i.Observer.Values(w)
100✔
82

100✔
83
        values := append([]float64{}, i.Min...)
100✔
84
        for j := 0; j < i.dataLen; j++ {
3,840,100✔
85
                for i, k := range i.Layers {
15,360,000✔
86
                        if k >= 0 {
23,040,000✔
87
                                values[i] = cannels[k][j]
11,520,000✔
88
                        }
11,520,000✔
89
                }
90
                i.picture.Pix[j] = i.valuesToColor(values[0], values[1], values[2])
3,840,000✔
91
        }
92

93
        scale := i.Scale
100✔
94
        if i.Scale <= 0 {
200✔
95
                scale = window.Scale(win, i.picture.Rect.W(), i.picture.Rect.H())
100✔
96
        }
100✔
97

98
        sprite := pixel.NewSprite(i.picture, i.picture.Bounds())
100✔
99
        sprite.Draw(win,
100✔
100
                pixel.IM.Moved(pixel.V(i.picture.Rect.W()/2.0, i.picture.Rect.H()/2.0)).
100✔
101
                        Scaled(pixel.Vec{}, scale),
100✔
102
        )
100✔
103
}
104

105
func (i *ImageRGB) valuesToColor(r, g, b float64) color.RGBA {
3,840,000✔
106
        return color.RGBA{
3,840,000✔
107
                R: norm(r, i.Min[0], i.slope[0]),
3,840,000✔
108
                G: norm(g, i.Min[1], i.slope[1]),
3,840,000✔
109
                B: norm(b, i.Min[2], i.slope[2]),
3,840,000✔
110
                A: 0xff,
3,840,000✔
111
        }
3,840,000✔
112
}
3,840,000✔
113

114
func norm(v, off, slope float64) uint8 {
11,520,000✔
115
        vv := (v - off) * slope
11,520,000✔
116
        if vv <= 0 {
13,384,000✔
117
                return 0
1,864,000✔
118
        }
1,864,000✔
119
        if vv >= 1 {
9,656,000✔
120
                return 255
×
121
        }
×
122
        return uint8(vv * 255)
9,656,000✔
123
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc