98 lines
2.0 KiB
Go
98 lines
2.0 KiB
Go
|
package webcam
|
||
|
|
||
|
import (
|
||
|
"image"
|
||
|
"image/color"
|
||
|
"time"
|
||
|
|
||
|
"fyne.io/fyne/v2"
|
||
|
"fyne.io/fyne/v2/canvas"
|
||
|
"fyne.io/fyne/v2/widget"
|
||
|
"gocv.io/x/gocv"
|
||
|
)
|
||
|
|
||
|
var _ fyne.WidgetRenderer = (*webcamRenderer)(nil)
|
||
|
|
||
|
type Webcam struct {
|
||
|
widget.BaseWidget
|
||
|
|
||
|
WebcamID int64
|
||
|
UpdateFPS int64
|
||
|
fpsTimer *time.Ticker
|
||
|
}
|
||
|
|
||
|
func NewWebcam() *Webcam {
|
||
|
w := &Webcam{}
|
||
|
w.ExtendBaseWidget(w)
|
||
|
w.WebcamID = 0
|
||
|
w.UpdateFPS = 25
|
||
|
|
||
|
return w
|
||
|
}
|
||
|
|
||
|
func (w *Webcam) Resize(s fyne.Size) {
|
||
|
w.BaseWidget.Resize(s)
|
||
|
}
|
||
|
|
||
|
func (w *Webcam) CreateRenderer() fyne.WidgetRenderer {
|
||
|
fpsTimer := time.NewTicker(time.Duration(1000/25) * time.Millisecond)
|
||
|
go func(w *Webcam) {
|
||
|
for {
|
||
|
_ = <-fpsTimer.C
|
||
|
w.Refresh()
|
||
|
}
|
||
|
}(w)
|
||
|
return newWebcamRenderer(w)
|
||
|
}
|
||
|
|
||
|
type webcamRenderer struct {
|
||
|
webcam *Webcam
|
||
|
background *canvas.Rectangle
|
||
|
currentframe *canvas.Raster
|
||
|
goCVVideoCapture *gocv.VideoCapture
|
||
|
}
|
||
|
|
||
|
func renderframe(w, h int) image.Image {
|
||
|
frameImage := image.NewRGBA(image.Rect(0, 0, w, h))
|
||
|
return frameImage
|
||
|
}
|
||
|
|
||
|
func (r *webcamRenderer) actualrenderframe(w, h int) image.Image {
|
||
|
webcam, _ := gocv.VideoCaptureDevice(int(r.webcam.WebcamID))
|
||
|
img := gocv.NewMat()
|
||
|
webcam.Read(&img)
|
||
|
frameImage, _ := img.ToImage() //no point doing anything other than returning anyway!
|
||
|
return frameImage
|
||
|
}
|
||
|
|
||
|
func newWebcamRenderer(w *Webcam) *webcamRenderer {
|
||
|
renderer := &webcamRenderer{
|
||
|
webcam: w,
|
||
|
background: canvas.NewRectangle(color.RGBA{255, 0, 255, 255}),
|
||
|
}
|
||
|
renderer.currentframe = canvas.NewRaster(renderer.actualrenderframe)
|
||
|
return renderer
|
||
|
}
|
||
|
|
||
|
func (r *webcamRenderer) Objects() []fyne.CanvasObject {
|
||
|
// The order is critical, rect is drawn first then currentframe
|
||
|
return []fyne.CanvasObject{r.background, r.currentframe}
|
||
|
}
|
||
|
|
||
|
func (r *webcamRenderer) Layout(s fyne.Size) {
|
||
|
r.background.Resize(s)
|
||
|
r.currentframe.Resize(s)
|
||
|
}
|
||
|
|
||
|
func (r *webcamRenderer) MinSize() fyne.Size {
|
||
|
return fyne.NewSize(200, 200)
|
||
|
}
|
||
|
|
||
|
func (r *webcamRenderer) Refresh() {
|
||
|
r.currentframe.Refresh()
|
||
|
}
|
||
|
|
||
|
func (r *webcamRenderer) Destroy() {
|
||
|
r.webcam.fpsTimer.Stop()
|
||
|
} // Called when the renderer is destroyed
|