---
# System prepended metadata

title: '03.線上拍照並回存（gocv, websocket)'
tags: [golang練習]

---

# 03.線上拍照並回存（gocv, websocket)
###### tags: `golang練習`

```go
func ws_connect(w http.ResponseWriter, r *http.Request) {
	//判斷請求是否為websocket升級請求。
	if websocket.IsWebSocketUpgrade(r) {
		conn, err := upgrader.Upgrade(w, r, w.Header())
		if err != nil {
			fmt.Println("websocket upgrader.Upgrade failed: ", err)
			return
		}
		
		//設定設備id、執行拍照、取得img.jpg的[]byte
		device_id := 0
		img_byte, err := camera(device_id)
		if err != nil {
			fmt.Println("func camera failed: ", err)
			return
		}

		//轉jpg -> base64並傳送至前端
		img_base64 := encode_img(img_byte)
		err = conn.WriteMessage(websocket.TextMessage, []byte(img_base64))
		if err != nil {
			fmt.Println("conn.WriteMessage failed: ", err)
			return
		}

		// 持續接收與回覆訊息
		for{
		_, c, err := conn.ReadMessage()
		if err != nil {
			fmt.Println("websocket conn.ReadMessage() failed: ", err)
			return
		}
		img_base64_return := string(c)
		err = decode_img_and_save(img_base64_return)
		if err == nil {
			conn.WriteMessage(websocket.TextMessage, []byte("儲存成功"))
		}
		}
	} else {
		fmt.Println("not connected")
		return
	}
}

//picture
func camera(device_id int) ([]byte, error) {
	// 確認catch到攝影機
	webcam, err := gocv.VideoCaptureDevice(device_id)
	if err != nil {
		fmt.Printf("Error opening video capture device: %v\n", err)
		return nil, err
	}

	// 等待鏡頭開啟（暖機）(約300ms抓500ms)
	time.Sleep(500 * time.Millisecond)

	// 新增Mat
	img := gocv.NewMat()

	// 讀取畫面進Mat
	if ok := webcam.Read(&img); !ok {
		fmt.Println("Erro happended in webcam.Read.")
		return nil, err
	}

	// 照片轉為jpeg碼並轉為[]byte形式
	img_jpg, err := gocv.IMEncode(gocv.JPEGFileExt, img)
	if err != nil {
		fmt.Println("gocv.IMEncode failed")
		return nil, err
	}
	img_byte := img_jpg.GetBytes()

	// 關機
	err = img.Close()
	if err != nil {
		fmt.Println("img.Close() failed")
		return nil, err
	}
	err = webcam.Close()
	if err != nil {
		fmt.Println("webcam.Close failed")
		return nil, err
	}
	return img_byte, nil
}

func encode_img(img []byte) (img_base64_str string) { //讀入
	img_base64_str = base64.StdEncoding.EncodeToString(img) //文件轉base64
	return img_base64_str
}

func decode_img_and_save(img_base64 string) error {
	ff, err := base64.StdEncoding.DecodeString(img_base64)
	if err != nil {
		fmt.Println("os.WriteFile faild: ", err)
		return err
	}
	err = os.WriteFile("selfie_save.jpg", ff, 0740)
	if err != nil {
		fmt.Println("os.WriteFile faild: ", err)
		return err
	}
	return nil
}

```
```go    
	// 照片轉為jpeg碼並轉為[]byte形式
	img_jpg, err := gocv.IMEncode(gocv.JPEGFileExt, img)
	if err != nil {
		fmt.Println("gocv.IMEncode failed")
		return nil, err
	}
	img_byte := img_jpg.GetBytes()
```
1. gocv.IMEncode(encode type, mat)
Load the image data from mat and convert it as the encode type you chose, and return the encode data.
1. (buffer *NativeByteBuffer) GetBytes()
make the encode data to the []byte

---
```go    
//轉jpg -> base64並傳送至前端
		img_base64 := encode_img(img_byte)
		err = conn.WriteMessage(websocket.TextMessage, []byte(img_base64))
		if err != nil {
			fmt.Println("conn.WriteMessage failed: ", err)
			return
		}
```
```go    
        func encode_img(img []byte) (img_base64_str string) { //讀入
	img_base64_str = base64.StdEncoding.EncodeToString(img) //文件轉base64
	return img_base64_str
}

```

1. **base64.StdEncoding.EncodeToString(data []byte)**
base64.StdEncoding will create an *Encoding encode by encodeStd(標準編碼) and use this *Encoding to encode your data to base64 data.
---

```go    
img_base64_return := string(c)
		err = decode_img_and_save(img_base64_return)
		if err == nil {
			conn.WriteMessage(websocket.TextMessage, []byte("儲存成功"))
		}
```
```go    
func decode_img_and_save(img_base64 string) error {
	ff, err := base64.StdEncoding.DecodeString(img_base64)
	if err != nil {
		fmt.Println("os.WriteFile faild: ", err)
		return err
	}
	err = os.WriteFile("selfie_save.jpg", ff, 0740)
	if err != nil {
		fmt.Println("os.WriteFile faild: ", err)
		return err
	}
	return nil
}
```
1. **base64.StdEncoding.DecodeString(data string):**
Decode data to the orginal data which is image_byte from the camera now.
2. **os.WriteFile(file name with data type, data, reading permission)**
Write the file wiht file type(like dog.jpg) from data you provided. It also set the permission.
其實 Linux 的檔案權限，共有四碼
第一碼為特殊用途，可省略，省略即代表 0 無作用
777 實際上是 0777 的簡寫
755 實際上是 0755 的簡寫
Please see for more: [here](http://linux.vbird.org/linux_basic/0210filepermission.php#locale)