# 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)