-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcamera_android.go
More file actions
177 lines (145 loc) · 4.02 KB
/
Copy pathcamera_android.go
File metadata and controls
177 lines (145 loc) · 4.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
package camera
/*
#cgo LDFLAGS: -landroid -llog -lcamera2ndk -lmediandk
#include "camera_android.c"
*/
import "C"
import (
"errors"
"fmt"
"image"
"sync"
"unsafe"
)
var (
copyImageFn func(buf []byte, width, height int) *image.RGBA
temp = image.NewRGBA(image.Rect(0, 0, 640, 480))
)
func init() {
copyImageFn = rotateImage90
}
//export onImageAvailableGo
func onImageAvailableGo(reader unsafe.Pointer) {
go func() {
aImageReader := (*C.AImageReader)(reader)
var aImage *C.AImage
C.AImageReader_acquireLatestImage(aImageReader, &aImage)
if aImage == nil {
return
}
var width, height C.int32_t
C.AImage_getWidth(aImage, &width)
C.AImage_getHeight(aImage, &height)
buf := make([]byte, width*height*4)
C.copyImage((*C.uint8_t)(unsafe.Pointer(&buf[0])), aImage)
C.AImage_delete(aImage)
// Convert the buffer to an image.RGBA
rgba := copyImageFn(buf, int(width), int(height))
// Send the frame buffer to the channel
select {
case frameBufferChan <- rgba:
default:
// Drop the frame if the channel is full
}
}()
}
func openCamera(cameraId, width, height int) error {
if C.openCamera(C.int(cameraId), C.int(width), C.int(height)) != 0 {
return fmt.Errorf("failed to initialize camera")
}
if cameraId != 0 {
copyImageFn = rotateImageMinus90AndMirror
}
return nil
}
func startCamera() error {
if C.startPreview() != 0 {
return fmt.Errorf("failed to start camera")
}
return nil
}
func stopCamera() error {
if C.stopPreview() != 0 {
return fmt.Errorf("failed to stop camera")
}
return nil
}
func closeCamera() {
C.closeCamera()
}
func copyImage(buf []byte, width, height int) *image.RGBA {
// Create the original RGBA image
temp := image.NewRGBA(image.Rect(0, 0, width, height))
copy(temp.Pix, buf)
return temp
}
func rotateImage90(buf []byte, width, height int) *image.RGBA {
// Create the original RGBA image
temp.Rect = image.Rect(0, 0, width, height)
temp.Stride = width * 4
temp.Pix = make([]uint8, width*height*4)
copy(temp.Pix, buf)
// Create a new RGBA image with swapped width and height for the rotated image
rotated := image.NewRGBA(image.Rect(0, 0, height, width))
// Rotate the image by 90 degrees clockwise
for y := 0; y < height; y++ {
for x := 0; x < width; x++ {
// Map the pixel from the original to the rotated image
rotated.Set(height-1-y, x, temp.At(x, y))
}
}
return rotated
}
func rotateImageMinus90(buf []byte, width, height int) *image.RGBA {
// Create the original RGBA image
temp := image.NewRGBA(image.Rect(0, 0, width, height))
copy(temp.Pix, buf)
// Create a new RGBA image with swapped width and height for the rotated image
rotated := image.NewRGBA(image.Rect(0, 0, height, width))
// Rotate the image by -90 degrees (270 degrees clockwise)
for y := 0; y < height; y++ {
for x := 0; x < width; x++ {
// Map the pixel from the original to the rotated image
rotated.Set(y, width-1-x, temp.At(x, y))
}
}
return rotated
}
func rotateImageMinus90AndMirror(buf []byte, width, height int) *image.RGBA {
// Create the original RGBA image
temp := image.NewRGBA(image.Rect(0, 0, width, height))
copy(temp.Pix, buf)
// Create a new RGBA image with swapped width and height for the rotated image
rotated := image.NewRGBA(image.Rect(0, 0, height, width))
// Rotate the image by -90 degrees (270 degrees clockwise) and mirror it horizontally
for y := 0; y < height; y++ {
for x := 0; x < width; x++ {
// Map the pixel from the original to the rotated and mirrored image
rotated.Set(height-1-y, width-1-x, temp.At(x, y))
}
}
return rotated
}
var (
errorStack []error
mutex sync.Mutex
)
//export pushError
func pushError(cstr *C.char) {
goStr := C.GoString(cstr)
err := errors.New(goStr)
mutex.Lock()
defer mutex.Unlock()
errorStack = append(errorStack, err)
}
// popError retrieves and removes the last error from the stack
func popError() error {
mutex.Lock()
defer mutex.Unlock()
if len(errorStack) == 0 {
return nil
}
err := errorStack[len(errorStack)-1]
errorStack = errorStack[:len(errorStack)-1]
return err
}