mirror of
https://github.com/gen2brain/cam2ip.git
synced 2025-12-15 20:08:30 +00:00
Add option to draw images with WebGL
This commit is contained in:
22
README.md
22
README.md
@@ -18,10 +18,10 @@ or
|
||||
|
||||
Binaries are compiled with static OpenCV library:
|
||||
|
||||
- [Android 32bit](https://github.com/gen2brain/cam2ip/releases/download/1.1/cam2ip-1.1-android.tar.gz)
|
||||
- [Linux 64bit](https://github.com/gen2brain/cam2ip/releases/download/1.1/cam2ip-1.1-64bit.tar.gz)
|
||||
- [RPi 32bit](https://github.com/gen2brain/cam2ip/releases/download/1.1/cam2ip-1.1-RPi.tar.gz)
|
||||
- [Windows 32bit](https://github.com/gen2brain/cam2ip/releases/download/1.1/cam2ip-1.1.zip)
|
||||
- [Android 32bit](https://github.com/gen2brain/cam2ip/releases/download/1.2/cam2ip-1.2-android.tar.gz)
|
||||
- [Linux 64bit](https://github.com/gen2brain/cam2ip/releases/download/1.2/cam2ip-1.2-64bit.tar.gz)
|
||||
- [RPi 32bit](https://github.com/gen2brain/cam2ip/releases/download/1.2/cam2ip-1.2-RPi.tar.gz)
|
||||
- [Windows 32bit](https://github.com/gen2brain/cam2ip/releases/download/1.2/cam2ip-1.2.zip)
|
||||
|
||||
|
||||
### Installation
|
||||
@@ -35,17 +35,19 @@ This will install app in `$GOPATH/bin/cam2ip`.
|
||||
```
|
||||
Usage of ./cam2ip:
|
||||
-bind-addr string
|
||||
Bind address (default ":56000")
|
||||
Bind address (default ":56000")
|
||||
-delay int
|
||||
Delay between frames, in milliseconds (default 10)
|
||||
Delay between frames, in milliseconds (default 10)
|
||||
-frame-height float
|
||||
Frame height (default 480)
|
||||
Frame height (default 480)
|
||||
-frame-width float
|
||||
Frame width (default 640)
|
||||
Frame width (default 640)
|
||||
-htpasswd-file string
|
||||
Path to htpasswd file, if empty auth is disabled
|
||||
Path to htpasswd file, if empty auth is disabled
|
||||
-index int
|
||||
Camera index
|
||||
Camera index
|
||||
-webgl
|
||||
Use WebGL to draw images
|
||||
```
|
||||
|
||||
### Handlers
|
||||
|
||||
@@ -21,6 +21,7 @@ func main() {
|
||||
flag.IntVar(&srv.Delay, "delay", 10, "Delay between frames, in milliseconds")
|
||||
flag.Float64Var(&srv.FrameWidth, "frame-width", 640, "Frame width")
|
||||
flag.Float64Var(&srv.FrameHeight, "frame-height", 480, "Frame height")
|
||||
flag.BoolVar(&srv.WebGL, "webgl", false, "Use WebGL to draw images")
|
||||
flag.StringVar(&srv.Bind, "bind-addr", ":56000", "Bind address")
|
||||
flag.StringVar(&srv.Htpasswd, "htpasswd-file", "", "Path to htpasswd file, if empty auth is disabled")
|
||||
flag.Parse()
|
||||
|
||||
115
handlers/html.go
115
handlers/html.go
@@ -13,7 +13,7 @@ type HTML struct {
|
||||
}
|
||||
|
||||
// NewHTML returns new HTML handler.
|
||||
func NewHTML(bind string, width, height float64) *HTML {
|
||||
func NewHTML(bind string, width, height float64, gl bool) *HTML {
|
||||
h := &HTML{}
|
||||
|
||||
b := strings.Split(bind, ":")
|
||||
@@ -21,11 +21,16 @@ func NewHTML(bind string, width, height float64) *HTML {
|
||||
bind = "127.0.0.1" + bind
|
||||
}
|
||||
|
||||
html = strings.Replace(html, "{BIND}", bind, -1)
|
||||
html = strings.Replace(html, "{WIDTH}", fmt.Sprintf("%.0f", width), -1)
|
||||
html = strings.Replace(html, "{HEIGHT}", fmt.Sprintf("%.0f", height), -1)
|
||||
tpl := html
|
||||
if gl {
|
||||
tpl = htmlWebGL
|
||||
}
|
||||
|
||||
h.Template = []byte(html)
|
||||
tpl = strings.Replace(tpl, "{BIND}", bind, -1)
|
||||
tpl = strings.Replace(tpl, "{WIDTH}", fmt.Sprintf("%.0f", width), -1)
|
||||
tpl = strings.Replace(tpl, "{HEIGHT}", fmt.Sprintf("%.0f", height), -1)
|
||||
|
||||
h.Template = []byte(tpl)
|
||||
return h
|
||||
}
|
||||
|
||||
@@ -51,7 +56,7 @@ var html = `<html>
|
||||
var image = new Image();
|
||||
|
||||
ws.onopen = function() {
|
||||
var context = document.getElementById("canvas").getContext("2d");
|
||||
var context = document.getElementById("canvas").getContext("2d", {alpha: false});
|
||||
image.onload = function() {
|
||||
context.drawImage(image, 0, 0);
|
||||
}
|
||||
@@ -72,3 +77,101 @@ var html = `<html>
|
||||
</table>
|
||||
</body>
|
||||
</html>`
|
||||
|
||||
var htmlWebGL = `<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>cam2ip</title>
|
||||
<script>
|
||||
var texture, vloc, tloc, vertexBuff, textureBuff;
|
||||
|
||||
ws = new WebSocket("ws://{BIND}/socket");
|
||||
var image = new Image();
|
||||
|
||||
ws.onopen = function() {
|
||||
var gl = document.getElementById('canvas').getContext('webgl');
|
||||
|
||||
var vertexShaderSrc =
|
||||
"attribute vec2 aVertex;" +
|
||||
"attribute vec2 aUV;" +
|
||||
"varying vec2 vTex;" +
|
||||
"void main(void) {" +
|
||||
" gl_Position = vec4(aVertex, 0.0, 1.0);" +
|
||||
" vTex = aUV;" +
|
||||
"}";
|
||||
|
||||
var fragmentShaderSrc =
|
||||
"precision mediump float;" +
|
||||
"varying vec2 vTex;" +
|
||||
"uniform sampler2D sampler0;" +
|
||||
"void main(void){" +
|
||||
" gl_FragColor = texture2D(sampler0, vTex);"+
|
||||
"}";
|
||||
|
||||
var vertShaderObj = gl.createShader(gl.VERTEX_SHADER);
|
||||
var fragShaderObj = gl.createShader(gl.FRAGMENT_SHADER);
|
||||
gl.shaderSource(vertShaderObj, vertexShaderSrc);
|
||||
gl.shaderSource(fragShaderObj, fragmentShaderSrc);
|
||||
gl.compileShader(vertShaderObj);
|
||||
gl.compileShader(fragShaderObj);
|
||||
|
||||
var program = gl.createProgram();
|
||||
gl.attachShader(program, vertShaderObj);
|
||||
gl.attachShader(program, fragShaderObj);
|
||||
|
||||
gl.linkProgram(program);
|
||||
gl.useProgram(program);
|
||||
|
||||
gl.viewport(0, 0, {WIDTH}, {HEIGHT});
|
||||
|
||||
vertexBuff = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuff);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, 1, -1, -1, 1, -1, 1, 1]), gl.STATIC_DRAW);
|
||||
|
||||
textureBuff = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, textureBuff);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 1, 0, 0, 1, 0, 1, 1]), gl.STATIC_DRAW);
|
||||
|
||||
vloc = gl.getAttribLocation(program, "aVertex");
|
||||
tloc = gl.getAttribLocation(program, "aUV");
|
||||
|
||||
texture = gl.createTexture();
|
||||
|
||||
image.onload = function() {
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||
|
||||
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuff);
|
||||
gl.enableVertexAttribArray(vloc);
|
||||
gl.vertexAttribPointer(vloc, 2, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, textureBuff);
|
||||
gl.enableVertexAttribArray(tloc);
|
||||
gl.vertexAttribPointer(tloc, 2, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);
|
||||
}
|
||||
}
|
||||
|
||||
ws.onmessage = function(e) {
|
||||
image.setAttribute("src", "data:image/jpeg;base64," + e.data);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body style="background-color: #000000">
|
||||
<table style="width:100%; height:100%">
|
||||
<tr style="height:100%">
|
||||
<td style="height:100%; text-align:center">
|
||||
<canvas id="canvas" width="{WIDTH}" height="{HEIGHT}"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>`
|
||||
|
||||
@@ -24,6 +24,7 @@ type Server struct {
|
||||
Delay int
|
||||
FrameWidth float64
|
||||
FrameHeight float64
|
||||
WebGL bool
|
||||
|
||||
Camera *camera.Camera
|
||||
}
|
||||
@@ -42,7 +43,7 @@ func (s *Server) ListenAndServe() error {
|
||||
basic = auth.NewBasicAuthenticator(realm, auth.HtpasswdFileProvider(s.Htpasswd))
|
||||
}
|
||||
|
||||
http.Handle("/html", newAuthHandler(handlers.NewHTML(s.Bind, s.FrameWidth, s.FrameHeight), basic))
|
||||
http.Handle("/html", newAuthHandler(handlers.NewHTML(s.Bind, s.FrameWidth, s.FrameHeight, s.WebGL), basic))
|
||||
http.Handle("/jpeg", newAuthHandler(handlers.NewJPEG(s.Camera), basic))
|
||||
http.Handle("/mjpeg", newAuthHandler(handlers.NewMJPEG(s.Camera, s.Delay), basic))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user